①データベース作成
MySQL使用
usersテーブル
mysql> create table users(user_id int primary key auto_increment, user_name text not null, mail_address text not null, password text not null);
letterテーブル
mysql> create table letters(letter_id integer primary key auto_increment, user_id integer, posted_date datetime, send_date datetime, source_address text not null, destination_address text not null, title text, content text);
②アプリの雛形作成
作業ディレクトリにて
composer create-project --prefer-dist cakephp/app TimeLetter
③データベース登録
config/app.phpにて
'username' => '****',
'password' => '************',
'database' => 'time_letter',
接続できたか確認
サーバ起動
bin\cake server
http://localhost:8765/(http://localhost:8765/)

接続できている。
③bakeコマンド
作業ディレクトリにてMVC雛形を作成
bin\cake bake all users
bin\cake bake all letters
必要なディレクトリ(usersとlettersのController,Model,Templateなど)が作成されたのを確認
ログイン機能実装
usersアプリケーションを修正してログイン機能を実装する。
AppController.phpを変更
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\Event;
class AppController extends Controller
{
// loginしてない状態で入れるページを設定
public function beforeFilter(Event $event)
{ $this->Auth->allow(['login', 'add']);
}
public function initialize()
{
parent::initialize();
$this->loadComponent('Paginator');
$this->loadComponent('RequestHandler', [
'enableBeforeRedirect' => false,
]);
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'loginRedirect' => [
'controller' => 'Users',
'action' => 'index'
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login'
],
'authenticate' => [
'Form' => [
'userModel' => 'Users',
'fields' => [
'username' => 'user_name',
'password' => 'password'
]
]
],
]);
}
}
authenticateで認証する項目を設定する。ここではusernameとpassword。fieldsのキーはauth固定で値はカラム名と等しくしなければならない。user_nameでカラムを作ったので変更。
UsesController.phpを変更
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Event\Event;
class UsersController extends AppController
{
public $paginate = [
'limit' => 5,
'order' => [
'Users.user_id' => 'asc'
]
];
public function initialize()
{
parent::initialize();
$this->loadComponent('Paginator');
}
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow(['login', 'add']);
}
public function index()
{
$this->set('users', $this->Users->find('all'));
$this->set('users', $this->paginate());
}
public function view($id = null)
{
$user = $this->Users->get($id, [
'contain' => []
]);
$this->set('user', $user);
$this->set('_serialize', ['user']);
}
public function add()
{
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'login']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
}
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Invalid username or password, try again'));
}
}
public function logout()
{
return $this->redirect($this->Auth->logout());
}
}
ここでもbeforeFilterを指定する。
またdelete,editはログイン機能には必要ないので削除し、login,logoutを作成
Entityを変更
<?php
namespace App\Model\Entity;
use Cake\ORM\Entity;
use Cake\Auth\DefaultPasswordHasher;
class User extends Entity
{
protected $_accessible = [
'user_name' => true,
'mail_address' => true,
'password' => true,
'user_id' => false
];
protected $_hidden = [
'password'
];
protected function _setPassword($password)
{
if (strlen($password) > 0) {
return (new DefaultPasswordHasher)->hash($password);
}
}
}
UsersTableを変更
<?php
namespace App\Model\Table;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class UsersTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('user_id');
$this->setPrimaryKey('user_id');
}
public function validationDefault(Validator $validator)
{
return $validator
->notEmpty('user_name', 'A username is required')
->notEmpty('mail_address', 'A mail address is required')
->notEmpty('password', 'A password is required');
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['mail_address']));
return $rules;
}
}
keyやfieldはカラム名にすること。
Templete
add.ctp
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('List Users'), ['action' => 'index']) ?></li>
</ul>
</nav>
<div class="users form large-9 medium-8 columns content">
<?= $this->Form->create($user) ?>
<fieldset>
<legend><?= __('Add User') ?></legend>
<?= $this->Form->control('user_name') ?>
<?= $this->Form->control('mail_address') ?>
<?= $this->Form->control('password') ?>
</fieldset>
<?= $this->Html->link(__('Login'), ['action' => 'login']) ?>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
index.ctp
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('Logout'), ['action' => 'logout']) ?></li>
</ul>
</nav>
<div class="users index large-9 medium-8 columns content">
<h3><?= __('Users') ?></h3>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th scope="col"><?= $this->Paginator->sort('user_id') ?></th>
<th scope="col"><?= $this->Paginator->sort('username') ?></th>
<th scope="col"><?= $this->Paginator->sort('password') ?></th>
<th scope="col" class="actions"><?= __('Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td><?= $this->Number->format($user->user_id) ?></td>
<td><?= h($user->user_name) ?></td>
<td><?= h($user->password) ?></td>
<td class="actions">
<?= $this->Html->link(__('View'), ['action' => 'view', $user->user_id]) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('next') . ' >') ?>
<?= $this->Paginator->last(__('last') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?></p>
</div>
</div>
login.ctp
<div class="users form large-9 medium-8 columns content">
<?= $this->Flash->render() ?>
<?= $this->Form->create() ?>
<fieldset>
<legend><?= __('Please enter your username and password') ?></legend>
<?= $this->Form->control('user_name') ?>
<?= $this->Form->control('password') ?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
view.ctp
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('List Users'), ['action' => 'index']) ?> </li>
<li><?= $this->Html->link(__('Logout'), ['action' => 'logout']) ?></li>
</ul>
</nav>
<div class="users view large-9 medium-8 columns content">
<h3><?= h($user->id) ?></h3>
<table class="vertical-table">
<tr>
<th scope="row"><?= __('Username') ?></th>
<td><?= h($user->user_name) ?></td>
</tr>
<tr>
<th scope="row"><?= __('Id') ?></th>
<td><?= $this->Number->format($user->id) ?></td>
</tr>
</table>
</div>