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.