Friction River Software

  • お問い合わせ

CakePHP5入門【CakePHP5実用編⑰】バージョンアップ

A子

本番環境に公開したのは良いんだけどさ

やっぱもう少し改良したいんだよね

B美

どうしたいの?

A子

うん

1.お試しユーザの「申込み」時と「最終登録」時に管理者宛てにメール通知する
2.入室制限とは別に、お試しユーザのみ「発言可能」か「閲覧のみ」の制約を部屋ごとに設定できるようにする
3.ユーザごとに(チャット画面の)背景色や文字色を設定できるようにする

…って感じかな

C菜

それ良いですね~

でも少し大変そうです~(汗)

B美

まぁ、何事も勉強よ

私は(なるべく)口出ししないから、できるだけ二人でやってみなさい

A子

よし!
それじゃ、まずは1番だね

1.お試しユーザの「申込み」時と「最終登録」時に管理者宛てにメール通知する

C菜

あっ、その前に~

config/const.php」ですけど、前回(本番環境へのデプロイ時)はファイルの内容を直接書き換えましたよね~

A子

ん?

そだね

C菜

バージョンアップのつど、開発環境と本番環境の両方で「config/const.php」の書き換えが発生するのはちょっと~
なので、このようにしませんか~?

define("ENVIRONMENT", 1);    //1…開発環境,2…本番環境

・・・

if (ENVIRONMENT == 1) {
    define("WEBSOCKET_IP", "192.168.1.205");    //WebSocketサーバのIPアドレス
    define("WEBSOCKET_NAME", "192.168.1.205");    //WebSocketサーバのドメイン名
} else if (ENVIRONMENT == 2) {
    define("WEBSOCKET_IP", "49.212.186.238");    //WebSocketサーバのIPアドレス
    define("WEBSOCKET_NAME", "friction-river.jp");    //WebSocketサーバのドメイン名
}

上記以外にも「BASIC認証」「サーバ証明書」「メール中に記載するURL」を同じようにif文で切り分けるということです~




A子

なるほど

本番環境にアップロードするときは「ENVIRONMENT」の値を「2」に変更するだけで良いってわけね

B美

うむ、素晴らしい!

const.php」がPHPファイル(プログラム)だってこと、よく分かってるじゃない

A子

んじゃ、あらためて1番の項目なんだけど…

「src/Mailer」の中にある「ApplicantMailer.php」にメソッドを追加すれば良いよね

public function info1($email)
{
    $this->setEmailFormat('html')
        ->setFrom([FROM_ADDRESS => APPLICATION_NAME])
        ->setTo(ADMIN_ADDRESS)
        ->setSubject(MAIL_INFO1_SUBJECT)
        ->viewBuilder()
            ->setTemplate('info1')
            ->setLayout('default')
            ->setVars(['email' => $email]);
}

public function info2($email)
{
    $this->setEmailFormat('html')
        ->setFrom([FROM_ADDRESS => APPLICATION_NAME])
        ->setTo(ADMIN_ADDRESS)
        ->setSubject(MAIL_INFO2_SUBJECT)
        ->viewBuilder()
            ->setTemplate('info2')
            ->setLayout('default')
            ->setVars(['email' => $email]);
}

info1」が「申込み」時に、「info2」が「最終登録」時に実行されるやつね

あ、もちろん以下の定数を「const.php」に追加するよ

define("ADMIN_ADDRESS", "xxxx@friction-river.jp");    //管理者メールアドレス
define("MAIL_INFO1_SUBJECT", "お試しユーザ申込み通知");    //管理者宛てメールのタイトル(申込み有り)
define("MAIL_INFO2_SUBJECT", "お試しユーザ登録通知");    //管理者宛てメールのタイトル(新規登録有り)
(「xxxx」は伏字)


C菜

では、「templates/email/html」の中に「info1.php」と「info2.php」というファイルを作成するです~


A子

あとは、このメソッドを「ApplicantsController.php」の中から呼び出すだけだね

具体的には「regist」メソッドと「finalCheck」メソッドに一行ずつ追加しただけ…


C菜

テストしてみたところ、うまくいきました~
では、次ですね~

2.入室制限とは別に、お試しユーザのみ「発言可能」か「閲覧のみ」の制約を部屋ごとに設定できるようにする

