Просмотр исходного кода

refactor: :art: mudei a função update nos repositories, melhorei o DTO e mais algumas mudanças

Denis 1 год назад
Родитель
Сommit
666def6dcd

+ 8 - 8
.env.example

@@ -19,14 +19,14 @@ LOG_STACK=single
 LOG_DEPRECATIONS_CHANNEL=null
 LOG_LEVEL=debug
 
-DB_CONNECTION=sqlite
-# DB_HOST=127.0.0.1
-# DB_PORT=3306
-# DB_DATABASE=laravel
-# DB_USERNAME=root
-# DB_PASSWORD=
+DB_CONNECTION=pgsql
+DB_HOST=127.0.0.1
+DB_PORT=5432
+DB_DATABASE=laravel_skeleton
+DB_USERNAME=postgres
+DB_PASSWORD=postgres
 
-SESSION_DRIVER=database
+SESSION_DRIVER=redis
 SESSION_LIFETIME=120
 SESSION_ENCRYPT=false
 SESSION_PATH=/
@@ -36,7 +36,7 @@ BROADCAST_CONNECTION=log
 FILESYSTEM_DISK=local
 QUEUE_CONNECTION=database
 
-CACHE_STORE=database
+CACHE_STORE=redis
 CACHE_PREFIX=
 
 MEMCACHED_HOST=127.0.0.1

+ 50 - 2
app/Commands/CreateCrud.php

@@ -4,6 +4,7 @@
 
 use Illuminate\Console\Command;
 use Illuminate\Filesystem\Filesystem;
+use Illuminate\Support\Str;
 
 class CreateCrud extends Command
 {
@@ -30,14 +31,19 @@ public function handle(): void
         $this->createRequest(name: $name);
         $this->createResource(name: $name);
         $this->updateAppServiceProvider(name: $name);
+        $this->createRoute(name: $name);
+        $this->createMigration(name: $name);
         $this->info(string: 'CRUD operations created successfully!');
     }
 
     protected function createModel($name): void
     {
+
+        $tableNameSnakeCase = Str::snake(Str::plural($name));
+
         $modelTemplate = str_replace(
-            search: ['{{modelName}}'],
-            replace: [$name],
+            search: ['{{modelName}}', '{{tableNameSnakeCase}}'],
+            replace: [$name, $tableNameSnakeCase],
             subject: $this->getStub(type: 'Model')
         );
 
@@ -145,6 +151,48 @@ protected function updateAppServiceProvider($name): void
         $this->files->put(path: $providerPath, contents: $content);
     }
 
+    protected function createRoute($name): void
+    {
+        $routeTemplate = str_replace(
+            search: [
+                '{{modelName}}',
+                '{{modelNameSnakeCase}}'
+            ],
+            replace: [
+                $name,
+                Str::snake($name)
+            ],
+            subject: $this->getStub(type: 'Route')
+        );
+
+        $routePath = base_path("routes/authRoutes/" . strtolower($name) . ".php");
+
+        if (!$this->files->isDirectory(base_path('routes/authRoutes'))) {
+            $this->files->makeDirectory(base_path('routes/authRoutes'), 0755, true);
+        }
+
+        $this->put(path: $routePath, contents: $routeTemplate);
+    }
+
+    protected function createMigration($name): void
+    {
+        $tableNameSnakeCase = Str::snake(Str::plural($name));
+
+        $migrationTemplate = str_replace(
+            search: ['{{tableNameSnakeCase}}'],
+            replace: [$tableNameSnakeCase],
+            subject: $this->getStub(type: 'Migration')
+        );
+
+        $timestamp = date('Y_m_d_His');
+        $filename = $timestamp . "_create_{$tableNameSnakeCase}_table.php";
+
+        $this->put(
+            path: database_path("migrations/{$filename}"),
+            contents: $migrationTemplate
+        );
+    }
+
     protected function getStub($type): string
     {
         return $this->files->get(path: storage_path(path: "stubs/{$type}.stub"));

+ 2 - 16
app/DTO/AuthDTO.php

@@ -14,25 +14,11 @@ public function __construct(
 
     public static function fromRequest(AuthRequest $request): self
     {
-        return new self(
-            email: $request->validated(key: 'email'),
-            password: $request->validated(key: 'password'),
-        );
+        return new self(...$request->validated());
     }
 
     public function toArray(): array
     {
-        return [
-            'email' => $this->email,
-            'password' => $this->password,
-        ];
-    }
-
-    public static function fromArray(array $data): self
-    {
-        return new self(
-            email: $data['email'],
-            password: $data['password'],
-        );
+        return get_object_vars($this);
     }
 }

+ 6 - 16
app/DTO/PermissionDTO.php

@@ -16,12 +16,12 @@ public function __construct(
 
     public static function fromRequest(PermissionRequest $request): self
     {
-        return new self(
-            scope: $request->validated(key: 'scope'),
-            description: $request->validated(key: 'description'),
-            bits: $request->validated(key: 'bits'),
-            parent_id: $request->validated(key: 'parent_id'),
-        );
+        return new self(...$request->validated());
+    }
+
+    public function toArray(): array
+    {
+        return get_object_vars($this);
     }
 
     public static function fromArray(array $data): self
@@ -33,14 +33,4 @@ public static function fromArray(array $data): self
             parent_id: isset($data['parent_id']) ? $data['parent_id'] : null,
         );
     }
