14 - Trabalhando com o Código do CakePHP 3
Sorte é o que acontece quando a preparação encontra a oportunidade.
Fluxo de Informações entre controllers, models e view/templates
Supondo que temos no aplicativo cliente, com apenas as tabelas users, groups e customers:
Controller/CustomersController.php
Model/CustomersTable.php
Template/Customers/index.ctp
Criar em src/Model/CustomersTable.php a função:
public function teste(){
$query = $this->find('all', [
'order' => ['Customers.id' => 'ASC']
]);
$row = $query->first(); // Ou ->last()
print "Model<br>";
return $row->name;
}
Chamar no index() do src/Controller/CustomersController.php:
public function index()
{
// Adionar as 3 linhas abaixo
print "Controller<br>";
// Mostrar o primeiro name:
print $this->Customers->teste();exit;
$customers = $this->paginate($this->Customers);
$this->set(compact('customers'));
}
Chamar pela web
http://localhost/clientes/users/index
Mostrará, pois primeiro foi ao controller, depois foi ao model, voltou ao controller e mostrou na view:
Controller
Model
Nome de um customer
Listagem de Users
View
Veja a ordem:
1) O controller recebe a requisição do usuário para mostrar o customer:
http://localhost/clientes/customers/index
2) O Controller envia para o Model pedindo o primeiro name
3) O Model processa e devolve
4) Então o controller envia para a view o primeiro name de customer
Para receber strings com segurança nos forms, usar a função h():
<!-- File: src/Template/Articles/view.ctp -->
<h1><?= h($article->title) ?></h1>
<p><?= h($article->body) ?></p>
Testar se uma requisição é realmente post:
if ($this->request->is('post')) {
Debugar
dd($variavel);
Carregar model que não é o default mas associado a este controller
$cliente=$this->LoadModel('Clientes');
Recebendo o nome da action atual
$action=$this->request->getParam('action');
print $action;
ou
use Cake\Routing\Router;
echo Router::getRequest()->params['action'];
Recebendo nome do Controller atual
$controller = $this->request->getParam('controller');
print $controller;
echo ucfirst(Router::getRequest()→params['controller']).'/'.Router::getRequest()→params['action'];
ou
use Cake\Routing\Router;
print Router::getRequest()->params['controller'];
Usando:
<?php echo $title_for_layout .' - '. ucfirst(Router::getRequest()->params['controller']).'/'.Router::getRequest()->params['action']; ?>
$title_for_layout é definida no beforeFilter().
Capturar nome do action atual:
$this->request->action
Capturar nome do controller:
$this->request->controller
Componente Flash
Uma forma eficiente de enviar mensagens do controller para as views
$this->Flash->msg
msg = success, set, error
public function index()
{
$controller = $this->request->getParam('controller');
$this->Flash->success(__('O nome deste controller é: '.$controller));
Acesso a Banco de Dados
O trabalho com bancos de dados no Cake é feito com dois objetos Tables (lida com coleções da dados, tabela, por exemplo) e Entities (lida com apenas um registro).
Para trabalhar com Tabelas num controller
Carregar o objeto Table
use Cake\ORM\TableRegistry;
Carregar o respectivo objeto
$clientes = TableRegistry::get('Clientes');
Agora pode trabalhar com seu conteúdo.
use Cake\Datasource\ConnectionManager;
$dsn = 'mysql://root:password@localhost/my_database';
ConnectionManager::config('default', ['url' => $dsn]);
$conn = ConnectionManager::get('default');
$results = $conn->execute('SELECT * FROM articles')->fetchall('assoc');
Também podemos usar query builder.
Redirecionamento para outras páginas
controller/action
$this->redirect(['controller' => 'Clientes', 'action' => 'index'])
URL
$this->redirect('http://ribafs.org')
Action do controller atual
$this->redirect(['action' => 'edit', $id]);
ou
$this->setAction('index')
Para o próprio link de onde veio
$this->redirect($this->referer());
Datasource
Se você precisar de mais controle sobre suas consultas, você pode fazer uso de instruções preparadas. Isso permite que você se comunique diretamente com o driver de banco de dados e enviar qualquer consulta personalizada que você queira:
$db = $this->getDataSource();
$db->fetchAll(
'SELECT * from users where username = ? AND password = ?',
array('jhon', '12345')
);
$db->fetchAll(
'SELECT * from users where username = :username AND password = :password',
array('username' => 'jhon','password' => '12345')
);
Outro exemplo:
$query = "SELECT * FROM user WHERE id=:user_id"
$data = $this->getDataSource()->fetchAll($query, array("usery_id" => $user_id), array("cache" => false));
Retornando os nomes de todas as tabelas do banco atual
$conn = ConnectionManager::get('default');
$driver = $conn->config()['driver'];
if($driver == 'Cake\Database\Driver\Postgres'){
$tables = $conn->execute("SELECT relname FROM pg_class WHERE relname !~ '^(pg_|sql_)' AND relkind = 'r';")->fetchAll();
}elseif($driver=='Cake\Database\Driver\Mysql'){
$tables = $conn->execute("SHOW tables")->fetchAll();
}
print $tables;
Identificar SGBD (mysql ou postgres):
Add ao início
use Cake\Datasource\ConnectionManager;
$conn = ConnectionManager::get('default');
$driver = $conn->config()['driver']; // Outros: database, etc.
if($driver == 'Cake\Database\Driver\Postgres'){
$this->paginate = [
'contain' => ['Users'],
'conditions' => ['or' => [
'Customers.name ilike' => '%' . $this->request->getQuery('search') . '%',
'Customers.phone ilike' => '%' . $this->request->getQuery('search') . '%'
]],
'order' => ['Customers.id' => 'DESC' ]
];
}elseif($driver=='Cake\Database\Driver\Mysql'){
$this->paginate = [
'contain' => ['Users'],
'conditions' => ['or' => [
'Customers.name like' => '%' . $this->request->getQuery('search') . '%',
'Customers.phone like' => '%' . $this->request->getQuery('search') . '%'
]],
'order' => ['Customers.id' => 'DESC' ]
];
}else{
print '<h2>Driver database dont supported!';
exit;
}
Comments fornecido por CComment