これって、「chat_rooms」テーブルに項目を追加しないといけないですね~

A子

だね

create table chat_rooms (
    id int auto_increment primary key,
    theme varchar(255) not null,
    admin_id int not null,
    delete_flag int not null,
    access_policy int,
    guest_read_write int,
    created datetime,
    modified datetime,
    foreign key(admin_id) references users(id)
) charset=utf8mb4;

で、どうかな?

C菜

良いと思います~
それでは、その項目に格納する値はこうしましょう~

define("GUEST_WRITE_OK", 1);    //発言許可
define("GUEST_READ_ONLY", 2);    //閲覧のみ
define("GUEST_POLICY", ["-", "発言許可", "閲覧のみ"]);

A子

うん、良いね
それじゃ「chat_rooms」テーブルを(ALTER TABLEで)修正しよう

mysql -u root -p chatdb[Enter]

ALTER TABLE chat_rooms
    ADD guest_read_write int AFTER access_policy;[Enter]

C菜

あ、「src/Model/Entity」の中にある「ChatRoom.php」の$_accessibleに一行追加しますね~

'guest_read_write' => true,

A子

まずはViewビューファイルを修正していこう

具体的には、「templates/ChatRooms」の中にある「add.php」「edit.php」「view.php」だね
(「index.php」は修正しなくても良いかな)

C菜

まずは「add.php」です~



B美

言うまでもないとは思うけど…
テスト実行する前に、必ずキャッシュクリアしておきなさいね

C菜

了解です~

A子

よし
次は「edit.php」だね

C菜

最後は「view.php」です~

A子

そしたら、次は「src/Controller」の中にある「ChatController.php」を書き換えよう

アクセス者が「お試しユーザ」で、かつチャットルームの制約が「お試しユーザは閲覧のみ」だった場合、フラグ($guest_ng)をtrueにするよ

$guest_ng = false;
if ($this->identity->role_num == GUEST && $chat_room->guest_read_write == GUEST_READ_ONLY) {
    //お試しユーザで、かつチャットルームの制約が「お試しユーザは閲覧のみ」である場合
    $guest_ng = true;
}
$this->set(compact('guest_ng'));

C菜

では、それに合わせて「templates/Chat」の中にある「index.php」を書き換えますね~



B美

バッチリね
さて、最後は3番だけど、どこまでやるつもり?

3.ユーザごとに(チャット画面の)背景色や文字色を設定できるようにする

A子

ん?
定数化している項目を「users」テーブルに追加するつもりだけど?

C菜

定数化しているのは以下の通りです~

定数名用途
SENT_COLOR#dcf8c6自分の発言の背景色
RECEIVED_COLOR#e5e5e5他人の発言の背景色
THEME_COLOR#006400テーマの文字色
USER_LIST_COLOR#fffacd入室ユーザリストの背景色

A子

あー、「テーマの文字色」は別に良いかな

でも、それ以外の三つは各ユーザが設定できるようにしよう
それぞれに文字色設定も加えて、全部で6項目だね

C菜

それでは「users」テーブルに追加する項目はこうですね~

項目名データ型用途
sent_backcolorvarchar(10)自分の発言の背景色
sent_forecolorvarchar(10)自分の発言の文字色
received_backcolorvarchar(10)他人の発言の背景色
received_forecolorvarchar(10)他人の発言の文字色
userlist_backcolorvarchar(10)入室ユーザリストの背景色
userlist_forecolorvarchar(10)入室ユーザリストの文字色

あ、データ型は「int」のほうが良いのでしょうか~?

B美

いいえ、「int」にすると逆に扱いづらくなるわよ

あと、色情報って必ず7文字以下の16進数だから、「varchar(7)」でも良いけどね
(まぁ、少し余裕を持たせて「varchar(10)」でもOK)

A子

よし、それじゃ「users」テーブルを次のように変更しよう

create table users (
    id int auto_increment primary key,
    email varchar(255),
    password varchar(255),
    status int,
    session varchar(255),
    login_time datetime,
    logout_time datetime,
    role_num int,
    sent_backcolor varchar(10),
    sent_forecolor varchar(10),
    received_backcolor varchar(10),
    received_forecolor varchar(10),
    userlist_backcolor varchar(10),
    userlist_forecolor varchar(10),

    created datetime,
    modified datetime
);