-
-    public function toArray(): array
-    {
-        return [
-            'scope' => $this->scope,
-            'description' => $this->description,
-            'bits' => $this->bits,
-            'parent_id' => $this->parent_id,
-        ];
-    }
 }

+ 3 - 14
app/DTO/RefreshTokenDTO.php

@@ -7,28 +7,17 @@
 readonly class RefreshTokenDTO
 {
     public function __construct(
-        public string $token,
+        public string $refresh_token,
     ) {
     }
 
     public static function fromRequest(RefreshTokenRequest $request): self
     {
-        return new self(
-            token: $request->validated(key: 'refresh_token'),
-        );
-    }
-
-    public static function fromArray(array $data): self
-    {
-        return new self(
-            token: $data['refresh_token'],
-        );
+        return new self(...$request->validated());
     }
 
     public function toArray(): array
     {
-        return [
-            'refresh_token' => $this->token,
-        ];
+        return get_object_vars($this);
     }
 }

+ 8 - 28
app/DTO/UserDTO.php

@@ -7,40 +7,20 @@
 readonly class UserDTO
 {
     public function __construct(
-        public string $name,
-        public string $email,
-        public ?string $password,
-        public ?string $type,
-    ) {
-    }
+        public ?string $name = null,
+        public ?string $email = null,
+        public ?string $password = null,
+        public ?string $type = null,
+        public ?string $language = null,
+    ) {}
 
     public static function fromRequest(UserRequest $request): self
     {
-        return new self(
-            name: $request->validated(key: 'name'),
-            email: $request->validated(key: 'email'),
-            password: $request->validated(key: 'password'),
-            type: $request->validated(key: 'type'),
-        );
-    }
-
-    public static function fromArray(array $data): self
-    {
-        return new self(
-            name: $data['name'],
-            email: $data['email'],
-            password: $data['password'],
-            type: $data['type'],
-        );
+        return new self(...$request->validated());
     }
 
     public function toArray(): array
     {
-        return [
-            'name' => $this->name,
-            'email' => $this->email,
-            'password' => $this->password,
-            'type' => $this->type,
-        ];
+        return get_object_vars($this);
     }
 }

+ 0 - 51
app/DTO/UserLanguageDTO.php

@@ -1,51 +0,0 @@
-<?php
-
-namespace App\DTO;
-
-use App\Http\Requests\UserLanguageRequest;
-use App\Enums\UserLanguageSource;
-
-readonly class UserLanguageDTO
-{
-    public function __construct(
-        public string $language,
-    ) {
-    }
-
-    public static function fromRequest(UserLanguageRequest $request): self
-    {
-        return new self(
-            language: $request->validated(key: 'language'),
-        );
-    }
-
-    public static function fromString(string $language): self
-    {
-        if (!UserLanguageSource::isValid(value: $language)) {
-            throw new \InvalidArgumentException(message: 'Invalid language');
-        }
-
-        return new self(
-            language: $language,
-        );
-    }
-
-    public static function fromArray(array $data): self
-    {
-        return new self(
-            language: $data['language'],
-        );
-    }
-
-    public function toArray(): array
-    {
-        return [
-            'language' => $this->language,
-        ];
-    }
-
-    public function toString(): string
-    {
-        return $this->language;
-    }
-}

+ 2 - 4
app/Http/Controllers/UserController.php

@@ -5,8 +5,6 @@
 use App\Http\Resources\UserResource;
 use App\Services\UserService;
 use App\DTO\UserDTO;
