From a48b2dbb1cfc24a744eac302cb836cdb96b49cf3 Mon Sep 17 00:00:00 2001 From: Dawid Miklas Date: Tue, 7 May 2024 21:42:13 +0200 Subject: [PATCH 1/8] better course DDD, Course creation command, handler, repository --- .../Course/Commands/CreateCourseCommand.php | 12 ---- .../Course/Controllers/CourseController.php | 26 ++++++-- .../Course/Handlers/CreateCourseHandler.php | 13 ---- .../Http/Course/Requests/CourseRequest.php | 20 ------ .../Http/Course/Resources/CourseResource.php | 20 ------ .../Http/Providers/AppServiceProvider.php | 16 ++--- .../Command/CreateCourseCommand.php | 16 +++++ .../CommandHandler/CreateCourseHandler.php | 30 +++++++++ .../Application/CourseServiceProvider.php | 18 +++++ .../Application/DTO/CreateCourseDto.php | 24 +++++++ app/Course/Domain/Entity/Course.php | 55 ++++++++++++++++ .../Repository/CourseRepositoryContract.php | 15 +++++ .../Persistence/Model/CourseModel.php | 35 ++++++++++ .../Repository/EloquentCourseRepository.php | 65 +++++++++++++++++++ app/Policies/CoursePolicy.php | 14 ++-- bootstrap/providers.php | 6 +- database/factories/CourseFactory.php | 4 +- ...183804_change_courses_table_id_to_uuid.php | 33 ++++++++++ database/seeders/CourseSeeder.php | 5 +- resources/js/Components/Course/CourseGrid.vue | 9 ++- resources/js/Components/NavLink.vue | 18 ++--- resources/js/Pages/Course/CreateCourse.vue | 33 ++++++---- routes/web.php | 5 +- src/Domains/Course/DTO/CreateCourseDto.php | 25 ------- src/Domains/Course/Models/Course.php | 20 ------ .../Repositories/CourseRepositoryContract.php | 10 --- 26 files changed, 370 insertions(+), 177 deletions(-) delete mode 100644 app/Application/Http/Course/Commands/CreateCourseCommand.php delete mode 100644 app/Application/Http/Course/Handlers/CreateCourseHandler.php delete mode 100644 app/Application/Http/Course/Requests/CourseRequest.php delete mode 100644 app/Application/Http/Course/Resources/CourseResource.php create mode 100644 app/Course/Application/Command/CreateCourseCommand.php create mode 100644 app/Course/Application/CommandHandler/CreateCourseHandler.php create mode 100644 app/Course/Application/CourseServiceProvider.php create mode 100644 app/Course/Application/DTO/CreateCourseDto.php create mode 100644 app/Course/Domain/Entity/Course.php create mode 100644 app/Course/Domain/Repository/CourseRepositoryContract.php create mode 100644 app/Course/Infrastructure/Persistence/Model/CourseModel.php create mode 100644 app/Course/Infrastructure/Persistence/Repository/EloquentCourseRepository.php create mode 100644 database/migrations/2024_05_07_183804_change_courses_table_id_to_uuid.php delete mode 100644 src/Domains/Course/DTO/CreateCourseDto.php delete mode 100644 src/Domains/Course/Models/Course.php delete mode 100644 src/Domains/Course/Repositories/CourseRepositoryContract.php diff --git a/app/Application/Http/Course/Commands/CreateCourseCommand.php b/app/Application/Http/Course/Commands/CreateCourseCommand.php deleted file mode 100644 index ef51722..0000000 --- a/app/Application/Http/Course/Commands/CreateCourseCommand.php +++ /dev/null @@ -1,12 +0,0 @@ -handle(command: $command); + + $command = new CreateCourseCommand( + name: $dto->name, + description: $dto->description, + author_id: $dto->author->id, + starts_at: $dto->starts_at, + ends_at: $dto->ends_at, + published_at: $dto->published_at, + ); + + $this->handler->handle(command: $command); return inertia(component: 'Course/CreateCourse'); } diff --git a/app/Application/Http/Course/Handlers/CreateCourseHandler.php b/app/Application/Http/Course/Handlers/CreateCourseHandler.php deleted file mode 100644 index 01037cc..0000000 --- a/app/Application/Http/Course/Handlers/CreateCourseHandler.php +++ /dev/null @@ -1,13 +0,0 @@ - $this->created_at, - 'updated_at' => $this->updated_at, - 'id' => $this->id, - ]; - } -} diff --git a/app/Application/Http/Providers/AppServiceProvider.php b/app/Application/Http/Providers/AppServiceProvider.php index 0d3fa8b..808125a 100644 --- a/app/Application/Http/Providers/AppServiceProvider.php +++ b/app/Application/Http/Providers/AppServiceProvider.php @@ -2,8 +2,6 @@ namespace App\Application\Http\Providers; -use Domains\Course\Repositories\CourseRepositoryContract; -use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider @@ -13,9 +11,7 @@ class AppServiceProvider extends ServiceProvider */ public function register(): void { - $this->app->bind( - CourseRepositoryContract::class, - ); + } /** @@ -23,10 +19,10 @@ public function register(): void */ public function boot(): void { - Factory::guessFactoryNamesUsing(function (string $modelName) { - $modelName = class_basename($modelName); - - return "Database\\Factories\\{$modelName}Factory"; - }); +// Factory::guessFactoryNamesUsing(function (string $modelName) { +// $modelName = class_basename($modelName); +// +// return "Database\\Factories\\{$modelName}Factory"; +// }); } } diff --git a/app/Course/Application/Command/CreateCourseCommand.php b/app/Course/Application/Command/CreateCourseCommand.php new file mode 100644 index 0000000..45b4bdf --- /dev/null +++ b/app/Course/Application/Command/CreateCourseCommand.php @@ -0,0 +1,16 @@ +toString(), + name: $command->name, + description: $command->description, + authorId: $command->author_id, + startsAt: $command->starts_at, + endsAt: $command->ends_at, + publishedAt: $command->published_at, + ); + + $this->courseRepository->save(course: $course); + } +} \ No newline at end of file diff --git a/app/Course/Application/CourseServiceProvider.php b/app/Course/Application/CourseServiceProvider.php new file mode 100644 index 0000000..600c6c3 --- /dev/null +++ b/app/Course/Application/CourseServiceProvider.php @@ -0,0 +1,18 @@ +app->bind( + CourseRepositoryContract::class, + EloquentCourseRepository::class + ); + } +} \ No newline at end of file diff --git a/app/Course/Application/DTO/CreateCourseDto.php b/app/Course/Application/DTO/CreateCourseDto.php new file mode 100644 index 0000000..6a6e987 --- /dev/null +++ b/app/Course/Application/DTO/CreateCourseDto.php @@ -0,0 +1,24 @@ +author = Auth::user(); + } +} \ No newline at end of file diff --git a/app/Course/Domain/Entity/Course.php b/app/Course/Domain/Entity/Course.php new file mode 100644 index 0000000..7e9f76c --- /dev/null +++ b/app/Course/Domain/Entity/Course.php @@ -0,0 +1,55 @@ +id; + } + + public function getName(): string + { + return $this->name; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getAuthorId(): int + { + return $this->authorId; + } + + public function getStartsAt(): ?DateTime + { + return $this->startsAt; + } + + public function getEndsAt(): ?DateTime + { + return $this->endsAt; + } + + public function getPublishedAt(): ?DateTime + { + return $this->publishedAt; + } + +} \ No newline at end of file diff --git a/app/Course/Domain/Repository/CourseRepositoryContract.php b/app/Course/Domain/Repository/CourseRepositoryContract.php new file mode 100644 index 0000000..66cdf79 --- /dev/null +++ b/app/Course/Domain/Repository/CourseRepositoryContract.php @@ -0,0 +1,15 @@ +{$model->getKeyName()})) { + $model->{$model->getKeyName()} = $this->newUniqueId(); + } + }); + } +} diff --git a/app/Course/Infrastructure/Persistence/Repository/EloquentCourseRepository.php b/app/Course/Infrastructure/Persistence/Repository/EloquentCourseRepository.php new file mode 100644 index 0000000..f41160f --- /dev/null +++ b/app/Course/Infrastructure/Persistence/Repository/EloquentCourseRepository.php @@ -0,0 +1,65 @@ +model->find(id: $course->getId()) ?? new CourseModel(); + $courseRecord->id = $course->getId() ?? Uuid::uuid4()->toString(); + $courseRecord->name = $course->getName(); + $courseRecord->description = $course->getDescription(); + $courseRecord->author_id = $course->getAuthorId(); + $courseRecord->starts_at = $course->getStartsAt(); + $courseRecord->ends_at = $course->getEndsAt(); + $courseRecord->published_at = $course->getPublishedAt(); + + $courseRecord->save(); + } + + public function findById(int $id): ?Course + { + $courseRecord = $this->model->find(id: $id); + + if ($courseRecord === null) { + return null; + } + + return new Course( + id: $courseRecord->id, + name: $courseRecord->name, + description: $courseRecord->description, + authorId: $courseRecord->author_id, + startsAt: $courseRecord->starts_at, + endsAt: $courseRecord->ends_at, + publishedAt: $courseRecord->published_at, + ); + } + + public function findAll(): Collection + { + return $this->model->get()->map(callback: function (CourseModel $courseRecord) { + return new Course( + id: $courseRecord->id, + name: $courseRecord->name, + description: $courseRecord->description, + authorId: $courseRecord->author_id, + startsAt: $courseRecord->starts_at, + endsAt: $courseRecord->ends_at, + publishedAt: $courseRecord->published_at, + ); + }); + } +} \ No newline at end of file diff --git a/app/Policies/CoursePolicy.php b/app/Policies/CoursePolicy.php index 06e7672..63fdd71 100644 --- a/app/Policies/CoursePolicy.php +++ b/app/Policies/CoursePolicy.php @@ -2,9 +2,9 @@ namespace App\Policies; -use Illuminate\Auth\Access\HandlesAuthorization; -use Domains\Course\Models\Course; +use App\Course\Infrastructure\Persistence\Model\CourseModel; use Domains\User\Models\User; +use Illuminate\Auth\Access\HandlesAuthorization; class CoursePolicy { @@ -15,7 +15,7 @@ public function viewAny(User $user): bool return true; } - public function view(User $user, Course $course): bool + public function view(User $user, CourseModel $course): bool { return true; } @@ -25,22 +25,22 @@ public function create(User $user): bool return true; } - public function update(User $user, Course $course): bool + public function update(User $user, CourseModel $course): bool { return true; } - public function delete(User $user, Course $course): bool + public function delete(User $user, CourseModel $course): bool { return true; } - public function restore(User $user, Course $course): bool + public function restore(User $user, CourseModel $course): bool { return true; } - public function forceDelete(User $user, Course $course): bool + public function forceDelete(User $user, CourseModel $course): bool { return true; } diff --git a/bootstrap/providers.php b/bootstrap/providers.php index c786bf5..2558357 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -1,5 +1,9 @@ uuid('new_id'); + $table->dropPrimary(); + $table->dropColumn('id'); + $table->renameColumn('new_id', 'id'); + $table->primary('id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('uuid', function (Blueprint $table) { + $table->dropPrimary(); + $table->dropColumn('id'); + $table->bigIncrements('id')->first(); + }); + } +}; diff --git a/database/seeders/CourseSeeder.php b/database/seeders/CourseSeeder.php index ae47c6e..dee0f25 100644 --- a/database/seeders/CourseSeeder.php +++ b/database/seeders/CourseSeeder.php @@ -2,8 +2,7 @@ namespace Database\Seeders; -use Domains\Course\Models\Course; -use Illuminate\Database\Console\Seeds\WithoutModelEvents; +use App\Course\Infrastructure\Persistence\Model\CourseModel; use Illuminate\Database\Seeder; class CourseSeeder extends Seeder @@ -13,7 +12,7 @@ class CourseSeeder extends Seeder */ public function run(): void { - Course::factory() + CourseModel::factory() ->count(30) ->create(); } diff --git a/resources/js/Components/Course/CourseGrid.vue b/resources/js/Components/Course/CourseGrid.vue index 5b15aaf..94de89c 100644 --- a/resources/js/Components/Course/CourseGrid.vue +++ b/resources/js/Components/Course/CourseGrid.vue @@ -1,5 +1,4 @@ - diff --git a/resources/js/Pages/Course/CreateCourse.vue b/resources/js/Pages/Course/CreateCourse.vue index 1605435..20b225f 100644 --- a/resources/js/Pages/Course/CreateCourse.vue +++ b/resources/js/Pages/Course/CreateCourse.vue @@ -1,4 +1,4 @@ -