C菜

それでは「users」テーブルを(ALTER TABLEで)修正しましょう~

mysql -u root -p chatdb[Enter]

ALTER TABLE users
    ADD sent_backcolor varchar(10) AFTER role_num,
    ADD sent_forecolor varchar(10) AFTER sent_backcolor,
    ADD received_backcolor varchar(10) AFTER sent_forecolor,
    ADD received_forecolor varchar(10) AFTER received_backcolor,
    ADD userlist_backcolor varchar(10) AFTER received_forecolor,
    ADD userlist_forecolor varchar(10) AFTER userlist_backcolor;[Enter]



A子

うん、良いね

んじゃ、念のためキャッシュクリアを実行しておこう

C菜

まずは、「src/Controller」の「UsersController.php」の中に「changeColor」メソッドを作りましょう~

public function changeColor()
{
    if ($this->request->is('post')) {
        $sent_backcolor = $this->request->getData('sent_backcolor');
        $sent_forecolor = $this->request->getData('sent_forecolor');
        $received_backcolor = $this->request->getData('received_backcolor');
        $received_forecolor = $this->request->getData('received_forecolor');
        $userlist_backcolor = $this->request->getData('userlist_backcolor');
        $userlist_forecolor = $this->request->getData('userlist_forecolor');

        $user = $this->Users->get($this->identity->id, contain: []);
        $user->sent_backcolor = $sent_backcolor;
        $user->sent_forecolor = $sent_forecolor;
        $user->received_backcolor = $received_backcolor;
        $user->received_forecolor = $received_forecolor;
        $user->userlist_backcolor = $userlist_backcolor;
        $user->userlist_forecolor = $userlist_forecolor;

        if ($this->Users->save($user)) {
            $this->Flash->success(__('色設定を変更しました。'));
            return $this->redirect(['controller' => 'Top', 'action' => 'index']);
        }
        $this->Flash->error(__('色設定の変更に失敗しました。'));
    }
}

あと「templates/Users」の中に「change_color.php」を新規作成しますね~




A子

ブラウザで確認してみるよ

うーん、分かりづらい…
デフォルト値が全部「黒色」だし、凡例も無いし…

C菜

先に「templates/Chat」の中にある「index.php」を修正したほうが良いかもしれませんね~
(凡例表示のためにも…)

えっと~
とりあえず修正が必要なのは~

①.「templates/layout」の中にある「default.php」
②.「webroot/css」の中にある「chat.css」
③.「templates/Chat」の中にある「index.php」

ですかね~?

A子

まずは①だけど、CSS変数を変更しよう

<style>
:root {
    --sent-backcolor: <?= $identity->sent_backcolor ?>;
    --sent-forecolor: <?= $identity->sent_forecolor ?>;
    --received-backcolor: <?= $identity->received_backcolor ?>;
    --received-forecolor: <?= $identity->received_forecolor ?>;
}
</style>

C菜

あ、ダメですよ~

その項目には、最初はNULLが入ってますから~

A子

あっ、そうか…

うーん、NULLなら定数の値で、NULLでなけりゃその値で…ってことにしたいよね

C菜

「$this->set()」で「default.php」へと渡しましょう

その準備を「AppController.php」の「beforeFilter」メソッドでやれば良いのではないでしょうか~?
(だって、「ChatController」でも「UsersController」でも使いますし…)

A子

OK、OK

$sent_backcolor = $this->identity->sent_backcolor == null ? SENT_COLOR : $this->identity->sent_backcolor;

という記述を全部で6種類記述すれば良いんじゃない?

B美

あー、ちょっと口を挟ませてもらうわね
A子が提示したように三項演算子を使っても良いんだけど、PHP7以降の新しい文法を使ってみても良いかもよ

$sent_backcolor = $this->identity->sent_backcolor ?? SENT_COLOR;

という書き方なの
これって「??」の左側が未定義またはNULLだった場合、「??」の右側の値になるのよ

C菜

三項演算子だと二回出現する「$this->identity->sent_backcolor」という部分が一回で済んでますね~
(効率的です~)

では、6種類を記述してみるです~

