Kontrolery i widoki w CakePHP 3
Teraz zajmiemy się utworzeniem kontrolera w celu pobrania danych oraz widoków aby je wyświetlić. Podczas gdy model jest używany do interakcji z bazami danych, kontroler jest używany do przetwarzania żądań oraz przekazywania zmiennych do widoku.
<?php
namespace App\Controller;
use App\Controller\AppController;
class UsersController extends AppController
{
private $roles = ['User' => 'User', 'Admin' => 'Admin', 'Disabled' => 'Disabled'];
public $paginate = [
'limit' => 30,
'order' => ['first_name' => 'ASC', 'last_name' => 'ASC']
];
public function index() {
$users = $this->paginate($this->Users);
$this->set(compact('users'));
$this->set('_serialize', ['users']);
}
public function view($id = null) {
$user = $this->Users->get($id);
$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->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$roles = $this->roles;
$this->set(compact('user', 'roles'));
$this->set('_serialize', ['user']);
}
public function edit($id = null) {
$user = $this->Users->get($id);
if ($this->request->is(['patch', 'post', 'put'])) {
if ($this->request->data['password'] == '') {
unset($this->request->data['password']); // unset the blank password
}
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
unset($user->password); // Unset the password so nothing is loaded or displayed in the form
$roles = $this->roles;
$this->set(compact('user', 'roles'));
$this->set('_serialize', ['user']);
}
public function delete($id = null) {
$this->request->allowMethod(['post', 'delete']);
$user = $this->Users->get($id);
if ($this->Users->delete($user)) {
$this->Flash->success(__('The user has been deleted.'));
} else {
$this->Flash->error(__('The user could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
}
Tablica roles zawiera listę dostępnych ról użytkowników, wartości do wyświetlenia i klucze, które mają być przechowywane w rekordach.
Zmienna paginate zastępuje domyślny limit 20 oraz ustawia kolejność sortowania.
Nie można używać wirtualnych pól, takich jak full_name, do sortowania list stronicowanych, ale można zdefiniować kolejność sortowania tak,
aby była taka sama jak pole wirtualne. Jest mały problem z tym w widoku, ale omówimy to później.
Być może zauważyłeś, że w funkcji edit(), unsetujemy pole hasła dwa razy. Najpierw (przy drugim wystąpieniu) usuwamy go przed wyświetleniem,
aby pole hasła pozostało puste. Hashowana wartość przechowywana w bazie danych nie jest przydatna przy edycji użytkownika.
Drugi raz przed przekazaniem danych do zapisu. Jeśli użytkownik nie ustawił nowego hasła, nie chcemy zapisywać pustego łańcucha w bazie danych, zastępując obecne hasło.
Kod widoku listy użytkowników (src/Template/Users/index.ctp). CakePHP używa dla plików widoków i elementów rozszerzenia .ctp.
Jest to domyślna lista rekordów z bazy danych.
<?php if (empty($_GET['direction'])) { $this->Paginator->options(['url' => ['direction' => null, 'sort' => null]]); } ?>
<div class="users index large-9 medium-8 columns content">
<?php echo $this->Html->link(__('New User'), ['action' => 'add'], ['class' => 'right']); ?>
<h3><?php echo __('Users') ?></h3>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th><?php echo $this->Paginator->sort('first_name', 'Name') ?></th>
<th><?php echo $this->Paginator->sort('username') ?></th>
<th><?php echo $this->Paginator->sort('email') ?></th>
<th><?php echo $this->Paginator->sort('role') ?></th>
<th class="actions"><?php echo __('Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td><?php echo $this->Html->link($user->full_name, ['action' => 'view', $user->id]) ?></td>
<td><?php echo h($user->username) ?></td>
<td><?php echo $this->Text->autoLinkEmails($user->email) ?></td>
<td><?php echo h($user->role) ?></td>
<td class="actions">
<?php echo $this->Html->link(__('View'), ['action' => 'view', $user->id]) ?> |
<?php echo $this->Html->link(__('Edit'), ['action' => 'edit', $user->id]) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="paginator">
<ul class="pagination">
<?php echo $this->Paginator->prev('< ' . __('previous')) ?>
<?php echo $this->Paginator->numbers() ?>
<?php echo $this->Paginator->next(__('next') . ' >') ?>
</ul>
<p>page <?php echo $this->Paginator->counter() ?></p>
</div>
</div>
Niestety między CakePHP 2 a 3 zmiana modelu danych uniemożliwiła sortowanie po wirtualnych polach (np. full_name), więc zauważysz, że nagłówek pierwszej kolumny to "first_name", a nie "full_name".
Ponadto kolejność sortowania jest teraz przekazywana za pośrednictwem adresu URL, niezależnie od tego, czy została wybrana kolejność sortowania, czy też nie, tracąc nasz domyślny rodzaj sortowania po first_name i last_name.
Taki jest cel pierwszego wiersza pliku: czyszczenie opcji sortowania i kierunku, o ile nie zostały one wyraźnie zaznaczone.
Widok dodawania użytkownika (src/Template/Users/add.ctp).
<?php $this->assign('title', 'Add User'); // Set the title for the page ?>
<div class="users form large-9 medium-8 columns content">
<?php echo $this->Form->create($user) ?>
<fieldset>
<legend><?php echo __('Add User') ?></legend>
<?php
echo $this->Form->input('username', ['autofocus' => true]);
echo $this->Form->input('first_name');
echo $this->Form->input('last_name');
echo $this->Form->input('password'); ?>
<p class="helper">Passwords must be at least 8 characters and contain at least 1 number, 1 uppercase, 1 lowercase and 1 special character</p>
<?php
echo $this->Form->input('confirm_password', ['type' => 'password']);
echo $this->Form->input('email');
echo $this->Form->input('role');
?>
</fieldset>
<?php echo $this->Form->button(__('Submit')); ?>
<?php echo $this->Html->link(__('Cancel'), ['action' => 'index'], ['class' => 'button']); ?>
<?php echo $this->Form->end(); ?>
</div>
W CakePHP dzięki Form Helperowi łatwo stworzymy wiele pól formularza na podstawie typu pola z bazy danych. W niektórych przypadkach, takich jak pole roli, zdaje sobie sprawę,
że istnieje tablica o nazwie $role i tworzy pole wyboru wykorzystujące tę tablicę. Ponieważ confirm_password nie jest polem w bazie danych, domyślnie jest polem tekstowym,
więc wykorzystując tablicę $options, możesz powiedzieć Cakeowi, aby uczynił ją polem hasła.
W celu dodania jakiegoś użytkownika wejdź w przeglądarce na adres localhost/users/add.
