🎶

ユーザー側の見た目をどうにかする

2024/01/18に公開

管理側はともかくユーザー側がデフォルトの見た目だとちょっと宜しくない
bootstrtapのテンプレートを使ってサクッと作ってしまおう

今回使用するテンプレートはこれ
https://startbootstrap.com/theme/clean-blog

まずユーザー側と管理側を分けるためにPostsController.phpを編集
indexとviewと同じアクションを名前を変えて作る
index→show view→detailとでもしておく
そしたらユーザー認証ので使うbeforeFilterメソッドを編集しこの二つは認証不要にする
あと管理側とユーザー側で見た目を変えられるように別で用意したユーザー用のdefault.phpを呼ぶようにする

PostsController.php
public function beforeFilter(\Cake\Event\EventInterface $event)
{
    parent::beforeFilter($event);
    // ここで指定したアクションは認証が不要になる
    $this->Authentication->addUnauthenticatedActions(['show', 'detail']);
}
    
public function show()
{
    // ... 表示用の処理 ...
	
    // ここに別テンプレートを呼ぶ処理を書く
    $this->viewBuilder()->setLayout('user_default');
}

これでshowとdetailは誰でもアクセスできるようになる
webrootにダウンロードしてきたcssとjsファイルをいれてuser_default.phpで読めるようにする
ついでにheaderとfooterをレイアウト分けする

user_default.php
<head>
    <?= $this->Html->charset() ?>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>
        <?= $cakeDescription ?>:
        <?= $this->fetch('title') ?>
    </title>
    <?= $this->Html->meta('icon') ?>
	

    <!-- font awesome -->
    <?= $this->Html->script('all.min.js') ?>
    <!-- google font ダウンロードしてローカルに保存したかったが面倒くさそうなのでやめた-->
    <?= $this->Html->css([
    'https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic',
    'https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800'
    ]) ?>
    <?= $this->Html->css('prism-tomorrow.min.css') ?>
    <!-- テンプレートのやつ -->
    <?= $this->Html->css('styles.css') ?>

    <?= $this->fetch('meta') ?>
    <?= $this->fetch('css') ?>
    <?= $this->fetch('script') ?>
</head>
<body>
	<?= $this->element('header') ?>
    <main class="main">
        <div class="container">
            <?= $this->Flash->render() ?>
            <?= $this->fetch('content') ?>
        </div>
    </main>
	<?= $this->element('footer') ?>

    <?= $this->Html->script('prism.js') ?>
    <?= $this->Html->script('bootstrap.bundle.min.js') ?>
    <!-- テンプレートのやつ -->
    <?= $this->Html->script('scripts.js') ?>
</body>

テンプレートを見返していたら投稿タイトルの下にサブタイトルがあることがわかる
テーブル構造もそれに合わせて修正する
ついでに背景画像も一緒に作る

bin/cake bake migration AddSubtitleToPosts
# 中身を作る
bin/cake migrations migrate

テンプレートとエンティティを修正すれば他のカラムと同じように編集、追加できるようになる

edit.php
<?php
/**
 * @var \App\View\AppView $this
 * @var \App\Model\Entity\Post $post
 * @var string[]|\Cake\Collection\CollectionInterface $categories
 */