$sent_backcolor = $this->identity->sent_backcolor ?? SENT_COLOR;
$sent_forecolor = $this->identity->sent_forecolor ?? '#000000';
$received_backcolor = $this->identity->received_backcolor ?? RECEIVED_COLOR;
$received_forecolor = $this->identity->received_forecolor ?? '#000000';
$userlist_backcolor = $this->identity->userlist_backcolor ?? USER_LIST_COLOR;
$userlist_forecolor = $this->identity->userlist_forecolor ?? '#000000';

$this->set(compact(
    'sent_backcolor',
    'sent_forecolor',
    'received_backcolor',
    'received_forecolor',
    'userlist_backcolor',
    'userlist_forecolor'
));

で、どうでしょうか~?
ちなみに、文字色のデフォルト値は黒('#000000')です~

A子

うん、それを踏まえた上で、「default.php」のCSS変数を変更しよう

<style>
:root {
    --sent-backcolor: <?= $sent_backcolor ?>;
    --sent-forecolor: <?= $sent_forecolor ?>;
    --received-backcolor: <?= $received_backcolor ?>;
    --received-forecolor: <?= $received_forecolor ?>;
}
</style>

あ、「$userlist_backcolor」と「$userlist_forecolor」については、「chat.css」内で使ってないから設定してないよ

C菜

それでは、次は②の「chat.css」です~

.sent {
    color: var(--sent-forecolor);
    background-color: var(--sent-backcolor);
    align-self: flex-end;
    text-align: right;
}

.received {
    color: var(--received-forecolor);
    background-color: var(--received-backcolor);
    align-self: flex-start;
    text-align: left;
}

.sent::after {
    content: "";
    position: absolute;
    right: -8px;
    top: 50%;
    transform: translateY(-50%);
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 8px 0 8px 10px;
    border-color: transparent transparent transparent var(--sent-backcolor);
}

.received::after {
    content: "";
    position: absolute;
    left: -8px;
    top: 50%;
    transform: translateY(-50%);
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 8px 10px 8px 0;
    border-color: transparent var(--received-backcolor) transparent transparent;
}


A子

あとは③だけど、ユーザリストのstyleタグの内容を変更するくらいだね

C菜

良いと思います~

A子

んじゃ、チャット画面を表示してみるね

うん、デフォルトの色になってるみたいで、特に問題ないかな

C菜

それでは、それを流用して「templates/Users」の中の「change_color.php」を書き換えてみますね~

色のデフォルト値設定と16進数表記も追加して、JavaScriptで凡例がリアルタイムに更新されるようにしてみました~
(ポイントはCSS変数の値を書き換えていることです~)





A子

テストしてみた…

うーん
さすがはC菜、一発で成功だよ

A子

あれ?
ちょっと待って…

更新」をクリックしたあと、あらためてもう一度同じ画面(チャット画面の背景色や文字色の変更)を表示してみたんだけど、何にも変わってないよ(汗)

B美

データベースを確認してみれば分かると思うけど、多分更新されているはずよ

そうね
一度「ログアウト」してから、再度「ログイン」してみなさい

A子

OK

あ、ばっちり更新されてるじゃん

C菜

わざわざログアウトしないとダメなんでしょうか~?

B美

いいえ
「UsersController.php」の「changeColor」メソッドに以下の一文を追加してみなさい
(これにより「セッション情報の再設定」を行うの)

$this->Authentication->setIdentity($user);

記述する箇所は「save」が成功したあとね

A子

お!

今度は(再ログインすることなく)即座に更新されたよ
(完璧じゃん!)

C菜

では、バージョンを更新しましょう~

Ver.1.1.0でどうでしょうか~?

A子

うん、良いと思うよ

最後に「const.php」の全体像を示しておこうか




B美

ふむ
なかなかのものね

あ、「FROM_ADDRESS」についても開発環境と本番環境で切り分けたのは良いと思うわよ
(受信側メールサーバがSPFレコードを確認する場合、プロバイダのメールアドレスで送信しないとメールが届かないからね)

A子

実は、色々テストしてるときに(たまたま)気が付いたんだよね(苦笑)
(宛先のアドレスがGmailだと届かないなぁ…って)

C菜

それでは最後に、各人の色設定をお披露目しましょう~

A子

モノトーンのB美に、ビビッドな私(A子)、パステルカラーのC菜か…

なんだか性格が出てる気がするよ(苦笑)