-use App\DTO\UserLanguageDTO;
-use App\Http\Requests\UserLanguageRequest;
 use App\Http\Requests\UserRequest;
 use Illuminate\Http\JsonResponse;
 
@@ -54,9 +52,9 @@ public function show(int $id): JsonResponse
         return $this->successResponse(payload: new UserResource($user));
     }
 
-    public function updateLanguage(UserLanguageRequest $request, int $id): JsonResponse
+    public function updateLanguage(UserRequest $request, int $id): JsonResponse
     {
-        $user = $this->userService->updateLanguage(UserLanguageDTO::fromRequest($request), $id);
+        $user = $this->userService->updateLanguage(UserDTO::fromRequest($request), $id);
         return $this->successResponse(payload: new UserResource($user), message: __('messages.updated'));
     }
 }

+ 5 - 8
app/Http/Middleware/SetUserLanguage.php

@@ -6,9 +6,7 @@
 use Illuminate\Http\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Illuminate\Support\Facades\App;
-use App\DTO\UserLanguageDTO;
 use App\Enums\UserLanguageSource;
-use Illuminate\Support\Facades\Log;
 
 class SetUserLanguage
 {
@@ -20,12 +18,11 @@ class SetUserLanguage
     public function handle(Request $request, Closure $next): Response
     {
         $language = substr($request->header('Accept-Language'), 0, 2);
-        try {
-            $language = UserLanguageDTO::fromString($language)->language;
-            App::setLocale($language);
-        } catch (\InvalidArgumentException $e) {
-            Log::error("message: {$e->getMessage()}");
-            $language = UserLanguageSource::English;
+        $language = UserLanguageSource::fromString($language);
+        if ($language) {
+            App::setLocale($language->value);
+        } else {
+            App::setLocale(UserLanguageSource::Portuguese->value);
         }
         return $next($request);
     }

+ 0 - 17
app/Http/Requests/UserLanguageRequest.php

@@ -1,17 +0,0 @@
-<?php
-
-namespace App\Http\Requests;
-
-use Illuminate\Foundation\Http\FormRequest;
-use Illuminate\Validation\Rule;
-use App\Enums\UserLanguageSource;
-
-class UserLanguageRequest extends FormRequest
-{
-    public function rules(): array
-    {
-        return [
-            'language' => ['required', Rule::enum(UserLanguageSource::class)],
-        ];
-    }
-}

+ 12 - 10
app/Http/Requests/UserRequest.php

@@ -11,24 +11,26 @@ class UserRequest extends FormRequest
     public function rules(): array
     {
         $rules = [
-            'name' => 'required|string',
+            'name' => 'sometimes|string|nullable',
             'password' => 'sometimes|string|nullable',
             'type' => ['sometimes', Rule::enum(UserTypeSource::class)],
+            'email' => 'sometimes|unique:users,email|email',
+            'language' => 'sometimes|string|nullable',
         ];
 
-        // Determine if the request is for creating or updating
         if ($this->isMethod('post')) {
-            // Rules for creating a new user
+
+            $rules['name'] = 'required|string';
+            $rules['password'] = 'required|string';
             $rules['email'] = 'required|unique:users,email|email';
-        } elseif ($this->isMethod('put') || $this->isMethod('patch')) {
-            // Rules for updating an existing user
-            $rules['email'] = [
-                'required',
-                'email',
-                Rule::unique('users', 'email')->ignore($this->route('id')),
-            ];
+            $rules['language'] = 'sometimes|string|in:pt,en,es';
+
+            if (!$this->has('language')) {
+                $this->merge(['language' => 'pt']);
+            };
         }
 
+
         return $rules;
     }
 }

+ 10 - 8
app/Repositories/PermissionRepository.php

@@ -33,16 +33,18 @@ public function findByScope(string $scope): ?Permission
         return $this->model->where(column: 'scope', operator: $scope)->first();
     }
 
-    public function update(PermissionDTO $permissionDTO, int $id): ?Permission
+    public function update(int $id, PermissionDTO $dto, array $fieldsToUpdate): ?Permission
     {
         $permission = $this->model->find(id: $id);
-        $permission->update(attributes: [
-            'scope' => $permissionDTO->scope,
-            'description' => $permissionDTO->description,
-            'bits' => $permissionDTO->bits,
-            'parent_id' => $permissionDTO->parent_id,
-        ]);
-        return $permission;
+
+        $updateFields = array_intersect_key(
+            $dto->toArray(),
+            array_flip($fieldsToUpdate)
+        );
+
+        $permission->update($updateFields);
+
+        return $permission->fresh();
     }
 
     public function store(PermissionDTO $permissionDTO): Permission

