From 19b2fd865abfe89ef1e113c1165928f631680905 Mon Sep 17 00:00:00 2001 From: Armando Garcia Date: Wed, 2 Feb 2022 11:48:58 -0400 Subject: [PATCH 1/7] New implementation Attachment (Migration, Model, Relations) --- app/Models/Attachment.php | 29 ++++++++++++++++ app/Models/Comment.php | 12 ++++++- app/Models/Post.php | 12 ++++++- ..._02_02_154220_create_attachments_table.php | 33 +++++++++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 app/Models/Attachment.php create mode 100644 database/migrations/2022_02_02_154220_create_attachments_table.php diff --git a/app/Models/Attachment.php b/app/Models/Attachment.php new file mode 100644 index 0000000..e79b8f6 --- /dev/null +++ b/app/Models/Attachment.php @@ -0,0 +1,29 @@ +morphTo(); + } +} diff --git a/app/Models/Comment.php b/app/Models/Comment.php index 623b35a..38c05c2 100644 --- a/app/Models/Comment.php +++ b/app/Models/Comment.php @@ -16,7 +16,7 @@ class Comment extends Model */ protected $fillable = [ 'body', - 'post_id' + 'post_id', ]; public function post() @@ -28,4 +28,14 @@ public function comment_attachments() { return $this->hasMany(CommentAttachment::class); } + + /** + * Get all of the comment's attachments.. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function attachments() + { + return $this->morphMany(Attachment::class, 'attachable'); + } } diff --git a/app/Models/Post.php b/app/Models/Post.php index 5899030..2b8acef 100644 --- a/app/Models/Post.php +++ b/app/Models/Post.php @@ -17,7 +17,7 @@ class Post extends Model protected $fillable = [ 'title', 'body', - 'user_id' + 'user_id', ]; public function user() @@ -34,4 +34,14 @@ public function post_attachments() { return $this->hasMany(PostAttachment::class); } + + /** + * Get all of the post's attachments. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function attachments() + { + return $this->morphMany(Attachment::class, 'attachable'); + } } diff --git a/database/migrations/2022_02_02_154220_create_attachments_table.php b/database/migrations/2022_02_02_154220_create_attachments_table.php new file mode 100644 index 0000000..709145d --- /dev/null +++ b/database/migrations/2022_02_02_154220_create_attachments_table.php @@ -0,0 +1,33 @@ +id(); + $table->morphs('attachable'); + $table->string('url'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('attachments'); + } +} From 8d86c4a776841af6ca76d99ef0715ade1635c126 Mon Sep 17 00:00:00 2001 From: Armando Garcia Date: Wed, 2 Feb 2022 12:41:07 -0400 Subject: [PATCH 2/7] Migrate to attachments script and feature test --- .../Commands/MigrateAttachmentsData.php | 91 +++++++++++++++++++ app/Console/Kernel.php | 4 +- phpunit.xml | 4 +- .../MigrateAttachmentsDataCommandTest.php | 38 ++++++++ 4 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 app/Console/Commands/MigrateAttachmentsData.php create mode 100644 tests/Feature/MigrateAttachmentsDataCommandTest.php diff --git a/app/Console/Commands/MigrateAttachmentsData.php b/app/Console/Commands/MigrateAttachmentsData.php new file mode 100644 index 0000000..ea0b3ad --- /dev/null +++ b/app/Console/Commands/MigrateAttachmentsData.php @@ -0,0 +1,91 @@ +line('Migrating...'); + $this->newLine(); + + PostAttachment::all()->each(function ($postAttachment) { + $this->setAttachmentArray($postAttachment); + }); + + CommentAttachment::all()->each(function ($commentAttachment) { + $this->setAttachmentArray($commentAttachment); + }); + + $this->withProgressBar(collect($this->attachmentArray)->chunk(100)->toArray(), function ($attachmentArray) { + Attachment::insert($attachmentArray); + }); + + $this->newLine(); + $this->newLine(); + $this->info('Done!'); + } + + /** + * Set attachmentArray. + * + * @param Illuminate\Database\Eloquent\Model $model + * + * @return void + */ + protected function setAttachmentArray(Model $model) + { + $attachable_type = (get_class($model) == PostAttachment::class) ? Post::class : Comment::class; + $attachable_id = ($attachable_type == Post::class) ? $model->post_id : $model->comment_id; + + $this->attachmentArray[] = [ + 'attachable_type' => $attachable_type, + 'attachable_id' => $attachable_id, + 'url' => $model->url, + 'updated_at' => $model->updated_at, + 'created_at' => $model->created_at, + ]; + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 69914e9..8fae394 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,6 +2,7 @@ namespace App\Console; +use App\Console\Commands\MigrateAttachmentsData; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; @@ -13,13 +14,12 @@ class Kernel extends ConsoleKernel * @var array */ protected $commands = [ - // + MigrateAttachmentsData::class, ]; /** * Define the application's command schedule. * - * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) diff --git a/phpunit.xml b/phpunit.xml index 4ae4d97..76a606b 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -21,8 +21,8 @@ - - + + diff --git a/tests/Feature/MigrateAttachmentsDataCommandTest.php b/tests/Feature/MigrateAttachmentsDataCommandTest.php new file mode 100644 index 0000000..d85d149 --- /dev/null +++ b/tests/Feature/MigrateAttachmentsDataCommandTest.php @@ -0,0 +1,38 @@ +artisan('migrate_attachments_data')->assertExitCode(0); + + $postAttachment = PostAttachment::all(); + + $postAttachment->pluck('url')->each(function ($url) { + $this->assertDatabaseHas('attachments', ['url' => $url]); + }); + + $commentAttachment = CommentAttachment::all(); + + $commentAttachment->pluck('url')->each(function ($url) { + $this->assertDatabaseHas('attachments', ['url' => $url]); + }); + + $totalAttachments = $postAttachment->count() + $commentAttachment->count(); + + $this->assertDatabaseCount('attachments', $totalAttachments); + } +} From 22dbc8214be1128ac87c6e497b3eb0f6bddd6931 Mon Sep 17 00:00:00 2001 From: Armando Garcia Date: Wed, 2 Feb 2022 13:27:25 -0400 Subject: [PATCH 3/7] Index view Test --- tests/Feature/IndexViewTest.php | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/Feature/IndexViewTest.php diff --git a/tests/Feature/IndexViewTest.php b/tests/Feature/IndexViewTest.php new file mode 100644 index 0000000..823bf28 --- /dev/null +++ b/tests/Feature/IndexViewTest.php @@ -0,0 +1,46 @@ +get('index'); + + $response + ->assertViewIs('index') + ->assertSuccessful() + ->assertSeeText('Title') + ->assertSeeText('Attachments') + ->assertSeeText('Comments') + ->assertSeeText('Comment Attachments') + ->assertSee('13') + ->assertSee('10') + ->assertSee('170'); + + $users = User::with('posts')->get(); + + $userNames = $users->map(function ($user) { + return $user->name.' posts'; + })->all(); + + $response->assertSeeTextInOrder($userNames); + + $postTitles = $users->map(function ($user) { + return $user->posts->pluck('title'); + })->flatten()->all(); + + $response->assertSeeTextInOrder($postTitles); + } +} From b25f78d723e67df52a6290d25a3dff236cd7d4d9 Mon Sep 17 00:00:00 2001 From: Armando Garcia Date: Wed, 2 Feb 2022 13:34:33 -0400 Subject: [PATCH 4/7] Change index approach to the new attachments table and update indexViewTest --- resources/views/index.blade.php | 6 +++--- tests/Feature/IndexViewTest.php | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php index b591ade..d3f4101 100644 --- a/resources/views/index.blade.php +++ b/resources/views/index.blade.php @@ -26,15 +26,15 @@ {{ $post->title }} - {{ $post->post_attachments()->count() }} + {{ $post->attachments()->count() }} {{ $post->comments()->count() }} {{ $post->comments->reduce(function ($carry, $comment) { - return $carry + $comment->comment_attachments()->count(); -}) }} + return $carry + $comment->attachments()->count(); + }) }} @endforeach diff --git a/tests/Feature/IndexViewTest.php b/tests/Feature/IndexViewTest.php index 823bf28..0561acb 100644 --- a/tests/Feature/IndexViewTest.php +++ b/tests/Feature/IndexViewTest.php @@ -16,6 +16,8 @@ public function test_index_view() { Artisan::call('db:seed'); + $this->artisan('migrate_attachments_data')->assertExitCode(0); + $response = $this->get('index'); $response From b2564cbff3e9a3c1395510235fd12d1114f5b686 Mon Sep 17 00:00:00 2001 From: Armando Garcia Date: Wed, 2 Feb 2022 13:44:50 -0400 Subject: [PATCH 5/7] Move the index route logic to a Controller --- app/Http/Controllers/HomeController.php | 18 ++++++++++++++++++ routes/web.php | 7 ++----- 2 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 app/Http/Controllers/HomeController.php diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php new file mode 100644 index 0000000..4100420 --- /dev/null +++ b/app/Http/Controllers/HomeController.php @@ -0,0 +1,18 @@ + \App\Models\User::all(), + ]); + } +} diff --git a/routes/web.php b/routes/web.php index 2509508..04bd48d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,5 +1,6 @@ \App\Models\User::all() - ]); -}); +Route::get('index', [HomeController::class, 'index']); From e5d1a5b5645f68fb638196bfee7380d4b7a5f5b5 Mon Sep 17 00:00:00 2001 From: Armando Garcia Date: Wed, 2 Feb 2022 14:00:23 -0400 Subject: [PATCH 6/7] Optimized HomeController index query, New Relation in Post model and clean up index view --- app/Http/Controllers/HomeController.php | 14 +++++++++++--- app/Models/Post.php | 10 ++++++++++ resources/views/index.blade.php | 8 +++----- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 4100420..91209e4 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -2,6 +2,8 @@ namespace App\Http\Controllers; +use App\Models\User; + class HomeController extends Controller { /** @@ -11,8 +13,14 @@ class HomeController extends Controller */ public function index() { - return view('index', [ - 'users' => \App\Models\User::all(), - ]); + $users = User::with([ + 'posts' => function ($post) { + $post->withCount('attachments'); + $post->withCount('comments'); + $post->withCount('commentAttachments'); + }, + ])->get(); + + return view('index', compact('users')); } } diff --git a/app/Models/Post.php b/app/Models/Post.php index 2b8acef..afca5b4 100644 --- a/app/Models/Post.php +++ b/app/Models/Post.php @@ -44,4 +44,14 @@ public function attachments() { return $this->morphMany(Attachment::class, 'attachable'); } + + /* + * Get all of comment attachments for the post. + * + * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough + */ + public function commentAttachments() + { + return $this->hasManyThrough(Attachment::class, Comment::class, 'post_id', 'attachable_id')->where('attachable_type', Comment::class); + } } diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php index d3f4101..1eec17c 100644 --- a/resources/views/index.blade.php +++ b/resources/views/index.blade.php @@ -26,15 +26,13 @@ {{ $post->title }} - {{ $post->attachments()->count() }} + {{ $post->attachments_count }} - {{ $post->comments()->count() }} + {{ $post->comments_count }} - {{ $post->comments->reduce(function ($carry, $comment) { - return $carry + $comment->attachments()->count(); - }) }} + {{ $post->comment_attachments_count }} @endforeach From ee3e212a1b4d8399862bcfac70e63000010d2955 Mon Sep 17 00:00:00 2001 From: Armando Garcia Date: Wed, 2 Feb 2022 14:35:17 -0400 Subject: [PATCH 7/7] Clean up, DocBlocks --- app/Models/Comment.php | 10 ++++++++++ app/Models/Post.php | 15 +++++++++++++++ app/Models/User.php | 10 ++++++++-- resources/views/index.blade.php | 32 ++++++++------------------------ tests/Feature/ExampleTest.php | 21 --------------------- tests/Unit/ExampleTest.php | 18 ------------------ 6 files changed, 41 insertions(+), 65 deletions(-) delete mode 100644 tests/Feature/ExampleTest.php delete mode 100644 tests/Unit/ExampleTest.php diff --git a/app/Models/Comment.php b/app/Models/Comment.php index 38c05c2..a7a6015 100644 --- a/app/Models/Comment.php +++ b/app/Models/Comment.php @@ -19,11 +19,21 @@ class Comment extends Model 'post_id', ]; + /** + * A comment belongs to a post. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ public function post() { return $this->belongsTo(Post::class); } + /** + * A comment may have many comment attachments. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ public function comment_attachments() { return $this->hasMany(CommentAttachment::class); diff --git a/app/Models/Post.php b/app/Models/Post.php index afca5b4..fb9d407 100644 --- a/app/Models/Post.php +++ b/app/Models/Post.php @@ -20,16 +20,31 @@ class Post extends Model 'user_id', ]; + /** + * A post belongs to a user. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ public function user() { return $this->belongsTo(User::class); } + /** + * A post may have many comments. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ public function comments() { return $this->hasMany(Comment::class); } + /** + * A post may have many post attachments. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ public function post_attachments() { return $this->hasMany(PostAttachment::class); diff --git a/app/Models/User.php b/app/Models/User.php index 5cefd5d..76144df 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,7 +2,6 @@ namespace App\Models; -use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; @@ -10,7 +9,9 @@ class User extends Authenticatable { - use HasApiTokens, HasFactory, Notifiable; + use HasApiTokens; + use HasFactory; + use Notifiable; /** * The attributes that are mass assignable. @@ -42,6 +43,11 @@ class User extends Authenticatable 'email_verified_at' => 'datetime', ]; + /** + * A user may have many posts. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ public function posts() { return $this->hasMany(Post::class); diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php index 1eec17c..1f5e246 100644 --- a/resources/views/index.blade.php +++ b/resources/views/index.blade.php @@ -5,35 +5,19 @@ - - - - + + + + @foreach ($user->posts as $post) - - - - + + + + @endforeach diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php deleted file mode 100644 index 4ae02bc..0000000 --- a/tests/Feature/ExampleTest.php +++ /dev/null @@ -1,21 +0,0 @@ -get('/'); - - $response->assertStatus(200); - } -} diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php deleted file mode 100644 index 62e8c3c..0000000 --- a/tests/Unit/ExampleTest.php +++ /dev/null @@ -1,18 +0,0 @@ -assertTrue(true); - } -}
- Title - - Attachments - - Comments - Comment Attachments - - TitleAttachmentsCommentsComment Attachments
- {{ $post->title }} - - {{ $post->attachments_count }} - - {{ $post->comments_count }} - - {{ $post->comment_attachments_count }} - {{ $post->title }}{{ $post->attachments_count }}{{ $post->comments_count }}{{ $post->comment_attachments_count }}