初めに
webアプリ開発ができたので、どんな感じで作成したのかをまとめたいと思います。
今回はマイページ編集についてです。
開発環境
macOS Sonoma 14.4.1
CentoOS Stream X_86_64
Apache/2.4.57
PHP 8.3.6
mysql Ver 8.0.36
phpMyAdmin 5.2.1
composer version 2.7.2
Laravel Installer 5.7.1
Laravel Framework 11.0.5
ソースコード
考えたこと
記事の新規登録
実装事例
権限があるユーザーには投稿一覧ボタンが出てきます。
押すと
記事一覧が表示されます
ダッシュボードを押すと「新しい記事を作る」ボタンが出てきます。
新規登録画面でタイトル、スラッグ、サムネイル、要約、内容、カテゴリーを指定すると記事が新しくできます
ビュー
<x-layout>
<x-setting heading="新規投稿">
<form method="POST" action="/admin/posts" enctype="multipart/form-data">
@csrf
<div class="py-2">
<x-form.label name="タイトル"/>
<input class="border border-gray-200 p-2 w-full rounded"
name="title"
id="title"
>
<x-form.error name="title"/>
</div>
<div class="py-2">
<x-form.label name="スラッグ"/>
<input class="border border-gray-200 p-2 w-full rounded"
name="slug"
id="slug"
>
<x-form.error name="slug"/>
</div>
<div class="py-2">
<x-form.label name="サムネイル"/>
<input class="border border-gray-200 p-2 w-full rounded"
name="thumbnail"
id="thumbnail"
type="file"
>
<x-form.error name="thumbnail"/>
</div>
<div class="py-2">
<x-form.label name="要約"/>
<textarea class="border border-gray-200 p-2 w-full rounded"
name="excerpt"
id="excerpt"
></textarea>
<x-form.error name="excerpt"/>
</div>
<div class="py-2">
<x-form.label name="内容"/>
<textarea class="border border-gray-200 p-2 w-full rounded"
name="body"
id="body"
></textarea>
<x-form.error name="body"/>
</div>
<x-form.field>
<x-form.label name="カテゴリー"/>
<select name="category_id" id="category_id" required>
@foreach (\App\Models\Category::all() as $category)
<option
value="{{ $category->id }}"
{{ old('category_id') == $category->id ? 'selected' : '' }}
>{{ ucwords($category->name) }}</option>
@endforeach
</select>
<x-form.error name="category"/>
</x-form.field>
<x-form.button>投稿</x-form.button>
</form>
</x-setting>
</x-layout>
記事の新規登録画面はフォームのラベルとエラーをコンポーネント化して左上のドロップダウンボタンもコンポーネントしました
コントローラ
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
class AdminPostController extends Controller
{
public function index()
{
return view('admin.posts.index', [
'posts' => Post::paginate(7)
]);
}
public function create()
{
return view('admin.posts.create');
}
public function store()
{
Post::create(array_merge($this->validatePost(), [
'user_id' => request()->user()->id,
'thumbnail' => request()->file('thumbnail')->store('thumbnails')
]));
return redirect('/')->with('success', '記事を作成しました。');
}
protected function validatePost(?Post $post = null): array
{
$post ??= new Post();
return request()->validate([
'title' => 'required|max:20',
'thumbnail' => $post->exists ? ['image'] : ['image'],
'slug' => ['required', Rule::unique('posts', 'slug')->ignore($post), 'alpha_dash' , 'lowercase', 'max:10'],
'excerpt' => 'required|max:40',
'body' => 'required|max:500',
'category_id' => ['required', Rule::exists('categories', 'id')]
]);
}
}
indexメソッドは投稿記事一覧画面の表示に使います。7記事ごとにページネーションされます
createメソッドは新規登録画面の表示をしています。
storeメソッドではPostモデルでカラムの登録をします。
array_mergeメソッドでvalidatePostメソッドのバリデーションと連結させています
ルート
Route::middleware('can:admin')->group(function () {
Route::resource('admin/posts', AdminPostController::class)->except('show','destroy');
});
記事のcrudの処理のルートが共通化できそうだったのでグループ化しておきました。
showはホーム画面で作っているので除きました。
destroyはajax処理で実装したかったので別で作成しました。
レスポンシブ対応
使われるスマホがiPhone8以上の画面サイズなのでiPhone8に対応させました。
改善していきたいこと
ビューで書いたcreate.blade.phpのactionのルートをベタ書きしているのでweb.phpのルートに置き換えられるのなら置き換えたいと思います。
カテゴリーを登録する画面がないので、データベースに直接登録するしか方法がありません。
記事を登録する際にカテゴリーも一緒に登録できるように変更していきたいと思います。
最後に
記事の新規登録画面ではあまり改善点が発見できなかったので、他の機能の修正や新規機能の追加に時間を当てたいと思います!