+ 1 - 1
app/Repositories/PermissionRepositoryInterface.php

@@ -16,7 +16,7 @@ public function find(int $id): ?Permission;
 
     public function findByScope(string $scope): ?Permission;
 
-    public function update(PermissionDTO $permissionDTO, int $id): ?Permission;
+    public function update(int $id, PermissionDTO $dto, array $fieldsToUpdate): ?Permission;
 
     public function store(PermissionDTO $permissionDTO): Permission;
 

+ 13 - 28
app/Repositories/UserRepository.php

@@ -5,7 +5,6 @@
 use App\Models\User;
 use Illuminate\Database\Eloquent\Collection;
 use App\DTO\UserDTO;
-use App\DTO\UserLanguageDTO;
 use Illuminate\Support\Facades\Auth;
 
 class UserRepository implements UserRepositoryInterface
@@ -13,9 +12,7 @@ class UserRepository implements UserRepositoryInterface
 
     public function __construct(
         protected User $model,
-    )
-    {
-    }
+    ) {}
 
     public function me(): ?User
     {
@@ -29,24 +26,21 @@ public function all(): ?Collection
 
     public function store(UserDTO $userDTO): User
     {
-        return $this->model->create(attributes: [
-            'name' => $userDTO->name,
-            'email' => $userDTO->email,
-            'password' => bcrypt(value: $userDTO->password),
-            'type' => $userDTO->type,
-        ]);
+        return $this->model->create($userDTO->toArray());
     }
 
-    public function update(UserDTO $userDTO, int $id): ?User
+    public function update(int $id, UserDTO $dto, array $fieldsToUpdate): User
     {
-        $user = $this->model->findOrFail(id: $id);
-        $user->update(attributes: [
-            'name' => $userDTO->name,
-            'email' => $userDTO->email,
-            'password' => bcrypt(value: $userDTO->password),
-            'type' => $userDTO->type,
-        ]);
-        return $user;
+        $user = User::findOrFail($id);
+
+        $updateFields = array_intersect_key(
+            $dto->toArray(),
+            array_flip($fieldsToUpdate)
+        );
+
+        $user->update($updateFields);
+
+        return $user->fresh();
     }
 
     public function delete(int $id): bool
@@ -63,13 +57,4 @@ public function findByEmail(string $email): ?User
     {
         return $this->model->where(column: 'email', operator: $email)->first();
     }
-
-    public function updateLanguage(UserLanguageDTO $languageDTO, int $id): ?User
-    {
-        $user = $this->model->findOrFail(id: $id);
-        $user->update(attributes: [
-            'language' => $languageDTO->language,
-        ]);
-        return $user;
-    }
 }

+ 1 - 4
app/Repositories/UserRepositoryInterface.php

@@ -5,7 +5,6 @@
 use App\Models\User;
 use Illuminate\Database\Eloquent\Collection;
 use App\DTO\UserDTO;
-use App\DTO\UserLanguageDTO;
 
 interface UserRepositoryInterface
 {
@@ -17,11 +16,9 @@ public function store(UserDTO $userDTO): User;
 
     public function find(int $id): ?User;
 
-    public function update(UserDTO $userDTO, int $id): ?User;
+    public function update(int $id, UserDTO $dto, array $fieldsToUpdate): ?User;
 
     public function delete(int $id): bool;
 
     public function findByEmail(string $email): ?User;
-
-    public function updateLanguage(UserLanguageDTO $language, int $id): ?User;
 }

+ 2 - 3
app/Services/AuthService.php