?>
<div class="row">
    <aside class="column">
        <div class="side-nav">
            <h4 class="heading"><?= __('Actions') ?></h4>
            <?= $this->Form->postLink(
                __('Delete'),
                ['action' => 'delete', $post->id],
                ['confirm' => __('Are you sure you want to delete # {0}?', $post->id), 'class' => 'side-nav-item'
            ) ?>
            <?= $this->Html->link(__('List Posts'), ['action' => 'index'], ['class' => 'side-nav-item']) ?>
        </div>
    </aside>
    <div class="column-responsive column-80">
        <div class="posts form content">
            <?= $this->Form->create($post, ['type' => 'file']) ?>
            <fieldset>
                <legend><?= __('Edit Post') ?></legend>
                <?php
                    echo $this->Form->control('title');
                    echo $this->Form->control('subtitle'); <!-- サブタイトル -->
                    echo $this->Form->control('body');
                    echo $this->Form->control('background_image', ['type' => 'file']); <!-- 画像 -->
                    echo $this->Form->control('category_id', ['options' => $categories, 'empty' => true]);
                ?>
            </fieldset>
            <?= $this->Form->button(__('Submit')) ?>
            <?= $this->Form->end() ?>
        </div>
    </div>
</div>

合わせてコントローラも編集
画像関連は少しややこい

PostsController.php
public function edit($id = null)
{
	$post = $this->Posts->get($id, [
		'contain' => [],
	]);

	if ($this->request->is(['patch', 'post', 'put'])) {
		$postData = $this->request->getData();

		// アップロードされた画像ファイルが存在し、エラーがないことを確認
		if ($postData['image'] && $postData['image']->getError() === UPLOAD_ERR_OK) {
			$file = $postData['image'];
			$ext = strtolower(pathinfo($file->getClientFilename(), PATHINFO_EXTENSION));
			$arr_ext = array('jpg', 'jpeg', 'gif', 'png', 'webp'); // 許可する拡張子

			if (in_array($ext, $arr_ext)) {
				$fileName = time() . '_' . $file->getClientFilename();
				$filePath = WWW_ROOT . 'img' . DS . $fileName;
				// ファイルを指定したパスに移動
				$file->moveTo($filePath);

				// データベースに保存するためのパスをpostDataにセット
				$postData['image'] = $fileName;
			}
		} else {
		    unset($postData['image']);
		}

		$post = $this->Posts->patchEntity($post, $postData);

		if ($this->Posts->save($post)) {
			$this->Flash->success(__('The post has been saved.'));
			return $this->redirect(['action' => 'index']);
		}
		$this->Flash->error(__('The post could not be saved. Please, try again.'));
	}

	$categories = $this->Posts->Categories->find('list', ['limit' => 200])->all();
	$this->set(compact('post', 'categories'));
}

headerは背景画像とタイトルをページごとにわけたいので変数を取得できるようにしておく

PostsController.php
public function detail($id = null)
{
    $post = $this->Posts->get($id, [
        'contain' => ['Categories', 'Comments', 'PostTags'],
    ]);

    // ... 省略 ...

    $this->set(compact('post'));
    // 画面に表示したいものを変数として渡す
    $this->set('backgroundImage', $post->image);
    $this->set('blogTitle', $post->title);
    $this->set('blogSubtitle', $post->subtitle);
    $this->viewBuilder()->setLayout('user_default');
}
header.php
<!-- templates/element -->
<!-- ファイルの頭で変数として渡し表示したいところで使う -->
<?php
    $bgImage = $backgroundImage ?? 'home-bg.jpg';
    $blogTitle = $blogTitle ?? 'Clean Blog';
    $blogSubtitle = $blogSubtitle ?? 'A Blog Theme by Start Bootstrap';
?>

<header class="masthead" style="background-image: url('<?= $this->Url->image($bgImage) ?>')">
    <div class="container position-relative px-4 px-lg-5">
        <div class="row gx-4 gx-lg-5 justify-content-center">
            <div class="col-md-10 col-lg-8 col-xl-7">
                <div class="site-heading">
                    <h1><?= $blogTitle ?></h1>
                    <span class="subheading"><?= $blogSubtitle ?></span>
                </div>
            </div>
        </div>
    </div>
</header>

これでタイトル、サブタイトル、背景画像が投稿に合わせたものに変わるようになった
画像はAIに適当にcakephpっぽいのを書いてもらった
タイトルは日本語になるとクソダサい

usersテーブルにtitle、subtitle、imageカラムを追加すればトップページの背景やタイトルも自身で更新できるようになる
postsテーブルにカラムを追加した時と同じようにマイグレしてuserのメソッドとテンプレートを編集する

PostsController.php
    public function initialize(): void
    {
        parent::initialize();
        $this->loadModel('Users');
	// 初期化メソッドでUserモデルを取得
    }
    
    // ... 省略 ...
    
    // showメソッドでusersテーブルのタイトルや背景画像を変数にして渡す
    public function show()
    {
        $this->paginate = [
            'contain' => ['Categories'],
        ];
        $posts = $this->paginate($this->Posts);

        $user = $this->Users->find()->first();

        $this->set(compact('posts'));
        $this->set('backgroundImage', $user->image);
        $this->set('blogTitle', $user->title);
        $this->set('blogSubtitle', $user->subtitle);
        $this->viewBuilder()->setLayout('user_default');
    }

やっぱり日本語にするとクソダサい

Discussion