@@ -12,8 +12,7 @@ class AuthService
 {
     public function __construct(
         protected AuthRepositoryInterface $authRepository,
-    ) {
-    }
+    ) {}
 
     public function login(AuthDTO $credentials): ?array
     {
@@ -37,7 +36,7 @@ public function login(AuthDTO $credentials): ?array
 
     public function refresh(RefreshTokenDTO $refreshToken): ?array
     {
-        $tokenModel = $this->authRepository->findToken( $refreshToken->token);
+        $tokenModel = $this->authRepository->findToken($refreshToken->refresh_token);
 
         if (!$tokenModel || !in_array(needle: 'refresh', haystack: $tokenModel->abilities) || $tokenModel->expires_at < now()) {
             return null;

+ 1 - 1
app/Services/PermissionService.php

@@ -41,7 +41,7 @@ public function store(PermissionDTO $permissionDTO): Permission
 
     public function update(PermissionDTO $permissionDTO, int $id): ?Permission
     {
-        return $this->permissionRepository->update(permissionDTO: $permissionDTO, id: $id);
+        return $this->permissionRepository->update(id: $id, dto: $permissionDTO, fieldsToUpdate: request()->keys());
     }
 
     public function delete(int $id): bool

+ 4 - 6
app/Services/UserService.php

@@ -5,15 +5,13 @@
 use Illuminate\Database\Eloquent\Collection;
 use App\Repositories\UserRepositoryInterface;
 use App\DTO\UserDTO;
-use App\DTO\UserLanguageDTO;
 use App\Models\User;
 
 class UserService
 {
     public function __construct(
         protected UserRepositoryInterface $userRepository,
-    ) {
-    }
+    ) {}
 
     public function me(): ?User
     {
@@ -37,7 +35,7 @@ public function store(UserDTO $userDTO): User
 
     public function update(UserDTO $userDTO, int $id): ?User
     {
-        return $this->userRepository->update(userDTO: $userDTO, id: $id);
+        return $this->userRepository->update(id: $id, dto: $userDTO, fieldsToUpdate: request()->keys());
     }
 
     public function delete(int $id): bool
@@ -50,8 +48,8 @@ public function findByEmail(string $email): ?User
         return $this->userRepository->findByEmail(email: $email);
     }
 
-    public function updateLanguage(UserLanguageDTO $language, int $id): ?User
+    public function updateLanguage(UserDTO $dto, int $id): ?User
     {
-        return $this->userRepository->updateLanguage(language: $language, id: $id);
+        return $this->userRepository->update(id: $id, dto: $dto, fieldsToUpdate: ['language']);
     }
 }

+ 6 - 0
app/Traits/EnumHelper.php

@@ -13,4 +13,10 @@ public static function toArray(): array
     {
         return array_column(self::cases(), 'value');
     }
+
+    public static function fromString(string $value): static
+    {
+        $cases = array_combine(array_map(fn($case) => $case->value, self::cases()), self::cases());
+        return $cases[$value] ?? null;
+    }
 }

+ 32 - 0
app/Traits/RemoveArchiveS3.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Traits;
+
+use Illuminate\Support\Facades\Storage;
+use Illuminate\Support\Str;
+
+trait RemoveArchiveS3
+{
+    /**
+     * Upload a base64 encoded image to S3 and return the URL.
+     *
+     * @param string $base64Image
+     * @param string $s3Folder
+     * @return string
+     * @throws \Exception
+     */
+    public function removeArchiveByUrl(string $url): bool
+    {
+        // Extrair o caminho relativo do S3 da URL completa
+        $oldImagePath = parse_url($url, PHP_URL_PATH);
+        $oldImagePath = ltrim($oldImagePath, '/'); // remover a barra inicial
+
+        // Excluir a imagem antiga do S3
+        if (Storage::disk('s3')->exists($oldImagePath)) {
+            Storage::disk('s3')->delete($oldImagePath);
+        }
+
+        // Return the URL of the uploaded image
+        return true;
+    }
+}

+ 50 - 0
app/Traits/UploadsBase64Image.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace App\Traits;
+
+use Illuminate\Support\Facades\Storage;
+use Illuminate\Support\Str;
+
+trait UploadsBase64Image
+{
+    /**
+     * Upload a base64 encoded image to S3 and return the URL.
+     *
+     * @param string $base64Image
+     * @param string $s3Folder
+     * @return string
+     * @throws \Exception
+     */
+    public function uploadBase64Image(string $base64Image, string $s3Folder): string
+    {
+        // Extract the file extension and base64 data
+        if (preg_match('/^data:image\/(\w+);base64,/', $base64Image, $type)) {
+            $base64Image = substr($base64Image, strpos($base64Image, ',') + 1);
+            $type = strtolower($type[1]); // jpg, png, gif
+
+            if (!in_array($type, ['jpg', 'jpeg', 'png', 'gif'])) {
+                throw new \Exception(__('validation.extensions', ['attribute' => __('general.image'), 'values' => 'jpg, jpeg, png, gif']));
+            }
+
+            $image = base64_decode($base64Image);
+
+            if ($image === false) {
+                throw new \Exception('Base64 decode failed');
+            }
+        } else {
+            throw new \Exception('Invalid base64 image format');
+        }
+
+        // Generate a unique filename
+        $filename = Str::random(20) . '.' . $type;
+
+        // Define the full path where the file will be stored
+        $filePath = $s3Folder . '/' . $filename;
+
+        // Save the file to S3
+        Storage::disk('s3')->put($filePath, $image);
+
+        // Return the URL of the uploaded image
+        return Storage::disk('s3')->url($filePath);
+    }
+}

+ 1 - 1
bootstrap/app.php

@@ -18,7 +18,7 @@
         health: '/up',
     )
     ->withMiddleware(function (Middleware $middleware) {
-        $middleware->statefulApi();
+        // $middleware->statefulApi();
         $middleware->append(SetUserLanguage::class);
         $middleware->alias([
             'permission' => CheckPermission::class,

+ 3 - 14
storage/stubs/DTO.stub

@@ -4,7 +4,7 @@ namespace App\DTO;
 
 use App\Http\Requests\{{modelName}}Request;
 
-class {{modelName}}DTO
+readonly class {{modelName}}DTO
 {
     public function __construct(
         // Add properties here
@@ -13,22 +13,11 @@ class {{modelName}}DTO
 
     public static function fromRequest({{modelName}}Request $request): self
     {
-        return new self(
-            // Initialize properties from $request
-        );
-    }
-
-    public static function fromArray(array $data): self
-    {
-        return new self(
-            // Initialize properties from $data
-        );
+        return new self(...$request->validated());
     }
 
     public function toArray(): array
     {
-        return [
-            // Convert properties to array
-        ];
+        return get_object_vars($this);
     }
 }

+ 28 - 0
storage/stubs/Migration.stub

@@ -0,0 +1,28 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::create('{{tableNameSnakeCase}}', function (Blueprint $table) {
+            $table->id();
+            // Add your columns here
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('{{tableNameSnakeCase}}');
+    }
+};

+ 2 - 0
storage/stubs/Model.stub

@@ -9,6 +9,8 @@ class {{modelName}} extends Model
 {
     use HasFactory;
 
+    $table = '{{tableNameSnakeCase}}';
+
     protected $fillable = [
         // Add fillable attributes here
     ];

+ 10 - 3
storage/stubs/Repository.stub

@@ -28,11 +28,18 @@ class {{modelName}}Repository implements {{modelName}}RepositoryInterface
         return $this->model->create($dto->toArray());
     }
 
-    public function update(int $id, {{modelName}}DTO $dto): {{modelName}}
+    public function update(int $id, {{modelName}}DTO $dto, array $fieldsToUpdate): {{modelName}}
     {
         $record = $this->find($id);
-        $record->update($dto->toArray());
-        return $record;
+
+        $updateFields = array_intersect_key(
+            $dto->toArray(),
+            array_flip($fieldsToUpdate)
+        );
+
+        $user->update($updateFields);
+
+        return $user->fresh();
     }
 
     public function delete(int $id): bool

+ 1 - 1
storage/stubs/RepositoryInterface.stub

@@ -14,7 +14,7 @@ interface {{modelName}}RepositoryInterface
 
     public function create({{modelName}}DTO $dto): {{modelName}};
 
-    public function update(int $id, {{modelName}}DTO $dto): {{modelName}};
+    public function update(int $id, {{modelName}}DTO $dto, array $fieldsToUpdate): {{modelName}};
 
     public function delete(int $id): bool;
 }

+ 14 - 0
storage/stubs/Route.stub

@@ -0,0 +1,14 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+use App\Http\Controllers\{{modelName}}Controller;
+
+Route::get('/{{modelNameSnakeCase}}', [{{modelName}}Controller::class, 'index']);
+
+Route::post('/{{modelNameSnakeCase}}', [{{modelName}}Controller::class, 'store']);
+
+Route::get('/{{modelNameSnakeCase}}/{id}', [{{modelName}}Controller::class, 'show']);
+
+Route::put('/{{modelNameSnakeCase}}/{id}', [{{modelName}}Controller::class, 'update']);
+
+Route::delete('/{{modelNameSnakeCase}}/{id}', [{{modelName}}Controller::class, 'destroy']);

+ 1 - 1
storage/stubs/Service.stub

@@ -31,7 +31,7 @@ class {{modelName}}Service
 
     public function updateItem({{modelName}}DTO $dto, int $id): {{modelName}}
     {
-        return $this->repository->update($id, $dto);
+        return $this->repository->update($id, $dto, request()->keys());
     }
 
     public function deleteItem(int $id): bool