MANUAL CAKEPHP 1.2


       Juan Basso




    3 de março de 2008
Sumário
PARTE I.                COMEÇANDO COM CAKEPHP ......................................................................7

Prefácio ................................................................................................................................................. 7
  Requisitos do leitor .................................................................................................................................. 7

Introdução ao CakePHP ......................................................................................................................... 7
   O que é CakePHP? Por que usar? ............................................................................................................. 7
   Onde obter ajuda? ................................................................................................................................... 8

Entendendo o Model-View-Controller (MVC) ........................................................................................ 9
  Introdução ................................................................................................................................................ 9
  Benefícios ............................................................................................................................................... 10


PARTE II.               PRINCÍPIOS BÁSICOS DO CAKEPHP ....................................................... 11

Estrutura CakePHP ............................................................................................................................... 11
   Extensões de controller ......................................................................................................................... 11
   Extensões de view .................................................................................................................................. 11
   Extensões do model ............................................................................................................................... 11
   Extensões de aplicação .......................................................................................................................... 12

Estrutura de arquivos do CakePHP ....................................................................................................... 12
   Estrutura do diretório App ..................................................................................................................... 13

Requisição típica do CakePHP .............................................................................................................. 13

Convenções CakePHP ........................................................................................................................... 15
  Convenções de arquivos e nome de classes .......................................................................................... 15
  Convenções de modelos ........................................................................................................................ 15
  Convenções de controladores................................................................................................................ 15
  Convenções de visões ............................................................................................................................ 16


PARTE III.                  DESENVOLVENDO COM CAKEPHP ...................................................... 17

Requisitos ............................................................................................................................................ 17

Preparativos para instalação................................................................................................................ 17
  Baixando o CakePHP .............................................................................................................................. 17
  Permissões ............................................................................................................................................. 17

Instalação ............................................................................................................................................ 18
   Desenvolvimento ................................................................................................................................... 18
   Produção ................................................................................................................................................ 18
   Instalação avançada ............................................................................................................................... 19
      Caminho de classes adicionais ........................................................................................................... 20

                                                                               i
Apache e mod_rewrite .......................................................................................................................... 20
    Comece agora! ....................................................................................................................................... 20

Configuração........................................................................................................................................ 21
  Configuração da base de dados ............................................................................................................. 21
  Configuração do núcleo ......................................................................................................................... 22
  As classes de configuração ..................................................................................................................... 22
     Classes de configuração ..................................................................................................................... 22
     Variáveis de configuração do núcleo ................................................................................................. 22
     Constantes de configuração .............................................................................................................. 22
  Configuração de rotas (Routes) ............................................................................................................. 22
  Inflexão personalizada ........................................................................................................................... 23
  Configuração de inicialização (bootstrap) .............................................................................................. 24

Controllers (Controladores) ................................................................................................................. 24
  Introdução .............................................................................................................................................. 24
  Atributos ................................................................................................................................................ 25
     $name ................................................................................................................................................ 25
     $components, $helpers e $uses ........................................................................................................ 25
     Relativo à página: $layout e $pageTitle ............................................................................................. 26
     Atributos dos parâmetros ($params) ................................................................................................ 26
     Outros atributos ................................................................................................................................ 27
  Métodos ................................................................................................................................................. 28
     Interagindo com as visões ................................................................................................................. 28
     Fluxo de controle ............................................................................................................................... 29
     Callbacks ............................................................................................................................................ 29
     Outros métodos ................................................................................................................................. 30

Components (Componentes) ............................................................................................................... 33
  Introdução .............................................................................................................................................. 33
  Construindo componentes personalizados............................................................................................ 33
  Acessando classes do MVC de dentro dos componentes ...................................................................... 34

Models (Modelos)................................................................................................................................ 34
 Introdução .............................................................................................................................................. 34
 Campos mágicos .................................................................................................................................... 34
 Atributos ................................................................................................................................................ 34
 Métodos ................................................................................................................................................. 34
 Associações ............................................................................................................................................ 34
    Introdução ......................................................................................................................................... 34
    hasOne ............................................................................................................................................... 35
    belongsTo .......................................................................................................................................... 37
    hasMany ............................................................................................................................................ 38
    hasAndBelongsToMany (HABTM) ...................................................................................................... 41
    Salvando dados em tabelas relacionadas (hasOne, hasMany, belongsTo) ....................................... 43
    Salvando dados em tabelas relacionadas (HABTM) .......................................................................... 44
    Criando e removendo relações durante execução ............................................................................ 45
 DataSources ........................................................................................................................................... 47
 Behaviors................................................................................................................................................ 47

                                                                              ii
Introdução ......................................................................................................................................... 47
        Usando Behaviors .............................................................................................................................. 47
        TreeBehavior ..................................................................................................................................... 47
        TranslateBehavior .............................................................................................................................. 47
        ACLBehavior ....................................................................................................................................... 47

Views (Visões)...................................................................................................................................... 47
   Templates / Skin ..................................................................................................................................... 47
   Layouts ................................................................................................................................................... 48
   Elements (Elementos) ............................................................................................................................ 50

Helpers (Ajudantes) ............................................................................................................................. 50
  Introdução .............................................................................................................................................. 50
  Helpers do CakePHP ............................................................................................................................... 51
  Criando helpers ...................................................................................................................................... 52
     Incluindo outros helpers .................................................................................................................... 52
     Usando seus helpers personalizados ................................................................................................. 53
     Contribuindo ...................................................................................................................................... 53

Scaffolding ........................................................................................................................................... 53
  Introdução .............................................................................................................................................. 53
  Personalizando os scaffolds ................................................................................................................... 54

CakePHP Console ................................................................................................................................. 55
  Introdução .............................................................................................................................................. 55
  Criando Shells e Tasks ............................................................................................................................ 55
     Criando suas Shells ............................................................................................................................ 55
     Tasks .................................................................................................................................................. 55

Gerando código com Bake ................................................................................................................... 55

Plugins ................................................................................................................................................. 55
   Criando um plugin .................................................................................................................................. 55
      Plugin de controladores ..................................................................................................................... 55
      Plugin de modelos ............................................................................................................................. 55
      Plugin de visões ................................................................................................................................. 55
      Plugin de informações ....................................................................................................................... 55

Constantes e funções globais ............................................................................................................... 55
  Funções globais ...................................................................................................................................... 55
  Constantes do núcleo ............................................................................................................................. 58
  Constantes do diretório ......................................................................................................................... 58


PARTE IV. TAREFAS COMUNS COM CAKEPHP ......................................................... 60

Validação de dados .............................................................................................................................. 60
  Regras simples ....................................................................................................................................... 60
  Uma regra por campo ............................................................................................................................ 60
     rule ..................................................................................................................................................... 60

                                                                               iii
required ............................................................................................................................................. 60
      allowEmpty ........................................................................................................................................ 60
      on ....................................................................................................................................................... 60
      message ............................................................................................................................................. 60
    Múltiplas regras por campo ................................................................................................................... 60
    Construindo regras de validação ............................................................................................................ 60
      alphaNumeric .................................................................................................................................... 60
      between ............................................................................................................................................. 60
      blank .................................................................................................................................................. 60
      cc ........................................................................................................................................................ 60
      comparison ........................................................................................................................................ 60
      date .................................................................................................................................................... 60
      email .................................................................................................................................................. 60
      ip ........................................................................................................................................................ 60
      minLength .......................................................................................................................................... 60
      maxLength ......................................................................................................................................... 60
      numeric .............................................................................................................................................. 60
      phone ................................................................................................................................................. 60
      postal ................................................................................................................................................. 60
      ssn ...................................................................................................................................................... 60
      url ....................................................................................................................................................... 60
    Regras de validação personalizada ........................................................................................................ 60
      Validação por expressões regulares personalizadas ......................................................................... 61
      Validação por métodos personalizados ............................................................................................. 61

Limpeza de dados ................................................................................................................................ 61

Manipulação de erros .......................................................................................................................... 61

Debugando .......................................................................................................................................... 61

Gerando caches ................................................................................................................................... 61

Logando ............................................................................................................................................... 61
  Introdução .............................................................................................................................................. 61
  Usando as funções de log ...................................................................................................................... 61

Testando .............................................................................................................................................. 62

Internacionalizando ............................................................................................................................. 62
   Definindo o locale da sua aplicação ....................................................................................................... 62
   Internacionalizando em CakePHP .......................................................................................................... 63

Paginação ............................................................................................................................................ 64
  Configurando os controladores ............................................................................................................. 64
  Paginando nas visões ............................................................................................................................. 64
  Paginando com AJAX .............................................................................................................................. 64
     Alterações no layout .......................................................................................................................... 64
     Alterações nas visões ......................................................................................................................... 64


                                                                                iv
PARTE V.                COMPONENTES INTERNOS ....................................................................... 65

Lista de controle de acessos (ACL)........................................................................................................ 65

Autenticação........................................................................................................................................ 65

Sessões ................................................................................................................................................ 65

Manipulando requisições ..................................................................................................................... 65

Segurança ............................................................................................................................................ 65

E-mail .................................................................................................................................................. 65

Cookies ................................................................................................................................................ 65
  Introdução .............................................................................................................................................. 65
  Configurando os controladores ............................................................................................................. 65
  Usando o componente ........................................................................................................................... 65


PARTE VI. HELPERS INTERNOS .................................................................................... 66

Formulários ......................................................................................................................................... 66
  Criando formulários ............................................................................................................................... 66
     $options['type'].................................................................................................................................. 66
     $options['action'] ............................................................................................................................... 67
     $options['url'] .................................................................................................................................... 67
     $options['default'] ............................................................................................................................. 67
  Fechando formulários ............................................................................................................................ 68
  Elemento de formulário mágico ............................................................................................................ 68
     $options['type'].................................................................................................................................. 69
     $options['before'], $options['between'] e $options['after'].............................................................. 69
     $options['options']............................................................................................................................. 69
     $options['multiple'] ........................................................................................................................... 70
     $options['maxLength'] ....................................................................................................................... 70
     $options['div'] .................................................................................................................................... 70
     $options['label'] ................................................................................................................................. 70
     $options['id'] ...................................................................................................................................... 70
     $options['error'] ................................................................................................................................ 70
     $options['selected'] ........................................................................................................................... 70
     $options['rows'], $options['cols'] ...................................................................................................... 70
     $options['empty'] .............................................................................................................................. 70
     $options['timeFormat'] ...................................................................................................................... 70
     $options['dateFormat'] ...................................................................................................................... 71
  Métodos específicos do elemento de formulário .................................................................................. 71

HTML ................................................................................................................................................... 73
  Inserindo elementos bem-formados ..................................................................................................... 73

JavaScript............................................................................................................................................. 73


                                                                              v
AJAX ....................................................................................................................................................... 73
    Opções do AjaxHelper ............................................................................................................................ 73
      Opções gerais..................................................................................................................................... 73
      Opções de callback ............................................................................................................................ 73
    Métodos ................................................................................................................................................. 73

Cache ................................................................................................................................................... 73

Form .................................................................................................................................................... 73

Number ............................................................................................................................................... 73

Text ..................................................................................................................................................... 73

Time..................................................................................................................................................... 73


PARTE VII.                   EXEMPLOS .................................................................................................. 74

Tutorial de como fazer um blog em CakePHP ....................................................................................... 74

Sistema simples de autenticação de usuários ...................................................................................... 74


PARTE VIII.                  APÊNDICES ................................................................................................. 75

Escritores da versão inglesa ................................................................................................................. 75

Tradutores para língua portuguesa ...................................................................................................... 75
   Apoio e revisão da versão traduzida ...................................................................................................... 75

Inflexão em português ......................................................................................................................... 75




                                                                                vi
Começando com CakePHP         7




           Parte I.    Começando com CakePHP
Prefácio
Bem vindo ao paraíso de desenvolvimento web.

Se você está lendo o prefácio de um manual técnico, é porque está lhe sobrando bastante
tempo. Não somos celebridades e o material é o que vem depois. Você pode pular estes
capítulos supérfluos e ir direto ao ponto nas seções que você quer.

Requisitos do leitor
Para ler este manual, você já deve estar familiarizado com o PHP. Conhecer de programação
orientada a objeto irá lhe ajudar bastante, porém eu suponho que as seções de introdução
deste manual servirão como um bom exemplo do que vem pela frente. Com isso, este material
é escrito para desenvolvedores de todos os níveis de habilidade que desejam criar algo
robusto, sustentável, rápido e agradável.

Devo alertar que haverá seções que abordam tecnologias que estão realmente fora do âmbito
deste manual. Administração de servidor Web, AJAX e JavaScript, por exemplo, podem ser
mencionados em partes do texto, mas na maior parte do texto nós estaremos focado no
CakePHP.

Introdução ao CakePHP
O que é CakePHP? Por que usar?
CakePHP é gratuito, de código aberto, uma framework em PHP para desenvolvimento ágil. É
uma estrutura fundamental para programadores criarem aplicações web. Nosso principal
objetivo é permitir que você trabalhe em uma estrutura que possa programar de forma rápida
e sem a perda de flexibilidade.

CakePHP joga fora a monotonia do desenvolvimento web. Nós oferecemos todas as
ferramentas que você precisa para começar programando o que realmente deseja: a lógica
específica da sua aplicação. Em vez de reinventar a roda cada vez que se constrói um novo
projeto, pegue uma cópia do CakePHP e comece a construir sua carruagem real da sua
aplicação.

CakePHP tem uma equipe de desenvolvedores e uma grande comunidade, trazendo grande
valor ao projeto. Além de manter você fora do reinvento da roda, usando CakePHP significa
que o núcleo da sua aplicação é bem testado e constantemente aperfeiçoado.

Abaixo segue uma pequena lista dos recursos que você poderá desfrutar no CakePHP:

      Ativo e com comunidade amigável;
      Licença flexível;
      Compatibilidade com PHP 4 e PHP 5;
      Integrando funcionalidade CRUD (Create, Read, Update and Delete, ou Criar, Ler,
       Atualizar e Excluir) para interagir com o banco de dados;
Começando com CakePHP         8


      Aplicações scaffolding;
      Geração de código;
      Arquitetura MVC (Model, View, Controller, ou Modelo, Visões, Controlador);
      Requisições ao expedidor com clareza, URLs personalizáveis e rotas;
      Validações internas;
       Templates rápidos e flexíveis (Sintaxe PHP e com ajudantes);
      Ajudantes para usar AJAX, JavaScript, HTML, formulários e outros nas visões;
      Componentes de E-mail, Cookie, Segurança, Sessões, Manipulação de Requisições e
       outros;
      Lista de controle de acessos flexível;
      Limpeza de dados;
      Flexibilidade com cache;
      Internacionalização;
      Funciona em qualquer subdiretório do seu website, com poucas configurações do
       Apache.

Onde obter ajuda?
Você começou no lugar certo. Este manual (e a API) deve ser provavelmente o primeiro lugar
que você vá para procurar as respostas das suas dúvidas. Assim como acontece com muitos
outros projetos de código aberto, nós obtemos novos usuários regularmente. Tentamos ser os
melhores para responder seus questionamentos em primeiro lugar. As respostas podem
demorar a chegar, mas permanecerá por tempos e ajudará a esclarecer outras pessoas. Tanto
o manual, quanto a API podem ser encontradas online.

http://manual.cakephp.com.br (em português)

http://manual.cakephp.org (em inglês)

http://api.cakephp.org/1.2 (em inglês)

Se você estiver assustado, dê um grito pelo canal de IRC internacional ou entre no grupo da
comunidade luso-brasileira. Além da equipe de desenvolvimento do núcleo do CakePHP no
canal, principalmente durante o dia. Se você precisar de alguma ajuda, deseja encontrar
usuários na sua área ou gostaria de doar o novo carro esportivo, gostaríamos de falar com
você.

Grupo da comunidade luso-brasileira: http://groups.google.com/group/cake-php-pt

#cakephp-pt @ irc.freenode.net (em português)

#cakephp @ irc.freenode.net (em inglês)

O CakePHP Bakery é uma casa para todas as coisas de CakePHP. Visite este site para ver
tutoriais, estudos de caso e exemplos de código. Assim que estiver familiarizado com o
CakePHP, faça o login e compartilhe seus conhecimentos com a comunidade para ganhar fama
e fortuna.

http://bakery.cakephp.org
Começando com CakePHP       9


O CakeForge é outro recurso que os desenvolvedores podem usar para hospedar seus projetos
usando CakePHP e compartilhar com outras pessoas. Se você está olhando para achar projetos
existentes, ou querendo compartilhar, acesso o CakeForge.

http://www.cakeforge.org

O site oficial do CakePHP está sempre esperando sua visita. Ele tem links para sites de outros
desenvolvedores, screencasts, oportunidade para doar ao projeto e downloads.

http://www.cakephp.org

Entendendo o Model-View-Controller (MVC)
Introdução
Aplicações bem escritas em CakePHP segue o design pattern MVC (Model-View-Controller ou
Modelo-Visão-Controlador). Programando em MVC separa sua aplicação em três partes
principais. O model representa os dados, a view representa a visualização dos dados e o
controller manipula e roteia as requisições dos usuários.




                             Figura 1. Requisição típica do CakePHP

A Figura 1 mostra um exemplo de uma simples requisição MVC em CakePHP. Para fins
ilustrativos, digamos que um usuário chamado Ricardo apenas clicou no link “Comprar um
bolo personalizado agora!” da sua aplicação.

   1. Ricardo clica no link apontando para http://www.exemplo.com.br/cakes/comprar e
      seu navegador faz uma requisição ao site;
   2. O dispatcher (expedidor) verifica a URL requisitada (/cakes/comprar) e redireciona ao
      controller correto;
   3. O controller executa a lógica específica da aplicação. Por exemplo, verifica se o Ricardo
      está logado;
   4. O controller também usa os models para acessar os dados da sua aplicação. Muitas
      vezes, os models representam as tabelas do banco de dados, mas podem representar
      registros LDAP, feeds de RSS ou até mesmo arquivos do sistema. Neste exemplo, o
      controller usa o model para trazer ao Ricardo as últimas compras do banco de dados;
   5. Depois que o controller fez sua mágica sobre os dados, ele repassa para a view. A view
      faz com que os dados fiquem prontos para a representação do usuário. As views em
      CakePHP normalmente vem no formato HTML, mas pode ser facilmente exibidas em
Começando com CakePHP          10


      PDF, documento XML, um objeto JSON ou outro formato qualquer, dependendo da
      sua necessidade;
   6. Uma vez que a visão tenha usado os dados provenientes do controller para construir a
      página, o conteúdo é retornado ao browser do Ricardo.

Aproximadamente toda requisição da sua aplicação seguirá o modelo básico do modelo. Nós
vamos especificar os detalhes mais adiante, mas mantenha essa visão geral no seu
pensamento.

Benefícios
Por que usar MVC? Porque é um verdadeiro padrão de desenvolvimento (design pattern) e
torna fácil a manutenção da sua aplicação, com pacotes modulares de rápido
desenvolvimento. Elaborar tarefas divididas entre models, views e controllers, faz com que sua
aplicação fique leve e independente. Novas funcionalidades são facilmente adicionadas e dar
nova cara nas características antigas pode ser feitas num piscar de olhos. O design modular e
separado também permite aos desenvolvedores e designers trabalhem simultaneamente,
incluindo a habilidade de um construir um rápido protótipo. A separação também permite que
os desenvolvedores alterem uma parte da aplicação sem afetar outras.

Se você nunca desenvolveu uma aplicação neste sentido, isso vai lhe agradar muito, mas
estamos confiantes que depois de construir sua primeira aplicação em CakePHP, você não vai
querer voltar atrás.
Princípios básicos do CakePHP      11




        Parte II.   Princípios básicos do CakePHP
Estrutura CakePHP
CakePHP possui a característica de usar as classes de Controller, Model e View, mas também
possui classes e objetos adicionais que fazem o desenvolvimento em MVC mais rápido e
agradável. Components, Behaviors e Helpers são classes que proporcionam extensibilidade e
reuso para adicionar funcionalidades rapidamente à base MVC das suas aplicações. Agora
vamos começar a subir um pouco o nível para analisar os detalhes de como usar estas
ferramentas mais tarde.

Extensões de controller
O Component (Componente) é uma classe que ajuda na lógica do controller. Se você tem a
mesma lógica e quer compartilhar entre controllers (ou aplicações), o component é uma boa
saída. Por exemplo, o component interno EmailComponent cria e envia e-mails em segundo
plano. Ao invés de escrever um método em cada controller que utiliza esta lógica, pode-se criar
um component que empacote esta funcionalidade e seja compartilhado entre os controllers.

Controllers também são equipados com callbacks. Estes callbacks estão disponíveis para que
você possa utilizar, apenas se você precisar inserir uma lógica entre operações do núcleo do
CakePHP. Os callbacks disponíveis incluem:

       beforeFilter(), executado antes de qualquer ação do controller;
       beforeRender(), executado depois da lógica do controller, mas antes da view ser
        renderizada;
       afterFilter(), executado depois de todas as lógicas do controller, incluindo a
        renderização da view. Não há diferença entre afterRender() e afterFilter(), exceto que
        você tenha feito uma chamada manualmente para render() no seu método do
        controller e tenha incluído alguma lógica depois dessa chamada.

Extensões de view
O Helper (Ajudante) é a classe que ajuda na lógica da view. Assim como o component ajuda o
controller, os helpers permitem a apresentação lógica ser acessada e compartilhada entre as
views. AjaxHelper é um dos principais helpers. Ele faz requisições AJAX facilmente de dentro
das views.

A maioria das aplicações tem partes do código que são usados repetidamente nas views.
CakePHP facilita o reuso de código na view com a utilização de layouts e elements (elementos).
Por padrão, toda view é renderizada por um controller seguindo algum layout. Os elements são
como pequenos trechos de código necessários que podem ser reutilizados em diversas views.

Extensões do model
Assim como as outras extensões, os Behaviors funcionam do mesmo modo, adicionando
funcionalidades entre os models. Por exemplo, se você armazenar os dados do usuário em
uma estrutura de árvore, você pode especificar o model User como comportamento de árvore
e ganhar funcionalidades para remover, adicionar e alterar nós em sua estrutura de árvore
fundamental.
Princípios básicos do CakePHP      12


Os models também são suportados por outra classe chamada DataSource. DataSources são
abstrações que permitem os models manipularem diferentes tipos de dados
consistentemente. Enquanto a principal fonte de dados numa aplicação CakePHP é via banco
de dados, você pode escrever DataSources adicionais que permitem seu model representar um
feed RSS, arquivo CSV, entidades LDAP ou eventos iCal. DataSources permite você associar
registros de diferentes fontes: ao invés de limitar em joins do SQL, DataSources permitem você
chamar seu model de LDAP que está associada a vários eventos iCal.

Assim como nos controllers, models têm recursos de callback como:

      beforeFind()
      afterFind()
      beforeValidate()
      beforeSave()
      afterSave()
      beforeDelete()
      afterDelete()

Os nomes desses métodos devem ser descritivos o bastante para que você saiba o que eles
fazem. Certifique-se de pegar os detalhes no capítulo sobre model.

Extensões de aplicação
Tanto os controllers, helpers e models têm uma classe pai que você pode usar para definir
modificações na aplicação. AppController (localizado em “/app/app_controller.php”),
AppHelper (localizado em “/app/app_helper.php”) e AppModel (localizado em
“/app/app_model.php”) são bons lugares para colocar métodos que você precisa para acessar
entre todos os controllers, helpers e models.

Embora não sejam classes ou arquivos, as rotas definem regras na requisição feita para o
CakePHP. As definições das rotas definem como o CakePHP deve mapear uma URL para um
método do controller. O behavior padrão assume que a URL “/controller/action/var1/var2”
mapeia para Controller::action($var1, $var2), mas você pode usar rotas para personalizar URLs
e como elas devem ser interpretadas pela sua aplicação.

Alguns recursos na sua aplicação podem ser empacotados com mérito. Um plugin é um pacote
de model, controller e view que realiza um objetivo específico que pode abranger vários
aplicativos. Um sistema de gestão de usuários ou um blog simplificado podem ser bons
exemplos de plugins para CakePHP.

Estrutura de arquivos do CakePHP
Vamos dar uma olhada o que é o CakePHP fora da caixa. Você que o CakePHP utiliza-se da
requisição básica do MVC, mas não sabe como que os arquivos são organizados.

      app
      cake
      docs
      index.php
Princípios básicos do CakePHP   13


       vendors

Quando você faz o download do CakePHP, você verá que possui quatro pastas principais. A
pasta app será o lugar da sua mágica: aqui serão guardados os arquivos da sua aplicação. A
pasta cake é onde a mágica acontece. Faça um compromisso pessoal de não editar os arquivos
desta pasta! Nós não ajudamos você se você modificá-la. A pasta docs contém as informações
de alterações, licença, etc. Finalmente, a pasta vendors é onde você colocará aplicativos de
terceiros para utilizar na aplicação, por exemplo, jQuery, prototype, FCKEditor, etc.

Estrutura do diretório App
A pasta app do CakePHP é onde normalmente você colocará sua aplicação em
desenvolvimento, Vamos dar uma olhada mais de perto dentro desta pasta.

                           Tabela 1. Descrição dos diretórios de app

Diretório     Descrição
config        Contém os arquivos de configuração. Detalhes das conexões ao banco de dados,
              bootstrapping, arquivos de configuração do núcleo e outros devem ser
              armazenados aqui.
controllers   Contém os controllers da sua aplicação e seus components.
locale        Guarda os arquivos com as strings para internacionalizaçao.
models        Contém os models, behaviors e datasources da sua aplicação.
plugins       Contém os pacotes de plugins.
tmp           Aqui é onde o CakePHP armazena os arquivos temporários. Os dados atuais são
              armazenados onde você tenha configurado o CakePHP, mas esta pasta
              normalmente é usada para guardar a descrição dos models, logs e outras
              informações, como as das sessões.
vendors       Qualquer classe ou biblioteca de terceiro deve ser armazenada aqui. Para fazer
              um acesso rápido e fácil, use a função vendors(). Você pode achar que esta
              pasta é redundante, já que existe uma pasta com mesmo nome no nível
              superior da estrutura. Nós vamos ver diferenças entre estas duas pastas quando
              discutirmos sobre manipulação de múltiplas aplicações e sistemas mais
              complexos.
views         Arquivos de apresentação devem vir aqui: elements, páginas de erro, helpers,
              layouts e arquivos de views.
webroot       No modo de produção, esta pasta deve servir como a pasta raiz da sua
              aplicação. Dentro desta pastas são guardados os arquivos públicos, como estilos
              CSS, imagens e arquivos de JavaScript.

Requisição típica do CakePHP
Nós cobrimos os ingredientes básicos no CakePHP, então vamos ver como cada objeto
funciona em uma completa requisição. Continuando com nossa requisição original de
exemplo, vamos imaginar que nosso amigo Ricardo tenha clicado no link em “Comprar um
bolo personalizado agora!” da sua aplicação CakePHP.
Princípios básicos do CakePHP       14




Figura 2. Requisição típica no CakePHP. Em preto, elemento necessário; Em cinza, elemento opcional;
                                          Em azul, callback

   1. Ricardo clica no link apontando para http://www.exemplo.com.br/cakes/buy, e seu
      navegador faz a requisição ao seu servidor de web;
   2. O roteador processa a URL, extraindo os parâmetros desta requisição: o controller,
      action (ação) e qualquer outro argumento que vai afetar na lógica do negócio durante
      esta requisição;
   3. Usando rotas, a requisição da URL é mapeada para a action do controller (um método
      específico da classe do controller). Neste caso, o método buy() do CakesController. O
      callback beforeFilter() do controller é chamado antes de qualquer action do controller
      ser executada;
   4. O controller pode usar métodos para ter acesso aos dados da aplicação. Neste
      exemplo, o controller usa o model para ver no banco de dados as últimas compras de
      Ricardo. Qualquer callback aplicável do modelo, behaviors e DataSources podem ser
      aplicados durante esta operação. Enquanto um model não é necessário, todos os
      controllers do CakePHP inicialmente requisitam de pelo menos um model;
   5. Depois do model ter adquiridos os dados, ele retorna-os ao controller. Podem ser
      aplicados callbacks no model;
   6. O controller pode usar components para refinar os dados ou efetuar outras operações
      (manipular sessões, autenticação ou enviar e-mails, por exemplo);
   7. Uma vez que o controller tenha usado os models e os components para preparado os
      dados suficientemente, estes dados são repassados as views usando o método set() do
      controller. Callbacks dos controllers podem ser aplicados antes dos dados serem
      enviados. A lógica da view é efetuada, podendo incluir elements ou helpers. Por
      padrão, as views são sempre renderizadas dentro de um layout;
   8. Além disso, callbacks dos controllers (como afterFilter) pode ser aplicado. Para
      completar, o código renderizado pela view vai para o navegador do Ricardo.
Princípios básicos do CakePHP      15


Convenções CakePHP
Nós somos grandes fãs de convenções nas configurações. Enquanto isso toma um pouco de
tempo para aprender as convenções do CakePHP, você ganha tempo em um longo processo:
seguindo as convenções, você ganha funcionalidades gratuitamente e livra-sede madrugas de
manutenção de arquivos de configuração. Convenções também fazem com que o sistema
fique uniformemente desenvolvido, permitindo outros desenvolvedores o ajudem mais
facilmente.

Convenções no CakePHP tem sido produzida por anos de experiência em desenvolvimento
web e boas práticas. Enquanto nós sugerimos você a usar essas convenções enquanto
desenvolve em CakePHP, nós devemos mencionar que muitos desses princípios são facilmente
sobrescritos por alguma coisa que é especialmente passado quando trabalha-se com sistemas
legados.

Convenções de arquivos e nome de classes
Em geral, nome dos arquivos são sublinhados, enquanto nome de classes são CamelCased, ou
seja, primeiras letras das palavras em maiúsculo. A classe KissesAndHugsController pode ser
encontrada no arquivo kisses_and_hugs_controller.php, por exemplo.

Porém, o nome da class e seu tipo não são necessariamente encontrados no nome do arquivo.
A classe EmailComponent é encontrada no arquivo chamado email.php e a classe HtmlHelper
é encontrada no arquivo html.php.

Convenções de modelos
Nome das classes de modelo devem ser no singular e CamelCased. Person, BigPerson e
ReallyBigPerson são todos os exemplos de nomes convencionados para modelos.

Os nomes das tabelas correspondem ao nome do modelo do CakePHP, mas no plural e
sublinhados. As tabelas para os modelos mencionados anteriormente devem ser people,
big_people e really_big_people, respectivamente.

Tabelas associadas, usadas em relações hasAndBelongsToMany entre modelos, devem ser
nomeadas depois dos modelos das tabelas que a compõem, em ordem alfabética
(apples_zebras em vez de zebras_apples). Se sua aplicação possui esse tipo de relação entre os
modelos Tag e Post, o nome deve ser posts_tags.

Convenções de controladores
O nome das classes de controladores são no plural, CamelCased e no final “Controller”.
PeopleController, BigPeopleController e ReallyBigPeopleController são todos os exemplos
convencionais para nome de controladores.

A primeira função que você deve escrever em um controlador deve ser o método index().
Quando alguém requisita um controlador sem ação, o behavior padrão é renderizar o método
index() do controlador. Por exemplo, a requisição para http://www.exemplo.com.br/apples/
mapeia para a chamada da função index() do ApplesController, assim como
http://www.exemplo.com.br/apples/view mapeia para a chamada da função view() no
ApplesController.
Princípios básicos do CakePHP     16


Você também pode alterar a visibilidade das funções do controlador em CakePHP colocando
sublinhados na frente do nome das funções. Se a função do controlador estiver com
sublinhado na frente, a função não será disponibilizada para acesso da web através do
dispatcher, mas estará disponível para uso interno.

Convenções de visões
Os arquivos de template das visões são chamados depois das funções que os controladores
mostram, na forma com sublinhados. A função getReady() da classe PeopleController irá
procurar pelo template da visão em /app/views/people/get_ready.ctp.

O modelo básico é /app/views/controller/underscored_function_name.ctp.

Nomeando os pedaços da aplicação usando as convenções do CakePHP, você ganha
funcionalidades sem luta e proteção configuração. Aqui o exemplo final que vincula as
associações:

      Tabela no banco de dados: “people”
      Classe do Modelo: “Person”, encontrada em /app/models/person.php
      Classe      do      Controlador:       “PeopleController”,   encontrado        em
       /app/controllers/people_controller.php
      Template da Visão: encontrado em /app/views/people/index.ctp

Usando      estas      convenções,     CakePHP       sabe     que     a requisição    para
http://www.exemplo.com.br/people/ mapeia para a chamada da função index() do
PeopleController, onde o modelo Person é automaticamente disponibilizado (e
automaticamente associado a tabela “people” no banco de dados), e renderiza isso para o
arquivo. Nenhuma destas relações foram configuradas por qualquer meio que não seja através
da criação de classes e arquivos que você precise criar em algum lugar.

Agora que você leu os fundamentos do CakePHP, você pode tentar seguir o Tutorial de como
fazer um blog em CakePHP, disponível na parte de Exemplos deste manual.
Desenvolvendo com CakePHP          17




        Parte III.   Desenvolvendo com CakePHP
Requisitos
       Servidor HTTP. Apache com mod_rewrite é preferido, mas não é obrigatório.
       PHP 4.3.2 ou superior. Sim! CakePHP funciona com PHP 4 e PHP 5.

Tecnicamente um banco de dados não é obrigatório, mas nós imaginamos que a maioria das
aplicações irão utilizar um. CakePHP suporte uma variedade de banco de dados:

       MySQL (4 ou superior);
       PostgreSQL;
       Firebird DB2;
       Microsoft SQL Server;
       Oracle;
       SQLite;
       ODBC;
       ADOdb.

Preparativos para instalação
Baixando o CakePHP
Há duas maneiras de pegar uma cópia do CakePHP, Primeiro: você pode baixar o arquivo
(zip/tar.gz/tar.bz2) ou você pode baixar o código do repositório SVN.

Para pegar a cópia estável, visite o site http://www.cakephp.org. Lá haverá um link chamado
“Download Now!” para baixar. Os arquivos do CakePHP também são armazenados no
CakeForge      e    você     pode       visitar   a   página    do     projeto     no   site
http://cakeforge.org/projects/cakephp.

Se      você     quer      os     arquivos      mais    atuais,     verifique      no      site
http://cakephp.org/downloads/index/nightly e verás a última versão estável, porém nem
sempre a última release. Nestas versões incluem correções entre releases. Ou seja, são versões
intermediárias entre releases, mas que são estáveis.

Para     pegar   os    arquivos   direto     do      repositório    SVN,    conecte-se     em
https://svn.cakephp.org/repo/branches/1.2.x.x.

Permissões
O CakePHP usa o diretório /app/tmp para diversas operações. Descritivos dos modelos, fazer
cache de visões e informações das sessões são alguns exemplos.

Assim, tenha certeza que o diretório /app/tmp na instalação do seu cake permite escrita pelo
usuário do servidor de web.
Desenvolvendo com CakePHP         18


Instalação
Instalando o CakePHP pode ser feito simplesmente descompactando o conteúdo no seu
servidor web ou de forma mais complexa e flexível, do jeito que você preferir. Esta seção vais
falar de três maneiras de instalar o CakePHP: desenvolvimento, produção e avançada.

      Desenvolvimento: fácil para começar, URL dos seus aplicativos incluem o diretório de
       instalação do CakePHP e é menos seguro;
      Produção: Requer maior habilidade para configurar o servidor web, porém mais
       seguro e com URLs mais amigáveis;
      Avançada: Com algumas configurações, permite você colocar os diretórios do CakePHP
       em diferentes locais do sistema, possibilitando compartilhar o núcleo do CakePHP
       entre diversas aplicações.

Desenvolvimento
Apenas coloque seus arquivos do CakePHP no diretório público do seu servidor web
(normalmente htdocs, www, public_html). Por exemplo, assumindo que o diretório público do
seu servidor web seja /var/www/html, os arquivos devem ficar desta maneira:

      /var/www/html
           o /cake_1_2
                  /app
                  /cake
                  /docs
                  /index.php
                  /vendors

Para ver a sua aplicação CakePHP, entre no link http://www.exemplo.com/cake_1_2/.

Produção
Para utilizar-se do modelo de produção, você precisará ter privilégios de acessar o diretório
público do servidor web. Escolhendo o modo de produção significa que todo o domínio age
como um único pedido CakePHP.

A disposição dos arquivos no modo de produção fica da seguinte maneira:

      /pasta_para_o_cake/
           o /app
                   /webroot (este diretório deve ser seu diretório público do servidor
                     web)
           o /cake
           o /docs
           o /index.php
           o /vendors

Se sua aplicação está hospedada no Apache, a diretiva DocumentRoot para seu domínio deve
ficar assim:

DocumentRoot /pasta_para_o_cake/app/webroot
Desenvolvendo com CakePHP         19


Para ver sua aplicação CakePHP, entre no link http://www.exemplo.com.br.

Instalação avançada
Aqui estão algumas situações que você escolhe o lugar onde os diretórios do CakePHP vão ficar
no seu sistema. Isto pode ser por causa de uma restrição do sistema ou para compartilhar as
bibliotecas entre diferentes aplicações. Esta seção descreve como espalhar seus diretórios dos
CakePHP no sistema.

Primeiro, note que há três partes principais da sua aplicação CakePHP:

    1. As bibliotecas do núcleo do CakePHP, em /cake;
    2. O código da sua aplicação, em /app;
    3. Os arquivos públicos da sua aplicação, normalmente em /app/webroot.

Cada um desses diretórios pode ser colocado em qualquer lugar do seu sistema, com exceção
do webroot, que precisa estar acessível pelo servidor web. Você pode mover a pasta webroot
para fora do diretório da sua aplicação (app), desde que informe ao Cake onde você vai colocá-
la.

Para configurar sua instalação do Cake, nós vamos ter que fazer algumas alterações no arquivo
/app/webroot/index.php. Aqui existem três constantes que precisaremos editar: ROOT,
APP_DIR e CAKE_CORE_INCLUDE_PATH.

       ROOT deve ser configurada para informar o diretório onde sua aplicação se encontra,
        ou seja, onde está a pasta app;
       APP_DIR deve ser configurada para informar qual a pasta app;
       CAKE_CORE_INCLUDE_PATH deve ser configurada para informar o diretório onde
        estão as bibliotecas do CakePHP (a pasta cake).

Vamos fazer um exemplo para que você veja como funciona a instalação avançada na prática.
Imagine que eu quero que a aplicação funcione como segue:

       As bibliotecas do CakePHP deverão ser colocadas em /usr/lib/cake;
       O diretório público da minha aplicação (webroot) deve ser em /var/www/meusite;
       O diretório da aplicação deve ser /home/eu/meusite.

Com estas configurações, eu preciso editar o meu arquivo webroot/index.php (que no final
deve estar em /var/www/meusite/index.php, neste exemplo) e ver o seguinte:

if (!defined('ROOT')) {
    define('ROOT', DS.'home'.DS.'eu');
}

if (!defined('APP_DIR')) {
    define ('APP_DIR', 'meusite');
}

if (!defined('CAKE_CORE_INCLUDE_PATH')) {
    define('CAKE_CORE_INCLUDE_PATH', DS.'usr'.DS.'lib'.DS.'cake');

           /app/webroot/index.php (parcialmente, comentários foram removidos)
Desenvolvendo com CakePHP         20


É recomendado que você use a constante DS no lugar das barras para entre os diretórios. Isso
previne que não cause erro quando se use a aplicação em sistemas operacionais diferentes,
tornando seu código mais portável.

Caminho de classes adicionais
Em algumas ocasiões é interessante você compartilhar as classes do MVC entre as aplicações
no mesmo sistema. Se você quer um mesmo controller para mesma aplicação, você pode usar
o arquivo bootstrap.php do CakePHP para adicionar estas classes adicionais.

No bootstrap.php, defina algumas variáveis com nomes especiais para fazer com que o
CakePHP olhe nestes diretórios a procura da sua classe:

$viewPaths           =   array();
$controllerPaths     =   array();
$modelPaths          =   array();
$helperPaths         =   array();
$componentPaths      =   array();
$behaviorPaths       =   array();

Cada um dessas variáveis especiais pode ser um conjunto na array com o diretório absoluto
onde estão às classes que você desejar. Tenha certeza que cada diretório especificado inclua
as barras com DS.

Apache e mod_rewrite
Enquanto o CakePHP é construído para trabalhar com o mod_rewrite e vimos que muitos
usuários apanham para conseguir fazer isto funcionar nos seus sistemas, nós lhe daremos
algumas dicas que você pode tentar para tentar rodar corretamente:

      Tenha certeza que o override está habilitado no .htaccess. Em seu httpd.conf, você
       deve olhar na seção que define seu Directory no servidor. Tenha certeza que
       AllowOverride está configurado como All para o diretório correto de DocumentRoot;
      Tenha certeza que você está editando o httpd.conf do sistema antes da configuração
       do usuário ou do site em específico;
      Tenha certeza que o arquivo .htacess está na pasta do CakePHP. Em alguns sistemas
       operacionais ele pode ficar oculto na hora de mover devido a interpretarem o “.”
       como sinônimo de ocultamento. Tenha certeza que sua cópia do CakePHP é do site ou
       repositório oficial do CakePHP e que foi extraído corretamente;
      Tenha certeza que você está carregando o mod_rewrite corretamente. Você pode ver
       algo como LoadModule rewrite_module libexec/httpd/mod_rewirte.so e AddModule
       mod_rewrite.c no seu httpd.conf;
      Se você está instalando no diretório do usuário (http://exemplo.com.br/~username),
       você terá que modificar o arquivo .htaccess no diretório da base da instalação do
       CakePHP. Apenas adicione a linha “RewriteBase /~meuusername/”.

Comece agora!
Tudo bem, vamos ver o CakePHP em ação. Dependendo de qual opção de instalação você
utilizou,  acesse    no    seu     navegador    o     link   http://exemplo.com.br    ou
http://exemplo.com.br/cake_instalado/. Neste ponto, você verá a página padrão do CakePHP
e a mensagem do estado da configuração do seu banco de dados.
Desenvolvendo com CakePHP        21


Parabéns! Você já pode criar sua primeira aplicação CakePHP.

Configuração
Configuração da base de dados
O CakePHP espera que os detalhes de configuração da base de dados estejam no arquivo
“app/config/database.php”. Um exemplo de configuração da base de dados pode ser
encontrado em “app/config/database.php.default”.

A configuração final deve ser parecida com o exemplo abaixo.

var $default = array('driver' => 'mysql',
  'persistent' => false,
  'host' => 'localhost',
  'login' => 'usuarioDB',
  'password' => 'senhaDB',
  'database' => 'basededados',
  'prefix' => '');

                         Exemplo de configuração da base de dados

A conexão $default é usada a menos que outra configuração seja especificada pela
propriedade $useDbConfig em um model. Por exemplo, se minha aplicação tiver uma base de
dados adicional do legacy além do padrão, eu poderia usá-la em meus models criando uma
nova conexão da base de dados de $legacy similar a configuração $default, e ajustando a var
$useDbConfig = 'legacy'; nos models apropriados.

Preencha corretamente os pares de chave/valor na configuração para atender melhor às suas
necessidades.

                           Tabela 2. Configurações da base de dados

Chave       Valor
driver      O nome do driver da base de dados para esta configuração. Exemplos: mysql,
            postgres, sqlite, pear-drivername, adodb-drivername, mssql, oracle, ou odbc.
persistent  Se usará ou não uma conexão persistente com a base de dados.
host        O nome do servidor da base de dados (ou endereço IP).
login       O usuário desta conta.
password    A senha desta conta.
database    O nome da base de dados que esta conexão irá usar.
prefix      Esta string será adicionada como prefixo no nome de todas tabelas de sua base
(opcional)  de dados.Se suas tabelas não possuem prefixo, deixe esta string vazia.
port        A porta TCP ou socket Unix usado para conectar com o servidor.
(opcional)
enconding Indica qual caractere definido será usado para enviar indicações SQL ao servidor.
schema      Usado em instalações de base de dados PostgreSQL para especificar qual schema
            usar.
Note que as configurações de prefixo são para as tabelas, não para os models. Por exemplo, se
você criou um relacionamento entre as tabelas Apple e Flavor, o nome será
prefixo_apples_flavors (não prefixo_apples_prefixo_flavors), isso se sua opção de prefixo
estiver como 'prefixo_'.
Desenvolvendo com CakePHP          22


A partir deste ponto, você deve dar uma olhada nas Convenções CakePHP, mostradas neste
manual. A nomenclatura correta para suas tabelas (e o nome de algumas colunas) pode livrar
de algumas implementações e configurações desnecessárias.

Configuração do núcleo

As classes de configuração

Classes de configuração

Variáveis de configuração do núcleo

Constantes de configuração

Configuração de rotas (Routes)
Routes é uma funcionalidade que mapeia URLs em ações do controller. Foi adicionado ao
CakePHP para tornar URL amigáveis mais configuráveis e flexíveis. Não é obrigatório o uso do
mod_rewrite para usar routes, mas usando-o fará sua barra de endereços muito mais limpa e
arrumada.

Routes no CakePHP 1.2 foi ampliada e pode ser muito mais poderosa.

Antes de você aprender sobre como configurar suas próprias rotas, você deveria saber que o
CakePHP vem configurado com um conjunto de rotas padrão. A configuração padrão de rotas
do CakePHP deixará as URLs mais bonitas para qualquer aplicação. Você pode acessar
diretamente uma ação via URL colocando seu nome na requisição. Você pode também passar
parâmetros para suas ações no controller usando a própria URL.

URL para a rota padrão:
http://examplo.com/controller/action/param1/param2/param3

A URL /noticias/ler mapeia para a ação ler() do controller Noticias (NoticiasController), e
/produtos/verInformacoes mapeia para a ação view_informacoes() do controller Produto
(ProdutosController). Se nenhuma ação é especificada na URL, a ação index() será chamada.

A rota padrão também permite passar parâmetros para as ações usando a URL. Uma
requisição /noticias/ler/12 seria equivalente a chamar o método ler(12) no controller Noticias
(NoticiasController), por exemplo.

Uma novidade no CakePHP 1.2 é a possibilidade de usar parâmetros nomeados. Você pode
nomear parâmetros e enviar seus valores usando a URL. Uma requisição
/noticias/ler/titulo:primeira+noticia/categoria:esportes teria como resultado uma chamada a
ação ler() do controller Noticias (NoticiasController). Nesta ação, você encontraria os valores
dos parâmetros título e categoria dentro de $this->passedArgs['titulo'] e $this-
>passedArgs['categoria'] respectivamente.

Alguns exemplos para a rota padrão:

URL mapeadas para as ações dos controladores, usando rotas padrão:

URL: /monkeys/jump
Desenvolvendo com CakePHP          23


Mapeado para: MonkeysController->jump();

URL: /products
Mapeado para: ProductsController->index();

URL: /tasks/view/45
Mapeado para: TasksController->view(45);

URL: /donations/view/recent/2001
Mapeado para: DonationsController->view('recent', '2001');

URL: /contents/view/chapter:models/section:associations
Mapeado para: ContentsController->view();
$this->passedArgs['chapter'] = 'models';
$this->passedArgs['section'] = 'associations';


Definindo suas próprias rotas permite você definir como sua aplicação irá responder a uma
dada URL. Defina suas próprias rotas no arquivo “/app/config/routes.php” usando o método
Router::connect().

O método connect() recebe três parâmetros: a URL que você deseja casar, o valor padrão para
os elementos de rota, e regras de expressões regulares para ajudar a encontrar elementos na
URL.

O formato básico para uma definição de rota é:

Router::connect(
    'URL',
    array('paramName' => 'defaultValue'),
    array('paramName' => 'matchingRegex')
)

Inflexão personalizada
As convenções de nomenclatura do Cake podem ser realmente legais. Você pode nomear sua
tabela big_boxes, seu model BigBox, seu controller BigBoxesController e tudo isso funciona em
conjunto automaticamente. A maneira que o CakePHP usa para associar todas juntas é através
da utilização de inflections (inflexões), que transformam as palavras do singular em plural e
vice-versa.

Existem ocasiões (especialmente para nossos amigos que não falam inglês - nosso caso), onde
você pode rodar o inflector do CakePHP (a classe que pluraliza, singulariza, camelCases e
under_scores) e não funcionar como você gostaria. Se o CakePHP não reconhecer seu Foci ou
Fish, editando o arquivo de configuração personalizada de inflexões você poderá indicar seus
casos especiais. O arquivo de configuração é encontrado em /app/config/inflections.php.

Neste arquivo, você irá encontrar seis variáveis. Cada uma permite você fazer o ajuste fino das
inflections do CakePHP.

Variáveis do inflections.php   Descrição
$pluralRules                   Este array contém regras de expressões regulares para
                               pluralizar casos especiais. A chave do array são os patterns e o
                               valor são as substituições.
Desenvolvendo com CakePHP         24


$uninflectedPlural             Um array que contém palavras que não precisam ser alteradas
                               quando passadas para o plural (lápis, etc.).
$irregularPlural               Um array que contém palavras e seus plurais. A chave do array
                               contém a forma no singular e o valor a forma no plural. Este
                               array deve ser usado para guardar palavras que não seguem as
                               definições em $pluralRules.
$singularRules                 Similar a $pluralRules, contém as regras para singularizar as
                               palavras.
$uninflectedSingular           Similar a $uninflectedPlural, contém as palavras que não
                               contém forma no singular. Por padrão, este array tem o
                               mesmo valor de $uninflectedPlural.
$irregularSingular             Similar a $irregularPlural, contém as palavras que possuem
                               apenas a forma singular.
A versão para língua portuguesa do inflections.php pode ser encontrada nos apêndices, com o
título Inflexão em português.

Configuração de inicialização (bootstrap)

Controllers (Controladores)
Introdução
Um controller (ou controlador) é usado para gerenciar a lógica para uma parte de sua
aplicação. Mais comumente, controllers são usados para gerenciar a lógica de um único model.
Por exemplo, se você está construindo um site para uma padaria online, você pode ter um
ReceitasController e um IngredientesController gerenciando suas receitas e seus ingredientes.
No CakePHP, controllers são nomeados de acordo com o model que manipulam, no plural.

O model Receita é manipulado pelo ReceitasController, o model Produto é manipulado pelo
ProdutosController, e por aí vai.

Seus controllers de aplicação são classes que estendem a classe CakePHP AppController, a qual
por sua vez estende a classe núcleo Controller. A classe AppController pode ser definida em
app/app_controller.php e deve conter métodos que são compartilhados entre todos os seus
controllers. A classe AppController estende o Controller que é uma classe padrão da biblioteca
CakePHP.

Controllers podem incluir qualquer número de métodos que são geralmente referidos como
actions (ações). Actions são métodos do controlador usados para mostrar views (visões). Uma
action é um único método de um controller. O dispatcher (despachante) do CakePHP chama
actions quando uma requisição casa uma URL com uma action do controller. Retornando ao
nosso exemplo da padaria online, nosso ReceitasController pode conter as actions ver(),
compartilhar()     e     buscar().   O     controller   poderia  ser     encontrado      em
app/controllers/receitas_controller.php e poderia conter:

<?php

class ReceitasController extends AppController {
    function ver($id) {
        // a lógica da action vai aqui...
    }
Desenvolvendo com CakePHP          25



     function compartilhar($cliente_id, $receita_id) {
         // a lógica da action vai aqui...
     }

     function buscar($busca) {
         // a lógica da action vai aqui...
     }
}

?>

                           app/controllers/receitas_controller.php

Para que você possa usar o controller de forma mais efetiva em sua aplicação, vamos cobrir
alguns dos principais atributos e métodos fornecidos pelos controllers do CakePHP.

Atributos
Para uma lista completa de atributos do controller e suas descrições visite a API do CakePHP.
Dê uma olhada http://api.cakephp.org/1.2/classController.html.

$name
Usuários PHP4 devem iniciar suas definições de controllers usando o atributo $name. O
atributo $name deve conter o nome do controller. Geralmente é apenas a forma plural do
nome do model. Isso cuida de alguns dos problemas de nomes de classe do PHP4 e ajuda o
CakePHP a encontrar os nomes das coisas.

<?php

class ReceitasController extends AppController {
    var $name = 'Receitas';
}

?>

                       Exemplo de uso do atributo $name do controller

$components, $helpers e $uses
Os próximos atributos de controller usados com maior freqüência dizem ao CakePHP que
helpers (ajudantes), components (componentes), e models você usará junto com o controller
atual. Usar esses atributos disponibiliza essas classes MVC para o controller como variáveis de
classe ($this->NomeDoModel, por exemplo).

Por favor, perceba que cada controller tem algumas dessas classes disponíveis por padrão,
então você pode nem mesmo ter que configurar o seu controller.

Controllers tem por padrão seu model principal disponível. Nosso ReceitasController terá o
model Receita disponível em $this->Receita, e nosso ProdutosController também tem acesso
ao model Produto em $this->Produto.

Os helpers Html e Session estão sempre disponíveis por padrão, assim como o component
Session. Para aprender mais sobre essas classes, lembre-se de dar uma olhada em suas
repectivas sessões mais a frente nesse manual.
Desenvolvendo com CakePHP          26


Vamos ver como chamar um controller CakePHP no qual você planeja usar classes MVC
adicionais.

<?php

class ReceitasController extends AppController {
    var $name = 'Receitas';

     var $uses = array('Receita', 'Usuário');
     var $helpers = array('Html', 'Ajax');
     var $components = array('Session', 'Email');
}

?>

Quando estiver definindo esses atributos, tenha certeza de incluir as classes padrão (como
Html no array $helpers, por exemplo) se você pretende usá-los.

Relativo à página: $layout e $pageTitle
Alguns poucos atributos existem nos controllers CakePHP que dão maior controle sobre como
suas views são embutidas em um layout.

O atributo $layout pode conter o nome do layout salvo em /app/views/layouts. Você
especifica um layout atribuindo ao atributo $layout o nome do arquivo de layout menos a
extensão .ctp. Se esse atributo não for definido, o CakePHP renderiza o layout default
(padrão). Se você não definiu um em /app/views/default.ctp, o layout default do núcleo do
CakePHP será renderizado.

<?php

class RecipesController extends AppController {
    function quickSave() {
        $this->layout = 'ajax';
    }
}

?>

                      Usando $layout para definir um layout alternativo

O atributo $pageTitle do controller torna possível definir o título da página renderizada. Para
que isso funcione apropriadamente, seu layout precisa ter embutido a variável
$title_for_layout entre as tags <title> no cabeçalho do documento HTML.

Apenas atribua à $pageTitle a string que você quer ver no <title> do seu documento.

Atributos dos parâmetros ($params)
Parâmetros do controller estão disponíveis em $this->params no seu controller CakePHP. Essa
variável é usada para dar acesso à informação sobre a requisição atual. O uso mais comum do
$this->params é obter acesso à informação que foi enviada ao controller via operações POST
ou GET.

        $this->params['form']
Desenvolvendo com CakePHP          27


              o   Qualquer dado do POST de qualquer formulário é guardado aqui, incluindo
                  também informação encontrada em $_FILES.
         $this->params['bare']
              o Guarda 1 se o layout atual está vazio, 0 se não.
         $this->params['isAjax']
              o Guarda 1 se o layout atual é 'ajax', 0 se não. Essa variável só é configurada se o
                  component RequestHandler está sendo usado no controller.
         $this->params['controller']
              o Guarda o nome do controller atual manipulando a requisição. Por exemplo, se
                  a URL /posts/ver/1 foi requisitada, $this->params['controller'] será igual à
                  'posts'.
         $this->params['action']
              o Guarda o nome da action atual manipulando a requisição. Por exemplo, se a
                  URL /posts/ver/1 é requisitada, $this->params['action'] será igual 'ver'.
         $this->params['pass']
              o Guarda a query string GET passada com a requisição atual. Por exemplo, se a
                  URL /posts/ver/?var1=3&var2=4 foi requisitada, $this->params['pass'] será
                  igual à '?var1=3&var2=4'.
         $this->params['url']
              o Guarda a URL atual requisitada, com os pares chave-valor das variáveis GET.
                  Por exemplo, se a URL /posts/view/?var1=3&var2=4 foi chamada, $this-
                  >params['url'] conterá:

    [url] => Array
(
       [url] => posts/view
       [var1] => 3
       [var2] => 4
)

         $this->data
              o Usado para manipular os dados POST enviados dos formulários FormHelper ao
                  controller.

// O FormHelper é usado para criar um elemento form:
$form->text('Usuario.primeiro_nome');

// Quando rederizado, se parece com:
<input name="data[Usuario][primeiro_nome]" value="" type="text" />

// Quando o formulário é enviado para o controller via POST,
// os dados são mostrados em $this->data

// O primeiro nome pode ser encontrado aqui:
$this->data['Usuario']['primeiro_nome'];

Outros atributos
Ainda que você possa dar uma olhada nos detalhes de todos os atributos de controllers na API,
existem outros atributos de controllers que merecem suas próprias sessões no manual.
Desenvolvendo com CakePHP          28


O atributo $cacheAction serve para criar cache das views, e o atributo $paginate é usado para
criar a paginação padrão para o controller. Para mais informação sobre como usar esses
atributos, dê uma olhada em suas respectivas sessões mais a frente nesse manual.

Métodos
Para uma lista completa de métodos do controller e suas descrições visite a API CakePHP. Dê
uma olhada http://api.cakephp.org/1.2/class_controller.html.

Interagindo com as visões
     set(string $var, mixed $value)

O método set() é a principal forma de enviar dados do seu controller para sua view. Uma vez
que você usou set(), a variável pode ser acessada na sua view.

// Primeiro você passa os dados do controller:

$this->set('cor', "pink");

// Então, na view, você pode utilizar os dados:

<p>Você selecionou a cor <?php echo $cor; ?> para colorizar o cake.</p>

                                     Exemplo de uso do set()

O método set() também pega um array associativo como seu primeiro parâmetro. Esse pode
ser geralmente um caminho rápido para atribuir um grupo de informações para a view.
Perceba que os índices de seu array sofrerão inflection antes de serem atribuídos à view
('indice_com_underline' se torna 'indiceComUnderline', etc.):

$dados = array(
    'cor' => 'pink',
    'tipo' => 'açucar',
    'preco_base' => 23.95
);

// fazem $cor, $tipo, e $precoBase
// disponíveis na view:

$this->set($dados);



       render(string $action, string $layout, string $file)

O método render() é automaticamente chamado ao final de cada action do controller
requisitada. Esse método executa toda a lógica da view (usando dados que você forneceu
usando o método set()), insere a view dentro do layout e o serve de volta para o usuário final.

O arquivo de view padrão renderizado é determinado por convenção. Se a action buscar() do
ReceitasController é requisitada, o arquivo de view /app/views/receitas/buscar.ctp será
renderizado.
Desenvolvendo com CakePHP       29


Ainda que o CakePHP vá automaticamente chamá-lo (a menos que você configure $this-
>autoRender para false) depois de cada lógica de action, você pode usá-lo para especificar um
arquivo de view alternativo configurando o nome da action no controller usando $action. Você
pode também especificar um arquivo alternativo um terceiro parâmetro, $file. Quando usar
$file, lembre-se de utilizar um pouco das constantes globais do CakePHP (como a VIEWS).

O parâmetro $layout permite especificar o layout na qual a view é renderizada.

Fluxo de controle
    redirect(string $url, integer $status, boolean $exit)

O método de controle de fluxo que você vai usar com maior freqüência é o redirect(). Esse
método pega seu primeiro parâmetro na forma de uma URL relativa CakePHP. Quando um
usuário fez uma compra com sucesso, você provavelmente irá redirecioná-lo para a tela de
recibo.

function comprar() {

    // A lógica para finalizar a compra vai aqui...

    if($sucesso) {
        $this->redirect('/compras/obrigado');
    } else {
        $this->redirect('/compras/confirmar');
    }
}

                                 Exemplo de uso do redirect()

O segundo parâmetro do redirect() lhe permite definir um código de status HTTP para
acompanhar o redirecionamento. Você pode querer usar 301 (movido permanentemente) ou
303 (veja outro), dependendo da natureza do redirecionamento.

Esse método não chama exit() depois de redirecionar a menos que você configure o terceiro
parâmetro para true.

       flash(string $message, string $url, integer $pause)

Similarmente, o método flash() é usado para direcionar o usuário para uma nova página depois
de uma operação. O método flash() é diferente pelo fato de mostrar uma mensagem antes de
passar o usuário para uma outra URL.

O primeiro parâmetro deve guardar a mensagem a ser mostrada, e o segundo parâmetro é
uma URL relativa CakePHP. CakePHP vai mostrar a mensagem na variável $message, por um
tempo definido em segundos na variável $pause antes de direcionar o usuário.

Para mensagens flash dentro da página, dê uma olhada no método setFlash() do component
Session.

Callbacks
Controllers CakePHP vem com callbacks para inserir lógica exatamente antes ou depois das
actions serem rederizadas.
Desenvolvendo com CakePHP        30


       beforeFilter()

Essa função é executada antes de qualquer action no controller. É o lugar ideal para checar
uma sessão ativa ou inspecionar permissões.

       beforeRender()

Chamada após a lógica da action do controller, mas antes da view ser renderizada. Esse
callback não é usado geralmente, mas pode ser necessário se você está chamando render()
manualmente antes do final de uma dada action.

       afterFilter()

Chamada depois de toda action do controller.

       afterRender()

Chamada depois que uma action tiver sido renderizada.

Outros métodos
    constructClasses()

Esse método carrega os models requeridos pelo controller. Esse processo de carregamento é
feito pelo CakePHP normalmente, mas o método é uma boa quando estiver acessando
controllers de diferentes perspectivas. Se você precisa do CakePHP em um script de linha de
comando ou outro uso de fora, constructClasses() pode ser uma boa.

       referrer()

Retorna a URL referida pela requisição atual.

       disableCache()

Usado para dizer ao navegador do usuário não fazer cache dos resultados na requisição atual.
Isso é diferente do cache da view, coberto no capítulo anterior.

       postConditions(array $data, mixed $op, string $bool, boolean $exclusive)

Use esse método para tornar um grupo de dados enviados por POST (de inputs compatíveis
com o helper Html) em um grupo de condições de busca para o model. Essa função oferece um
atalho rápido para criar lógica de busca. Por exemplo, um usuário administrativo pode querer
ser capaz de buscar compras para saber quais itens precisam ser enviados. Você pode criar um
rápido formulário baseado no model Compra. Então a action do controller pode usar os dados
enviados do formulário para criar as condições de busca.

function index() {
    $c = $this->Compras->findAll($this->postConditions($this->data));
    $this->set('compras', $c);
}
Desenvolvendo com CakePHP         31


Se $this->data['Compra']['destino'] é igual a “Padaria da Cidade Velha”, postConditions
converte essa condição para um array compatível para uso no método NomeDoModel-
>findAll(). Nesse caso, array(“Compra.destino” => “Padaria da Cidade Velha”).

Se você quer usar um operador SQL diferente entre os termos, forneça-os usando o segundo
parâmetro.

/*
Conteúdo de $this->data
array(
    'Compra' => array(
        'num_de_itens' => '4',
        'fornecedor' => 'Trigo Integral LTDA'
    )
)
*/

// Vamos pegar compras que tem ao menos 4 itens e contém 'Trigo Integral
LTDA'
$c = $this->Compra->findAll($this->postConditions(
    $this->data,
    array('>=', 'LIKE')
));

O índice nas especificações de operadores é a ordem das colunas no array $this->data. Já que
num_de_itens é o primeiro, o operador >= aplica-se a ele.

O terceiro parâmetro lhe permite dizer ao CakePHP que operador booleano SQL usar entre as
condições de busca. Strings com 'AND', 'OR', e 'XOR' são todos valores válidos.

Finalmente, se o último parâmetro está configurado para true, e o parâmetro $op é um array,
os campos não incluídos em $op não serão incluídos nas condições retornadas.

      cleanUpFields(string $modelClass = null)

Esse método de conveniência concatena as várias partes de datas em $this->data antes de
salvar. Se você tem inputs de data do helper Form, esse método concatena o ano, mês, dia e
hora em uma string mais compatível com banco de dados.

Esse método usa o model padrão do controller (por ex.: o model Cookie para o controller
CookiesController) como alvo para a concatenação, mas uma classe alternativa pode ser usada
como primeiro parâmetro.

      paginate()

Esse método é usado para paginar os resultados divididos pelos seus models. Você pode
especificar tamanhos de páginas, condições de busca do model e mais. Detalhes sobre esse
método mais a frente. Dê uma olhada no capítulo de paginação mais a frente nesse manual.

      requestAction(string $url, array $options)

Essa função chama uma action de controller de qualquer lugar e retorna os dados dessa action.
A       $url     passada       é       uma        URL        relativa      ao       CakePHP
Desenvolvendo com CakePHP         32


(/nomedocontroller/nomedaaction/parametros). Se o array $options incluir um valor de
returno. AutoRender é automaticamente configurada para true para a action do controller,
tendo a requestAction te levando para a view totalmente renderizada.

Nota: apesar de ser possível usar requestAction() para pegar uma view totalmente
renderizada, a perda performance que você obtém passando por toda a camada da view
novamente na realidade não faz valer a pena. O método requestAction() é melhor usado em
conjunto com elements - como um caminho para enviar lógica de negócio para um element
antes da renderização.

Primeiro, vamos ver como pegar dados da action do controller. Primeiro, nós precisamos criar
a action do controller que retorna algum dado que precisamos em vários lugares através da
aplicação:

// Aqui está nosso controller simples:

class UsuariosController extends AppController {
    function pegarListaDeUsuarios() {
        return $this->Usuario->findAll("Usuario.ativo = 1");
    }
}

Imagine que nós precisamos criar uma simples tabela mostrando os usuários ativos no
sistema. Ao invés de duplicar o código de geração de lista em outro controller, nós podemos
pegar dados do UsuariosController->pegarListaDeUsuarios() ao invés de usar requestAction();

class ProdutosController extends AppController {
    function mostrarProdutosDoUsuario() {
        $this->set(
            'usuarios',
            $this->requestAction('/usuarios/pegarListaDeUsuarios')
        );

         // Agora a variável $usuarios na view vai ter dados do
         // UsuariosController::pegarListaDeUsuarios().
    }
}

Se você tem um element na sua aplicação que não é estático, você pode querer usar
requestAction() para enviar lógica equivalente à do controller para o element a medida em que
você o injeta nas suas views. Apesar de elements sempre tem acesso a qualquer variável da
view que o controller passou, essa é uma forma de passar dados para o element vindos de
outro controller.

Se você criou uma action do controller que fornece a lógica necessária, você pode pegar dados
e passá-lo para o segundo parâmetro do método renderElement() da view usando
requestAction().

<?php
echo $this->renderElement(
    'usuarios',
    $this->requestAction('/usuarios/pegarListaDeUsuarios')
);
Desenvolvendo com CakePHP          33


?>

Se o array '$options' contiver um valor “return”, a action do controller será renderizada dentro
de um layout vazio e retornada. Dessa forma, a função requestAction() é útil também em
situações Ajax onde um pequeno elemento de uma view precisa ser preenchido antes ou
durante uma atualização Ajax.

Components (Componentes)
Introdução
Components (Componentes) são pacotes com funções lógicas que são usadas para serem
compartilhadas entre os controllers. Se você está querendo copiar e colar coisas entre os
controllers, você pode criar funcionalidades em components para isso.

O CakePHP já vem com um conjunto de components para os mais diversos usos, por exemplo:

        Segurança
        Sessões
        Lista de controle de acessos (ACL)
        E-mails
        Cookies
        Autenticação
        Manipulação de requisições

Cada um dos components será explicado em outros capítulos. Por enquanto, mostraremos
apenas como criar seus próprios components. Criando components ajuda a manter o código do
controller limpo e permite que você reuse o código entre os projetos ou controllers.

Construindo componentes personalizados
Suponha que sua aplicação online precisa utilizar funções complexas de matemática em
diversas partes da aplicação. Poderíamos, então, criar um component para que esta lógica seja
compartilhada entre diversos controllers.

O primeiro passo é criar um arquivo para o component e uma classe. Crie o arquivo em
/app/controllers/components/math.php. A estrutura básica do arquivo do component é
similar a apresentada abaixo.

<?php

class MathComponent extends Object {
    function doComplexOperation($amount1, $amount2) {
        return $amount1 + $amount2;
    }
}

?>

Quando seu component estiver criado, nós podemos utilizá-lo nos controllers da aplicação
colocando o nome do component no vetor da variável $components:

// Isso faz com que o novo component possa ser acessado usando $this->Math
Desenvolvendo com CakePHP          34



var $components = ('Math', 'Session');

Acessando classes do MVC de dentro dos componentes
Para ter acesso a instância do controlador dentro do seu novo component, você precisa
implementar o método startup(). Este é um método especial que trás a referência do
controller como primeiro parâmetro e esta função é chamada automaticamente depois da
função beforeFilter() do controller. Se por alguma razão você não quer que o método startup()
seja executado quando o controller é instanciado, defina o valor da variável $disableStartup
para true.

Se você deseja inserir uma lógica antes que o controller seja chamado, use o método initialize()
no seu component.

<?php

class MathComponent extends Object {
    // chamado antes de Controller:beforeFilter()
    function initialize() {

     }

     // chamado depois de Controller::beforeFilter()
     function startup(&$controller) {

     }

     function doComplexOperation($amount1, $amount2) {
         return $amount1 + $amount2;
     }
}

?>

Você pode também querer utilizar outros components dentro de um component
personalizado. Para isso, basta criar a variável $components na classe (assim como você faria
em um controller) como um array que contenha os nomes dos components que você deseja
utilizar.

Models (Modelos)
Introdução

Campos mágicos

Atributos

Métodos

Associações

Introdução
Um dos mais poderosos recursos do CakePHP é o mapeamento relacional fornecido pelos
models. No CakePHP, as ligações entre os models são manipuladas através de associações.
Desenvolvendo com CakePHP   35


Definir as relações entre os diversos objetos em sua aplicação deve ser um processo natural.
Por exemplo: em uma base de dados de receitas, uma receita pode ter muitas opiniões,
opiniões têm um único autor, e os autores podem ter muitas receitas. Definir a forma como
estas relações trabalham permite o acesso aos seus dados de uma forma intuitiva e poderosa.

O objetivo desta seção é para mostrar-lhe como planejar, definir, utilizar as associações entre
os models no CakePHP. Porque a forma mais comum de armazenamento em aplicações web é
uma base relacional, a maior parte daquilo que nós vamos cobrir neste manual será, em um
banco de dados com um contexto relacionado.

Os quatro tipos de associação no CakePHP são: hasOne, hasMany, belongsTo, e
hasAndBelongsToMany (HABTM).

                                  Tabela 3. Tipos de associações possíveis

Tipo de associação         Exemplo
hasOne                     Um usuário tem um perfil.
hasMany                    Usuários em um sistema pode ter várias receitas.
belongsTo                  Uma receita pertence a um usuário.
hasAndBelongsToMany Receitas tem, e pertencem a muitas tags1.
Associações são definidas através da criação de uma classe variável com o nome da associação
que você está definindo. A classe variável às vezes pode ser tão simples como uma string, mas
pode ser tão completa como um array multidimensional utilizado para definir associações
específicas.

<?php

class User extends AppModel {
    var $name = 'User';
    var $hasOne = 'Profile';
    var $hasMany = array(
        'Recipe' => array(
            'className' => 'Recipe',
            'conditions' => 'Recipe.approved = 1',
            'order'       => 'Recipe.created DESC'
        )
    );
}

?>

hasOne
Vamos criar um model chamado User que tenha a relação hasOne com o model Profile.

Primeiro, suas tabelas da base de dados devem ser introduzidas corretamente. Para uma
relação hasOne trabalhar, uma tabela tem de incluir uma chave estrangeira que aponta para
um registro na outra. Neste caso, a tabela profiles deverá conter um campo chamado user_id.
O padrão básico é:

HasOne: os *outros* models contêm a chave estrangeira.

1
    Tag: palavra-chave ou etiqueta, neste contexto significa palavra-chave.
Desenvolvendo com CakePHP         36



Apple hasOne Banana => bananas.apple_id
User hasOne Profile => profiles.user_id
Doctor hasOne Mentor => mentors.doctor_id

O arquivo do model User será salvo em “/app/models/user.php”. Para definir a associação
“User hasOne Profile”, adicione a propriedade $hasOne a classe do model. Lembre-se de ter
um model Profile em “/app/models/profile.php”, ou a associação não irá funcionar.

<?php

class User extends AppModel {
    var $name = 'User';
    var $hasOne = 'Profile';
}

?>

Existem duas formas de descrever essa relação nos seus models. O método mais simples
consiste em definir o atributo $hasOne para uma string contendo o nome da classe do model
associado, como fizemos anteriormente.

Se você precisar de mais controle, você pode definir suas associações usando um array. Por
exemplo, você pode querer classificar linhas relacionadas em ordem decrescente, de acordo
com uma data, ou você pode querer limitar a associação para incluir apenas alguns registros.

<?php

class User extends AppModel {
    var $name = 'User';
    var $hasOne = array(
        'Profile' => array(
            'className'     => 'Profile',
            'conditions'    => 'Profile.published = 1',
            'dependent'     => true
        )
    );
}

?>

As possíveis chaves do array para associações hasOne são:

className: o nome da classe do model a ser associado ao model atual. Se você estiver
definindo um relacionamento “User hasOne Profile”, o valor da chave className deve ser
igual a 'Profile';

foreignKey: o nome da chave estrangeira encontrada no outro model. Isto é especialmente útil
se você precisa definir múltiplos relacionamentos hasOne. O valor padrão para esta chave é o
nome no singular do outro model, seguida de “_id”.

conditions: Um fragmento SQL utilizado para filtrar registros relacionados do model. É uma
boa prática a utilização dos nomes dos modelos nos fragmentos SQL: “Profile.approved = 1” é
sempre melhor do que apenas “approved = 1”.
Desenvolvendo com CakePHP        37


fields: A lista de campos da tabela a serem recuperados quando os dados do model associado
são coletados. Retorna todos os campos por padrão.

dependent: Quando true, e o método delete() do model é chamado com o parâmetro cascade
(cascata) para true, os registros associados do model também são apagados. Neste caso,
defini-lo true, a exclusão do User também vai apagar o seu Profile associado.

Uma vez que esta associação tenha sido definida, operações de busca sobre o modelo User
também vai buscar um registro relacionado de Profile, se existir:

// Exemplo de resultados de uma chamada $this->User->find();

Array
(
    [User] => Array
        (
            [id] => 121
            [name] => Gwoo the Kungwoo
            [created] => 2007-05-01 10:31:01
        )
    [Profile] => Array
        (
            [id] => 12
            [user_id] => 121
            [skill] => Baking Cakes
            [created] => 2007-05-01 10:31:01
        )
)

belongsTo
Agora que temos o acesso aos dados do Profile pelo model User, vamos definir uma associação
belongsTo no model Profile, a fim de obter acesso aos dados relacionados de User. A
associação belongsTo é um complemento natural à associações hasOne e hasMany : ele nos
permite ver os dados da outra direção.

Quando você estiver fazendo suas tabelas na base de dados, com um relacionamento
belongsTo, seguir esta convenção:

belongsTo: O model *atual* contém a chave estrangeira.

Banana belongsTo Apple          => bananas.apple_id
Profile belongsTo User          => profiles.user_id
Mentor belongsTo Doctor         => mentors.doctor_id

Se uma tabela contém uma chave estrangeira, ela faz relacionamento belongsTo.

Podemos definir a associação belongsTo no nosso model Profile em “/app/models/profile.php”
usando a sintaxe de string como segue:

<?php

class Profile extends AppModel {
    var $name = 'Profile';
    var $belongsTo = 'User';
}
Desenvolvendo com CakePHP       38



?>

As possíveis chaves do array para associações belongsTo são:

className: o nome da classe do model a ser associado ao model atual. Se você estiver
definindo um relacionamento “Profile belongsTo User”, o valor da chave className deve ser
igual a 'User';

foreignKey: O nome da chave estrangeira encontrada no outro model. Isto é especialmente
útil se você precisa definir múltiplos relacionamentos belongsTo. O valor padrão para esta
chave é o singular do nome do outro model, seguida de '_id'.

conditions: Um fragmento SQL utilizado para filtrar registros relacionados do model. É uma
boa prática a utilização dos nomes dos models nos fragmentos SQL: “User.active = 1” é sempre
melhor do que apenas “active = 1”.

fields: A lista de campos da tabela a serem recuperados quando os dados do model associado
são coletados. Retorna todos os campos por padrão.

Uma vez que esta associação tenha sido definida, as operações de busca sobre o model Profile
também vai buscar um registro ligado ao registro de User se existir:

// Exemplo de resultados de uma chamada $this->Profile->find().

Array
(
   [Profile] => Array
        (
            [id] => 12
            [user_id] => 121
            [skill] => Baking Cakes
            [created] => 2007-05-01 10:31:01
        )
    [User] => Array
        (
            [id] => 121
            [name] => Gwoo the Kungwoo
            [created] => 2007-05-01 10:31:01
        )
)

hasMany
Próximo passo: definir uma associação “User hasMany Comment”. A associação hasMany nos
permitirá buscar comentários de um usuário quando faz uma operação de busca no model
User.

Quando você estiver fazendo suas tabelas na base de dados, com um relacionamento
hasMany, seguir esta convenção:

hasMany: os *outros* models contêm a chave estrangeira.

User hasMany Comment          => Comment.user_id
Cake hasMany Virtue           => Virtue.cake_id
Desenvolvendo com CakePHP         39


Product hasMany Option        => Option.product_id

Podemos definir a associação hasMany no nosso model User /app/models/user.php usando a
sintaxe string como segue:

<?php

class User extends AppModel {
    var $name = 'User';
    var $hasMany = 'Comment';
}

?>

Nós também podemos definir uma relação mais específica utilizando sintaxe de array:

<?php

class User extends AppModel {
    var $name = 'User';
    var $hasMany = array(
        'Comment' => array(
            'className'      => 'Comment',
            'foreignKey'     => 'user_id',
            'conditions'     => 'Comment.status = 1',
            'order'     => 'Comment.created DESC',
            'limit'         => '5',
            'dependent'=> true
        )
    );
}

?>

As possíveis chaves do array para associações hasMany são:

className: o nome da classe do model a ser associado ao model atual. Se você estiver
definindo um relacionamento “User hasMany Comment”, a chave className deve ser igual
“Comment”.

foreignKey: o nome da chave estrangeira encontrada no outro model. Isto é especialmente útil
se você precisa definir múltiplos relacionamentos hasMany. O valor padrão para esta chave é o
nome do outro model no singular, seguida de “_id”.

conditions: Um fragmento SQL utilizado para filtrar registros no model relacionado. É uma boa
prática a utilização nome do model nos fragmentos SQL: “Comment.status = 1” é sempre
melhor do que apenas “status = 1”.

fields: A lista de campos a serem recuperados quando os dados do model associado são
coletados. Retorna todos os campos por padrão.

order: Um fragmento SQL que define a classificação para a ordem para o retorno de linhas
associadas.

limit: O número máximo de linhas associadas que você quer que retorne.
Desenvolvendo com CakePHP         40


offset: O número de linhas associadas para saltar sobre (dadas as atuais condições e ordem),
antes de ir buscar e associar.

dependent: Quando true, é possível a eliminação recursiva. Neste exemplo, Os registros de
Comment serão apagados quando o seu associado registro de User for excluído.

Nota: o segundo parâmetro do método Model->delete() deve ser true, a fim de ocorrer a
supressão (eliminação) recursiva.

finderQuery: Uma completa consulta SQL CakePHP que pode-se usar para buscar registros
associados. Isto deve ser utilizado em situações que exijam muito resultado personalizado.

Uma vez que esta associação tenha sido definida, As operações de busca sobre o model User
também vai buscar registros relacionados em Comment se existirem:

// Exemplo de resultados de uma chamada $this->User->find();

Array
(
    [User] => Array
        (
            [id] => 121
            [name] => Gwoo the Kungwoo
            [created] => 2007-05-01 10:31:01
        )
    [Comment] => Array
        (
            [0] => Array
                (
                    [id] => 123
                    [user_id] => 121
                    [title] => On Gwoo the Kungwoo
                    [body] => The Kungwooness is not so Gwooish
                    [created] => 2006-05-01 10:31:01
                )
            [1] => Array
                (
                    [id] => 123
                    [user_id] => 121
                    [title] => More on Gwoo
                    [body] => But what of the Nut?
                    [created] => 2006-05-01 10:41:01
                )
        )
)

Uma coisa para se lembrar é que você precisará de um nova associação “Comment belongsTo
User”, a fim de obter os dados de ambos os sentidos. O que temos esboçado nesta seção lhe
dá poderes para obter os dados dos comentários do usuário. Adicionando a associação
Comment belongsTo User no model Comment lhe dá poderes para obter os dados do usuário a
partir do model Comment - completa a ligação e permitindo que haja o fluxo de informação a
partir de qualquer perspectiva de model.
Desenvolvendo com CakePHP        41


hasAndBelongsToMany (HABTM)
Tudo bem. Neste ponto, você já pode chamar você mesmo de profissional em associações de
models no CakePHP. Você já está bem versado (experiente) nas três associações que ocupam a
maior parte das relações entre objetos.

Vamos resolver o último tipo de relacionamento: hasAndBelongsToMany, ou HABTM. Esta
associação é usada quando você tem dois models que precisam se juntar, várias vezes, muitas
vezes, de muitas formas diferentes.

A principal diferença entre hasMany e HABTM é que a ligação entre os modelos em HABTM
não é exclusiva. Por exemplo, estamos prestes a juntar nosso model Recipe (Receita) com o
model Tag usando HABTM. Anexando a tag “Italian” a minha receita “grandma's Gnocci” não
“esgota” o registro do Tag. Também posso marcar o meu churrasco Honey Glazed Spaghettio's
com a tag “Italian” se eu quiser.

Ligações entre objetos associados com hasMany são exclusivos. Se User hasMany Comment,
um comentário é apenas ligado a um usuário específico. Deixou-se para ganhar.

Avancemos. É preciso criar uma tabela extra no banco de dados para manipular associações
HABTM. Esta nova tabela deve juntar o nome das tabelas associadas, incluindo os nomes de
ambos os models envolvidos, em ordem alfabética. O conteúdo da tabela deve ser de pelo
menos dois campos, cada um com uma chave estrangeira (que devem ser inteiros) apontando
para ambas as chaves primárias dos modelos envolvidos.

HABTM: Requer uma tabela separada que inclui os dois nomes dos models.

Nota: O nome da tabela deve estar em ordem alfabética.

Recipe HABTM Tag     => recipes_tags.recipe_id, recipes_tags.tag_id
Cake HABTM Fan       => cakes_fans.cake_id, cakes_fans.fan_id
Foo HABTM Bar        => bars_foos.foo_id, bars_foos.bar_id

Uma vez que esta nova tabela foi criada, podemos definir a associação HABTM nos arquivos
dos models. Estamos indo saltar diretamente a sintaxe array desta vez:

<?php

class Recipe extends AppModel {
    var $name = 'Recipe';
    var $hasAndBelongsToMany = array(
        'Tag' =>
            array('className'                   => 'Tag',
                 'joinTable'                    => 'recipes_tags',
                 'foreignKey'                   => 'tag_id',
                 'associationForeignKey'        => 'recipe_id',
                 'conditions'                   => '',
                 'order'                        => '',
                 'limit'                        => '',
                 'uniq'                         => true,
                 'finderQuery'                    => '',
                 'deleteQuery'                  => '',
                 'insertQuery'                   => ''
            )
        );
Desenvolvendo com CakePHP         42


}

?>

foreignKey: O nome da chave estrangeira encontrada no outro model. Isto é especialmente
útil se você precisa definir múltiplos relacionamentos HABTM. O valor padrão para esta chave
é o nome do outro model no singular, seguida de “_id”.

associationForeignKey: O nome da chave estrangeira encontrada no model atual. Isto é
especialmente útil se você precisa definir múltiplos relacionamentos HABTM. O valor padrão
para esta chave é o nome do atual model no singular, seguida de “_id”.

conditions: Um fragmento SQL utilizado para filtrar registros no model relacionado. É uma boa
prática a utilização nome do model nos fragmentos SQL: “Recipe.status = 1” é sempre melhor
do que apenas “status = 1”.

fields: A lista de campos a serem recuperados quando os dados do model associado são
coletados. Retorna todos os campos por padrão.

order: Um fragmento SQL que define a classificação para a ordem para o retorno de linhas
associadas.

limit: O número máximo de linhas associadas que você quer que retorne.

offset: O número de linhas associadas para saltar sobre (dadas as atuais condições e ordem),
antes de ir buscar e associar.

dependent: Quando true, é possível a eliminação recursiva. Neste exemplo, Os registros de
Comment serão apagados quando o seu associado registro de User for excluído.

Nota: o segundo parâmetro do método Model->delete() deve ser true, a fim de ocorrer a
supressão (eliminação) recursiva.

finderQuery, deleteQuery, insertQuery: Uma completa consulta SQL CakePHP que pode-se
usar para buscar registros associados. Isto deve ser utilizado em situações que exijam muito
resultado personalizado.

Uma vez que esta associação tenha sido definida, operações de busca sobre o model Recipe
(Receita) também vai buscar registros relacionados em Tag caso existam:

// Exemplo de resultados de uma chamada $this->Recipe->find();

Array
(
    [Recipe] => Array
        (
            [id] => 2745
            [name] => Chocolate Frosted Sugar Bombs
            [created] => 2007-05-01 10:31:01
            [user_id] => 2346
        )
    [Tag] => Array
        (
Desenvolvendo com CakePHP        43


              [0] => Array
                  (
                      [id] => 123
                      [name] => Breakfast
                  )
             [1] => Array
                  (
                      [id] => 123
                      [name] => Dessert
                  )
             [2] => Array
                  (
                      [id] => 123
                      [name] => Heart Disease
                  )
         )
)

Lembre-se de definir uma associação HABTM no model Tag se quiser buscar dados do model
Recipe, quando se utiliza o model Tag para pesquisas.

Salvando dados em tabelas relacionadas (hasOne, hasMany, belongsTo)
Ao trabalhar com models associados, é importante perceber que ao salvar os dados do model
deve sempre ser feita pelo model CakePHP correspondente. Se você está salvando um novo
Post e seus comentários associados, então você deve usar ambos os models Post e Comment
durante a operação de salvamento.

Se nenhum dos registros do model associado, existem ainda no sistema (por exemplo, você
pretende gravar um novo User com seus respectivos registros de Profile ao mesmo tempo),
você precisa primeiro salvar o primário, ou model pai.

Para ter uma idéia de como isso funciona, vamos imaginar que temos uma função no nosso
UsersController que manipula o salvamento de um novo User e seu relacionado Profile. O
exemplo mostrado abaixo, a função irá assumir que você POSTou dados suficientes (usando o
FormHelper) para criar um único usuário e um único perfil.

function add() {
    if (!empty($this->data)) {
        // Podemos salvar os dados de User
        // Deve-se estar em $this->data['User']

         $this->User->save($this->data);

         // Agora nós adicionamos a informação que identifica
         // o usuário da base de dados a $this->data['Profile']
         // e salvamos o Profile.

         // A ID do usuário recém-criado foi definida
         // em $this->User->id.

         $this->data['Profile']['user_id'] = $this->User->id;

         // O salvamento do Profile pode ocorrer no model User
         // Porque a nossa relação "User hasOne Profile", pode acessar
         // o model Profile através do model User:
Desenvolvendo com CakePHP         44



         $this->User->Profile->save($this->data);
    }
}

Como regra geral, quando se trabalha com associações hasOne, hasMany, e belongsTo. Estas
são todas as informações sobre a sua implementação. A idéia básica é obter a chave de um
model e colocá-la no campo chave estrangeira do outro. Por vezes, este poderia envolver a
utilização do atributo $id da classe do model após um save(), mas outras vezes isso pode
envolver apenas recolher o ID de um input hidden em um formulário que é apenas tenha sido
POSTado a uma função do controller.

Salvando dados em tabelas relacionadas (HABTM)
Salvando models que estão associados por hasOne, belongsTo, e hasMany é bastante simples:
basta você preencher o campo chave estrangeira com a ID do model associado. Feito isso,
basta você chamar o método save() sobre o model, e tudo fica ligado corretamente.

Com HABTM, é um pouco complicado, mas temos ido fora da nossa forma a torná-lo o mais
simples possível. Em consonância (concordância), juntamente com o nosso exemplo, vamos
precisar fazer algum tipo de formulário que relaciona tags a receitas. Vamos agora criar um
formulário que gera tags, e associá-las a uma lista de receitas existentes.

Talvez você realmente deseje criar um formulário que cria novas tags e associá-las durante a
execução - mas pelo bem da simplicidade, vamos apenas mostrar-lhe como associá-los e deixá-
lo continuar a partir daí.

Vamos apenas iniciar com a parte do formulário que gera uma tag. Lembra-se de nosso
original exemplo “Recipe HABTM Tags”? O mais simples de HTML pode parecer algo como isto:

<?php echo $form->create('Tag');?>
    <?php echo $form->hidden(
        'Recipe.Recipe',
        array('value' => $recipe_id)
    )
    ?>
    <p><?php echo $form->input('Tag.name');?></p>
    <p><?php echo $form->end('Adicionar Tag');?></p>
</form>

Ligações HABTM são formadas por um campo de formulário, nomeado com o nome do outro
model envolvido na associação HABTM. Neste exemplo, você pode ver o campo hidden
'Recipe/Recipe' cujo valor é definido com a ID da receita que queremos relacionar para a tag
que será salva. A função do controller que trata este formulário poderá ser semelhante a esta:

function add() {
    // Primeiro, vamos obter a ID da tag atual
    $this->Tag->recursive = 0;
    $tag = $this->Tag->findByName($this->data['Tag']['name']);

    // Você pode querer criar a tag aqui se não existir,
    // Mas nós estamos assumindo que ela existe para avançar. :)

    // Definimos esta ID em $this->data, marcando-a como a
Desenvolvendo com CakePHP         45


     // tag que queremos associar.
     $this->data['Tag']['id'] = $tag['Tag']['id'];

     // Definimos a ID da receita em $this->data, marcando-a como a
     // receita que queremos associar.
     $this->data['Recipe']['Recipe'] = array(
         $this->data['Recipe']['Recipe']
     );

     // Salva a associação
     if ($this->Tag->save($this->data)) {
         // Faça alguma coisa quando obter sucesso.
     }
}

Voila, dados dos models estão associados. Para analisar: a fim de salvar relacionamentos
HABTM, preencher $this->data['OutroModelo']['OutroModelo'] com um array contendo a ID
(ou IDs) dos registros que você deseja associar, e salvar o model atual , certificando-se que
$this->data[ModeloAtual]['id'] esteja em vigor.

Criando e removendo relações durante execução
Por vezes, torna-se necessário criar e destruir associações no model durante a execução. Isso
pode acontecer por algum número de razões:

        Você deseja reduzir a quantidade coletada de dados associados, mas todas as suas
         associações estão no primeiro nível de recursão;
        Você quer mudar o modo como uma associação é definida, a fim de ordenar ou filtrar
         dados associados.

Esta criação e destruição de associação é feita usando os métodos bindModel() e
unbindModel() do model CakePHP. Vamos configurar alguns models, para que possamos ver
como bindModel() e unbindModel() trabalham. Nós vamos começar com dois models:

<?php

class Leader extends AppModel {
    var $name = 'Leader';

     var $hasMany = array(
         'Follower' => array(
             'className' => 'Follower',
             'order'     => 'Follower.rank'
         )
     );
}

?>

<?php

class Follower extends AppModel {
    var $name = 'Follower';
}

?>
Desenvolvendo com CakePHP        46


Agora, no LeadersController, podemos usar o método find() do model Leader para buscar um
líder e seus seguidores associados. Como você pode ver acima, a associação em sintaxe de
array no model Leader define um relacionamento “Leader hasMany Follower”. Para fins de
demonstração, vamos usar unbindModel() para remover esta associação em uma função do
controller.

function someAction() {
    // Isto recupera Líderes, e seus seguidores associados
    $this->Leader->findAll();

    // Vamos remover o hasMany ...
    $this->Leader->unbindModel(
        array('hasMany' => array('Follower'))
    );

    // Agora usando a função find() irá retornar
    // Líderes, sem os seus seguidores
    $this->Leader->find();

    // NOTA: unbindModel() afeta somente a mais próxima
    // função find(). Uma nova chamada find() será usada
    // a informação configurada na associação do model.

    // Já utilizando findAll(), após unbindModel(),
    // esta vai buscar Líderes com seguidores
    // associados mais uma vez ...

    $this->Leader->findAll();
}

Mais um lembrete. Removendo ou adicionando associações usando bind e unbindModel() só
funciona para a próxima operação do model, a menos que o segundo parâmetro $reset for
escolhido para true. Se o segundo parâmetro foi escolhido para true, ao vincular este
parâmetro, a funções binds, mantém-se em vigor para o restante dos pedidos ou pesquisas.

Aqui está a base para o uso padrão de unbindModel():

$this->Model->unbindModel(
    array('associationType' => array('associatedModelClassName'))
);

//   associationType =>    O   tipo   de associação             com    o   outro     model
(associatedModelClassName) que você quer remover.

Agora que removida com êxito uma associação durante a execução, vamos adicionar uma.
Nossa como de ainda temos Líderes sem princípios necessitamos alguns Princípios associados.
O arquivo do model para o nosso model Principle está vazio, com exceção para a declaração
var $name. Vamos associar alguns princípios para ao nosso model Leader durante a execução
(mas lembre: apenas servirá a próxima operação de busca). Esta função aparece no
LeadersController:

function anotherAction() {
    // Não há "Leader hasMany Principles" no
    // arquivo do model leader.php,
    // aqui somente vamos encontrar Líderes.
Desenvolvendo com CakePHP         47


    $this->Leader->findAll();

    // Vamos usar bindModel() para adicionar uma nova associação
    // para o model Leader.
    $this->Leader->bindModel(
        array('hasMany' => array(
                'Principle' => array(
                    'className' => 'Principle'
                )
            )
        )
    );

    // Agora que está ligado corretamente,
    // Podemos utilizar uma única função find() para buscar
    // Líderes com seus associados princípios:
    $this->Leader->findAll();
}

Isto é o que você tem. A base para uso do bindModel() é o encapsulamento de uma associação
normal dentro de um array cuja chave é nomeada após o tipo de associação que você está
tentando criar:

$this->Model->bindModel(
        array('associationName' => array(
                'associatedModelClassName' => array(
                    // Aqui você pode usar normalmente as chaves e/ou opções
de associação.
                )
            )
        )
    );

Embora o model recém-vinculado não precise de nenhum tipo de associação na definição do
model dentro do arquivo dele, ele ainda precisa ser introduzido corretamente para que a nova
associação funcione corretamente.

DataSources

Behaviors

Introdução

Usando Behaviors

TreeBehavior

TranslateBehavior

ACLBehavior

Views (Visões)
Templates / Skin
Em CakePHP, você fala com seus usuários através da camada das views. A maior parte do
tempo, suas views estarão mostrando documentos (x)HTML para os navegadores, mas você
Desenvolvendo com CakePHP          48


pode também precisar servir dados AMF para um objeto Flash, responder a uma aplicação
remota via SOAP, ou exportar um arquivo CSV para um usuário.

Os arquivos de view do CakePHP são escritos em PHP comum e tem a extensão padrão de .ctp
(CakePHP Template). Esses arquivos contêm toda a lógica de apresentação necessária para
transformar os dados recebidos do controller em um formato que está pronto para a
audiência.

Arquivos de view são guardados em /app/views/, em um diretório com o nome do controller
que usa os arquivos, e nomeado de acordo com a view a qual corresponde. Por exemplo, a
action   ver()   do     controller Produtos    será  normalmente      encontrada   em
/app/views/produtos/ver.ctp.

A camada da view no CakePHP pode ser feita de algumas diferentes partes. Cada parte tem
diferentes usos, e será coberta em seu capítulo:

      layouts: arquivos view que contém o código da apresentação que é encontrado
       envolvendo muitas interfaces em sua aplicação. A maior parte das views é renderizada
       dentro de um layout;
      elements: pedaços de código pequenos e reutilizáveis. Elements são geralmente
       renderizados dentro de views;
      helpers: essas classes encapsulam lógica da view que é necessária em muitos lugares
       na camada da view. Entre outras coisas, helpers no CakePHP podem ajudá-lo a
       construir formulários, construir funcionalidade Ajax, paginar dados do model, ou servir
       feeds RSS.

Layouts
Um layout contém código de apresentação que envolve uma view. Qualquer coisa que você
quiser ver em todas as suas views deve ser colocada em um layout.

Arquivos de layout devem ser colocados em /app/views/layouts. O layout padrão pode ser
sobrescrito criando um novo layout padrão em /app/views/layouts/default.ctp. Uma vez que
um novo layout foi criado, código de view renderizado pelo controller é colocado dentro do
layout padrão quando a página é renderizada.

Quando você cria um layout, você precisa dizer ao CakePHP onde colocar o código de suas
views. Para tanto, garanta que seu layout tem um lugar para o conteúdo do layout através da
variável $content_for_layout (e opcionalmente, título para o layout através da variável
$title_for_layout). Aqui vai um exemplo do que um layout padrão deve parecer:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><?php echo $title_for_layout?></title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
</head>
<body>

<!-- Se você gostaria que algum tipo de menu seja
Desenvolvendo com CakePHP           49


mostrado em todas as suas views, insira ele aqui -->
<div id="header">
    <div id="menu">...</div>
</div>

<!-- É aqui que eu quero que minhas views apareçam                 -->
<?php echo $content_for_layout ?>

<!-- Adicione um rodapé para cada página mostrada -->
<div id="footer">...</div>

</body>
</html>

Para configurar um título para o layout, é mais fácil fazê-lo no controller, usando a variável de
controller $pageTitle.

class UsuariosController extends AppController {
    function verAtivos() {
        $this->pageTitle = 'Ver Usuários Ativos';
    }
}

Você pode criar quantos layouts você desejar: apenas coloque-os no diretório
/app/views/layouts, e escolha entre eles o ideal para cada action do controller usando a
variável $layout ou a função setLayout(). Controllers que não tenham a variável $layout
configurada usarão o layout padrão.

Por exemplo, se uma sessão do meu site incluir um pequeno espaço para banner, eu posso
criar um novo layout com um pequeno espaço para propaganda e especificá-lo como layout
para todas as actions de controller usando algo como:

class UsuariosController extends AppController {

     var $layout = 'padrao_propag_mini';

     function verAtivos() {
         $this->pageTitle = 'Ver Usuários Ativos';
         $this->layout = 'padrao_propag_mini';
     }

     function verImagem() {
         $this->layout = 'imagem';
         // imprimir a imagem para o usuário
     }
}

CakePHP tem em seu núcleo, dois layouts (além do layout padrão) que você pode usar em suas
aplicações: 'ajax' e 'flash'. O layout Ajax é ótimo para criar respostas Ajax - é um layout vazio (a
maior parte das chamadas ajax requer pouca marcação em retorno, ao invés uma interface
totalmente renderizada). O layout flash é usado para mensagens mostradas pelos métodos
flash() dos controllers.

Três outros layouts - xml, js, e rss - existem no núcleo para acelerar e facilitar servir conteúdo
diferente de text/html.
Desenvolvendo com CakePHP         50


Elements (Elementos)
Muitas aplicações têm pequenos blocos de código de apresentação que precisa ser repetido
de página em página, algumas vezes em diferentes lugares no layout. O CakePHP te ajuda a
repetir partes do seu website que precisam ser reutilizadas. Essas partes reutilizáveis são
chamadas elements. Um element é basicamente uma mini-view que pode ser incluída em
outras views.

Elements vivem no diretório /app/views/elements/, e tem uma extensão .ctp no nome de
arquivo.

Por padrão, elements são estáticos. Você pode dar vida aos seus elements e passar para eles
variáveis da view usando um parâmetro adicional no método renderElement().

// Chamando um element sem parâmetros
// Esse element só contém código estático de view.
<?php echo $this->element('ajuda'); ?>

// Chamando um element passando um array de dados,
// permitindo que o element se comporte dinamicamente.
<?php echo
$this->element(
    'ajuda',
    array('mensagem' => 'Ah, esse texto é realmente muito útil.'));
?>

Nota: Você pode aproveitar o sistema de cache de view do CakePHP se você fornecer “cache”
como true no segundo parâmetro do método element().

// Renderiza o element e faz cache dele por um dia
<?php echo $this->element('ajuda', array('cache' => true)); ?>

Dentro do arquivo element, todos as variáveis estão disponíveis como os nomes dos índices do
array fornecido (muito parecido com como set() funciona no controller com arquivos de view).
No exemplo acima, o arquivo /app/views/elements/ajuda.ctp pode usar a variável
$mensagem.

Uma forma de aproveitar totalmente os elements é usar requestAction(). A função
requestAction() preenche a view com variáveis da action do controller e as retorna como um
array. Isso torna possível aos seus elements agir realmente no estilo MVC. Crie uma action do
controller que prepara as variáveis da view para seus elements e chame requestAction() dentro
do segundo parâmetro de requestElement() para preencher o element com as variáveis de
view vindas do controller.

Elements podem ser usados para fazer a view mais legível, colocando os elementos repetitivos
em seus próprios arquivos. Eles podem também ajudá-lo a reutilizar fragmentos de conteúdo
em sua aplicação.

Helpers (Ajudantes)
Introdução
Helpers (Ajudantes) são classes do tipo component para a camada de apresentação da sua
aplicação. Eles contêm lógica de apresentação que é compartilhada entre muitas views,
Desenvolvendo com CakePHP         51


elements ou layouts. Cada helper estende AppHelper (opcionalmente definido em
/app/app_helper.php), uma classe que guarda qualquer lógica necessária para todos os
helpers.

O propósito desse capítulo é mostrar a você como criar seus próprios helpers, destacar
algumas tarefas básicas que os helpers do CakePHP podem ajudá-lo a realizar.

Você usa helpers em CakePHP tornando os controllers conscientes deles. Cada controller tem
uma variável de classe especial chamada $helpers que mantém uma lista dos helpers
disponíveis para todas as views que esse controller renderiza. Para disponibilizar um helper em
sua view do controller, adicione o nome do helper no array $helpers desse controller.

<?php

class PadeirosController extends AppController {
    var $helpers = array('Form', 'Html', 'Javascript', 'Time');
}

?>

Helpers do CakePHP
O CakePHP tem alguns helpers muito úteis na criação de views. Eles ajudam na criação de
marcação bem formatada (incluindo formulários), ajudam na formatação de texto, datas e
números, e pode até acelerar uma funcionalidade Ajax. Aqui está uma lista rápida dos helpers
com um resumo das suas habilidades. Para mais informação sobre um helper particular, dê
uma olhada em sua respectiva sessão da parte de Helpers internos.

                             Tabela 4. Helpers internos do CakePHP

Helper CakePHP      Descrição
Ajax                Usado também com a biblioteca JavaScript Prototype para criar
                    funcionalidade Ajax nas views. Contém métodos de atalho para
                    arrastar/soltar, formulários ajax & links, observers, e mais.
Cache               Usado internamente para para criar cache do conteúdo das views.
Form                Cria formulários HTML e elementos de formulários com habilidade de
                    auto-popular e manipulam problemas de validação.
Html                Métodos de conveniência para criação de marcação bem formatada.
                    Imagens, links, tabelas, tags de cabeçalho e mais.
Javascript          Usado para escapar valores para uso em JavaScripts, escrever dados para
                    objetos JSON, e formatar blocos de código.
Number              Formatação de números e moedas
Paginator           Paginação de dados do model e organização.
Rss                 Métodos de conveniência para exportar dados XML RSS
Session             Acesso para escrita de valores de sessão nas views
Text                Links automáticos, destaques, e truncamento automático de palavras.
Time                Detecção de proximidade (é o ano quem vem?), formatação de strings
                    (Hoje, 10:30 am) e conversão de zona de tempo.
Xml                 Métodos de conveniência para criar cabeçalhos e elementos XML.
Desenvolvendo com CakePHP       52


Criando helpers
Se um helper interno (ou um mostrado em Cakeforge ou em Bakery) não se adapta a suas
necessidades, helpers são fáceis de fazer.

Vamos dizer que nós queremos criar um helper que pode ser usado para imprimir um tipo
específico de link CSS que você precisa em muitos lugares diferentes em sua aplicação. Para
colocar sua lógica na estrutura de helpers dos CakePHP, você deve criar uma nova classe em
/app/views/helpers. Vamos chamar nosso helper de LinkHelper. O arquivo de classe PHP atual
vai se parecer com isso:

<?php
/* /app/views/helpers/link.php */

class LinkHelper extends AppHelper {
    function editar($titulo, $caminho) {
        // Lógica para criar links especialmente formatados vai aqui...
    }
}

?>

        output(string $string)

Use essa função para enviar qualquer dado de volta para sua view.

function editar($titulo, $caminho) {
    // Use essa função para enviar qualquer dado formatado
    // de volta para sua view:

     return $this->output(
         "<div class="editarContainer">
          <a href="$caminho" class="editar">$titulo</a>
          </div>"
     );
}

Incluindo outros helpers
Você pode querer usar alguma funcionalidade já existente em outro helper. Para tanto, você
pode especificar os helpers que você deseja usar com o array $helper, formatado exatamente
como você faria no controller.

// /app/views/helpers/link.php (usando outros helpers)
class LinkHelper extends Helper {
    var $helpers = array('Html');

     function editar($titulo, $caminho) {
         // Usando o helper HTML para criar
         // dados formatados:

        $link       =    $this->Html->link($titulo,      $caminho,    array('class'     =>
'editar'));

          return $this->output("<div class="editarContainer">$link</div>");
     }
}
Desenvolvendo com CakePHP         53


Usando seus helpers personalizados
Uma vez que você criou seu helper e o colocou em /app/views/helpers/, você estará habilitado
a usá-lo em seus controllers usando a variável especial $helpers.

Assim que seu controller estiver consciente de sua nova classe, você pode usá-la em suas views
acessando uma variável com o nome do helper:

<!-- faz um link usando o novo helper -->
<?php $link->editar('Mudar esta receita', '/receitas/editar/5') ?>

Nota: lembre-se de incluir o HtmlHelper e/ou FormHelper em seu array $helpers se você
planeja usá-los em qualquer lugar.

Contribuindo
Por favor, considere doar seu código de volta ao CakePHP - contate um dos desenvolvedores
usando nosso sistema de Trac ou a lista de e-mails, ou abra um novo projeto em CakeForge
para compartilhar seu novo helper com outros.

Scaffolding
Introdução
Scaffold (equivalente em português seria andaime, aqui trataremos como protótipo) de
aplicação é uma técnica que permite ao desenvolvedor definir e criar uma aplicação básica que
pode criar, obter, atualizar e excluir objetos. Scaffold em CakePHP também permite
desenvolvedores definir como objetos são relacionados com outros, e criar e quebrar essas
ligações.

Tudo que é necessário para criar um scaffold é um model e seu controller. Uma vez que você
configurou a variável $scaffold no seu controller você já tem tudo funcionando.

O scaffold do CakePHP é muito legal. Ele te dá uma aplicação CRUD (Create - Criar, Retrive -
Obter, Update - Atualizar, Delete - Excluir) totalmente funcional em minutos. Tão legal que
você vai querer usá-lo em aplicações em fase de produção. Agora, nós também pensamos que
ele é legal, mas, por favor, perceba que scaffold é... bem... apenas scaffold. É uma estrutura
simples que você põe para funcionar muito rápido no início do projeto para ter algo
funcionando o mais rápido possível. Ele não tem intenção de ser completamente flexível, ele é
mais como uma forma de já começar com algo funcionando. Se você se perceber precisando
personalizar suas lógica e suas views, é hora deixar de lado seu scaffold e escrever um pouco
de código. O console Bake do CakePHP, coberto em uma sessão mais a frente, é ótimo
próximo passo: ele gera todo o código que produzirá um resultado parecido com o scaffold
atual.

Scaffold é uma ótima forma de lidar com as partes iniciais do desenvolvimento de uma
aplicação web. Esquemas de banco de dados iniciais estão sujeitos a mudanças, o que é
perfeitamente normal na parte inicial do processo de design. E aí existe um problema:
desenvolvedores web detestam criar formulários que nunca serão realmente usados. Para
reduzir o trabalho do desenvolvedor, o scaffold foi adicionado no CakePHP. Ao fazer scaffold o
CakePHP analisa suas tabelas do banco de dados e cria listas padronizadas com botões add,
Desenvolvendo com CakePHP       54


delete e edit, formulários padrões de edição e views padronizadas para inspeção de itens no
banco de dados.

Para adicionar scaffold na sua aplicação, em seu controller adicione a variável $scaffold:

<?php

class CategoriasController extends AppController {
    var $scaffold;
}

?>

Assumindo que você criou até mesmo o arquivo de classe model Categoria (em
/app/models/categoria.php), você está pronto para ir. Visite http://exemplo.com/categorias
para ver seu novo scaffold.

Nota: criar métodos em controllers que tem scaffold pode causar resultados não desejados.
Por exemplo, se você criar uma método index() em um controller com scaffold, seu método
index será renderizado ao invés da funcionalidade do scaffold.

O scaffold está ciente das associações entre models, então se o seu model Categoria está
associado através de belongsTo a um model Usuario, você verá a listagem de IDs do Usuario.
Se você ao invés do ID quer ver outra coisa (como o nome do usuário), você pode configurar a
variável $displayField no model.

Vamos configurar a variável $displayField na class Usuario para que as categorias mostrem
usuários pelo nome ao invés de apenas o ID no scaffold. Esse recurso faz com que o scaffold se
torne mais legível em muitas situações.

<?php

class Usuario extends AppModel {
    var $name = 'Usuario';
    var $displayField = 'nome';
}

?>

Personalizando os scaffolds
Se você está procurando por algo um pouco diferente em suas views de scaffold, você pode
criar templates. Nós não recomendamos essa técnica para aplicações em nível de produção,
mas esse nível de personalização pode ser útil durante as fases de interação.

A personalização é feita através da criação de templates para as views:

Views scaffold personalizadas para um controller específico (PostsController
neste exemplo) deve ser colocado assim:
/app/views/posts/scaffold.index.ctp
/app/views/posts/scaffold.show.ctp
/app/views/posts/scaffold.edit.ctp
/app/views/posts/scaffold.new.ctp

Views scaffold para todos os controllers devem ser colocadas assim:
Desenvolvendo com CakePHP         55


/app/views/scaffolds/index.ctp
/app/views/scaffolds/show.ctp
/app/views/scaffolds/edit.ctp
/app/views/scaffolds/new.ctp
/app/views/scaffolds/add.ctp

CakePHP Console
Introdução

Criando Shells e Tasks

Criando suas Shells

Tasks

Gerando código com Bake

Plugins
Criando um plugin

Plugin de controladores

Plugin de modelos

Plugin de visões

Plugin de informações

Constantes e funções globais
Embora a maior parte do seu dia-a-dia no trabalho com o CakePHP será utilizando as classes e
os métodos do núcleo, o CakePHP apresenta inúmeras funções globais que podem ser úteis.
Muitas destas funções são para o uso das classes do CakePHP (carregando classes Models ou
Components), mas muitas outras funções tornam o trabalho com arrays ou strings um pouco
mais fácil.

Iremos também abranger algumas das constantes disponíveis. Fazendo uso destas constantes,
as atualizações irão se tornar mais fáceis, mas também, são uma maneira conveniente de
apontar para determinados arquivos ou diretórios em suas aplicações.

Funções globais
Aqui estão as funções globais disponíveis no CakePHP. Muitos delas são longas funções do PHP
convenientemente reescritas, mas algumas (como vendor(), e uses()) podem ser usadas para
incluir códigos ou executar outras funções úteis. Provavelmente, se você estiver querendo
uma função para realizar uma tarefa repetitiva, ela estará aqui.

       __(string $string_id, boolean $return = false)

Esta função manipula a internacionalização nas aplicações CakePHP. A string $string_id
identifica a ID para uma tradução, e o segundo parâmetro lhe permite "echoar" a string
diretamente (este é o padrão), ou devolvê-la para o tratamento posterior (você deve passar
Desenvolvendo com CakePHP         56


um valor booleano 'true' para ativar esse             comportamento).     Confira   a   seção
Internacionalizando para obter mais informações.

      a(mixed $one, $two, $three...)

Retorna uma array com os parâmetros utilizados na chamada desta função.

print_r(a('foo', 'bar'));

// Saída:
array(
    [0] => 'foo',
    [1] => 'bar'
)

      aa(array $one, $two, $three...)

Usado para criar arrays associativas, formada com os parâmetros utilizados na chamada desta
função.

echo aa('a','b');

// Saída:

array(
'a' => 'b'
)

      am(array $one, $two, $three...)

Agrupa todas as arrays passadas como parâmetros.

      convertSlash(string $string)

Converte barras em underlines e remove o primeiro e ultimo underline em uma string. Retorna
a string convertida.

      countdim(array $array)

Retorna o número de dimensões de uma array fornecida.

      debug(mixed $var, boolean $showHtml = false)

Se o nível de debug da aplicação é diferente de zero, $var é impresso na tela. Se $showHTML
for verdadeiro (true), os dados serão exibidos de forma mais amigável à leitura no navegador.

      e(mixed $data)

Conveniente reescrita da função echo().

      env(string $key)

Retorna uma variável de ambiente a partir de fontes disponíveis. Utilizado como um backup
caso $_SERVER ou $_ENV estiverem desabilitados.
Desenvolvendo com CakePHP         57


Esta função também emula PHP_SELF e DOCUMENT_ROOT em servidores que não os
suportam. De fato, é uma boa idéia usar sempre a função env() em vez de usar $_SERVER ou
getenv() (especialmente se você pretende distribuir seu código), uma vez que ele é um
completo emulador das variáveis citadas acima.

      fileExistsInPath(string $file)

Verifica se o arquivo fornecido está dentro do atual include_path do PHP. Retorna um
resultado booleano.

      ife($condition, $ifNotEmpty, $ifEmpty)

Utilizado em operações ternárias. Se $condition não é vazio, $ifNotEmpty é retornado se não
$ifEmpty é retornado.

      loadBehavior()
      loadComponent()
      loadController()
      loadControllers()
      loadHelper()
      loadModel()
      loadModels()
      loadPluginComponent()
      loadPluginController()
      loadPluginHelper()
      loadPluginModels()
      loadView()

Este conjunto de funções globais é usado para carregar classes do núcleo do CakePHP para
posterior instanciação. Basta fornecer o nome da(s) classe(s) que você gostaria de carregar.
Isto é especialmente útil para o console de tarefas.

loadModel('Orders');

$Order = new Order();

      low(string $string)

Conveniente reescrita da função strtolower() do PHP.

      paths()

Retorna uma array contendo o caminho dos diretórios do CakePHP indexados por Models,
Behaviors, Controllers, Components, e Helpers.

      pr(mixed $var)

Conveniente reescrita da função print_r() do PHP, com a adição da tag <pre> englobando a
saída de print_r().
Desenvolvendo com CakePHP      58


        r(string $search, string $replace, string $subject)

Conveniente reescrita da função str_replace() do PHP.

        stripslashes_deep(array $value)

Retira as barras da array informada de forma recursiva, retornando a array modificada.

        up(string $string)

Conveniente reescrita da função strtoupper() do PHP.

        uses(string $lib1, $lib2, $lib3...)

Usado para carregar bibliotecas do núcleo do CakePHP (encontradas em cake/libs/).

        vendor(string $lib1, $lib2, $lib3...)

Usado para carregar bibliotecas externas (de terceiros) encontrados no diretório /vendors ou
app/vendors.

Constantes do núcleo
                                    Tabela 5. Constantes do CakePHP

Constante             Descrição
COMPRESS_CSS          Se definido como verdadeiro (true) as folhas de estilo CSS serão
                      compactadas em modo de produção. Isto requer um diretório /var/cache
                      com permissão de escrita pelo servidor. Para utilizar, inclua suas folhas de
                      estilo referenciando-as com o caminho /ccss (diferente de /css) ou utilize o
                      método Controller::cssTag().
LOG_ERROR             Constante de erro. Usado para diferenciar erros de Log e Debug.
                      Atualmente o PHP suporta LOG_DEBUG

Constantes do diretório
                                   Tabela 6. Constantes dos diretórios

Constante                  Caminho absoluto dos diretórios do aplicativo
APP                        Diretório raiz
APP_PATH                   Diretório do aplicativo
CACHE                      Diretório para os arquivos de cache do aplicativo
CAKE                       Diretório do CakePHP
COMPONENTS                 Diretório dos components
CONFIGS                    Diretório dos arquivos de configuração do aplicativo
CONTROLLER_TESTS           Diretório do controller de testes
CONTROLLERS                Diretório dos controladors
CSS                        Diretório dos arquivos CSS
ELEMENTS                   Diretório dos elements
HELPER_TESTS               Diretório dos helpers de teste
HELPERS                    Diretório dos helpers
INFLECTIONS                Diretório das inflexões (geralmente o mesmo diretório dos arquivos
                           de configuração)
JS                         Diretório dos arquivos JavaScript (no webroot)
Desenvolvendo com CakePHP       59


LAYOUTS       Diretório dos layouts
LIB_TESTS     Diretório das bibliotecas de testes do CakePHP
LIBS          Diretório das bibliotecas do CakePHP
LOGS          Diretório dos arquivos de log (no app)
MODEL_TESTS   Diretório dos models de teste
MODELS        Diretório dos models
SCRIPTS       Diretório de scripts do CakePHP
TESTS         Diretório de testes (pai das pastas models, controllers, etc. No
              diretório de testes)
TMP           Diretório de arquivos temporários
VENDORS       Diretório para bibliotecas externas (de terceiros)
VIEWS         Diretório das views
Tarefas comuns com CakePHP   60




         Parte IV.   Tarefas comuns com CakePHP
Validação de dados
Regras simples

Uma regra por campo

rule

required

allowEmpty

on

message

Múltiplas regras por campo

Construindo regras de validação

alphaNumeric

between

blank

cc

comparison

date

email

ip

minLength

maxLength

numeric

phone

postal

ssn

url

Regras de validação personalizada
Tarefas comuns com CakePHP        61


Validação por expressões regulares personalizadas

Validação por métodos personalizados

Limpeza de dados

Manipulação de erros

Debugando

Gerando caches

Logando
Introdução
Enquanto algumas definições da Classe de Configuração do CakePHP podem realmente ajudá-
lo a ver o que está acontecendo por debaixo dos panos, há certos momentos em que você
precisa logar os dados no disco (em um arquivo de texto) para descobrir o que está
acontecendo. Num mundo que está cada vez mais dependente de tecnologias como SOAP e
AJAX, o ato de debugar pode ser bastante difícil.

Logar também pode ser uma maneira de descobrir o que está acontecendo na sua aplicação ao
longo do tempo. Quais os termos de busca estão sendo usados? Quais erros estão sendo
mostrados aos meus usuários? Quantas vezes uma determinada consulta está sendo
executada?

Logar dados no CakePHP é fácil. A função log() faz parte da classe Object, que é uma classe
ancestral comum para quase todas as outras classes do CakePHP. Se o contexto for uma classe
CakePHP (Model, Controller, Component... quase todas), você pode logar seus dados.

Usando as funções de log
A função log() recebe dois parâmetros. A primeira é a mensagem que você gostaria de
escrever no arquivo de log. Por padrão, esta mensagem de erro é escrita no log de erros
encontrado em app/tmp/logs/error.log:

// Execute isto dentro de uma classe do CakePHP:

$this->log("Algo não funciona!");

// O resultado será adicionado ao final do arquivo app/tmp/logs/error.log

2007-11-02 10:22:02 Error: Algo não funciona!

O segundo parâmetro é usado para definir o tipo de mensagem de log que você deseja
escrever. Se não for informado, o padrão é LOG_ERROR, que escreverá no arquivo
mencionado anteriormente. Você pode passar este segundo parâmetro como LOG_DEBUG e
escrever as suas mensagens no arquivo de log para debug encontrado em
app/tmp/logs/debug.log

// Execute isto dentro de uma classe do CakePHP:
Tarefas comuns com CakePHP         62


$this->log('Uma mensagem de debugação.', LOG_DEBUG);

// O resultado será adicionado ao final do arquivo app/tmp/logs/debug.log (em
vez de error.log)

2007-11-02 10:22:02 Error: Uma mensagem de debugação.

Observação: O diretório app/tmp deve ter permissão de escrita pelo usuário do servidor web
para que esta função execute corretamente.

Testando

Internacionalizando
Um dos melhores caminhos para chegar a uma grande platéia é fazer um aplicativo em
diversos idiomas. Isso pode representar uma grande tarefa, mas os recursos de
internacionalização no CakePHP fazem isto muito mais fácil.

Primeiro, é importante que você entenda a terminologia. O termo localização (localization)
refere-se à adaptação de uma aplicação para atender as necessidades de um idioma específico
(ou cultura), como, por exemplo, um locale. Internacionalização (internacionalization) refere-
se à habilidade de sua aplicação se "localizável". Internacionalização e localização são
abreviadas como i18n e l10n, respectivamente; 18 e 10 representam a quantidade de
caracteres entre o primeiro e o último caractere.

Definindo o locale da sua aplicação
Qualquer controlador que usa o conteúdo localizado inclui a classe L10 do núcleo do CakePHP.

<?php

// Include the L10n class:
uses(‘L10n’);

class RecipesController extends AppController {
    // ...
}
?>

Em seguida, você precisa criar os arquivos de idioma que controlam as strings
internacionalizáveis. Cada idioma contém um conjunto de strings com suas IDs. Criando estes
arquivos, você tem um caminho para ser organizado e traduzido. Cada idioma deve conter o
arquivo default.po em uma pasta com o nome do idioma a que se refere.

/app/locale/eng/LC_MESSAGES/default.po (Inglês)
/app/locale/fre/LC_MESSAGES/default.po (Francês)
/app/locale/por/LC_MESSAGES/default.po (Português)
/app/local/pt_br/LC_MESSAGES/default.po (Português - Brasil)

A pasta locale fica dentro da pasta app da sua instalação do CakePHP. Os caracteres de
localização (ex: eng, por, pt_br) seguem o padrão ISO 639-2 (exemplos podem ser encontrados
no site do Library of Congress, http://www.loc.gov/standards/iso639-2/php/code_list.php).
Tarefas comuns com CakePHP         63


Depois de criar os arquivos, preencha-os com as strings chaves e os valores usados para o
processo de internacionalização. Cada string chave deve ter um único valor correspondente.
Aqui um exemplo básico que deve estar dentro do arquivo .po do idioma português:

msgid "purchase"
msgstr "Para comprar o item selecionado, clique em Comprar Agora."

msgid "search"
msgstr "Clique aqui para procurar na nossa base de dados."

Note que seus arquivos .po devem ser codificados usando o padrão ISO-8859-1, e que estes
não excedam o limite de 1024 caracteres na string de valor (msgstr).

Depois de criar os arquivos .po corretamente, sua aplicação já está internacionalizada.

Internacionalizando em CakePHP
Usando os dados de localização na sua aplicação é simples. O primeiro passo é avisar ao
CakePHP qual idioma sua aplicação deve utilizar para mostrar o conteúdo. Isso pode ser feito
detectando subdomínios (en.exemplo.com.br ou pt.exemplo.com.br), usando a informação do
browser ou qualquer outra maneira.

Alteração de idioma deve ser feita no controlador:

$this->L10n = new L10n();
$this->L10n->get("en");

Configure::write('Config.language', "en");

Você pode por este código no beforeFilter para fazer com que cada ação no controlador seja
mostrada usando o idioma corretamente, ou você pode querer colocar isso em uma ação que
manipule a autenticação, ou ainda colocar para escolher o idioma padrão.

Para fazer suas strings internacionalizáveis, utilize a função __(). Esta função está disponível
globalmente, mas você provavelmente utilizará mais nas visões. O primeiro parâmetro da
função é o texto que vai na msgid do arquivo .po. Este conteúdo é exibido (echo) por padrão,
mas um segundo parâmetro pode ser utilizado (opcional), que informa se você quer retornar o
texto (para manipulação de links, por exemplo). O pequeno exemplo abaixo mostra como
internacionalizar strings usando a função __(). A atual saída depende do idioma que foi
selecionado usando a classe L10n e as configurações setadas.

<hr />
 <p><?php __("purchase"); ?></p>
<hr />

Lembre-se de usar o parâmetro de retorno em métodos de helper se você deseja que o
conteúdo seja traduzido na chamada do método do ajudante. Use o segundo parâmetro do
__() para retornar os dados ao invés de exibir (echo):

<?php echo $form->error(
    'Card.cardNumber',
    __("errorCardNumber", true),
    array('escape' => false)
); ?>
Tarefas comuns com CakePHP   64


Paginação
Configurando os controladores

Paginando nas visões

Paginando com AJAX

Alterações no layout

Alterações nas visões
Componentes internos   65




             Parte V.   Componentes internos
Lista de controle de acessos (ACL)

Autenticação

Sessões

Manipulando requisições

Segurança

E-mail

Cookies
Introdução

Configurando os controladores

Usando o componente
Helpers internos     66




                    Parte VI.    Helpers internos
Formulários
O FormHelper é uma nova adição ao CakePHP. A maior parte do trabalho pesado na criação de
formulário é agora feita usando esta nova classe, em vez dos (agora obsoletos) métodos do
HtmlHelper. O FormHelper centra-se na criação de formulários rapidamente, de uma forma
que irá dinamizar validação, re-preenchimento e o layout. O FormHelper também é flexível,
que vai fazer quase tudo para você automagicamente ou você pode usar métodos específicos
para obter apenas o que necessita.

Criando formulários
O primeiro método que você precisará usar na ordem para ganhar vantagens do FormHelper é
o create(). Este método especial retorna uma tag de abertura de formulário.

      create(string $model = null, array $options = array())

Todos os parâmetros são opcionais. Se create() é chamada sem parâmetros fornecidos, Esta
assume que você está construindo um formulário que será submetido a função add() do
controlador atual, via POST. O elemento do formulário também é retornado com o atributo id
seguindo um padrão DOM “ModelActionForm”, em forma de camelo. Se eu fosse chamar
create() dentro de uma visão (view) do controlador UserController, Eu veria algo como a
seguinte saída na visão.

<form id="UserAddForm" method="post" action="/users/add">

O método create() permite personalizar muito mais usando os parâmetros, no entanto.
Primeiro, você pode especificar um nome de modelo. Este modelo é, então, assumido como o
padrão para todos os campos do formulário, bem como o id em DOM da tag do formulário é
alterada.

<?php echo $form->create('Recipe'); ?>

// Saída:
<form id="RecipeAddForm" method="post" action="/recipes/add">

                                      * Recipe = Receita

O array $options é onde a maior parte da configuração do formulário acontece. Este array
especial pode conter um número de diferentes pares valor-chave que afetam a forma como a
tag do formulário é gerada.

$options['type']
Esta chave é utilizada para especificar o tipo de formulário a ser criado. Os valores válidos
incluem 'post', 'get', 'file', 'put' e 'delete'.

Preenchendo com 'post' ou 'get' muda o modo de como o formulário submete a informação.

<?php echo $form->create('User', array('type' => 'get')); ?>
Helpers internos      67



// Saída:
<form id="UserAddForm" method="get" action="/users/add">

Especificando 'file' muda a forma de submeter para o método “post”, e inclui um atributo
enctype de “multipart/form-data” na tag do formulário. Isto é para ser usado se houver algum
elemento de entrada de arquivo, dentro do formulário. A ausência de um bom atributo
enctype, fará com que o upload de arquivo não funcione.

<?php echo $form->create('User', array('type' => 'file')); ?>

// Saída:
<form     id="UserAddForm"           enctype="multipart/form-data"             method="post"
action="/users/add">

Quando estiver usando “put” ou “delete”, o formulário será funcionalmente equivalente a um
formulário submetido em modo 'post', mas, quando submetido, o método de solicitação HTTP
será ultrapassado com 'PUT' ou 'DELETE', respectivamente. Isto permite o CakePHP emular
adequadamente o suporte em navegadores web.

$options['action']
A chave $action permite que você aponte o formulário para uma action específica no seu
controller atual. Por exemplo, se você gostaria de apontar o formulário para a action login() do
controller atual, você deve fornecer um array $options como o seguinte:

<?php echo $form->create('Usuario', array('action' => 'login')); ?>

// Saída:
<form id="UsuarioLoginForm" method="post" action="/usuarios/login">

$options['url']
Se o destino do formulário atual não é o controller atual, você pode especificar a URL para o
atributo action do formulário utilizando a chave 'url' do array $options. A URL pode ser
fornecida em relação a sua aplicação CakePHP (URL relativa), ou pode apontar para um
domínio externo (URL absoluta).

<?php echo $form->create(null, array('url' => 'recipes/add')); ?>

// Saída:
<form method="post" action="/recipes/add">

<?php echo $form->create(null, array(
    'url' => 'http://www.google.com/search'
    'type' => 'get'
)); ?>

// Saída:
<form method="get" action="http://www.google.com/search">

$options['default']
Se 'default' foi definido para booleano false, a forma de submeter é modificada, de modo que
pressionando o botão submit não envia o formulário. Se o formulário destina-se a ser
Helpers internos   68


submetido via AJAX, a configuração 'default' para false suprime a forma do comportamento
padrão, para que você possa pegar os dados e enviá-los via AJAX.

Fechando formulários
O FormHelper inclui também um método end() que completa a marcação do formulário.
Freqüentemente, end() só imprime uma tag de fechamento de formulário, mas usando o end()
também permite o FormHelper inserir elementos hidden de formulário quando necessários,
isso tudo depende da forma de como é usado.

<?php echo $form->create(); ?>

<!-- Form elements go here -->

<?php echo $form->end(); ?>

Se uma string é fornecida como o primeiro parâmetro para end(), o FormHelper retorna um
botão de submissão nomeado (ou com o valor) da string dada, juntamente com a tag de
fechamento o formulário.

<?php echo $form->end('Finish'); ?>

Saída:

<div class="submit">
    <input type="submit" value="Finish" />
</div>
</form>

Elemento de formulário mágico
Primeiro, vamos olhar para alguns dos muitos métodos de criação automática de formulários
do FormHelper. O principal método que vamos olhar é o input(). Este método irá
automaticamente deduzir o campo do modelo que foi fornecido no primeiro parâmetro, e
criará um campo de formulário adequado para esse campo.

         Tabela 7. Tipo de campos na interface conforme tipo de campo no banco de dados

Tipo da coluna                    Resultando no campo de formulário
string (char, varchar, etc.)      text
boolean, tinyint(1)               checkbox
Text                              textarea
text, nomeado como password, password
passwd, ou psword
Date                              selects de dia, mês, e ano.
datetime, timestamp               selects de dia, mês, ano, hora, minuto, e meridiano
Time                              selects de hora, minuto, e meridiano
Por exemplo, vamos supor que o meu model User inclui campos de username (varchar), a
password (varchar), approved (datetime) e quote (text). Posso usar o método input() do
FormHelper para criar uma entrada adequada para todos estes campos de formulário.

<?php echo $form->create(); ?>

    <?php
Helpers internos     69


         echo $form->input('username');          //   text
         echo $form->input('password');          //   text
         echo $form->input('approved');          //   selects de dia, mês, ano,
                                                 //   hora, minuto, meridiano
         echo $form->input('quote');             //   textarea
    ?>

<?php echo $form->end('Adicionar'); ?>

$options['type']
Você pode forçar o tipo de uma entrada (e sobrepor a dedução pelo model), especificando o
tipo. Além dos tipos de campos encontrados na tabela acima, você também pode criar
entradas 'file', e 'password'.

<?php $form->input('field', array('type' => 'file'));

Saída:

<div class="input">
    <label for="UserField">Field</label>
    <input type="file" name="data[User][field]" id="UserField" />
</div>

$options['before'], $options['between'] e $options['after']
Utilize estas chaves se você precisa injetar alguma marcação dentro da saída do método
input().

<?php echo $form->input('field', array(
    'before' => '--before--',
    'after' => '--after--',
    'between' => '--between---'
));?>

Saída:

<div class="input">
--before--
<label for="UserField">Field</label>
--between---
<input name="data[User][field]" type="text" value="" id="UserField" />
--after--
</div>

$options['options']
Esta chave permite que você especifique manualmente as opções para uma entrada select, ou
para um grupo de rádio. A menos que 'type' esteja especificada como 'radio', o FormHelper irá
assumir que a meta de saída é um entrada select.

<?php
    echo $form->input('field', array('options' => array(1,2,3,4,5)));
?>

Saída:

<div class="input">
    <label for="UserField">Field</label>
Helpers internos     70


    <select name="data[User][field]" id="UserField">
        <option value="0">1</option>
        <option value="1">2</option>
        <option value="2">3</option>
        <option value="3">4</option>
        <option value="4">5</option>
    </select>
</div>

As opções também podem ser preenchidas como pares chave-valor.

$options['multiple']
Se 'multiple', foi escolhida para true para uma entrada que retorna um select, a escolha nesta
entrada select permitirá várias seleções.

$options['maxLength']
Define o número máximo de caracteres permitidos em uma entrada de texto.

$options['div']
Defina esta chave false para desativar a saída do div em torno da entrada e de seu marcador
(label).

$options['label']
Defina esta chave false para desativar a saída do marcador (label) que habitualmente
acompanha o input.

$options['id']
Definir esta chave para forçar o valor da id DOM para a entrada.

$options['error']
Esta chave deve ser ajustada para uma string que será mostrada na eventualidade de um erro
de validação. Se 'error' não está definida, uma mensagem de erro genérico padrão será
mostrada.

$options['selected']
Usado em combinação com uma entrada do tipo select. Defina 'selected' para o valor do item
que deseja ser selecionado por padrão quando a entrada é renderizada.

$options['rows'], $options['cols']
Estas duas chaves especificam o número de linhas e colunas em uma entrada de texto
(textarea).

$options['empty']
Se escolhida para true, força a entrada para permanecer vazia. Isso é útil para entrada de
senha que normalmente não deveria está preenchida com uma senha do usuário como
acontece com o valor padrão.

$options['timeFormat']
Utilizado para especificar o formato do tempo nas entradas relacionadas com o tempo. Os
valores válidos incluem '12', '24', 'none'.
Helpers internos     71


$options['dateFormat']
Utilizado para especificar o formato do conjunto de entradas para selecionar uma data. Os
valores válidos incluem 'DMY', 'MDY', 'YMD', e 'NONE'.

Métodos específicos do elemento de formulário
O restante dos métodos disponíveis no FormHelper são para a criação específica de elementos
de formulários. Muitos destes métodos também fazem uso de um parâmetro especial
$options. Neste caso, porém, $options é usado principalmente para especificar atributos da
tag HTML(tais como o valor ou id (DOM) de um elemento do formulário).

<?php echo $form->text('username', array('class' => 'users')); ?>

Saída:

<input       name="data[User][username]"                type="text"          class="users"
id="UserUsername" />

        checkbox(string $fieldName, array $options)

Cria um elemento checkbox. Este método também gera um elemento hidden associado para
forçar a apresentação de dados para o especificado campo.

<?php echo $form->checkbox('done'); ?>

Saída:

<input type="hidden" name="data[User][done]" value="0" id="UserDone_" />
<input type="checkbox" name="data[User][done]" value="1" id="UserDone" />

        year(string $fieldName, int $minYear, int $maxYear, mixed $selected, array
         $attributes, boolean $showEmpty)

Cria um elemento select preenchido com o passar dos anos a partir de $minYear para
$maxYear, com o ano $selected selecionado por padrão. Atributos HTML podem ser
oferecidos em $attributes. Se $showEmpty é false, o elemento select não inclue a opção vazia.

        month(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty)

Cria um elemento select preenchido com nomes dos meses.

        dateTime(string $fieldName, string $dateFormat = 'DMY', $timeFormat = '12', mixed
         $selected, array $attributes, boolean $showEmpty)

Cria um conjunto de entradas select para selecionar data e hora. Os valores válidos para
$dateformat são 'DMY', 'MDY', 'YMD' ou 'NONE'. Os valores válidos para $timeFormat são
'12','24', e 'NONE'.

        day(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty)

Cria um elemento select preenchido com os dias (numérico) do mês.

        hour(string $fieldName, boolean $format24Hours, mixed $selected, array $attributes,
         Boolean $showEmpty)
Helpers internos     72


Cria um elemento select preenchido com a hora do dia.

      minute(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty)

Cria um elemento select preenchido com os minutos da hora.

      meridian(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty)

Cria um elemento select preenchido com 'am' e 'pm'.

      error(string $fieldName, string $text, array $options)

Mostra uma mensagem de erro de validação, especificado por $text, para o determinado
campo, no evento que um erro de validação tenha ocorrido.

      file(string $fieldName, array $options)

Cria uma entrada de arquivo.

      hidden(string $fieldName, array $options)

Cria uma entrada de fomulário hidden.

      isFieldError(string $fieldName)

Retorna true se o campo fornecido em $fieldName tem uma validação de erro ativa.

      label(string $fieldName, string $text, array $attributes)

Cria um elemento tag (etiqueta), preenchido com $text.

      password(string $fieldName, array $options)

Cria uma entrada de senha (password).

      radio(string $fieldName, array $options, array $attributes)

Cria uma entrada radio.

      select(string $fieldName, array $options, mixed $selected, array $attributes, boolean
       $showEmpty)

Cria um elemento select, preenchido com os itens de $options, com uma opção selecionada
por padrão, especificada por $selected. Defina $showEmpty para false se você não quer uma
opção vazia dentro do select.

      submit(string $caption, array $options)

Cria um botão Submit com legenda $caption. Se a definição de $caption for uma URL de uma
imagem (que contém o caracter '.' (ponto)), o botão submit será exibido como uma imagem.

      submitImage(string $path, array $options)
Helpers internos   73


Cria um botão imagem de submissão, com a imagem especificada pela URL em $path
(caminho).

       text(string $fieldName, array $options)

Cria uma entrada textarea.

       textarea(string $fieldName, array $options)

Cria uma entrada textarea.

HTML
Inserindo elementos bem-formados

JavaScript
AJAX

Opções do AjaxHelper

Opções gerais

Opções de callback

Métodos

Cache

Form

Number

Text

Time
Exemplos   74




                    Parte VII.   Exemplos
Tutorial de como fazer um blog em CakePHP

Sistema simples de autenticação de usuários
Apêndices     75




                         Parte VIII.   Apêndices
Escritores da versão inglesa
       José Lorenzo
       derelm
       mar3k
       Tarique Sani
       Aaron Thies
       Ahsanul Bari
       Nate Abele
       Garrett J. Woodworth
       Larry Masters
       Mark Story

Tradutores para língua portuguesa
       Bill Jr.
       Juan Basso
       Julio Protzek
       Sadjow Medeiros Leão
       Tarcísio Sassara
       Tulio Faria

Apoio e revisão da versão traduzida
    Gustavo Carreno
    Icaro Monteiro

Inflexão em português
Abaixo segue o código para a inflexão para língua portuguesa. Caso você queira utilizar,
coloque o código no arquivo /app/config/inflections.php.

<?php
        /*
        * Por Sadjow Medeiros Leão (sadjow@gmail.com)
        * Baseado em http://forum.rubyonbr.org/forums/14/topics/520
        */

        $pluralRules = array(

               # # Regra geral: adiciona um "s" no final da palavra

               # #casa - casas
               '/^([a-zA-Z]*)a$/i'     => '1as',
               # #pe - pes
               '/^([a-zA-Z]*)e$/i'     => '1es',
               # #sem exemplo
               '/^([a-zA-Z]*)i$/i'     => '1is',
               # #carro - carros
               '/^([a-zA-Z]*)o$/i'     => '1os',
Apêndices   76


               # #pneu - pneus
               '/^([a-zA-Z]*)u$/i' => '1us',


               # # Se a palavra termina com "r" or "z", adiciona "es"
               # #luz - luzes
               # #flor - flores
               # #arroz - arrozes

               '/^([a-zA-Z]*)r$/i' => '1res',
               '/^([a-zA-Z]*)z$/i' => '1zes',

               # # Se a palavra termina com "al", "el", "ol", "ul": Troca "l"
por "is"
               # #farol - farois
               # #hospital - hospitais
               # #telemovel - telemoveis
               # #pincel - pinceis
               # #anzol - anzois
               '/^([a-zA-Z]*)al$/i' => '1ais',
               '/^([a-zA-Z]*)el$/i' => '1eis',
               '/^([a-zA-Z]*)ol$/i' => '1ois',
               '/^([a-zA-Z]*)ul$/i' => '1uis',


             # # Se palavra termina em "il" e tem acento agudo na última
sílaba, troca "il", por "is"
             #cantil - cantis
             '/^([a-zA-Z]*)il$/i' => '1is',

             # # TODO
             # # Se a palavra termina com "il" e tiver um acento agudo na
penultima sílaba, troca "il" por "eis"
             # # sem exemplo

               // Esse aqui é um pouco mais complicado. Fiquei de fazer, porque
não tem como
               // identificar acentos quando não se usa acentos( nome das
tabelas)
               // Ainda estou pensando. Me ajuda ok?!

               # # Se a palavra termina com "m", troca "m" por "ns"
               # #armazem - armazens
               # #portagem - portagens
               # inflect.plural /^([a-zA-z]*)m$/i, '1ns'
               '/^([a-zA-Z]*)m$/i' => '1ns',

               # #TODO
               # # Se a palavra termina com "s" e tem uma sílaba, troca "s"
por "es"
               #   #sem exemplo
               #   #inflect.plural /^([a-zA-z]*)e$/i, '1es'
               #
               #   #TODO
               #   # Se a palavra termina com "x" fica a mesma
               #   #sem exemplo... professor X, telvez?
               #   #inflect.plural /^([a-zA-z]*)x$/i, '1x'
               #
Apêndices    77


             #   # Se a palavra termina com "ão", Existem 3 jeitos para o
prural: ãos, ães, ões
             # #NOTA: Difícil de achar, Eu usei os casos mais conhecidos
             #    # e depois usei os casos irregulares (lá embaixo em
$irregularPlural) para os outros. Se alguém conhece
             # # mais casos, por favor adicione na lista e mande-me um e-
mail, obrigado!
             # #
             # #cão - cães
             # #colchão - colchões
             # #portão - portões
             # #pão - pães
             # #alemão - alemães
             # #chão - ?
             # #pilhão - pilhões
             # #canhão - canhões
             # #bidão - bidões
             # #mão - mãos
             '/^([a-zA-Z]*)ao$/i' => '1oes'

       );
/**
 * This is a key only array of plural words that should not be inflected.
 * Notice the last comma
 *
 * $uninflectedPlural = array('.*[nrlm]ese', '.*deer', '.*fish', '.*measles',
'.*ois', '.*pox');
 */
       $uninflectedPlural = array();
/**
 * This is a key => value array of plural irregular words.
 * If key matches then the value is returned.
 *
 *    $irregularPlural = array('atlas' => 'atlases', 'beef' => 'beefs',
'brother' => 'brothers')
 */
       //$irregularPlural = array();
       /*
             Sadjow Medeiros Leão (sadjow@gmail.com)
             // Irregular
       */

      $irregularPlural = array(
            'cao' => 'caes',
            'pao' => 'paes',
            'mao' => 'maos',
            'alemao' => 'alemaes'
      );

/**
 * This is a key => value array of regex used to match words.
 * If key matches then the value is returned.
 *
 * $singularRules = array('/(s)tatuses$/i' => '12tatus', '/(matr)ices$/i'
=>'1ix','/(vert|ind)ices$/i')
 */
      //$singularRules = array();
      /*
      * Sadjow Medeiros Leão ( sadjow@gmail.com )
Apêndices    78


      */

      $singularRules = array(
            # #pes - pe
            # #carros - carro
            # #pneus - pneu
            '/^([a-zA-Z]*)as$/i'   =>   '1a',
            '/^([a-zA-Z]*)es$/i'   =>   '1e',
            '/^([a-zA-Z]*)is$/i'   =>   '1i',
            '/^([a-zA-Z]*)os$/i'   =>   '1o',
            '/^([a-zA-Z]*)us$/i'   =>   '1u',

            # #luzes - luz
            # #flores - flor
            # #arrozes - arroz
            '/^([a-zA-Z]*)res$/i' => '1r',
            '/^([a-zA-Z]*)zes$/i' => '1z',

            # #cantis - cantil
            '/^([a-zA-Z]*)is$/i' => '1il',
            #
            # #farois - farol
            # #hospitais - hospital
            # #telemoveis - telemovel
            # #pinceis - pincel
            # #anzois - anzol
            '/^([a-zA-Z]*)ais$/i' => '1al',
            '/^([a-zA-Z]*)eis$/i' => '1el',
            '/^([a-zA-Z]*)ois$/i' => '1ol',
            '/^([a-zA-Z]*)uis$/i' => '1ul',
            #
            # #armazens - armazem
            # #portagens - portagem
            '/^([a-zA-Z]*)ns$/i' => '1m',
            #
            # #cães - cão
            # #colchões - colchão
            # #portões - portão
            # #pães - pão
            # #alemães - alemão
            '/^([a-zA-Z]*)oes$/i' => '1ao',
            '/^([a-zA-Z]*)aes$/i' => '1ao',
            '/^([a-zA-Z]*)aos$/i' => '1ao'

      );

/**
 * This is a key only array of singular words that should not be inflected.
 * You should not have to change this value below if you do change it use
same format
 * as the $uninflectedPlural above.
 */
      $uninflectedSingular = $uninflectedPlural;
/**
 * This is a key => value array of singular irregular words.
 * Most of the time this will be a reverse of the above $irregularPlural
array
 * You should not have to change this value below if you do change it use
same format
Apêndices     79


 *
 * $irregularSingular = array('atlases' => 'atlas', 'beefs'   =>   'beef',
'brothers' => 'brother')
 */
      $irregularSingular = array_flip($irregularPlural);
?>

Manual cake

  • 1.
    MANUAL CAKEPHP 1.2 Juan Basso 3 de março de 2008
  • 2.
    Sumário PARTE I. COMEÇANDO COM CAKEPHP ......................................................................7 Prefácio ................................................................................................................................................. 7 Requisitos do leitor .................................................................................................................................. 7 Introdução ao CakePHP ......................................................................................................................... 7 O que é CakePHP? Por que usar? ............................................................................................................. 7 Onde obter ajuda? ................................................................................................................................... 8 Entendendo o Model-View-Controller (MVC) ........................................................................................ 9 Introdução ................................................................................................................................................ 9 Benefícios ............................................................................................................................................... 10 PARTE II. PRINCÍPIOS BÁSICOS DO CAKEPHP ....................................................... 11 Estrutura CakePHP ............................................................................................................................... 11 Extensões de controller ......................................................................................................................... 11 Extensões de view .................................................................................................................................. 11 Extensões do model ............................................................................................................................... 11 Extensões de aplicação .......................................................................................................................... 12 Estrutura de arquivos do CakePHP ....................................................................................................... 12 Estrutura do diretório App ..................................................................................................................... 13 Requisição típica do CakePHP .............................................................................................................. 13 Convenções CakePHP ........................................................................................................................... 15 Convenções de arquivos e nome de classes .......................................................................................... 15 Convenções de modelos ........................................................................................................................ 15 Convenções de controladores................................................................................................................ 15 Convenções de visões ............................................................................................................................ 16 PARTE III. DESENVOLVENDO COM CAKEPHP ...................................................... 17 Requisitos ............................................................................................................................................ 17 Preparativos para instalação................................................................................................................ 17 Baixando o CakePHP .............................................................................................................................. 17 Permissões ............................................................................................................................................. 17 Instalação ............................................................................................................................................ 18 Desenvolvimento ................................................................................................................................... 18 Produção ................................................................................................................................................ 18 Instalação avançada ............................................................................................................................... 19 Caminho de classes adicionais ........................................................................................................... 20 i
  • 3.
    Apache e mod_rewrite.......................................................................................................................... 20 Comece agora! ....................................................................................................................................... 20 Configuração........................................................................................................................................ 21 Configuração da base de dados ............................................................................................................. 21 Configuração do núcleo ......................................................................................................................... 22 As classes de configuração ..................................................................................................................... 22 Classes de configuração ..................................................................................................................... 22 Variáveis de configuração do núcleo ................................................................................................. 22 Constantes de configuração .............................................................................................................. 22 Configuração de rotas (Routes) ............................................................................................................. 22 Inflexão personalizada ........................................................................................................................... 23 Configuração de inicialização (bootstrap) .............................................................................................. 24 Controllers (Controladores) ................................................................................................................. 24 Introdução .............................................................................................................................................. 24 Atributos ................................................................................................................................................ 25 $name ................................................................................................................................................ 25 $components, $helpers e $uses ........................................................................................................ 25 Relativo à página: $layout e $pageTitle ............................................................................................. 26 Atributos dos parâmetros ($params) ................................................................................................ 26 Outros atributos ................................................................................................................................ 27 Métodos ................................................................................................................................................. 28 Interagindo com as visões ................................................................................................................. 28 Fluxo de controle ............................................................................................................................... 29 Callbacks ............................................................................................................................................ 29 Outros métodos ................................................................................................................................. 30 Components (Componentes) ............................................................................................................... 33 Introdução .............................................................................................................................................. 33 Construindo componentes personalizados............................................................................................ 33 Acessando classes do MVC de dentro dos componentes ...................................................................... 34 Models (Modelos)................................................................................................................................ 34 Introdução .............................................................................................................................................. 34 Campos mágicos .................................................................................................................................... 34 Atributos ................................................................................................................................................ 34 Métodos ................................................................................................................................................. 34 Associações ............................................................................................................................................ 34 Introdução ......................................................................................................................................... 34 hasOne ............................................................................................................................................... 35 belongsTo .......................................................................................................................................... 37 hasMany ............................................................................................................................................ 38 hasAndBelongsToMany (HABTM) ...................................................................................................... 41 Salvando dados em tabelas relacionadas (hasOne, hasMany, belongsTo) ....................................... 43 Salvando dados em tabelas relacionadas (HABTM) .......................................................................... 44 Criando e removendo relações durante execução ............................................................................ 45 DataSources ........................................................................................................................................... 47 Behaviors................................................................................................................................................ 47 ii
  • 4.
    Introdução ......................................................................................................................................... 47 Usando Behaviors .............................................................................................................................. 47 TreeBehavior ..................................................................................................................................... 47 TranslateBehavior .............................................................................................................................. 47 ACLBehavior ....................................................................................................................................... 47 Views (Visões)...................................................................................................................................... 47 Templates / Skin ..................................................................................................................................... 47 Layouts ................................................................................................................................................... 48 Elements (Elementos) ............................................................................................................................ 50 Helpers (Ajudantes) ............................................................................................................................. 50 Introdução .............................................................................................................................................. 50 Helpers do CakePHP ............................................................................................................................... 51 Criando helpers ...................................................................................................................................... 52 Incluindo outros helpers .................................................................................................................... 52 Usando seus helpers personalizados ................................................................................................. 53 Contribuindo ...................................................................................................................................... 53 Scaffolding ........................................................................................................................................... 53 Introdução .............................................................................................................................................. 53 Personalizando os scaffolds ................................................................................................................... 54 CakePHP Console ................................................................................................................................. 55 Introdução .............................................................................................................................................. 55 Criando Shells e Tasks ............................................................................................................................ 55 Criando suas Shells ............................................................................................................................ 55 Tasks .................................................................................................................................................. 55 Gerando código com Bake ................................................................................................................... 55 Plugins ................................................................................................................................................. 55 Criando um plugin .................................................................................................................................. 55 Plugin de controladores ..................................................................................................................... 55 Plugin de modelos ............................................................................................................................. 55 Plugin de visões ................................................................................................................................. 55 Plugin de informações ....................................................................................................................... 55 Constantes e funções globais ............................................................................................................... 55 Funções globais ...................................................................................................................................... 55 Constantes do núcleo ............................................................................................................................. 58 Constantes do diretório ......................................................................................................................... 58 PARTE IV. TAREFAS COMUNS COM CAKEPHP ......................................................... 60 Validação de dados .............................................................................................................................. 60 Regras simples ....................................................................................................................................... 60 Uma regra por campo ............................................................................................................................ 60 rule ..................................................................................................................................................... 60 iii
  • 5.
    required ............................................................................................................................................. 60 allowEmpty ........................................................................................................................................ 60 on ....................................................................................................................................................... 60 message ............................................................................................................................................. 60 Múltiplas regras por campo ................................................................................................................... 60 Construindo regras de validação ............................................................................................................ 60 alphaNumeric .................................................................................................................................... 60 between ............................................................................................................................................. 60 blank .................................................................................................................................................. 60 cc ........................................................................................................................................................ 60 comparison ........................................................................................................................................ 60 date .................................................................................................................................................... 60 email .................................................................................................................................................. 60 ip ........................................................................................................................................................ 60 minLength .......................................................................................................................................... 60 maxLength ......................................................................................................................................... 60 numeric .............................................................................................................................................. 60 phone ................................................................................................................................................. 60 postal ................................................................................................................................................. 60 ssn ...................................................................................................................................................... 60 url ....................................................................................................................................................... 60 Regras de validação personalizada ........................................................................................................ 60 Validação por expressões regulares personalizadas ......................................................................... 61 Validação por métodos personalizados ............................................................................................. 61 Limpeza de dados ................................................................................................................................ 61 Manipulação de erros .......................................................................................................................... 61 Debugando .......................................................................................................................................... 61 Gerando caches ................................................................................................................................... 61 Logando ............................................................................................................................................... 61 Introdução .............................................................................................................................................. 61 Usando as funções de log ...................................................................................................................... 61 Testando .............................................................................................................................................. 62 Internacionalizando ............................................................................................................................. 62 Definindo o locale da sua aplicação ....................................................................................................... 62 Internacionalizando em CakePHP .......................................................................................................... 63 Paginação ............................................................................................................................................ 64 Configurando os controladores ............................................................................................................. 64 Paginando nas visões ............................................................................................................................. 64 Paginando com AJAX .............................................................................................................................. 64 Alterações no layout .......................................................................................................................... 64 Alterações nas visões ......................................................................................................................... 64 iv
  • 6.
    PARTE V. COMPONENTES INTERNOS ....................................................................... 65 Lista de controle de acessos (ACL)........................................................................................................ 65 Autenticação........................................................................................................................................ 65 Sessões ................................................................................................................................................ 65 Manipulando requisições ..................................................................................................................... 65 Segurança ............................................................................................................................................ 65 E-mail .................................................................................................................................................. 65 Cookies ................................................................................................................................................ 65 Introdução .............................................................................................................................................. 65 Configurando os controladores ............................................................................................................. 65 Usando o componente ........................................................................................................................... 65 PARTE VI. HELPERS INTERNOS .................................................................................... 66 Formulários ......................................................................................................................................... 66 Criando formulários ............................................................................................................................... 66 $options['type'].................................................................................................................................. 66 $options['action'] ............................................................................................................................... 67 $options['url'] .................................................................................................................................... 67 $options['default'] ............................................................................................................................. 67 Fechando formulários ............................................................................................................................ 68 Elemento de formulário mágico ............................................................................................................ 68 $options['type'].................................................................................................................................. 69 $options['before'], $options['between'] e $options['after'].............................................................. 69 $options['options']............................................................................................................................. 69 $options['multiple'] ........................................................................................................................... 70 $options['maxLength'] ....................................................................................................................... 70 $options['div'] .................................................................................................................................... 70 $options['label'] ................................................................................................................................. 70 $options['id'] ...................................................................................................................................... 70 $options['error'] ................................................................................................................................ 70 $options['selected'] ........................................................................................................................... 70 $options['rows'], $options['cols'] ...................................................................................................... 70 $options['empty'] .............................................................................................................................. 70 $options['timeFormat'] ...................................................................................................................... 70 $options['dateFormat'] ...................................................................................................................... 71 Métodos específicos do elemento de formulário .................................................................................. 71 HTML ................................................................................................................................................... 73 Inserindo elementos bem-formados ..................................................................................................... 73 JavaScript............................................................................................................................................. 73 v
  • 7.
    AJAX ....................................................................................................................................................... 73 Opções do AjaxHelper ............................................................................................................................ 73 Opções gerais..................................................................................................................................... 73 Opções de callback ............................................................................................................................ 73 Métodos ................................................................................................................................................. 73 Cache ................................................................................................................................................... 73 Form .................................................................................................................................................... 73 Number ............................................................................................................................................... 73 Text ..................................................................................................................................................... 73 Time..................................................................................................................................................... 73 PARTE VII. EXEMPLOS .................................................................................................. 74 Tutorial de como fazer um blog em CakePHP ....................................................................................... 74 Sistema simples de autenticação de usuários ...................................................................................... 74 PARTE VIII. APÊNDICES ................................................................................................. 75 Escritores da versão inglesa ................................................................................................................. 75 Tradutores para língua portuguesa ...................................................................................................... 75 Apoio e revisão da versão traduzida ...................................................................................................... 75 Inflexão em português ......................................................................................................................... 75 vi
  • 8.
    Começando com CakePHP 7 Parte I. Começando com CakePHP Prefácio Bem vindo ao paraíso de desenvolvimento web. Se você está lendo o prefácio de um manual técnico, é porque está lhe sobrando bastante tempo. Não somos celebridades e o material é o que vem depois. Você pode pular estes capítulos supérfluos e ir direto ao ponto nas seções que você quer. Requisitos do leitor Para ler este manual, você já deve estar familiarizado com o PHP. Conhecer de programação orientada a objeto irá lhe ajudar bastante, porém eu suponho que as seções de introdução deste manual servirão como um bom exemplo do que vem pela frente. Com isso, este material é escrito para desenvolvedores de todos os níveis de habilidade que desejam criar algo robusto, sustentável, rápido e agradável. Devo alertar que haverá seções que abordam tecnologias que estão realmente fora do âmbito deste manual. Administração de servidor Web, AJAX e JavaScript, por exemplo, podem ser mencionados em partes do texto, mas na maior parte do texto nós estaremos focado no CakePHP. Introdução ao CakePHP O que é CakePHP? Por que usar? CakePHP é gratuito, de código aberto, uma framework em PHP para desenvolvimento ágil. É uma estrutura fundamental para programadores criarem aplicações web. Nosso principal objetivo é permitir que você trabalhe em uma estrutura que possa programar de forma rápida e sem a perda de flexibilidade. CakePHP joga fora a monotonia do desenvolvimento web. Nós oferecemos todas as ferramentas que você precisa para começar programando o que realmente deseja: a lógica específica da sua aplicação. Em vez de reinventar a roda cada vez que se constrói um novo projeto, pegue uma cópia do CakePHP e comece a construir sua carruagem real da sua aplicação. CakePHP tem uma equipe de desenvolvedores e uma grande comunidade, trazendo grande valor ao projeto. Além de manter você fora do reinvento da roda, usando CakePHP significa que o núcleo da sua aplicação é bem testado e constantemente aperfeiçoado. Abaixo segue uma pequena lista dos recursos que você poderá desfrutar no CakePHP:  Ativo e com comunidade amigável;  Licença flexível;  Compatibilidade com PHP 4 e PHP 5;  Integrando funcionalidade CRUD (Create, Read, Update and Delete, ou Criar, Ler, Atualizar e Excluir) para interagir com o banco de dados;
  • 9.
    Começando com CakePHP 8  Aplicações scaffolding;  Geração de código;  Arquitetura MVC (Model, View, Controller, ou Modelo, Visões, Controlador);  Requisições ao expedidor com clareza, URLs personalizáveis e rotas;  Validações internas;  Templates rápidos e flexíveis (Sintaxe PHP e com ajudantes);  Ajudantes para usar AJAX, JavaScript, HTML, formulários e outros nas visões;  Componentes de E-mail, Cookie, Segurança, Sessões, Manipulação de Requisições e outros;  Lista de controle de acessos flexível;  Limpeza de dados;  Flexibilidade com cache;  Internacionalização;  Funciona em qualquer subdiretório do seu website, com poucas configurações do Apache. Onde obter ajuda? Você começou no lugar certo. Este manual (e a API) deve ser provavelmente o primeiro lugar que você vá para procurar as respostas das suas dúvidas. Assim como acontece com muitos outros projetos de código aberto, nós obtemos novos usuários regularmente. Tentamos ser os melhores para responder seus questionamentos em primeiro lugar. As respostas podem demorar a chegar, mas permanecerá por tempos e ajudará a esclarecer outras pessoas. Tanto o manual, quanto a API podem ser encontradas online. http://manual.cakephp.com.br (em português) http://manual.cakephp.org (em inglês) http://api.cakephp.org/1.2 (em inglês) Se você estiver assustado, dê um grito pelo canal de IRC internacional ou entre no grupo da comunidade luso-brasileira. Além da equipe de desenvolvimento do núcleo do CakePHP no canal, principalmente durante o dia. Se você precisar de alguma ajuda, deseja encontrar usuários na sua área ou gostaria de doar o novo carro esportivo, gostaríamos de falar com você. Grupo da comunidade luso-brasileira: http://groups.google.com/group/cake-php-pt #cakephp-pt @ irc.freenode.net (em português) #cakephp @ irc.freenode.net (em inglês) O CakePHP Bakery é uma casa para todas as coisas de CakePHP. Visite este site para ver tutoriais, estudos de caso e exemplos de código. Assim que estiver familiarizado com o CakePHP, faça o login e compartilhe seus conhecimentos com a comunidade para ganhar fama e fortuna. http://bakery.cakephp.org
  • 10.
    Começando com CakePHP 9 O CakeForge é outro recurso que os desenvolvedores podem usar para hospedar seus projetos usando CakePHP e compartilhar com outras pessoas. Se você está olhando para achar projetos existentes, ou querendo compartilhar, acesso o CakeForge. http://www.cakeforge.org O site oficial do CakePHP está sempre esperando sua visita. Ele tem links para sites de outros desenvolvedores, screencasts, oportunidade para doar ao projeto e downloads. http://www.cakephp.org Entendendo o Model-View-Controller (MVC) Introdução Aplicações bem escritas em CakePHP segue o design pattern MVC (Model-View-Controller ou Modelo-Visão-Controlador). Programando em MVC separa sua aplicação em três partes principais. O model representa os dados, a view representa a visualização dos dados e o controller manipula e roteia as requisições dos usuários. Figura 1. Requisição típica do CakePHP A Figura 1 mostra um exemplo de uma simples requisição MVC em CakePHP. Para fins ilustrativos, digamos que um usuário chamado Ricardo apenas clicou no link “Comprar um bolo personalizado agora!” da sua aplicação. 1. Ricardo clica no link apontando para http://www.exemplo.com.br/cakes/comprar e seu navegador faz uma requisição ao site; 2. O dispatcher (expedidor) verifica a URL requisitada (/cakes/comprar) e redireciona ao controller correto; 3. O controller executa a lógica específica da aplicação. Por exemplo, verifica se o Ricardo está logado; 4. O controller também usa os models para acessar os dados da sua aplicação. Muitas vezes, os models representam as tabelas do banco de dados, mas podem representar registros LDAP, feeds de RSS ou até mesmo arquivos do sistema. Neste exemplo, o controller usa o model para trazer ao Ricardo as últimas compras do banco de dados; 5. Depois que o controller fez sua mágica sobre os dados, ele repassa para a view. A view faz com que os dados fiquem prontos para a representação do usuário. As views em CakePHP normalmente vem no formato HTML, mas pode ser facilmente exibidas em
  • 11.
    Começando com CakePHP 10 PDF, documento XML, um objeto JSON ou outro formato qualquer, dependendo da sua necessidade; 6. Uma vez que a visão tenha usado os dados provenientes do controller para construir a página, o conteúdo é retornado ao browser do Ricardo. Aproximadamente toda requisição da sua aplicação seguirá o modelo básico do modelo. Nós vamos especificar os detalhes mais adiante, mas mantenha essa visão geral no seu pensamento. Benefícios Por que usar MVC? Porque é um verdadeiro padrão de desenvolvimento (design pattern) e torna fácil a manutenção da sua aplicação, com pacotes modulares de rápido desenvolvimento. Elaborar tarefas divididas entre models, views e controllers, faz com que sua aplicação fique leve e independente. Novas funcionalidades são facilmente adicionadas e dar nova cara nas características antigas pode ser feitas num piscar de olhos. O design modular e separado também permite aos desenvolvedores e designers trabalhem simultaneamente, incluindo a habilidade de um construir um rápido protótipo. A separação também permite que os desenvolvedores alterem uma parte da aplicação sem afetar outras. Se você nunca desenvolveu uma aplicação neste sentido, isso vai lhe agradar muito, mas estamos confiantes que depois de construir sua primeira aplicação em CakePHP, você não vai querer voltar atrás.
  • 12.
    Princípios básicos doCakePHP 11 Parte II. Princípios básicos do CakePHP Estrutura CakePHP CakePHP possui a característica de usar as classes de Controller, Model e View, mas também possui classes e objetos adicionais que fazem o desenvolvimento em MVC mais rápido e agradável. Components, Behaviors e Helpers são classes que proporcionam extensibilidade e reuso para adicionar funcionalidades rapidamente à base MVC das suas aplicações. Agora vamos começar a subir um pouco o nível para analisar os detalhes de como usar estas ferramentas mais tarde. Extensões de controller O Component (Componente) é uma classe que ajuda na lógica do controller. Se você tem a mesma lógica e quer compartilhar entre controllers (ou aplicações), o component é uma boa saída. Por exemplo, o component interno EmailComponent cria e envia e-mails em segundo plano. Ao invés de escrever um método em cada controller que utiliza esta lógica, pode-se criar um component que empacote esta funcionalidade e seja compartilhado entre os controllers. Controllers também são equipados com callbacks. Estes callbacks estão disponíveis para que você possa utilizar, apenas se você precisar inserir uma lógica entre operações do núcleo do CakePHP. Os callbacks disponíveis incluem:  beforeFilter(), executado antes de qualquer ação do controller;  beforeRender(), executado depois da lógica do controller, mas antes da view ser renderizada;  afterFilter(), executado depois de todas as lógicas do controller, incluindo a renderização da view. Não há diferença entre afterRender() e afterFilter(), exceto que você tenha feito uma chamada manualmente para render() no seu método do controller e tenha incluído alguma lógica depois dessa chamada. Extensões de view O Helper (Ajudante) é a classe que ajuda na lógica da view. Assim como o component ajuda o controller, os helpers permitem a apresentação lógica ser acessada e compartilhada entre as views. AjaxHelper é um dos principais helpers. Ele faz requisições AJAX facilmente de dentro das views. A maioria das aplicações tem partes do código que são usados repetidamente nas views. CakePHP facilita o reuso de código na view com a utilização de layouts e elements (elementos). Por padrão, toda view é renderizada por um controller seguindo algum layout. Os elements são como pequenos trechos de código necessários que podem ser reutilizados em diversas views. Extensões do model Assim como as outras extensões, os Behaviors funcionam do mesmo modo, adicionando funcionalidades entre os models. Por exemplo, se você armazenar os dados do usuário em uma estrutura de árvore, você pode especificar o model User como comportamento de árvore e ganhar funcionalidades para remover, adicionar e alterar nós em sua estrutura de árvore fundamental.
  • 13.
    Princípios básicos doCakePHP 12 Os models também são suportados por outra classe chamada DataSource. DataSources são abstrações que permitem os models manipularem diferentes tipos de dados consistentemente. Enquanto a principal fonte de dados numa aplicação CakePHP é via banco de dados, você pode escrever DataSources adicionais que permitem seu model representar um feed RSS, arquivo CSV, entidades LDAP ou eventos iCal. DataSources permite você associar registros de diferentes fontes: ao invés de limitar em joins do SQL, DataSources permitem você chamar seu model de LDAP que está associada a vários eventos iCal. Assim como nos controllers, models têm recursos de callback como:  beforeFind()  afterFind()  beforeValidate()  beforeSave()  afterSave()  beforeDelete()  afterDelete() Os nomes desses métodos devem ser descritivos o bastante para que você saiba o que eles fazem. Certifique-se de pegar os detalhes no capítulo sobre model. Extensões de aplicação Tanto os controllers, helpers e models têm uma classe pai que você pode usar para definir modificações na aplicação. AppController (localizado em “/app/app_controller.php”), AppHelper (localizado em “/app/app_helper.php”) e AppModel (localizado em “/app/app_model.php”) são bons lugares para colocar métodos que você precisa para acessar entre todos os controllers, helpers e models. Embora não sejam classes ou arquivos, as rotas definem regras na requisição feita para o CakePHP. As definições das rotas definem como o CakePHP deve mapear uma URL para um método do controller. O behavior padrão assume que a URL “/controller/action/var1/var2” mapeia para Controller::action($var1, $var2), mas você pode usar rotas para personalizar URLs e como elas devem ser interpretadas pela sua aplicação. Alguns recursos na sua aplicação podem ser empacotados com mérito. Um plugin é um pacote de model, controller e view que realiza um objetivo específico que pode abranger vários aplicativos. Um sistema de gestão de usuários ou um blog simplificado podem ser bons exemplos de plugins para CakePHP. Estrutura de arquivos do CakePHP Vamos dar uma olhada o que é o CakePHP fora da caixa. Você que o CakePHP utiliza-se da requisição básica do MVC, mas não sabe como que os arquivos são organizados.  app  cake  docs  index.php
  • 14.
    Princípios básicos doCakePHP 13  vendors Quando você faz o download do CakePHP, você verá que possui quatro pastas principais. A pasta app será o lugar da sua mágica: aqui serão guardados os arquivos da sua aplicação. A pasta cake é onde a mágica acontece. Faça um compromisso pessoal de não editar os arquivos desta pasta! Nós não ajudamos você se você modificá-la. A pasta docs contém as informações de alterações, licença, etc. Finalmente, a pasta vendors é onde você colocará aplicativos de terceiros para utilizar na aplicação, por exemplo, jQuery, prototype, FCKEditor, etc. Estrutura do diretório App A pasta app do CakePHP é onde normalmente você colocará sua aplicação em desenvolvimento, Vamos dar uma olhada mais de perto dentro desta pasta. Tabela 1. Descrição dos diretórios de app Diretório Descrição config Contém os arquivos de configuração. Detalhes das conexões ao banco de dados, bootstrapping, arquivos de configuração do núcleo e outros devem ser armazenados aqui. controllers Contém os controllers da sua aplicação e seus components. locale Guarda os arquivos com as strings para internacionalizaçao. models Contém os models, behaviors e datasources da sua aplicação. plugins Contém os pacotes de plugins. tmp Aqui é onde o CakePHP armazena os arquivos temporários. Os dados atuais são armazenados onde você tenha configurado o CakePHP, mas esta pasta normalmente é usada para guardar a descrição dos models, logs e outras informações, como as das sessões. vendors Qualquer classe ou biblioteca de terceiro deve ser armazenada aqui. Para fazer um acesso rápido e fácil, use a função vendors(). Você pode achar que esta pasta é redundante, já que existe uma pasta com mesmo nome no nível superior da estrutura. Nós vamos ver diferenças entre estas duas pastas quando discutirmos sobre manipulação de múltiplas aplicações e sistemas mais complexos. views Arquivos de apresentação devem vir aqui: elements, páginas de erro, helpers, layouts e arquivos de views. webroot No modo de produção, esta pasta deve servir como a pasta raiz da sua aplicação. Dentro desta pastas são guardados os arquivos públicos, como estilos CSS, imagens e arquivos de JavaScript. Requisição típica do CakePHP Nós cobrimos os ingredientes básicos no CakePHP, então vamos ver como cada objeto funciona em uma completa requisição. Continuando com nossa requisição original de exemplo, vamos imaginar que nosso amigo Ricardo tenha clicado no link em “Comprar um bolo personalizado agora!” da sua aplicação CakePHP.
  • 15.
    Princípios básicos doCakePHP 14 Figura 2. Requisição típica no CakePHP. Em preto, elemento necessário; Em cinza, elemento opcional; Em azul, callback 1. Ricardo clica no link apontando para http://www.exemplo.com.br/cakes/buy, e seu navegador faz a requisição ao seu servidor de web; 2. O roteador processa a URL, extraindo os parâmetros desta requisição: o controller, action (ação) e qualquer outro argumento que vai afetar na lógica do negócio durante esta requisição; 3. Usando rotas, a requisição da URL é mapeada para a action do controller (um método específico da classe do controller). Neste caso, o método buy() do CakesController. O callback beforeFilter() do controller é chamado antes de qualquer action do controller ser executada; 4. O controller pode usar métodos para ter acesso aos dados da aplicação. Neste exemplo, o controller usa o model para ver no banco de dados as últimas compras de Ricardo. Qualquer callback aplicável do modelo, behaviors e DataSources podem ser aplicados durante esta operação. Enquanto um model não é necessário, todos os controllers do CakePHP inicialmente requisitam de pelo menos um model; 5. Depois do model ter adquiridos os dados, ele retorna-os ao controller. Podem ser aplicados callbacks no model; 6. O controller pode usar components para refinar os dados ou efetuar outras operações (manipular sessões, autenticação ou enviar e-mails, por exemplo); 7. Uma vez que o controller tenha usado os models e os components para preparado os dados suficientemente, estes dados são repassados as views usando o método set() do controller. Callbacks dos controllers podem ser aplicados antes dos dados serem enviados. A lógica da view é efetuada, podendo incluir elements ou helpers. Por padrão, as views são sempre renderizadas dentro de um layout; 8. Além disso, callbacks dos controllers (como afterFilter) pode ser aplicado. Para completar, o código renderizado pela view vai para o navegador do Ricardo.
  • 16.
    Princípios básicos doCakePHP 15 Convenções CakePHP Nós somos grandes fãs de convenções nas configurações. Enquanto isso toma um pouco de tempo para aprender as convenções do CakePHP, você ganha tempo em um longo processo: seguindo as convenções, você ganha funcionalidades gratuitamente e livra-sede madrugas de manutenção de arquivos de configuração. Convenções também fazem com que o sistema fique uniformemente desenvolvido, permitindo outros desenvolvedores o ajudem mais facilmente. Convenções no CakePHP tem sido produzida por anos de experiência em desenvolvimento web e boas práticas. Enquanto nós sugerimos você a usar essas convenções enquanto desenvolve em CakePHP, nós devemos mencionar que muitos desses princípios são facilmente sobrescritos por alguma coisa que é especialmente passado quando trabalha-se com sistemas legados. Convenções de arquivos e nome de classes Em geral, nome dos arquivos são sublinhados, enquanto nome de classes são CamelCased, ou seja, primeiras letras das palavras em maiúsculo. A classe KissesAndHugsController pode ser encontrada no arquivo kisses_and_hugs_controller.php, por exemplo. Porém, o nome da class e seu tipo não são necessariamente encontrados no nome do arquivo. A classe EmailComponent é encontrada no arquivo chamado email.php e a classe HtmlHelper é encontrada no arquivo html.php. Convenções de modelos Nome das classes de modelo devem ser no singular e CamelCased. Person, BigPerson e ReallyBigPerson são todos os exemplos de nomes convencionados para modelos. Os nomes das tabelas correspondem ao nome do modelo do CakePHP, mas no plural e sublinhados. As tabelas para os modelos mencionados anteriormente devem ser people, big_people e really_big_people, respectivamente. Tabelas associadas, usadas em relações hasAndBelongsToMany entre modelos, devem ser nomeadas depois dos modelos das tabelas que a compõem, em ordem alfabética (apples_zebras em vez de zebras_apples). Se sua aplicação possui esse tipo de relação entre os modelos Tag e Post, o nome deve ser posts_tags. Convenções de controladores O nome das classes de controladores são no plural, CamelCased e no final “Controller”. PeopleController, BigPeopleController e ReallyBigPeopleController são todos os exemplos convencionais para nome de controladores. A primeira função que você deve escrever em um controlador deve ser o método index(). Quando alguém requisita um controlador sem ação, o behavior padrão é renderizar o método index() do controlador. Por exemplo, a requisição para http://www.exemplo.com.br/apples/ mapeia para a chamada da função index() do ApplesController, assim como http://www.exemplo.com.br/apples/view mapeia para a chamada da função view() no ApplesController.
  • 17.
    Princípios básicos doCakePHP 16 Você também pode alterar a visibilidade das funções do controlador em CakePHP colocando sublinhados na frente do nome das funções. Se a função do controlador estiver com sublinhado na frente, a função não será disponibilizada para acesso da web através do dispatcher, mas estará disponível para uso interno. Convenções de visões Os arquivos de template das visões são chamados depois das funções que os controladores mostram, na forma com sublinhados. A função getReady() da classe PeopleController irá procurar pelo template da visão em /app/views/people/get_ready.ctp. O modelo básico é /app/views/controller/underscored_function_name.ctp. Nomeando os pedaços da aplicação usando as convenções do CakePHP, você ganha funcionalidades sem luta e proteção configuração. Aqui o exemplo final que vincula as associações:  Tabela no banco de dados: “people”  Classe do Modelo: “Person”, encontrada em /app/models/person.php  Classe do Controlador: “PeopleController”, encontrado em /app/controllers/people_controller.php  Template da Visão: encontrado em /app/views/people/index.ctp Usando estas convenções, CakePHP sabe que a requisição para http://www.exemplo.com.br/people/ mapeia para a chamada da função index() do PeopleController, onde o modelo Person é automaticamente disponibilizado (e automaticamente associado a tabela “people” no banco de dados), e renderiza isso para o arquivo. Nenhuma destas relações foram configuradas por qualquer meio que não seja através da criação de classes e arquivos que você precise criar em algum lugar. Agora que você leu os fundamentos do CakePHP, você pode tentar seguir o Tutorial de como fazer um blog em CakePHP, disponível na parte de Exemplos deste manual.
  • 18.
    Desenvolvendo com CakePHP 17 Parte III. Desenvolvendo com CakePHP Requisitos  Servidor HTTP. Apache com mod_rewrite é preferido, mas não é obrigatório.  PHP 4.3.2 ou superior. Sim! CakePHP funciona com PHP 4 e PHP 5. Tecnicamente um banco de dados não é obrigatório, mas nós imaginamos que a maioria das aplicações irão utilizar um. CakePHP suporte uma variedade de banco de dados:  MySQL (4 ou superior);  PostgreSQL;  Firebird DB2;  Microsoft SQL Server;  Oracle;  SQLite;  ODBC;  ADOdb. Preparativos para instalação Baixando o CakePHP Há duas maneiras de pegar uma cópia do CakePHP, Primeiro: você pode baixar o arquivo (zip/tar.gz/tar.bz2) ou você pode baixar o código do repositório SVN. Para pegar a cópia estável, visite o site http://www.cakephp.org. Lá haverá um link chamado “Download Now!” para baixar. Os arquivos do CakePHP também são armazenados no CakeForge e você pode visitar a página do projeto no site http://cakeforge.org/projects/cakephp. Se você quer os arquivos mais atuais, verifique no site http://cakephp.org/downloads/index/nightly e verás a última versão estável, porém nem sempre a última release. Nestas versões incluem correções entre releases. Ou seja, são versões intermediárias entre releases, mas que são estáveis. Para pegar os arquivos direto do repositório SVN, conecte-se em https://svn.cakephp.org/repo/branches/1.2.x.x. Permissões O CakePHP usa o diretório /app/tmp para diversas operações. Descritivos dos modelos, fazer cache de visões e informações das sessões são alguns exemplos. Assim, tenha certeza que o diretório /app/tmp na instalação do seu cake permite escrita pelo usuário do servidor de web.
  • 19.
    Desenvolvendo com CakePHP 18 Instalação Instalando o CakePHP pode ser feito simplesmente descompactando o conteúdo no seu servidor web ou de forma mais complexa e flexível, do jeito que você preferir. Esta seção vais falar de três maneiras de instalar o CakePHP: desenvolvimento, produção e avançada.  Desenvolvimento: fácil para começar, URL dos seus aplicativos incluem o diretório de instalação do CakePHP e é menos seguro;  Produção: Requer maior habilidade para configurar o servidor web, porém mais seguro e com URLs mais amigáveis;  Avançada: Com algumas configurações, permite você colocar os diretórios do CakePHP em diferentes locais do sistema, possibilitando compartilhar o núcleo do CakePHP entre diversas aplicações. Desenvolvimento Apenas coloque seus arquivos do CakePHP no diretório público do seu servidor web (normalmente htdocs, www, public_html). Por exemplo, assumindo que o diretório público do seu servidor web seja /var/www/html, os arquivos devem ficar desta maneira:  /var/www/html o /cake_1_2  /app  /cake  /docs  /index.php  /vendors Para ver a sua aplicação CakePHP, entre no link http://www.exemplo.com/cake_1_2/. Produção Para utilizar-se do modelo de produção, você precisará ter privilégios de acessar o diretório público do servidor web. Escolhendo o modo de produção significa que todo o domínio age como um único pedido CakePHP. A disposição dos arquivos no modo de produção fica da seguinte maneira:  /pasta_para_o_cake/ o /app  /webroot (este diretório deve ser seu diretório público do servidor web) o /cake o /docs o /index.php o /vendors Se sua aplicação está hospedada no Apache, a diretiva DocumentRoot para seu domínio deve ficar assim: DocumentRoot /pasta_para_o_cake/app/webroot
  • 20.
    Desenvolvendo com CakePHP 19 Para ver sua aplicação CakePHP, entre no link http://www.exemplo.com.br. Instalação avançada Aqui estão algumas situações que você escolhe o lugar onde os diretórios do CakePHP vão ficar no seu sistema. Isto pode ser por causa de uma restrição do sistema ou para compartilhar as bibliotecas entre diferentes aplicações. Esta seção descreve como espalhar seus diretórios dos CakePHP no sistema. Primeiro, note que há três partes principais da sua aplicação CakePHP: 1. As bibliotecas do núcleo do CakePHP, em /cake; 2. O código da sua aplicação, em /app; 3. Os arquivos públicos da sua aplicação, normalmente em /app/webroot. Cada um desses diretórios pode ser colocado em qualquer lugar do seu sistema, com exceção do webroot, que precisa estar acessível pelo servidor web. Você pode mover a pasta webroot para fora do diretório da sua aplicação (app), desde que informe ao Cake onde você vai colocá- la. Para configurar sua instalação do Cake, nós vamos ter que fazer algumas alterações no arquivo /app/webroot/index.php. Aqui existem três constantes que precisaremos editar: ROOT, APP_DIR e CAKE_CORE_INCLUDE_PATH.  ROOT deve ser configurada para informar o diretório onde sua aplicação se encontra, ou seja, onde está a pasta app;  APP_DIR deve ser configurada para informar qual a pasta app;  CAKE_CORE_INCLUDE_PATH deve ser configurada para informar o diretório onde estão as bibliotecas do CakePHP (a pasta cake). Vamos fazer um exemplo para que você veja como funciona a instalação avançada na prática. Imagine que eu quero que a aplicação funcione como segue:  As bibliotecas do CakePHP deverão ser colocadas em /usr/lib/cake;  O diretório público da minha aplicação (webroot) deve ser em /var/www/meusite;  O diretório da aplicação deve ser /home/eu/meusite. Com estas configurações, eu preciso editar o meu arquivo webroot/index.php (que no final deve estar em /var/www/meusite/index.php, neste exemplo) e ver o seguinte: if (!defined('ROOT')) { define('ROOT', DS.'home'.DS.'eu'); } if (!defined('APP_DIR')) { define ('APP_DIR', 'meusite'); } if (!defined('CAKE_CORE_INCLUDE_PATH')) { define('CAKE_CORE_INCLUDE_PATH', DS.'usr'.DS.'lib'.DS.'cake'); /app/webroot/index.php (parcialmente, comentários foram removidos)
  • 21.
    Desenvolvendo com CakePHP 20 É recomendado que você use a constante DS no lugar das barras para entre os diretórios. Isso previne que não cause erro quando se use a aplicação em sistemas operacionais diferentes, tornando seu código mais portável. Caminho de classes adicionais Em algumas ocasiões é interessante você compartilhar as classes do MVC entre as aplicações no mesmo sistema. Se você quer um mesmo controller para mesma aplicação, você pode usar o arquivo bootstrap.php do CakePHP para adicionar estas classes adicionais. No bootstrap.php, defina algumas variáveis com nomes especiais para fazer com que o CakePHP olhe nestes diretórios a procura da sua classe: $viewPaths = array(); $controllerPaths = array(); $modelPaths = array(); $helperPaths = array(); $componentPaths = array(); $behaviorPaths = array(); Cada um dessas variáveis especiais pode ser um conjunto na array com o diretório absoluto onde estão às classes que você desejar. Tenha certeza que cada diretório especificado inclua as barras com DS. Apache e mod_rewrite Enquanto o CakePHP é construído para trabalhar com o mod_rewrite e vimos que muitos usuários apanham para conseguir fazer isto funcionar nos seus sistemas, nós lhe daremos algumas dicas que você pode tentar para tentar rodar corretamente:  Tenha certeza que o override está habilitado no .htaccess. Em seu httpd.conf, você deve olhar na seção que define seu Directory no servidor. Tenha certeza que AllowOverride está configurado como All para o diretório correto de DocumentRoot;  Tenha certeza que você está editando o httpd.conf do sistema antes da configuração do usuário ou do site em específico;  Tenha certeza que o arquivo .htacess está na pasta do CakePHP. Em alguns sistemas operacionais ele pode ficar oculto na hora de mover devido a interpretarem o “.” como sinônimo de ocultamento. Tenha certeza que sua cópia do CakePHP é do site ou repositório oficial do CakePHP e que foi extraído corretamente;  Tenha certeza que você está carregando o mod_rewrite corretamente. Você pode ver algo como LoadModule rewrite_module libexec/httpd/mod_rewirte.so e AddModule mod_rewrite.c no seu httpd.conf;  Se você está instalando no diretório do usuário (http://exemplo.com.br/~username), você terá que modificar o arquivo .htaccess no diretório da base da instalação do CakePHP. Apenas adicione a linha “RewriteBase /~meuusername/”. Comece agora! Tudo bem, vamos ver o CakePHP em ação. Dependendo de qual opção de instalação você utilizou, acesse no seu navegador o link http://exemplo.com.br ou http://exemplo.com.br/cake_instalado/. Neste ponto, você verá a página padrão do CakePHP e a mensagem do estado da configuração do seu banco de dados.
  • 22.
    Desenvolvendo com CakePHP 21 Parabéns! Você já pode criar sua primeira aplicação CakePHP. Configuração Configuração da base de dados O CakePHP espera que os detalhes de configuração da base de dados estejam no arquivo “app/config/database.php”. Um exemplo de configuração da base de dados pode ser encontrado em “app/config/database.php.default”. A configuração final deve ser parecida com o exemplo abaixo. var $default = array('driver' => 'mysql', 'persistent' => false, 'host' => 'localhost', 'login' => 'usuarioDB', 'password' => 'senhaDB', 'database' => 'basededados', 'prefix' => ''); Exemplo de configuração da base de dados A conexão $default é usada a menos que outra configuração seja especificada pela propriedade $useDbConfig em um model. Por exemplo, se minha aplicação tiver uma base de dados adicional do legacy além do padrão, eu poderia usá-la em meus models criando uma nova conexão da base de dados de $legacy similar a configuração $default, e ajustando a var $useDbConfig = 'legacy'; nos models apropriados. Preencha corretamente os pares de chave/valor na configuração para atender melhor às suas necessidades. Tabela 2. Configurações da base de dados Chave Valor driver O nome do driver da base de dados para esta configuração. Exemplos: mysql, postgres, sqlite, pear-drivername, adodb-drivername, mssql, oracle, ou odbc. persistent Se usará ou não uma conexão persistente com a base de dados. host O nome do servidor da base de dados (ou endereço IP). login O usuário desta conta. password A senha desta conta. database O nome da base de dados que esta conexão irá usar. prefix Esta string será adicionada como prefixo no nome de todas tabelas de sua base (opcional) de dados.Se suas tabelas não possuem prefixo, deixe esta string vazia. port A porta TCP ou socket Unix usado para conectar com o servidor. (opcional) enconding Indica qual caractere definido será usado para enviar indicações SQL ao servidor. schema Usado em instalações de base de dados PostgreSQL para especificar qual schema usar. Note que as configurações de prefixo são para as tabelas, não para os models. Por exemplo, se você criou um relacionamento entre as tabelas Apple e Flavor, o nome será prefixo_apples_flavors (não prefixo_apples_prefixo_flavors), isso se sua opção de prefixo estiver como 'prefixo_'.
  • 23.
    Desenvolvendo com CakePHP 22 A partir deste ponto, você deve dar uma olhada nas Convenções CakePHP, mostradas neste manual. A nomenclatura correta para suas tabelas (e o nome de algumas colunas) pode livrar de algumas implementações e configurações desnecessárias. Configuração do núcleo As classes de configuração Classes de configuração Variáveis de configuração do núcleo Constantes de configuração Configuração de rotas (Routes) Routes é uma funcionalidade que mapeia URLs em ações do controller. Foi adicionado ao CakePHP para tornar URL amigáveis mais configuráveis e flexíveis. Não é obrigatório o uso do mod_rewrite para usar routes, mas usando-o fará sua barra de endereços muito mais limpa e arrumada. Routes no CakePHP 1.2 foi ampliada e pode ser muito mais poderosa. Antes de você aprender sobre como configurar suas próprias rotas, você deveria saber que o CakePHP vem configurado com um conjunto de rotas padrão. A configuração padrão de rotas do CakePHP deixará as URLs mais bonitas para qualquer aplicação. Você pode acessar diretamente uma ação via URL colocando seu nome na requisição. Você pode também passar parâmetros para suas ações no controller usando a própria URL. URL para a rota padrão: http://examplo.com/controller/action/param1/param2/param3 A URL /noticias/ler mapeia para a ação ler() do controller Noticias (NoticiasController), e /produtos/verInformacoes mapeia para a ação view_informacoes() do controller Produto (ProdutosController). Se nenhuma ação é especificada na URL, a ação index() será chamada. A rota padrão também permite passar parâmetros para as ações usando a URL. Uma requisição /noticias/ler/12 seria equivalente a chamar o método ler(12) no controller Noticias (NoticiasController), por exemplo. Uma novidade no CakePHP 1.2 é a possibilidade de usar parâmetros nomeados. Você pode nomear parâmetros e enviar seus valores usando a URL. Uma requisição /noticias/ler/titulo:primeira+noticia/categoria:esportes teria como resultado uma chamada a ação ler() do controller Noticias (NoticiasController). Nesta ação, você encontraria os valores dos parâmetros título e categoria dentro de $this->passedArgs['titulo'] e $this- >passedArgs['categoria'] respectivamente. Alguns exemplos para a rota padrão: URL mapeadas para as ações dos controladores, usando rotas padrão: URL: /monkeys/jump
  • 24.
    Desenvolvendo com CakePHP 23 Mapeado para: MonkeysController->jump(); URL: /products Mapeado para: ProductsController->index(); URL: /tasks/view/45 Mapeado para: TasksController->view(45); URL: /donations/view/recent/2001 Mapeado para: DonationsController->view('recent', '2001'); URL: /contents/view/chapter:models/section:associations Mapeado para: ContentsController->view(); $this->passedArgs['chapter'] = 'models'; $this->passedArgs['section'] = 'associations'; Definindo suas próprias rotas permite você definir como sua aplicação irá responder a uma dada URL. Defina suas próprias rotas no arquivo “/app/config/routes.php” usando o método Router::connect(). O método connect() recebe três parâmetros: a URL que você deseja casar, o valor padrão para os elementos de rota, e regras de expressões regulares para ajudar a encontrar elementos na URL. O formato básico para uma definição de rota é: Router::connect( 'URL', array('paramName' => 'defaultValue'), array('paramName' => 'matchingRegex') ) Inflexão personalizada As convenções de nomenclatura do Cake podem ser realmente legais. Você pode nomear sua tabela big_boxes, seu model BigBox, seu controller BigBoxesController e tudo isso funciona em conjunto automaticamente. A maneira que o CakePHP usa para associar todas juntas é através da utilização de inflections (inflexões), que transformam as palavras do singular em plural e vice-versa. Existem ocasiões (especialmente para nossos amigos que não falam inglês - nosso caso), onde você pode rodar o inflector do CakePHP (a classe que pluraliza, singulariza, camelCases e under_scores) e não funcionar como você gostaria. Se o CakePHP não reconhecer seu Foci ou Fish, editando o arquivo de configuração personalizada de inflexões você poderá indicar seus casos especiais. O arquivo de configuração é encontrado em /app/config/inflections.php. Neste arquivo, você irá encontrar seis variáveis. Cada uma permite você fazer o ajuste fino das inflections do CakePHP. Variáveis do inflections.php Descrição $pluralRules Este array contém regras de expressões regulares para pluralizar casos especiais. A chave do array são os patterns e o valor são as substituições.
  • 25.
    Desenvolvendo com CakePHP 24 $uninflectedPlural Um array que contém palavras que não precisam ser alteradas quando passadas para o plural (lápis, etc.). $irregularPlural Um array que contém palavras e seus plurais. A chave do array contém a forma no singular e o valor a forma no plural. Este array deve ser usado para guardar palavras que não seguem as definições em $pluralRules. $singularRules Similar a $pluralRules, contém as regras para singularizar as palavras. $uninflectedSingular Similar a $uninflectedPlural, contém as palavras que não contém forma no singular. Por padrão, este array tem o mesmo valor de $uninflectedPlural. $irregularSingular Similar a $irregularPlural, contém as palavras que possuem apenas a forma singular. A versão para língua portuguesa do inflections.php pode ser encontrada nos apêndices, com o título Inflexão em português. Configuração de inicialização (bootstrap) Controllers (Controladores) Introdução Um controller (ou controlador) é usado para gerenciar a lógica para uma parte de sua aplicação. Mais comumente, controllers são usados para gerenciar a lógica de um único model. Por exemplo, se você está construindo um site para uma padaria online, você pode ter um ReceitasController e um IngredientesController gerenciando suas receitas e seus ingredientes. No CakePHP, controllers são nomeados de acordo com o model que manipulam, no plural. O model Receita é manipulado pelo ReceitasController, o model Produto é manipulado pelo ProdutosController, e por aí vai. Seus controllers de aplicação são classes que estendem a classe CakePHP AppController, a qual por sua vez estende a classe núcleo Controller. A classe AppController pode ser definida em app/app_controller.php e deve conter métodos que são compartilhados entre todos os seus controllers. A classe AppController estende o Controller que é uma classe padrão da biblioteca CakePHP. Controllers podem incluir qualquer número de métodos que são geralmente referidos como actions (ações). Actions são métodos do controlador usados para mostrar views (visões). Uma action é um único método de um controller. O dispatcher (despachante) do CakePHP chama actions quando uma requisição casa uma URL com uma action do controller. Retornando ao nosso exemplo da padaria online, nosso ReceitasController pode conter as actions ver(), compartilhar() e buscar(). O controller poderia ser encontrado em app/controllers/receitas_controller.php e poderia conter: <?php class ReceitasController extends AppController { function ver($id) { // a lógica da action vai aqui... }
  • 26.
    Desenvolvendo com CakePHP 25 function compartilhar($cliente_id, $receita_id) { // a lógica da action vai aqui... } function buscar($busca) { // a lógica da action vai aqui... } } ?> app/controllers/receitas_controller.php Para que você possa usar o controller de forma mais efetiva em sua aplicação, vamos cobrir alguns dos principais atributos e métodos fornecidos pelos controllers do CakePHP. Atributos Para uma lista completa de atributos do controller e suas descrições visite a API do CakePHP. Dê uma olhada http://api.cakephp.org/1.2/classController.html. $name Usuários PHP4 devem iniciar suas definições de controllers usando o atributo $name. O atributo $name deve conter o nome do controller. Geralmente é apenas a forma plural do nome do model. Isso cuida de alguns dos problemas de nomes de classe do PHP4 e ajuda o CakePHP a encontrar os nomes das coisas. <?php class ReceitasController extends AppController { var $name = 'Receitas'; } ?> Exemplo de uso do atributo $name do controller $components, $helpers e $uses Os próximos atributos de controller usados com maior freqüência dizem ao CakePHP que helpers (ajudantes), components (componentes), e models você usará junto com o controller atual. Usar esses atributos disponibiliza essas classes MVC para o controller como variáveis de classe ($this->NomeDoModel, por exemplo). Por favor, perceba que cada controller tem algumas dessas classes disponíveis por padrão, então você pode nem mesmo ter que configurar o seu controller. Controllers tem por padrão seu model principal disponível. Nosso ReceitasController terá o model Receita disponível em $this->Receita, e nosso ProdutosController também tem acesso ao model Produto em $this->Produto. Os helpers Html e Session estão sempre disponíveis por padrão, assim como o component Session. Para aprender mais sobre essas classes, lembre-se de dar uma olhada em suas repectivas sessões mais a frente nesse manual.
  • 27.
    Desenvolvendo com CakePHP 26 Vamos ver como chamar um controller CakePHP no qual você planeja usar classes MVC adicionais. <?php class ReceitasController extends AppController { var $name = 'Receitas'; var $uses = array('Receita', 'Usuário'); var $helpers = array('Html', 'Ajax'); var $components = array('Session', 'Email'); } ?> Quando estiver definindo esses atributos, tenha certeza de incluir as classes padrão (como Html no array $helpers, por exemplo) se você pretende usá-los. Relativo à página: $layout e $pageTitle Alguns poucos atributos existem nos controllers CakePHP que dão maior controle sobre como suas views são embutidas em um layout. O atributo $layout pode conter o nome do layout salvo em /app/views/layouts. Você especifica um layout atribuindo ao atributo $layout o nome do arquivo de layout menos a extensão .ctp. Se esse atributo não for definido, o CakePHP renderiza o layout default (padrão). Se você não definiu um em /app/views/default.ctp, o layout default do núcleo do CakePHP será renderizado. <?php class RecipesController extends AppController { function quickSave() { $this->layout = 'ajax'; } } ?> Usando $layout para definir um layout alternativo O atributo $pageTitle do controller torna possível definir o título da página renderizada. Para que isso funcione apropriadamente, seu layout precisa ter embutido a variável $title_for_layout entre as tags <title> no cabeçalho do documento HTML. Apenas atribua à $pageTitle a string que você quer ver no <title> do seu documento. Atributos dos parâmetros ($params) Parâmetros do controller estão disponíveis em $this->params no seu controller CakePHP. Essa variável é usada para dar acesso à informação sobre a requisição atual. O uso mais comum do $this->params é obter acesso à informação que foi enviada ao controller via operações POST ou GET.  $this->params['form']
  • 28.
    Desenvolvendo com CakePHP 27 o Qualquer dado do POST de qualquer formulário é guardado aqui, incluindo também informação encontrada em $_FILES.  $this->params['bare'] o Guarda 1 se o layout atual está vazio, 0 se não.  $this->params['isAjax'] o Guarda 1 se o layout atual é 'ajax', 0 se não. Essa variável só é configurada se o component RequestHandler está sendo usado no controller.  $this->params['controller'] o Guarda o nome do controller atual manipulando a requisição. Por exemplo, se a URL /posts/ver/1 foi requisitada, $this->params['controller'] será igual à 'posts'.  $this->params['action'] o Guarda o nome da action atual manipulando a requisição. Por exemplo, se a URL /posts/ver/1 é requisitada, $this->params['action'] será igual 'ver'.  $this->params['pass'] o Guarda a query string GET passada com a requisição atual. Por exemplo, se a URL /posts/ver/?var1=3&var2=4 foi requisitada, $this->params['pass'] será igual à '?var1=3&var2=4'.  $this->params['url'] o Guarda a URL atual requisitada, com os pares chave-valor das variáveis GET. Por exemplo, se a URL /posts/view/?var1=3&var2=4 foi chamada, $this- >params['url'] conterá: [url] => Array ( [url] => posts/view [var1] => 3 [var2] => 4 )  $this->data o Usado para manipular os dados POST enviados dos formulários FormHelper ao controller. // O FormHelper é usado para criar um elemento form: $form->text('Usuario.primeiro_nome'); // Quando rederizado, se parece com: <input name="data[Usuario][primeiro_nome]" value="" type="text" /> // Quando o formulário é enviado para o controller via POST, // os dados são mostrados em $this->data // O primeiro nome pode ser encontrado aqui: $this->data['Usuario']['primeiro_nome']; Outros atributos Ainda que você possa dar uma olhada nos detalhes de todos os atributos de controllers na API, existem outros atributos de controllers que merecem suas próprias sessões no manual.
  • 29.
    Desenvolvendo com CakePHP 28 O atributo $cacheAction serve para criar cache das views, e o atributo $paginate é usado para criar a paginação padrão para o controller. Para mais informação sobre como usar esses atributos, dê uma olhada em suas respectivas sessões mais a frente nesse manual. Métodos Para uma lista completa de métodos do controller e suas descrições visite a API CakePHP. Dê uma olhada http://api.cakephp.org/1.2/class_controller.html. Interagindo com as visões  set(string $var, mixed $value) O método set() é a principal forma de enviar dados do seu controller para sua view. Uma vez que você usou set(), a variável pode ser acessada na sua view. // Primeiro você passa os dados do controller: $this->set('cor', "pink"); // Então, na view, você pode utilizar os dados: <p>Você selecionou a cor <?php echo $cor; ?> para colorizar o cake.</p> Exemplo de uso do set() O método set() também pega um array associativo como seu primeiro parâmetro. Esse pode ser geralmente um caminho rápido para atribuir um grupo de informações para a view. Perceba que os índices de seu array sofrerão inflection antes de serem atribuídos à view ('indice_com_underline' se torna 'indiceComUnderline', etc.): $dados = array( 'cor' => 'pink', 'tipo' => 'açucar', 'preco_base' => 23.95 ); // fazem $cor, $tipo, e $precoBase // disponíveis na view: $this->set($dados);  render(string $action, string $layout, string $file) O método render() é automaticamente chamado ao final de cada action do controller requisitada. Esse método executa toda a lógica da view (usando dados que você forneceu usando o método set()), insere a view dentro do layout e o serve de volta para o usuário final. O arquivo de view padrão renderizado é determinado por convenção. Se a action buscar() do ReceitasController é requisitada, o arquivo de view /app/views/receitas/buscar.ctp será renderizado.
  • 30.
    Desenvolvendo com CakePHP 29 Ainda que o CakePHP vá automaticamente chamá-lo (a menos que você configure $this- >autoRender para false) depois de cada lógica de action, você pode usá-lo para especificar um arquivo de view alternativo configurando o nome da action no controller usando $action. Você pode também especificar um arquivo alternativo um terceiro parâmetro, $file. Quando usar $file, lembre-se de utilizar um pouco das constantes globais do CakePHP (como a VIEWS). O parâmetro $layout permite especificar o layout na qual a view é renderizada. Fluxo de controle  redirect(string $url, integer $status, boolean $exit) O método de controle de fluxo que você vai usar com maior freqüência é o redirect(). Esse método pega seu primeiro parâmetro na forma de uma URL relativa CakePHP. Quando um usuário fez uma compra com sucesso, você provavelmente irá redirecioná-lo para a tela de recibo. function comprar() { // A lógica para finalizar a compra vai aqui... if($sucesso) { $this->redirect('/compras/obrigado'); } else { $this->redirect('/compras/confirmar'); } } Exemplo de uso do redirect() O segundo parâmetro do redirect() lhe permite definir um código de status HTTP para acompanhar o redirecionamento. Você pode querer usar 301 (movido permanentemente) ou 303 (veja outro), dependendo da natureza do redirecionamento. Esse método não chama exit() depois de redirecionar a menos que você configure o terceiro parâmetro para true.  flash(string $message, string $url, integer $pause) Similarmente, o método flash() é usado para direcionar o usuário para uma nova página depois de uma operação. O método flash() é diferente pelo fato de mostrar uma mensagem antes de passar o usuário para uma outra URL. O primeiro parâmetro deve guardar a mensagem a ser mostrada, e o segundo parâmetro é uma URL relativa CakePHP. CakePHP vai mostrar a mensagem na variável $message, por um tempo definido em segundos na variável $pause antes de direcionar o usuário. Para mensagens flash dentro da página, dê uma olhada no método setFlash() do component Session. Callbacks Controllers CakePHP vem com callbacks para inserir lógica exatamente antes ou depois das actions serem rederizadas.
  • 31.
    Desenvolvendo com CakePHP 30  beforeFilter() Essa função é executada antes de qualquer action no controller. É o lugar ideal para checar uma sessão ativa ou inspecionar permissões.  beforeRender() Chamada após a lógica da action do controller, mas antes da view ser renderizada. Esse callback não é usado geralmente, mas pode ser necessário se você está chamando render() manualmente antes do final de uma dada action.  afterFilter() Chamada depois de toda action do controller.  afterRender() Chamada depois que uma action tiver sido renderizada. Outros métodos  constructClasses() Esse método carrega os models requeridos pelo controller. Esse processo de carregamento é feito pelo CakePHP normalmente, mas o método é uma boa quando estiver acessando controllers de diferentes perspectivas. Se você precisa do CakePHP em um script de linha de comando ou outro uso de fora, constructClasses() pode ser uma boa.  referrer() Retorna a URL referida pela requisição atual.  disableCache() Usado para dizer ao navegador do usuário não fazer cache dos resultados na requisição atual. Isso é diferente do cache da view, coberto no capítulo anterior.  postConditions(array $data, mixed $op, string $bool, boolean $exclusive) Use esse método para tornar um grupo de dados enviados por POST (de inputs compatíveis com o helper Html) em um grupo de condições de busca para o model. Essa função oferece um atalho rápido para criar lógica de busca. Por exemplo, um usuário administrativo pode querer ser capaz de buscar compras para saber quais itens precisam ser enviados. Você pode criar um rápido formulário baseado no model Compra. Então a action do controller pode usar os dados enviados do formulário para criar as condições de busca. function index() { $c = $this->Compras->findAll($this->postConditions($this->data)); $this->set('compras', $c); }
  • 32.
    Desenvolvendo com CakePHP 31 Se $this->data['Compra']['destino'] é igual a “Padaria da Cidade Velha”, postConditions converte essa condição para um array compatível para uso no método NomeDoModel- >findAll(). Nesse caso, array(“Compra.destino” => “Padaria da Cidade Velha”). Se você quer usar um operador SQL diferente entre os termos, forneça-os usando o segundo parâmetro. /* Conteúdo de $this->data array( 'Compra' => array( 'num_de_itens' => '4', 'fornecedor' => 'Trigo Integral LTDA' ) ) */ // Vamos pegar compras que tem ao menos 4 itens e contém 'Trigo Integral LTDA' $c = $this->Compra->findAll($this->postConditions( $this->data, array('>=', 'LIKE') )); O índice nas especificações de operadores é a ordem das colunas no array $this->data. Já que num_de_itens é o primeiro, o operador >= aplica-se a ele. O terceiro parâmetro lhe permite dizer ao CakePHP que operador booleano SQL usar entre as condições de busca. Strings com 'AND', 'OR', e 'XOR' são todos valores válidos. Finalmente, se o último parâmetro está configurado para true, e o parâmetro $op é um array, os campos não incluídos em $op não serão incluídos nas condições retornadas.  cleanUpFields(string $modelClass = null) Esse método de conveniência concatena as várias partes de datas em $this->data antes de salvar. Se você tem inputs de data do helper Form, esse método concatena o ano, mês, dia e hora em uma string mais compatível com banco de dados. Esse método usa o model padrão do controller (por ex.: o model Cookie para o controller CookiesController) como alvo para a concatenação, mas uma classe alternativa pode ser usada como primeiro parâmetro.  paginate() Esse método é usado para paginar os resultados divididos pelos seus models. Você pode especificar tamanhos de páginas, condições de busca do model e mais. Detalhes sobre esse método mais a frente. Dê uma olhada no capítulo de paginação mais a frente nesse manual.  requestAction(string $url, array $options) Essa função chama uma action de controller de qualquer lugar e retorna os dados dessa action. A $url passada é uma URL relativa ao CakePHP
  • 33.
    Desenvolvendo com CakePHP 32 (/nomedocontroller/nomedaaction/parametros). Se o array $options incluir um valor de returno. AutoRender é automaticamente configurada para true para a action do controller, tendo a requestAction te levando para a view totalmente renderizada. Nota: apesar de ser possível usar requestAction() para pegar uma view totalmente renderizada, a perda performance que você obtém passando por toda a camada da view novamente na realidade não faz valer a pena. O método requestAction() é melhor usado em conjunto com elements - como um caminho para enviar lógica de negócio para um element antes da renderização. Primeiro, vamos ver como pegar dados da action do controller. Primeiro, nós precisamos criar a action do controller que retorna algum dado que precisamos em vários lugares através da aplicação: // Aqui está nosso controller simples: class UsuariosController extends AppController { function pegarListaDeUsuarios() { return $this->Usuario->findAll("Usuario.ativo = 1"); } } Imagine que nós precisamos criar uma simples tabela mostrando os usuários ativos no sistema. Ao invés de duplicar o código de geração de lista em outro controller, nós podemos pegar dados do UsuariosController->pegarListaDeUsuarios() ao invés de usar requestAction(); class ProdutosController extends AppController { function mostrarProdutosDoUsuario() { $this->set( 'usuarios', $this->requestAction('/usuarios/pegarListaDeUsuarios') ); // Agora a variável $usuarios na view vai ter dados do // UsuariosController::pegarListaDeUsuarios(). } } Se você tem um element na sua aplicação que não é estático, você pode querer usar requestAction() para enviar lógica equivalente à do controller para o element a medida em que você o injeta nas suas views. Apesar de elements sempre tem acesso a qualquer variável da view que o controller passou, essa é uma forma de passar dados para o element vindos de outro controller. Se você criou uma action do controller que fornece a lógica necessária, você pode pegar dados e passá-lo para o segundo parâmetro do método renderElement() da view usando requestAction(). <?php echo $this->renderElement( 'usuarios', $this->requestAction('/usuarios/pegarListaDeUsuarios') );
  • 34.
    Desenvolvendo com CakePHP 33 ?> Se o array '$options' contiver um valor “return”, a action do controller será renderizada dentro de um layout vazio e retornada. Dessa forma, a função requestAction() é útil também em situações Ajax onde um pequeno elemento de uma view precisa ser preenchido antes ou durante uma atualização Ajax. Components (Componentes) Introdução Components (Componentes) são pacotes com funções lógicas que são usadas para serem compartilhadas entre os controllers. Se você está querendo copiar e colar coisas entre os controllers, você pode criar funcionalidades em components para isso. O CakePHP já vem com um conjunto de components para os mais diversos usos, por exemplo:  Segurança  Sessões  Lista de controle de acessos (ACL)  E-mails  Cookies  Autenticação  Manipulação de requisições Cada um dos components será explicado em outros capítulos. Por enquanto, mostraremos apenas como criar seus próprios components. Criando components ajuda a manter o código do controller limpo e permite que você reuse o código entre os projetos ou controllers. Construindo componentes personalizados Suponha que sua aplicação online precisa utilizar funções complexas de matemática em diversas partes da aplicação. Poderíamos, então, criar um component para que esta lógica seja compartilhada entre diversos controllers. O primeiro passo é criar um arquivo para o component e uma classe. Crie o arquivo em /app/controllers/components/math.php. A estrutura básica do arquivo do component é similar a apresentada abaixo. <?php class MathComponent extends Object { function doComplexOperation($amount1, $amount2) { return $amount1 + $amount2; } } ?> Quando seu component estiver criado, nós podemos utilizá-lo nos controllers da aplicação colocando o nome do component no vetor da variável $components: // Isso faz com que o novo component possa ser acessado usando $this->Math
  • 35.
    Desenvolvendo com CakePHP 34 var $components = ('Math', 'Session'); Acessando classes do MVC de dentro dos componentes Para ter acesso a instância do controlador dentro do seu novo component, você precisa implementar o método startup(). Este é um método especial que trás a referência do controller como primeiro parâmetro e esta função é chamada automaticamente depois da função beforeFilter() do controller. Se por alguma razão você não quer que o método startup() seja executado quando o controller é instanciado, defina o valor da variável $disableStartup para true. Se você deseja inserir uma lógica antes que o controller seja chamado, use o método initialize() no seu component. <?php class MathComponent extends Object { // chamado antes de Controller:beforeFilter() function initialize() { } // chamado depois de Controller::beforeFilter() function startup(&$controller) { } function doComplexOperation($amount1, $amount2) { return $amount1 + $amount2; } } ?> Você pode também querer utilizar outros components dentro de um component personalizado. Para isso, basta criar a variável $components na classe (assim como você faria em um controller) como um array que contenha os nomes dos components que você deseja utilizar. Models (Modelos) Introdução Campos mágicos Atributos Métodos Associações Introdução Um dos mais poderosos recursos do CakePHP é o mapeamento relacional fornecido pelos models. No CakePHP, as ligações entre os models são manipuladas através de associações.
  • 36.
    Desenvolvendo com CakePHP 35 Definir as relações entre os diversos objetos em sua aplicação deve ser um processo natural. Por exemplo: em uma base de dados de receitas, uma receita pode ter muitas opiniões, opiniões têm um único autor, e os autores podem ter muitas receitas. Definir a forma como estas relações trabalham permite o acesso aos seus dados de uma forma intuitiva e poderosa. O objetivo desta seção é para mostrar-lhe como planejar, definir, utilizar as associações entre os models no CakePHP. Porque a forma mais comum de armazenamento em aplicações web é uma base relacional, a maior parte daquilo que nós vamos cobrir neste manual será, em um banco de dados com um contexto relacionado. Os quatro tipos de associação no CakePHP são: hasOne, hasMany, belongsTo, e hasAndBelongsToMany (HABTM). Tabela 3. Tipos de associações possíveis Tipo de associação Exemplo hasOne Um usuário tem um perfil. hasMany Usuários em um sistema pode ter várias receitas. belongsTo Uma receita pertence a um usuário. hasAndBelongsToMany Receitas tem, e pertencem a muitas tags1. Associações são definidas através da criação de uma classe variável com o nome da associação que você está definindo. A classe variável às vezes pode ser tão simples como uma string, mas pode ser tão completa como um array multidimensional utilizado para definir associações específicas. <?php class User extends AppModel { var $name = 'User'; var $hasOne = 'Profile'; var $hasMany = array( 'Recipe' => array( 'className' => 'Recipe', 'conditions' => 'Recipe.approved = 1', 'order' => 'Recipe.created DESC' ) ); } ?> hasOne Vamos criar um model chamado User que tenha a relação hasOne com o model Profile. Primeiro, suas tabelas da base de dados devem ser introduzidas corretamente. Para uma relação hasOne trabalhar, uma tabela tem de incluir uma chave estrangeira que aponta para um registro na outra. Neste caso, a tabela profiles deverá conter um campo chamado user_id. O padrão básico é: HasOne: os *outros* models contêm a chave estrangeira. 1 Tag: palavra-chave ou etiqueta, neste contexto significa palavra-chave.
  • 37.
    Desenvolvendo com CakePHP 36 Apple hasOne Banana => bananas.apple_id User hasOne Profile => profiles.user_id Doctor hasOne Mentor => mentors.doctor_id O arquivo do model User será salvo em “/app/models/user.php”. Para definir a associação “User hasOne Profile”, adicione a propriedade $hasOne a classe do model. Lembre-se de ter um model Profile em “/app/models/profile.php”, ou a associação não irá funcionar. <?php class User extends AppModel { var $name = 'User'; var $hasOne = 'Profile'; } ?> Existem duas formas de descrever essa relação nos seus models. O método mais simples consiste em definir o atributo $hasOne para uma string contendo o nome da classe do model associado, como fizemos anteriormente. Se você precisar de mais controle, você pode definir suas associações usando um array. Por exemplo, você pode querer classificar linhas relacionadas em ordem decrescente, de acordo com uma data, ou você pode querer limitar a associação para incluir apenas alguns registros. <?php class User extends AppModel { var $name = 'User'; var $hasOne = array( 'Profile' => array( 'className' => 'Profile', 'conditions' => 'Profile.published = 1', 'dependent' => true ) ); } ?> As possíveis chaves do array para associações hasOne são: className: o nome da classe do model a ser associado ao model atual. Se você estiver definindo um relacionamento “User hasOne Profile”, o valor da chave className deve ser igual a 'Profile'; foreignKey: o nome da chave estrangeira encontrada no outro model. Isto é especialmente útil se você precisa definir múltiplos relacionamentos hasOne. O valor padrão para esta chave é o nome no singular do outro model, seguida de “_id”. conditions: Um fragmento SQL utilizado para filtrar registros relacionados do model. É uma boa prática a utilização dos nomes dos modelos nos fragmentos SQL: “Profile.approved = 1” é sempre melhor do que apenas “approved = 1”.
  • 38.
    Desenvolvendo com CakePHP 37 fields: A lista de campos da tabela a serem recuperados quando os dados do model associado são coletados. Retorna todos os campos por padrão. dependent: Quando true, e o método delete() do model é chamado com o parâmetro cascade (cascata) para true, os registros associados do model também são apagados. Neste caso, defini-lo true, a exclusão do User também vai apagar o seu Profile associado. Uma vez que esta associação tenha sido definida, operações de busca sobre o modelo User também vai buscar um registro relacionado de Profile, se existir: // Exemplo de resultados de uma chamada $this->User->find(); Array ( [User] => Array ( [id] => 121 [name] => Gwoo the Kungwoo [created] => 2007-05-01 10:31:01 ) [Profile] => Array ( [id] => 12 [user_id] => 121 [skill] => Baking Cakes [created] => 2007-05-01 10:31:01 ) ) belongsTo Agora que temos o acesso aos dados do Profile pelo model User, vamos definir uma associação belongsTo no model Profile, a fim de obter acesso aos dados relacionados de User. A associação belongsTo é um complemento natural à associações hasOne e hasMany : ele nos permite ver os dados da outra direção. Quando você estiver fazendo suas tabelas na base de dados, com um relacionamento belongsTo, seguir esta convenção: belongsTo: O model *atual* contém a chave estrangeira. Banana belongsTo Apple => bananas.apple_id Profile belongsTo User => profiles.user_id Mentor belongsTo Doctor => mentors.doctor_id Se uma tabela contém uma chave estrangeira, ela faz relacionamento belongsTo. Podemos definir a associação belongsTo no nosso model Profile em “/app/models/profile.php” usando a sintaxe de string como segue: <?php class Profile extends AppModel { var $name = 'Profile'; var $belongsTo = 'User'; }
  • 39.
    Desenvolvendo com CakePHP 38 ?> As possíveis chaves do array para associações belongsTo são: className: o nome da classe do model a ser associado ao model atual. Se você estiver definindo um relacionamento “Profile belongsTo User”, o valor da chave className deve ser igual a 'User'; foreignKey: O nome da chave estrangeira encontrada no outro model. Isto é especialmente útil se você precisa definir múltiplos relacionamentos belongsTo. O valor padrão para esta chave é o singular do nome do outro model, seguida de '_id'. conditions: Um fragmento SQL utilizado para filtrar registros relacionados do model. É uma boa prática a utilização dos nomes dos models nos fragmentos SQL: “User.active = 1” é sempre melhor do que apenas “active = 1”. fields: A lista de campos da tabela a serem recuperados quando os dados do model associado são coletados. Retorna todos os campos por padrão. Uma vez que esta associação tenha sido definida, as operações de busca sobre o model Profile também vai buscar um registro ligado ao registro de User se existir: // Exemplo de resultados de uma chamada $this->Profile->find(). Array ( [Profile] => Array ( [id] => 12 [user_id] => 121 [skill] => Baking Cakes [created] => 2007-05-01 10:31:01 ) [User] => Array ( [id] => 121 [name] => Gwoo the Kungwoo [created] => 2007-05-01 10:31:01 ) ) hasMany Próximo passo: definir uma associação “User hasMany Comment”. A associação hasMany nos permitirá buscar comentários de um usuário quando faz uma operação de busca no model User. Quando você estiver fazendo suas tabelas na base de dados, com um relacionamento hasMany, seguir esta convenção: hasMany: os *outros* models contêm a chave estrangeira. User hasMany Comment => Comment.user_id Cake hasMany Virtue => Virtue.cake_id
  • 40.
    Desenvolvendo com CakePHP 39 Product hasMany Option => Option.product_id Podemos definir a associação hasMany no nosso model User /app/models/user.php usando a sintaxe string como segue: <?php class User extends AppModel { var $name = 'User'; var $hasMany = 'Comment'; } ?> Nós também podemos definir uma relação mais específica utilizando sintaxe de array: <?php class User extends AppModel { var $name = 'User'; var $hasMany = array( 'Comment' => array( 'className' => 'Comment', 'foreignKey' => 'user_id', 'conditions' => 'Comment.status = 1', 'order' => 'Comment.created DESC', 'limit' => '5', 'dependent'=> true ) ); } ?> As possíveis chaves do array para associações hasMany são: className: o nome da classe do model a ser associado ao model atual. Se você estiver definindo um relacionamento “User hasMany Comment”, a chave className deve ser igual “Comment”. foreignKey: o nome da chave estrangeira encontrada no outro model. Isto é especialmente útil se você precisa definir múltiplos relacionamentos hasMany. O valor padrão para esta chave é o nome do outro model no singular, seguida de “_id”. conditions: Um fragmento SQL utilizado para filtrar registros no model relacionado. É uma boa prática a utilização nome do model nos fragmentos SQL: “Comment.status = 1” é sempre melhor do que apenas “status = 1”. fields: A lista de campos a serem recuperados quando os dados do model associado são coletados. Retorna todos os campos por padrão. order: Um fragmento SQL que define a classificação para a ordem para o retorno de linhas associadas. limit: O número máximo de linhas associadas que você quer que retorne.
  • 41.
    Desenvolvendo com CakePHP 40 offset: O número de linhas associadas para saltar sobre (dadas as atuais condições e ordem), antes de ir buscar e associar. dependent: Quando true, é possível a eliminação recursiva. Neste exemplo, Os registros de Comment serão apagados quando o seu associado registro de User for excluído. Nota: o segundo parâmetro do método Model->delete() deve ser true, a fim de ocorrer a supressão (eliminação) recursiva. finderQuery: Uma completa consulta SQL CakePHP que pode-se usar para buscar registros associados. Isto deve ser utilizado em situações que exijam muito resultado personalizado. Uma vez que esta associação tenha sido definida, As operações de busca sobre o model User também vai buscar registros relacionados em Comment se existirem: // Exemplo de resultados de uma chamada $this->User->find(); Array ( [User] => Array ( [id] => 121 [name] => Gwoo the Kungwoo [created] => 2007-05-01 10:31:01 ) [Comment] => Array ( [0] => Array ( [id] => 123 [user_id] => 121 [title] => On Gwoo the Kungwoo [body] => The Kungwooness is not so Gwooish [created] => 2006-05-01 10:31:01 ) [1] => Array ( [id] => 123 [user_id] => 121 [title] => More on Gwoo [body] => But what of the Nut? [created] => 2006-05-01 10:41:01 ) ) ) Uma coisa para se lembrar é que você precisará de um nova associação “Comment belongsTo User”, a fim de obter os dados de ambos os sentidos. O que temos esboçado nesta seção lhe dá poderes para obter os dados dos comentários do usuário. Adicionando a associação Comment belongsTo User no model Comment lhe dá poderes para obter os dados do usuário a partir do model Comment - completa a ligação e permitindo que haja o fluxo de informação a partir de qualquer perspectiva de model.
  • 42.
    Desenvolvendo com CakePHP 41 hasAndBelongsToMany (HABTM) Tudo bem. Neste ponto, você já pode chamar você mesmo de profissional em associações de models no CakePHP. Você já está bem versado (experiente) nas três associações que ocupam a maior parte das relações entre objetos. Vamos resolver o último tipo de relacionamento: hasAndBelongsToMany, ou HABTM. Esta associação é usada quando você tem dois models que precisam se juntar, várias vezes, muitas vezes, de muitas formas diferentes. A principal diferença entre hasMany e HABTM é que a ligação entre os modelos em HABTM não é exclusiva. Por exemplo, estamos prestes a juntar nosso model Recipe (Receita) com o model Tag usando HABTM. Anexando a tag “Italian” a minha receita “grandma's Gnocci” não “esgota” o registro do Tag. Também posso marcar o meu churrasco Honey Glazed Spaghettio's com a tag “Italian” se eu quiser. Ligações entre objetos associados com hasMany são exclusivos. Se User hasMany Comment, um comentário é apenas ligado a um usuário específico. Deixou-se para ganhar. Avancemos. É preciso criar uma tabela extra no banco de dados para manipular associações HABTM. Esta nova tabela deve juntar o nome das tabelas associadas, incluindo os nomes de ambos os models envolvidos, em ordem alfabética. O conteúdo da tabela deve ser de pelo menos dois campos, cada um com uma chave estrangeira (que devem ser inteiros) apontando para ambas as chaves primárias dos modelos envolvidos. HABTM: Requer uma tabela separada que inclui os dois nomes dos models. Nota: O nome da tabela deve estar em ordem alfabética. Recipe HABTM Tag => recipes_tags.recipe_id, recipes_tags.tag_id Cake HABTM Fan => cakes_fans.cake_id, cakes_fans.fan_id Foo HABTM Bar => bars_foos.foo_id, bars_foos.bar_id Uma vez que esta nova tabela foi criada, podemos definir a associação HABTM nos arquivos dos models. Estamos indo saltar diretamente a sintaxe array desta vez: <?php class Recipe extends AppModel { var $name = 'Recipe'; var $hasAndBelongsToMany = array( 'Tag' => array('className' => 'Tag', 'joinTable' => 'recipes_tags', 'foreignKey' => 'tag_id', 'associationForeignKey' => 'recipe_id', 'conditions' => '', 'order' => '', 'limit' => '', 'uniq' => true, 'finderQuery' => '', 'deleteQuery' => '', 'insertQuery' => '' ) );
  • 43.
    Desenvolvendo com CakePHP 42 } ?> foreignKey: O nome da chave estrangeira encontrada no outro model. Isto é especialmente útil se você precisa definir múltiplos relacionamentos HABTM. O valor padrão para esta chave é o nome do outro model no singular, seguida de “_id”. associationForeignKey: O nome da chave estrangeira encontrada no model atual. Isto é especialmente útil se você precisa definir múltiplos relacionamentos HABTM. O valor padrão para esta chave é o nome do atual model no singular, seguida de “_id”. conditions: Um fragmento SQL utilizado para filtrar registros no model relacionado. É uma boa prática a utilização nome do model nos fragmentos SQL: “Recipe.status = 1” é sempre melhor do que apenas “status = 1”. fields: A lista de campos a serem recuperados quando os dados do model associado são coletados. Retorna todos os campos por padrão. order: Um fragmento SQL que define a classificação para a ordem para o retorno de linhas associadas. limit: O número máximo de linhas associadas que você quer que retorne. offset: O número de linhas associadas para saltar sobre (dadas as atuais condições e ordem), antes de ir buscar e associar. dependent: Quando true, é possível a eliminação recursiva. Neste exemplo, Os registros de Comment serão apagados quando o seu associado registro de User for excluído. Nota: o segundo parâmetro do método Model->delete() deve ser true, a fim de ocorrer a supressão (eliminação) recursiva. finderQuery, deleteQuery, insertQuery: Uma completa consulta SQL CakePHP que pode-se usar para buscar registros associados. Isto deve ser utilizado em situações que exijam muito resultado personalizado. Uma vez que esta associação tenha sido definida, operações de busca sobre o model Recipe (Receita) também vai buscar registros relacionados em Tag caso existam: // Exemplo de resultados de uma chamada $this->Recipe->find(); Array ( [Recipe] => Array ( [id] => 2745 [name] => Chocolate Frosted Sugar Bombs [created] => 2007-05-01 10:31:01 [user_id] => 2346 ) [Tag] => Array (
  • 44.
    Desenvolvendo com CakePHP 43 [0] => Array ( [id] => 123 [name] => Breakfast ) [1] => Array ( [id] => 123 [name] => Dessert ) [2] => Array ( [id] => 123 [name] => Heart Disease ) ) ) Lembre-se de definir uma associação HABTM no model Tag se quiser buscar dados do model Recipe, quando se utiliza o model Tag para pesquisas. Salvando dados em tabelas relacionadas (hasOne, hasMany, belongsTo) Ao trabalhar com models associados, é importante perceber que ao salvar os dados do model deve sempre ser feita pelo model CakePHP correspondente. Se você está salvando um novo Post e seus comentários associados, então você deve usar ambos os models Post e Comment durante a operação de salvamento. Se nenhum dos registros do model associado, existem ainda no sistema (por exemplo, você pretende gravar um novo User com seus respectivos registros de Profile ao mesmo tempo), você precisa primeiro salvar o primário, ou model pai. Para ter uma idéia de como isso funciona, vamos imaginar que temos uma função no nosso UsersController que manipula o salvamento de um novo User e seu relacionado Profile. O exemplo mostrado abaixo, a função irá assumir que você POSTou dados suficientes (usando o FormHelper) para criar um único usuário e um único perfil. function add() { if (!empty($this->data)) { // Podemos salvar os dados de User // Deve-se estar em $this->data['User'] $this->User->save($this->data); // Agora nós adicionamos a informação que identifica // o usuário da base de dados a $this->data['Profile'] // e salvamos o Profile. // A ID do usuário recém-criado foi definida // em $this->User->id. $this->data['Profile']['user_id'] = $this->User->id; // O salvamento do Profile pode ocorrer no model User // Porque a nossa relação "User hasOne Profile", pode acessar // o model Profile através do model User:
  • 45.
    Desenvolvendo com CakePHP 44 $this->User->Profile->save($this->data); } } Como regra geral, quando se trabalha com associações hasOne, hasMany, e belongsTo. Estas são todas as informações sobre a sua implementação. A idéia básica é obter a chave de um model e colocá-la no campo chave estrangeira do outro. Por vezes, este poderia envolver a utilização do atributo $id da classe do model após um save(), mas outras vezes isso pode envolver apenas recolher o ID de um input hidden em um formulário que é apenas tenha sido POSTado a uma função do controller. Salvando dados em tabelas relacionadas (HABTM) Salvando models que estão associados por hasOne, belongsTo, e hasMany é bastante simples: basta você preencher o campo chave estrangeira com a ID do model associado. Feito isso, basta você chamar o método save() sobre o model, e tudo fica ligado corretamente. Com HABTM, é um pouco complicado, mas temos ido fora da nossa forma a torná-lo o mais simples possível. Em consonância (concordância), juntamente com o nosso exemplo, vamos precisar fazer algum tipo de formulário que relaciona tags a receitas. Vamos agora criar um formulário que gera tags, e associá-las a uma lista de receitas existentes. Talvez você realmente deseje criar um formulário que cria novas tags e associá-las durante a execução - mas pelo bem da simplicidade, vamos apenas mostrar-lhe como associá-los e deixá- lo continuar a partir daí. Vamos apenas iniciar com a parte do formulário que gera uma tag. Lembra-se de nosso original exemplo “Recipe HABTM Tags”? O mais simples de HTML pode parecer algo como isto: <?php echo $form->create('Tag');?> <?php echo $form->hidden( 'Recipe.Recipe', array('value' => $recipe_id) ) ?> <p><?php echo $form->input('Tag.name');?></p> <p><?php echo $form->end('Adicionar Tag');?></p> </form> Ligações HABTM são formadas por um campo de formulário, nomeado com o nome do outro model envolvido na associação HABTM. Neste exemplo, você pode ver o campo hidden 'Recipe/Recipe' cujo valor é definido com a ID da receita que queremos relacionar para a tag que será salva. A função do controller que trata este formulário poderá ser semelhante a esta: function add() { // Primeiro, vamos obter a ID da tag atual $this->Tag->recursive = 0; $tag = $this->Tag->findByName($this->data['Tag']['name']); // Você pode querer criar a tag aqui se não existir, // Mas nós estamos assumindo que ela existe para avançar. :) // Definimos esta ID em $this->data, marcando-a como a
  • 46.
    Desenvolvendo com CakePHP 45 // tag que queremos associar. $this->data['Tag']['id'] = $tag['Tag']['id']; // Definimos a ID da receita em $this->data, marcando-a como a // receita que queremos associar. $this->data['Recipe']['Recipe'] = array( $this->data['Recipe']['Recipe'] ); // Salva a associação if ($this->Tag->save($this->data)) { // Faça alguma coisa quando obter sucesso. } } Voila, dados dos models estão associados. Para analisar: a fim de salvar relacionamentos HABTM, preencher $this->data['OutroModelo']['OutroModelo'] com um array contendo a ID (ou IDs) dos registros que você deseja associar, e salvar o model atual , certificando-se que $this->data[ModeloAtual]['id'] esteja em vigor. Criando e removendo relações durante execução Por vezes, torna-se necessário criar e destruir associações no model durante a execução. Isso pode acontecer por algum número de razões:  Você deseja reduzir a quantidade coletada de dados associados, mas todas as suas associações estão no primeiro nível de recursão;  Você quer mudar o modo como uma associação é definida, a fim de ordenar ou filtrar dados associados. Esta criação e destruição de associação é feita usando os métodos bindModel() e unbindModel() do model CakePHP. Vamos configurar alguns models, para que possamos ver como bindModel() e unbindModel() trabalham. Nós vamos começar com dois models: <?php class Leader extends AppModel { var $name = 'Leader'; var $hasMany = array( 'Follower' => array( 'className' => 'Follower', 'order' => 'Follower.rank' ) ); } ?> <?php class Follower extends AppModel { var $name = 'Follower'; } ?>
  • 47.
    Desenvolvendo com CakePHP 46 Agora, no LeadersController, podemos usar o método find() do model Leader para buscar um líder e seus seguidores associados. Como você pode ver acima, a associação em sintaxe de array no model Leader define um relacionamento “Leader hasMany Follower”. Para fins de demonstração, vamos usar unbindModel() para remover esta associação em uma função do controller. function someAction() { // Isto recupera Líderes, e seus seguidores associados $this->Leader->findAll(); // Vamos remover o hasMany ... $this->Leader->unbindModel( array('hasMany' => array('Follower')) ); // Agora usando a função find() irá retornar // Líderes, sem os seus seguidores $this->Leader->find(); // NOTA: unbindModel() afeta somente a mais próxima // função find(). Uma nova chamada find() será usada // a informação configurada na associação do model. // Já utilizando findAll(), após unbindModel(), // esta vai buscar Líderes com seguidores // associados mais uma vez ... $this->Leader->findAll(); } Mais um lembrete. Removendo ou adicionando associações usando bind e unbindModel() só funciona para a próxima operação do model, a menos que o segundo parâmetro $reset for escolhido para true. Se o segundo parâmetro foi escolhido para true, ao vincular este parâmetro, a funções binds, mantém-se em vigor para o restante dos pedidos ou pesquisas. Aqui está a base para o uso padrão de unbindModel(): $this->Model->unbindModel( array('associationType' => array('associatedModelClassName')) ); // associationType => O tipo de associação com o outro model (associatedModelClassName) que você quer remover. Agora que removida com êxito uma associação durante a execução, vamos adicionar uma. Nossa como de ainda temos Líderes sem princípios necessitamos alguns Princípios associados. O arquivo do model para o nosso model Principle está vazio, com exceção para a declaração var $name. Vamos associar alguns princípios para ao nosso model Leader durante a execução (mas lembre: apenas servirá a próxima operação de busca). Esta função aparece no LeadersController: function anotherAction() { // Não há "Leader hasMany Principles" no // arquivo do model leader.php, // aqui somente vamos encontrar Líderes.
  • 48.
    Desenvolvendo com CakePHP 47 $this->Leader->findAll(); // Vamos usar bindModel() para adicionar uma nova associação // para o model Leader. $this->Leader->bindModel( array('hasMany' => array( 'Principle' => array( 'className' => 'Principle' ) ) ) ); // Agora que está ligado corretamente, // Podemos utilizar uma única função find() para buscar // Líderes com seus associados princípios: $this->Leader->findAll(); } Isto é o que você tem. A base para uso do bindModel() é o encapsulamento de uma associação normal dentro de um array cuja chave é nomeada após o tipo de associação que você está tentando criar: $this->Model->bindModel( array('associationName' => array( 'associatedModelClassName' => array( // Aqui você pode usar normalmente as chaves e/ou opções de associação. ) ) ) ); Embora o model recém-vinculado não precise de nenhum tipo de associação na definição do model dentro do arquivo dele, ele ainda precisa ser introduzido corretamente para que a nova associação funcione corretamente. DataSources Behaviors Introdução Usando Behaviors TreeBehavior TranslateBehavior ACLBehavior Views (Visões) Templates / Skin Em CakePHP, você fala com seus usuários através da camada das views. A maior parte do tempo, suas views estarão mostrando documentos (x)HTML para os navegadores, mas você
  • 49.
    Desenvolvendo com CakePHP 48 pode também precisar servir dados AMF para um objeto Flash, responder a uma aplicação remota via SOAP, ou exportar um arquivo CSV para um usuário. Os arquivos de view do CakePHP são escritos em PHP comum e tem a extensão padrão de .ctp (CakePHP Template). Esses arquivos contêm toda a lógica de apresentação necessária para transformar os dados recebidos do controller em um formato que está pronto para a audiência. Arquivos de view são guardados em /app/views/, em um diretório com o nome do controller que usa os arquivos, e nomeado de acordo com a view a qual corresponde. Por exemplo, a action ver() do controller Produtos será normalmente encontrada em /app/views/produtos/ver.ctp. A camada da view no CakePHP pode ser feita de algumas diferentes partes. Cada parte tem diferentes usos, e será coberta em seu capítulo:  layouts: arquivos view que contém o código da apresentação que é encontrado envolvendo muitas interfaces em sua aplicação. A maior parte das views é renderizada dentro de um layout;  elements: pedaços de código pequenos e reutilizáveis. Elements são geralmente renderizados dentro de views;  helpers: essas classes encapsulam lógica da view que é necessária em muitos lugares na camada da view. Entre outras coisas, helpers no CakePHP podem ajudá-lo a construir formulários, construir funcionalidade Ajax, paginar dados do model, ou servir feeds RSS. Layouts Um layout contém código de apresentação que envolve uma view. Qualquer coisa que você quiser ver em todas as suas views deve ser colocada em um layout. Arquivos de layout devem ser colocados em /app/views/layouts. O layout padrão pode ser sobrescrito criando um novo layout padrão em /app/views/layouts/default.ctp. Uma vez que um novo layout foi criado, código de view renderizado pelo controller é colocado dentro do layout padrão quando a página é renderizada. Quando você cria um layout, você precisa dizer ao CakePHP onde colocar o código de suas views. Para tanto, garanta que seu layout tem um lugar para o conteúdo do layout através da variável $content_for_layout (e opcionalmente, título para o layout através da variável $title_for_layout). Aqui vai um exemplo do que um layout padrão deve parecer: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title><?php echo $title_for_layout?></title> <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"> </head> <body> <!-- Se você gostaria que algum tipo de menu seja
  • 50.
    Desenvolvendo com CakePHP 49 mostrado em todas as suas views, insira ele aqui --> <div id="header"> <div id="menu">...</div> </div> <!-- É aqui que eu quero que minhas views apareçam --> <?php echo $content_for_layout ?> <!-- Adicione um rodapé para cada página mostrada --> <div id="footer">...</div> </body> </html> Para configurar um título para o layout, é mais fácil fazê-lo no controller, usando a variável de controller $pageTitle. class UsuariosController extends AppController { function verAtivos() { $this->pageTitle = 'Ver Usuários Ativos'; } } Você pode criar quantos layouts você desejar: apenas coloque-os no diretório /app/views/layouts, e escolha entre eles o ideal para cada action do controller usando a variável $layout ou a função setLayout(). Controllers que não tenham a variável $layout configurada usarão o layout padrão. Por exemplo, se uma sessão do meu site incluir um pequeno espaço para banner, eu posso criar um novo layout com um pequeno espaço para propaganda e especificá-lo como layout para todas as actions de controller usando algo como: class UsuariosController extends AppController { var $layout = 'padrao_propag_mini'; function verAtivos() { $this->pageTitle = 'Ver Usuários Ativos'; $this->layout = 'padrao_propag_mini'; } function verImagem() { $this->layout = 'imagem'; // imprimir a imagem para o usuário } } CakePHP tem em seu núcleo, dois layouts (além do layout padrão) que você pode usar em suas aplicações: 'ajax' e 'flash'. O layout Ajax é ótimo para criar respostas Ajax - é um layout vazio (a maior parte das chamadas ajax requer pouca marcação em retorno, ao invés uma interface totalmente renderizada). O layout flash é usado para mensagens mostradas pelos métodos flash() dos controllers. Três outros layouts - xml, js, e rss - existem no núcleo para acelerar e facilitar servir conteúdo diferente de text/html.
  • 51.
    Desenvolvendo com CakePHP 50 Elements (Elementos) Muitas aplicações têm pequenos blocos de código de apresentação que precisa ser repetido de página em página, algumas vezes em diferentes lugares no layout. O CakePHP te ajuda a repetir partes do seu website que precisam ser reutilizadas. Essas partes reutilizáveis são chamadas elements. Um element é basicamente uma mini-view que pode ser incluída em outras views. Elements vivem no diretório /app/views/elements/, e tem uma extensão .ctp no nome de arquivo. Por padrão, elements são estáticos. Você pode dar vida aos seus elements e passar para eles variáveis da view usando um parâmetro adicional no método renderElement(). // Chamando um element sem parâmetros // Esse element só contém código estático de view. <?php echo $this->element('ajuda'); ?> // Chamando um element passando um array de dados, // permitindo que o element se comporte dinamicamente. <?php echo $this->element( 'ajuda', array('mensagem' => 'Ah, esse texto é realmente muito útil.')); ?> Nota: Você pode aproveitar o sistema de cache de view do CakePHP se você fornecer “cache” como true no segundo parâmetro do método element(). // Renderiza o element e faz cache dele por um dia <?php echo $this->element('ajuda', array('cache' => true)); ?> Dentro do arquivo element, todos as variáveis estão disponíveis como os nomes dos índices do array fornecido (muito parecido com como set() funciona no controller com arquivos de view). No exemplo acima, o arquivo /app/views/elements/ajuda.ctp pode usar a variável $mensagem. Uma forma de aproveitar totalmente os elements é usar requestAction(). A função requestAction() preenche a view com variáveis da action do controller e as retorna como um array. Isso torna possível aos seus elements agir realmente no estilo MVC. Crie uma action do controller que prepara as variáveis da view para seus elements e chame requestAction() dentro do segundo parâmetro de requestElement() para preencher o element com as variáveis de view vindas do controller. Elements podem ser usados para fazer a view mais legível, colocando os elementos repetitivos em seus próprios arquivos. Eles podem também ajudá-lo a reutilizar fragmentos de conteúdo em sua aplicação. Helpers (Ajudantes) Introdução Helpers (Ajudantes) são classes do tipo component para a camada de apresentação da sua aplicação. Eles contêm lógica de apresentação que é compartilhada entre muitas views,
  • 52.
    Desenvolvendo com CakePHP 51 elements ou layouts. Cada helper estende AppHelper (opcionalmente definido em /app/app_helper.php), uma classe que guarda qualquer lógica necessária para todos os helpers. O propósito desse capítulo é mostrar a você como criar seus próprios helpers, destacar algumas tarefas básicas que os helpers do CakePHP podem ajudá-lo a realizar. Você usa helpers em CakePHP tornando os controllers conscientes deles. Cada controller tem uma variável de classe especial chamada $helpers que mantém uma lista dos helpers disponíveis para todas as views que esse controller renderiza. Para disponibilizar um helper em sua view do controller, adicione o nome do helper no array $helpers desse controller. <?php class PadeirosController extends AppController { var $helpers = array('Form', 'Html', 'Javascript', 'Time'); } ?> Helpers do CakePHP O CakePHP tem alguns helpers muito úteis na criação de views. Eles ajudam na criação de marcação bem formatada (incluindo formulários), ajudam na formatação de texto, datas e números, e pode até acelerar uma funcionalidade Ajax. Aqui está uma lista rápida dos helpers com um resumo das suas habilidades. Para mais informação sobre um helper particular, dê uma olhada em sua respectiva sessão da parte de Helpers internos. Tabela 4. Helpers internos do CakePHP Helper CakePHP Descrição Ajax Usado também com a biblioteca JavaScript Prototype para criar funcionalidade Ajax nas views. Contém métodos de atalho para arrastar/soltar, formulários ajax & links, observers, e mais. Cache Usado internamente para para criar cache do conteúdo das views. Form Cria formulários HTML e elementos de formulários com habilidade de auto-popular e manipulam problemas de validação. Html Métodos de conveniência para criação de marcação bem formatada. Imagens, links, tabelas, tags de cabeçalho e mais. Javascript Usado para escapar valores para uso em JavaScripts, escrever dados para objetos JSON, e formatar blocos de código. Number Formatação de números e moedas Paginator Paginação de dados do model e organização. Rss Métodos de conveniência para exportar dados XML RSS Session Acesso para escrita de valores de sessão nas views Text Links automáticos, destaques, e truncamento automático de palavras. Time Detecção de proximidade (é o ano quem vem?), formatação de strings (Hoje, 10:30 am) e conversão de zona de tempo. Xml Métodos de conveniência para criar cabeçalhos e elementos XML.
  • 53.
    Desenvolvendo com CakePHP 52 Criando helpers Se um helper interno (ou um mostrado em Cakeforge ou em Bakery) não se adapta a suas necessidades, helpers são fáceis de fazer. Vamos dizer que nós queremos criar um helper que pode ser usado para imprimir um tipo específico de link CSS que você precisa em muitos lugares diferentes em sua aplicação. Para colocar sua lógica na estrutura de helpers dos CakePHP, você deve criar uma nova classe em /app/views/helpers. Vamos chamar nosso helper de LinkHelper. O arquivo de classe PHP atual vai se parecer com isso: <?php /* /app/views/helpers/link.php */ class LinkHelper extends AppHelper { function editar($titulo, $caminho) { // Lógica para criar links especialmente formatados vai aqui... } } ?>  output(string $string) Use essa função para enviar qualquer dado de volta para sua view. function editar($titulo, $caminho) { // Use essa função para enviar qualquer dado formatado // de volta para sua view: return $this->output( "<div class="editarContainer"> <a href="$caminho" class="editar">$titulo</a> </div>" ); } Incluindo outros helpers Você pode querer usar alguma funcionalidade já existente em outro helper. Para tanto, você pode especificar os helpers que você deseja usar com o array $helper, formatado exatamente como você faria no controller. // /app/views/helpers/link.php (usando outros helpers) class LinkHelper extends Helper { var $helpers = array('Html'); function editar($titulo, $caminho) { // Usando o helper HTML para criar // dados formatados: $link = $this->Html->link($titulo, $caminho, array('class' => 'editar')); return $this->output("<div class="editarContainer">$link</div>"); } }
  • 54.
    Desenvolvendo com CakePHP 53 Usando seus helpers personalizados Uma vez que você criou seu helper e o colocou em /app/views/helpers/, você estará habilitado a usá-lo em seus controllers usando a variável especial $helpers. Assim que seu controller estiver consciente de sua nova classe, você pode usá-la em suas views acessando uma variável com o nome do helper: <!-- faz um link usando o novo helper --> <?php $link->editar('Mudar esta receita', '/receitas/editar/5') ?> Nota: lembre-se de incluir o HtmlHelper e/ou FormHelper em seu array $helpers se você planeja usá-los em qualquer lugar. Contribuindo Por favor, considere doar seu código de volta ao CakePHP - contate um dos desenvolvedores usando nosso sistema de Trac ou a lista de e-mails, ou abra um novo projeto em CakeForge para compartilhar seu novo helper com outros. Scaffolding Introdução Scaffold (equivalente em português seria andaime, aqui trataremos como protótipo) de aplicação é uma técnica que permite ao desenvolvedor definir e criar uma aplicação básica que pode criar, obter, atualizar e excluir objetos. Scaffold em CakePHP também permite desenvolvedores definir como objetos são relacionados com outros, e criar e quebrar essas ligações. Tudo que é necessário para criar um scaffold é um model e seu controller. Uma vez que você configurou a variável $scaffold no seu controller você já tem tudo funcionando. O scaffold do CakePHP é muito legal. Ele te dá uma aplicação CRUD (Create - Criar, Retrive - Obter, Update - Atualizar, Delete - Excluir) totalmente funcional em minutos. Tão legal que você vai querer usá-lo em aplicações em fase de produção. Agora, nós também pensamos que ele é legal, mas, por favor, perceba que scaffold é... bem... apenas scaffold. É uma estrutura simples que você põe para funcionar muito rápido no início do projeto para ter algo funcionando o mais rápido possível. Ele não tem intenção de ser completamente flexível, ele é mais como uma forma de já começar com algo funcionando. Se você se perceber precisando personalizar suas lógica e suas views, é hora deixar de lado seu scaffold e escrever um pouco de código. O console Bake do CakePHP, coberto em uma sessão mais a frente, é ótimo próximo passo: ele gera todo o código que produzirá um resultado parecido com o scaffold atual. Scaffold é uma ótima forma de lidar com as partes iniciais do desenvolvimento de uma aplicação web. Esquemas de banco de dados iniciais estão sujeitos a mudanças, o que é perfeitamente normal na parte inicial do processo de design. E aí existe um problema: desenvolvedores web detestam criar formulários que nunca serão realmente usados. Para reduzir o trabalho do desenvolvedor, o scaffold foi adicionado no CakePHP. Ao fazer scaffold o CakePHP analisa suas tabelas do banco de dados e cria listas padronizadas com botões add,
  • 55.
    Desenvolvendo com CakePHP 54 delete e edit, formulários padrões de edição e views padronizadas para inspeção de itens no banco de dados. Para adicionar scaffold na sua aplicação, em seu controller adicione a variável $scaffold: <?php class CategoriasController extends AppController { var $scaffold; } ?> Assumindo que você criou até mesmo o arquivo de classe model Categoria (em /app/models/categoria.php), você está pronto para ir. Visite http://exemplo.com/categorias para ver seu novo scaffold. Nota: criar métodos em controllers que tem scaffold pode causar resultados não desejados. Por exemplo, se você criar uma método index() em um controller com scaffold, seu método index será renderizado ao invés da funcionalidade do scaffold. O scaffold está ciente das associações entre models, então se o seu model Categoria está associado através de belongsTo a um model Usuario, você verá a listagem de IDs do Usuario. Se você ao invés do ID quer ver outra coisa (como o nome do usuário), você pode configurar a variável $displayField no model. Vamos configurar a variável $displayField na class Usuario para que as categorias mostrem usuários pelo nome ao invés de apenas o ID no scaffold. Esse recurso faz com que o scaffold se torne mais legível em muitas situações. <?php class Usuario extends AppModel { var $name = 'Usuario'; var $displayField = 'nome'; } ?> Personalizando os scaffolds Se você está procurando por algo um pouco diferente em suas views de scaffold, você pode criar templates. Nós não recomendamos essa técnica para aplicações em nível de produção, mas esse nível de personalização pode ser útil durante as fases de interação. A personalização é feita através da criação de templates para as views: Views scaffold personalizadas para um controller específico (PostsController neste exemplo) deve ser colocado assim: /app/views/posts/scaffold.index.ctp /app/views/posts/scaffold.show.ctp /app/views/posts/scaffold.edit.ctp /app/views/posts/scaffold.new.ctp Views scaffold para todos os controllers devem ser colocadas assim:
  • 56.
    Desenvolvendo com CakePHP 55 /app/views/scaffolds/index.ctp /app/views/scaffolds/show.ctp /app/views/scaffolds/edit.ctp /app/views/scaffolds/new.ctp /app/views/scaffolds/add.ctp CakePHP Console Introdução Criando Shells e Tasks Criando suas Shells Tasks Gerando código com Bake Plugins Criando um plugin Plugin de controladores Plugin de modelos Plugin de visões Plugin de informações Constantes e funções globais Embora a maior parte do seu dia-a-dia no trabalho com o CakePHP será utilizando as classes e os métodos do núcleo, o CakePHP apresenta inúmeras funções globais que podem ser úteis. Muitas destas funções são para o uso das classes do CakePHP (carregando classes Models ou Components), mas muitas outras funções tornam o trabalho com arrays ou strings um pouco mais fácil. Iremos também abranger algumas das constantes disponíveis. Fazendo uso destas constantes, as atualizações irão se tornar mais fáceis, mas também, são uma maneira conveniente de apontar para determinados arquivos ou diretórios em suas aplicações. Funções globais Aqui estão as funções globais disponíveis no CakePHP. Muitos delas são longas funções do PHP convenientemente reescritas, mas algumas (como vendor(), e uses()) podem ser usadas para incluir códigos ou executar outras funções úteis. Provavelmente, se você estiver querendo uma função para realizar uma tarefa repetitiva, ela estará aqui.  __(string $string_id, boolean $return = false) Esta função manipula a internacionalização nas aplicações CakePHP. A string $string_id identifica a ID para uma tradução, e o segundo parâmetro lhe permite "echoar" a string diretamente (este é o padrão), ou devolvê-la para o tratamento posterior (você deve passar
  • 57.
    Desenvolvendo com CakePHP 56 um valor booleano 'true' para ativar esse comportamento). Confira a seção Internacionalizando para obter mais informações.  a(mixed $one, $two, $three...) Retorna uma array com os parâmetros utilizados na chamada desta função. print_r(a('foo', 'bar')); // Saída: array( [0] => 'foo', [1] => 'bar' )  aa(array $one, $two, $three...) Usado para criar arrays associativas, formada com os parâmetros utilizados na chamada desta função. echo aa('a','b'); // Saída: array( 'a' => 'b' )  am(array $one, $two, $three...) Agrupa todas as arrays passadas como parâmetros.  convertSlash(string $string) Converte barras em underlines e remove o primeiro e ultimo underline em uma string. Retorna a string convertida.  countdim(array $array) Retorna o número de dimensões de uma array fornecida.  debug(mixed $var, boolean $showHtml = false) Se o nível de debug da aplicação é diferente de zero, $var é impresso na tela. Se $showHTML for verdadeiro (true), os dados serão exibidos de forma mais amigável à leitura no navegador.  e(mixed $data) Conveniente reescrita da função echo().  env(string $key) Retorna uma variável de ambiente a partir de fontes disponíveis. Utilizado como um backup caso $_SERVER ou $_ENV estiverem desabilitados.
  • 58.
    Desenvolvendo com CakePHP 57 Esta função também emula PHP_SELF e DOCUMENT_ROOT em servidores que não os suportam. De fato, é uma boa idéia usar sempre a função env() em vez de usar $_SERVER ou getenv() (especialmente se você pretende distribuir seu código), uma vez que ele é um completo emulador das variáveis citadas acima.  fileExistsInPath(string $file) Verifica se o arquivo fornecido está dentro do atual include_path do PHP. Retorna um resultado booleano.  ife($condition, $ifNotEmpty, $ifEmpty) Utilizado em operações ternárias. Se $condition não é vazio, $ifNotEmpty é retornado se não $ifEmpty é retornado.  loadBehavior()  loadComponent()  loadController()  loadControllers()  loadHelper()  loadModel()  loadModels()  loadPluginComponent()  loadPluginController()  loadPluginHelper()  loadPluginModels()  loadView() Este conjunto de funções globais é usado para carregar classes do núcleo do CakePHP para posterior instanciação. Basta fornecer o nome da(s) classe(s) que você gostaria de carregar. Isto é especialmente útil para o console de tarefas. loadModel('Orders'); $Order = new Order();  low(string $string) Conveniente reescrita da função strtolower() do PHP.  paths() Retorna uma array contendo o caminho dos diretórios do CakePHP indexados por Models, Behaviors, Controllers, Components, e Helpers.  pr(mixed $var) Conveniente reescrita da função print_r() do PHP, com a adição da tag <pre> englobando a saída de print_r().
  • 59.
    Desenvolvendo com CakePHP 58  r(string $search, string $replace, string $subject) Conveniente reescrita da função str_replace() do PHP.  stripslashes_deep(array $value) Retira as barras da array informada de forma recursiva, retornando a array modificada.  up(string $string) Conveniente reescrita da função strtoupper() do PHP.  uses(string $lib1, $lib2, $lib3...) Usado para carregar bibliotecas do núcleo do CakePHP (encontradas em cake/libs/).  vendor(string $lib1, $lib2, $lib3...) Usado para carregar bibliotecas externas (de terceiros) encontrados no diretório /vendors ou app/vendors. Constantes do núcleo Tabela 5. Constantes do CakePHP Constante Descrição COMPRESS_CSS Se definido como verdadeiro (true) as folhas de estilo CSS serão compactadas em modo de produção. Isto requer um diretório /var/cache com permissão de escrita pelo servidor. Para utilizar, inclua suas folhas de estilo referenciando-as com o caminho /ccss (diferente de /css) ou utilize o método Controller::cssTag(). LOG_ERROR Constante de erro. Usado para diferenciar erros de Log e Debug. Atualmente o PHP suporta LOG_DEBUG Constantes do diretório Tabela 6. Constantes dos diretórios Constante Caminho absoluto dos diretórios do aplicativo APP Diretório raiz APP_PATH Diretório do aplicativo CACHE Diretório para os arquivos de cache do aplicativo CAKE Diretório do CakePHP COMPONENTS Diretório dos components CONFIGS Diretório dos arquivos de configuração do aplicativo CONTROLLER_TESTS Diretório do controller de testes CONTROLLERS Diretório dos controladors CSS Diretório dos arquivos CSS ELEMENTS Diretório dos elements HELPER_TESTS Diretório dos helpers de teste HELPERS Diretório dos helpers INFLECTIONS Diretório das inflexões (geralmente o mesmo diretório dos arquivos de configuração) JS Diretório dos arquivos JavaScript (no webroot)
  • 60.
    Desenvolvendo com CakePHP 59 LAYOUTS Diretório dos layouts LIB_TESTS Diretório das bibliotecas de testes do CakePHP LIBS Diretório das bibliotecas do CakePHP LOGS Diretório dos arquivos de log (no app) MODEL_TESTS Diretório dos models de teste MODELS Diretório dos models SCRIPTS Diretório de scripts do CakePHP TESTS Diretório de testes (pai das pastas models, controllers, etc. No diretório de testes) TMP Diretório de arquivos temporários VENDORS Diretório para bibliotecas externas (de terceiros) VIEWS Diretório das views
  • 61.
    Tarefas comuns comCakePHP 60 Parte IV. Tarefas comuns com CakePHP Validação de dados Regras simples Uma regra por campo rule required allowEmpty on message Múltiplas regras por campo Construindo regras de validação alphaNumeric between blank cc comparison date email ip minLength maxLength numeric phone postal ssn url Regras de validação personalizada
  • 62.
    Tarefas comuns comCakePHP 61 Validação por expressões regulares personalizadas Validação por métodos personalizados Limpeza de dados Manipulação de erros Debugando Gerando caches Logando Introdução Enquanto algumas definições da Classe de Configuração do CakePHP podem realmente ajudá- lo a ver o que está acontecendo por debaixo dos panos, há certos momentos em que você precisa logar os dados no disco (em um arquivo de texto) para descobrir o que está acontecendo. Num mundo que está cada vez mais dependente de tecnologias como SOAP e AJAX, o ato de debugar pode ser bastante difícil. Logar também pode ser uma maneira de descobrir o que está acontecendo na sua aplicação ao longo do tempo. Quais os termos de busca estão sendo usados? Quais erros estão sendo mostrados aos meus usuários? Quantas vezes uma determinada consulta está sendo executada? Logar dados no CakePHP é fácil. A função log() faz parte da classe Object, que é uma classe ancestral comum para quase todas as outras classes do CakePHP. Se o contexto for uma classe CakePHP (Model, Controller, Component... quase todas), você pode logar seus dados. Usando as funções de log A função log() recebe dois parâmetros. A primeira é a mensagem que você gostaria de escrever no arquivo de log. Por padrão, esta mensagem de erro é escrita no log de erros encontrado em app/tmp/logs/error.log: // Execute isto dentro de uma classe do CakePHP: $this->log("Algo não funciona!"); // O resultado será adicionado ao final do arquivo app/tmp/logs/error.log 2007-11-02 10:22:02 Error: Algo não funciona! O segundo parâmetro é usado para definir o tipo de mensagem de log que você deseja escrever. Se não for informado, o padrão é LOG_ERROR, que escreverá no arquivo mencionado anteriormente. Você pode passar este segundo parâmetro como LOG_DEBUG e escrever as suas mensagens no arquivo de log para debug encontrado em app/tmp/logs/debug.log // Execute isto dentro de uma classe do CakePHP:
  • 63.
    Tarefas comuns comCakePHP 62 $this->log('Uma mensagem de debugação.', LOG_DEBUG); // O resultado será adicionado ao final do arquivo app/tmp/logs/debug.log (em vez de error.log) 2007-11-02 10:22:02 Error: Uma mensagem de debugação. Observação: O diretório app/tmp deve ter permissão de escrita pelo usuário do servidor web para que esta função execute corretamente. Testando Internacionalizando Um dos melhores caminhos para chegar a uma grande platéia é fazer um aplicativo em diversos idiomas. Isso pode representar uma grande tarefa, mas os recursos de internacionalização no CakePHP fazem isto muito mais fácil. Primeiro, é importante que você entenda a terminologia. O termo localização (localization) refere-se à adaptação de uma aplicação para atender as necessidades de um idioma específico (ou cultura), como, por exemplo, um locale. Internacionalização (internacionalization) refere- se à habilidade de sua aplicação se "localizável". Internacionalização e localização são abreviadas como i18n e l10n, respectivamente; 18 e 10 representam a quantidade de caracteres entre o primeiro e o último caractere. Definindo o locale da sua aplicação Qualquer controlador que usa o conteúdo localizado inclui a classe L10 do núcleo do CakePHP. <?php // Include the L10n class: uses(‘L10n’); class RecipesController extends AppController { // ... } ?> Em seguida, você precisa criar os arquivos de idioma que controlam as strings internacionalizáveis. Cada idioma contém um conjunto de strings com suas IDs. Criando estes arquivos, você tem um caminho para ser organizado e traduzido. Cada idioma deve conter o arquivo default.po em uma pasta com o nome do idioma a que se refere. /app/locale/eng/LC_MESSAGES/default.po (Inglês) /app/locale/fre/LC_MESSAGES/default.po (Francês) /app/locale/por/LC_MESSAGES/default.po (Português) /app/local/pt_br/LC_MESSAGES/default.po (Português - Brasil) A pasta locale fica dentro da pasta app da sua instalação do CakePHP. Os caracteres de localização (ex: eng, por, pt_br) seguem o padrão ISO 639-2 (exemplos podem ser encontrados no site do Library of Congress, http://www.loc.gov/standards/iso639-2/php/code_list.php).
  • 64.
    Tarefas comuns comCakePHP 63 Depois de criar os arquivos, preencha-os com as strings chaves e os valores usados para o processo de internacionalização. Cada string chave deve ter um único valor correspondente. Aqui um exemplo básico que deve estar dentro do arquivo .po do idioma português: msgid "purchase" msgstr "Para comprar o item selecionado, clique em Comprar Agora." msgid "search" msgstr "Clique aqui para procurar na nossa base de dados." Note que seus arquivos .po devem ser codificados usando o padrão ISO-8859-1, e que estes não excedam o limite de 1024 caracteres na string de valor (msgstr). Depois de criar os arquivos .po corretamente, sua aplicação já está internacionalizada. Internacionalizando em CakePHP Usando os dados de localização na sua aplicação é simples. O primeiro passo é avisar ao CakePHP qual idioma sua aplicação deve utilizar para mostrar o conteúdo. Isso pode ser feito detectando subdomínios (en.exemplo.com.br ou pt.exemplo.com.br), usando a informação do browser ou qualquer outra maneira. Alteração de idioma deve ser feita no controlador: $this->L10n = new L10n(); $this->L10n->get("en"); Configure::write('Config.language', "en"); Você pode por este código no beforeFilter para fazer com que cada ação no controlador seja mostrada usando o idioma corretamente, ou você pode querer colocar isso em uma ação que manipule a autenticação, ou ainda colocar para escolher o idioma padrão. Para fazer suas strings internacionalizáveis, utilize a função __(). Esta função está disponível globalmente, mas você provavelmente utilizará mais nas visões. O primeiro parâmetro da função é o texto que vai na msgid do arquivo .po. Este conteúdo é exibido (echo) por padrão, mas um segundo parâmetro pode ser utilizado (opcional), que informa se você quer retornar o texto (para manipulação de links, por exemplo). O pequeno exemplo abaixo mostra como internacionalizar strings usando a função __(). A atual saída depende do idioma que foi selecionado usando a classe L10n e as configurações setadas. <hr /> <p><?php __("purchase"); ?></p> <hr /> Lembre-se de usar o parâmetro de retorno em métodos de helper se você deseja que o conteúdo seja traduzido na chamada do método do ajudante. Use o segundo parâmetro do __() para retornar os dados ao invés de exibir (echo): <?php echo $form->error( 'Card.cardNumber', __("errorCardNumber", true), array('escape' => false) ); ?>
  • 65.
    Tarefas comuns comCakePHP 64 Paginação Configurando os controladores Paginando nas visões Paginando com AJAX Alterações no layout Alterações nas visões
  • 66.
    Componentes internos 65 Parte V. Componentes internos Lista de controle de acessos (ACL) Autenticação Sessões Manipulando requisições Segurança E-mail Cookies Introdução Configurando os controladores Usando o componente
  • 67.
    Helpers internos 66 Parte VI. Helpers internos Formulários O FormHelper é uma nova adição ao CakePHP. A maior parte do trabalho pesado na criação de formulário é agora feita usando esta nova classe, em vez dos (agora obsoletos) métodos do HtmlHelper. O FormHelper centra-se na criação de formulários rapidamente, de uma forma que irá dinamizar validação, re-preenchimento e o layout. O FormHelper também é flexível, que vai fazer quase tudo para você automagicamente ou você pode usar métodos específicos para obter apenas o que necessita. Criando formulários O primeiro método que você precisará usar na ordem para ganhar vantagens do FormHelper é o create(). Este método especial retorna uma tag de abertura de formulário.  create(string $model = null, array $options = array()) Todos os parâmetros são opcionais. Se create() é chamada sem parâmetros fornecidos, Esta assume que você está construindo um formulário que será submetido a função add() do controlador atual, via POST. O elemento do formulário também é retornado com o atributo id seguindo um padrão DOM “ModelActionForm”, em forma de camelo. Se eu fosse chamar create() dentro de uma visão (view) do controlador UserController, Eu veria algo como a seguinte saída na visão. <form id="UserAddForm" method="post" action="/users/add"> O método create() permite personalizar muito mais usando os parâmetros, no entanto. Primeiro, você pode especificar um nome de modelo. Este modelo é, então, assumido como o padrão para todos os campos do formulário, bem como o id em DOM da tag do formulário é alterada. <?php echo $form->create('Recipe'); ?> // Saída: <form id="RecipeAddForm" method="post" action="/recipes/add"> * Recipe = Receita O array $options é onde a maior parte da configuração do formulário acontece. Este array especial pode conter um número de diferentes pares valor-chave que afetam a forma como a tag do formulário é gerada. $options['type'] Esta chave é utilizada para especificar o tipo de formulário a ser criado. Os valores válidos incluem 'post', 'get', 'file', 'put' e 'delete'. Preenchendo com 'post' ou 'get' muda o modo de como o formulário submete a informação. <?php echo $form->create('User', array('type' => 'get')); ?>
  • 68.
    Helpers internos 67 // Saída: <form id="UserAddForm" method="get" action="/users/add"> Especificando 'file' muda a forma de submeter para o método “post”, e inclui um atributo enctype de “multipart/form-data” na tag do formulário. Isto é para ser usado se houver algum elemento de entrada de arquivo, dentro do formulário. A ausência de um bom atributo enctype, fará com que o upload de arquivo não funcione. <?php echo $form->create('User', array('type' => 'file')); ?> // Saída: <form id="UserAddForm" enctype="multipart/form-data" method="post" action="/users/add"> Quando estiver usando “put” ou “delete”, o formulário será funcionalmente equivalente a um formulário submetido em modo 'post', mas, quando submetido, o método de solicitação HTTP será ultrapassado com 'PUT' ou 'DELETE', respectivamente. Isto permite o CakePHP emular adequadamente o suporte em navegadores web. $options['action'] A chave $action permite que você aponte o formulário para uma action específica no seu controller atual. Por exemplo, se você gostaria de apontar o formulário para a action login() do controller atual, você deve fornecer um array $options como o seguinte: <?php echo $form->create('Usuario', array('action' => 'login')); ?> // Saída: <form id="UsuarioLoginForm" method="post" action="/usuarios/login"> $options['url'] Se o destino do formulário atual não é o controller atual, você pode especificar a URL para o atributo action do formulário utilizando a chave 'url' do array $options. A URL pode ser fornecida em relação a sua aplicação CakePHP (URL relativa), ou pode apontar para um domínio externo (URL absoluta). <?php echo $form->create(null, array('url' => 'recipes/add')); ?> // Saída: <form method="post" action="/recipes/add"> <?php echo $form->create(null, array( 'url' => 'http://www.google.com/search' 'type' => 'get' )); ?> // Saída: <form method="get" action="http://www.google.com/search"> $options['default'] Se 'default' foi definido para booleano false, a forma de submeter é modificada, de modo que pressionando o botão submit não envia o formulário. Se o formulário destina-se a ser
  • 69.
    Helpers internos 68 submetido via AJAX, a configuração 'default' para false suprime a forma do comportamento padrão, para que você possa pegar os dados e enviá-los via AJAX. Fechando formulários O FormHelper inclui também um método end() que completa a marcação do formulário. Freqüentemente, end() só imprime uma tag de fechamento de formulário, mas usando o end() também permite o FormHelper inserir elementos hidden de formulário quando necessários, isso tudo depende da forma de como é usado. <?php echo $form->create(); ?> <!-- Form elements go here --> <?php echo $form->end(); ?> Se uma string é fornecida como o primeiro parâmetro para end(), o FormHelper retorna um botão de submissão nomeado (ou com o valor) da string dada, juntamente com a tag de fechamento o formulário. <?php echo $form->end('Finish'); ?> Saída: <div class="submit"> <input type="submit" value="Finish" /> </div> </form> Elemento de formulário mágico Primeiro, vamos olhar para alguns dos muitos métodos de criação automática de formulários do FormHelper. O principal método que vamos olhar é o input(). Este método irá automaticamente deduzir o campo do modelo que foi fornecido no primeiro parâmetro, e criará um campo de formulário adequado para esse campo. Tabela 7. Tipo de campos na interface conforme tipo de campo no banco de dados Tipo da coluna Resultando no campo de formulário string (char, varchar, etc.) text boolean, tinyint(1) checkbox Text textarea text, nomeado como password, password passwd, ou psword Date selects de dia, mês, e ano. datetime, timestamp selects de dia, mês, ano, hora, minuto, e meridiano Time selects de hora, minuto, e meridiano Por exemplo, vamos supor que o meu model User inclui campos de username (varchar), a password (varchar), approved (datetime) e quote (text). Posso usar o método input() do FormHelper para criar uma entrada adequada para todos estes campos de formulário. <?php echo $form->create(); ?> <?php
  • 70.
    Helpers internos 69 echo $form->input('username'); // text echo $form->input('password'); // text echo $form->input('approved'); // selects de dia, mês, ano, // hora, minuto, meridiano echo $form->input('quote'); // textarea ?> <?php echo $form->end('Adicionar'); ?> $options['type'] Você pode forçar o tipo de uma entrada (e sobrepor a dedução pelo model), especificando o tipo. Além dos tipos de campos encontrados na tabela acima, você também pode criar entradas 'file', e 'password'. <?php $form->input('field', array('type' => 'file')); Saída: <div class="input"> <label for="UserField">Field</label> <input type="file" name="data[User][field]" id="UserField" /> </div> $options['before'], $options['between'] e $options['after'] Utilize estas chaves se você precisa injetar alguma marcação dentro da saída do método input(). <?php echo $form->input('field', array( 'before' => '--before--', 'after' => '--after--', 'between' => '--between---' ));?> Saída: <div class="input"> --before-- <label for="UserField">Field</label> --between--- <input name="data[User][field]" type="text" value="" id="UserField" /> --after-- </div> $options['options'] Esta chave permite que você especifique manualmente as opções para uma entrada select, ou para um grupo de rádio. A menos que 'type' esteja especificada como 'radio', o FormHelper irá assumir que a meta de saída é um entrada select. <?php echo $form->input('field', array('options' => array(1,2,3,4,5))); ?> Saída: <div class="input"> <label for="UserField">Field</label>
  • 71.
    Helpers internos 70 <select name="data[User][field]" id="UserField"> <option value="0">1</option> <option value="1">2</option> <option value="2">3</option> <option value="3">4</option> <option value="4">5</option> </select> </div> As opções também podem ser preenchidas como pares chave-valor. $options['multiple'] Se 'multiple', foi escolhida para true para uma entrada que retorna um select, a escolha nesta entrada select permitirá várias seleções. $options['maxLength'] Define o número máximo de caracteres permitidos em uma entrada de texto. $options['div'] Defina esta chave false para desativar a saída do div em torno da entrada e de seu marcador (label). $options['label'] Defina esta chave false para desativar a saída do marcador (label) que habitualmente acompanha o input. $options['id'] Definir esta chave para forçar o valor da id DOM para a entrada. $options['error'] Esta chave deve ser ajustada para uma string que será mostrada na eventualidade de um erro de validação. Se 'error' não está definida, uma mensagem de erro genérico padrão será mostrada. $options['selected'] Usado em combinação com uma entrada do tipo select. Defina 'selected' para o valor do item que deseja ser selecionado por padrão quando a entrada é renderizada. $options['rows'], $options['cols'] Estas duas chaves especificam o número de linhas e colunas em uma entrada de texto (textarea). $options['empty'] Se escolhida para true, força a entrada para permanecer vazia. Isso é útil para entrada de senha que normalmente não deveria está preenchida com uma senha do usuário como acontece com o valor padrão. $options['timeFormat'] Utilizado para especificar o formato do tempo nas entradas relacionadas com o tempo. Os valores válidos incluem '12', '24', 'none'.
  • 72.
    Helpers internos 71 $options['dateFormat'] Utilizado para especificar o formato do conjunto de entradas para selecionar uma data. Os valores válidos incluem 'DMY', 'MDY', 'YMD', e 'NONE'. Métodos específicos do elemento de formulário O restante dos métodos disponíveis no FormHelper são para a criação específica de elementos de formulários. Muitos destes métodos também fazem uso de um parâmetro especial $options. Neste caso, porém, $options é usado principalmente para especificar atributos da tag HTML(tais como o valor ou id (DOM) de um elemento do formulário). <?php echo $form->text('username', array('class' => 'users')); ?> Saída: <input name="data[User][username]" type="text" class="users" id="UserUsername" />  checkbox(string $fieldName, array $options) Cria um elemento checkbox. Este método também gera um elemento hidden associado para forçar a apresentação de dados para o especificado campo. <?php echo $form->checkbox('done'); ?> Saída: <input type="hidden" name="data[User][done]" value="0" id="UserDone_" /> <input type="checkbox" name="data[User][done]" value="1" id="UserDone" />  year(string $fieldName, int $minYear, int $maxYear, mixed $selected, array $attributes, boolean $showEmpty) Cria um elemento select preenchido com o passar dos anos a partir de $minYear para $maxYear, com o ano $selected selecionado por padrão. Atributos HTML podem ser oferecidos em $attributes. Se $showEmpty é false, o elemento select não inclue a opção vazia.  month(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty) Cria um elemento select preenchido com nomes dos meses.  dateTime(string $fieldName, string $dateFormat = 'DMY', $timeFormat = '12', mixed $selected, array $attributes, boolean $showEmpty) Cria um conjunto de entradas select para selecionar data e hora. Os valores válidos para $dateformat são 'DMY', 'MDY', 'YMD' ou 'NONE'. Os valores válidos para $timeFormat são '12','24', e 'NONE'.  day(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty) Cria um elemento select preenchido com os dias (numérico) do mês.  hour(string $fieldName, boolean $format24Hours, mixed $selected, array $attributes, Boolean $showEmpty)
  • 73.
    Helpers internos 72 Cria um elemento select preenchido com a hora do dia.  minute(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty) Cria um elemento select preenchido com os minutos da hora.  meridian(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty) Cria um elemento select preenchido com 'am' e 'pm'.  error(string $fieldName, string $text, array $options) Mostra uma mensagem de erro de validação, especificado por $text, para o determinado campo, no evento que um erro de validação tenha ocorrido.  file(string $fieldName, array $options) Cria uma entrada de arquivo.  hidden(string $fieldName, array $options) Cria uma entrada de fomulário hidden.  isFieldError(string $fieldName) Retorna true se o campo fornecido em $fieldName tem uma validação de erro ativa.  label(string $fieldName, string $text, array $attributes) Cria um elemento tag (etiqueta), preenchido com $text.  password(string $fieldName, array $options) Cria uma entrada de senha (password).  radio(string $fieldName, array $options, array $attributes) Cria uma entrada radio.  select(string $fieldName, array $options, mixed $selected, array $attributes, boolean $showEmpty) Cria um elemento select, preenchido com os itens de $options, com uma opção selecionada por padrão, especificada por $selected. Defina $showEmpty para false se você não quer uma opção vazia dentro do select.  submit(string $caption, array $options) Cria um botão Submit com legenda $caption. Se a definição de $caption for uma URL de uma imagem (que contém o caracter '.' (ponto)), o botão submit será exibido como uma imagem.  submitImage(string $path, array $options)
  • 74.
    Helpers internos 73 Cria um botão imagem de submissão, com a imagem especificada pela URL em $path (caminho).  text(string $fieldName, array $options) Cria uma entrada textarea.  textarea(string $fieldName, array $options) Cria uma entrada textarea. HTML Inserindo elementos bem-formados JavaScript AJAX Opções do AjaxHelper Opções gerais Opções de callback Métodos Cache Form Number Text Time
  • 75.
    Exemplos 74 Parte VII. Exemplos Tutorial de como fazer um blog em CakePHP Sistema simples de autenticação de usuários
  • 76.
    Apêndices 75 Parte VIII. Apêndices Escritores da versão inglesa  José Lorenzo  derelm  mar3k  Tarique Sani  Aaron Thies  Ahsanul Bari  Nate Abele  Garrett J. Woodworth  Larry Masters  Mark Story Tradutores para língua portuguesa  Bill Jr.  Juan Basso  Julio Protzek  Sadjow Medeiros Leão  Tarcísio Sassara  Tulio Faria Apoio e revisão da versão traduzida  Gustavo Carreno  Icaro Monteiro Inflexão em português Abaixo segue o código para a inflexão para língua portuguesa. Caso você queira utilizar, coloque o código no arquivo /app/config/inflections.php. <?php /* * Por Sadjow Medeiros Leão (sadjow@gmail.com) * Baseado em http://forum.rubyonbr.org/forums/14/topics/520 */ $pluralRules = array( # # Regra geral: adiciona um "s" no final da palavra # #casa - casas '/^([a-zA-Z]*)a$/i' => '1as', # #pe - pes '/^([a-zA-Z]*)e$/i' => '1es', # #sem exemplo '/^([a-zA-Z]*)i$/i' => '1is', # #carro - carros '/^([a-zA-Z]*)o$/i' => '1os',
  • 77.
    Apêndices 76 # #pneu - pneus '/^([a-zA-Z]*)u$/i' => '1us', # # Se a palavra termina com "r" or "z", adiciona "es" # #luz - luzes # #flor - flores # #arroz - arrozes '/^([a-zA-Z]*)r$/i' => '1res', '/^([a-zA-Z]*)z$/i' => '1zes', # # Se a palavra termina com "al", "el", "ol", "ul": Troca "l" por "is" # #farol - farois # #hospital - hospitais # #telemovel - telemoveis # #pincel - pinceis # #anzol - anzois '/^([a-zA-Z]*)al$/i' => '1ais', '/^([a-zA-Z]*)el$/i' => '1eis', '/^([a-zA-Z]*)ol$/i' => '1ois', '/^([a-zA-Z]*)ul$/i' => '1uis', # # Se palavra termina em "il" e tem acento agudo na última sílaba, troca "il", por "is" #cantil - cantis '/^([a-zA-Z]*)il$/i' => '1is', # # TODO # # Se a palavra termina com "il" e tiver um acento agudo na penultima sílaba, troca "il" por "eis" # # sem exemplo // Esse aqui é um pouco mais complicado. Fiquei de fazer, porque não tem como // identificar acentos quando não se usa acentos( nome das tabelas) // Ainda estou pensando. Me ajuda ok?! # # Se a palavra termina com "m", troca "m" por "ns" # #armazem - armazens # #portagem - portagens # inflect.plural /^([a-zA-z]*)m$/i, '1ns' '/^([a-zA-Z]*)m$/i' => '1ns', # #TODO # # Se a palavra termina com "s" e tem uma sílaba, troca "s" por "es" # #sem exemplo # #inflect.plural /^([a-zA-z]*)e$/i, '1es' # # #TODO # # Se a palavra termina com "x" fica a mesma # #sem exemplo... professor X, telvez? # #inflect.plural /^([a-zA-z]*)x$/i, '1x' #
  • 78.
    Apêndices 77 # # Se a palavra termina com "ão", Existem 3 jeitos para o prural: ãos, ães, ões # #NOTA: Difícil de achar, Eu usei os casos mais conhecidos # # e depois usei os casos irregulares (lá embaixo em $irregularPlural) para os outros. Se alguém conhece # # mais casos, por favor adicione na lista e mande-me um e- mail, obrigado! # # # #cão - cães # #colchão - colchões # #portão - portões # #pão - pães # #alemão - alemães # #chão - ? # #pilhão - pilhões # #canhão - canhões # #bidão - bidões # #mão - mãos '/^([a-zA-Z]*)ao$/i' => '1oes' ); /** * This is a key only array of plural words that should not be inflected. * Notice the last comma * * $uninflectedPlural = array('.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox'); */ $uninflectedPlural = array(); /** * This is a key => value array of plural irregular words. * If key matches then the value is returned. * * $irregularPlural = array('atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers') */ //$irregularPlural = array(); /* Sadjow Medeiros Leão (sadjow@gmail.com) // Irregular */ $irregularPlural = array( 'cao' => 'caes', 'pao' => 'paes', 'mao' => 'maos', 'alemao' => 'alemaes' ); /** * This is a key => value array of regex used to match words. * If key matches then the value is returned. * * $singularRules = array('/(s)tatuses$/i' => '12tatus', '/(matr)ices$/i' =>'1ix','/(vert|ind)ices$/i') */ //$singularRules = array(); /* * Sadjow Medeiros Leão ( sadjow@gmail.com )
  • 79.
    Apêndices 78 */ $singularRules = array( # #pes - pe # #carros - carro # #pneus - pneu '/^([a-zA-Z]*)as$/i' => '1a', '/^([a-zA-Z]*)es$/i' => '1e', '/^([a-zA-Z]*)is$/i' => '1i', '/^([a-zA-Z]*)os$/i' => '1o', '/^([a-zA-Z]*)us$/i' => '1u', # #luzes - luz # #flores - flor # #arrozes - arroz '/^([a-zA-Z]*)res$/i' => '1r', '/^([a-zA-Z]*)zes$/i' => '1z', # #cantis - cantil '/^([a-zA-Z]*)is$/i' => '1il', # # #farois - farol # #hospitais - hospital # #telemoveis - telemovel # #pinceis - pincel # #anzois - anzol '/^([a-zA-Z]*)ais$/i' => '1al', '/^([a-zA-Z]*)eis$/i' => '1el', '/^([a-zA-Z]*)ois$/i' => '1ol', '/^([a-zA-Z]*)uis$/i' => '1ul', # # #armazens - armazem # #portagens - portagem '/^([a-zA-Z]*)ns$/i' => '1m', # # #cães - cão # #colchões - colchão # #portões - portão # #pães - pão # #alemães - alemão '/^([a-zA-Z]*)oes$/i' => '1ao', '/^([a-zA-Z]*)aes$/i' => '1ao', '/^([a-zA-Z]*)aos$/i' => '1ao' ); /** * This is a key only array of singular words that should not be inflected. * You should not have to change this value below if you do change it use same format * as the $uninflectedPlural above. */ $uninflectedSingular = $uninflectedPlural; /** * This is a key => value array of singular irregular words. * Most of the time this will be a reverse of the above $irregularPlural array * You should not have to change this value below if you do change it use same format
  • 80.
    Apêndices 79 * * $irregularSingular = array('atlases' => 'atlas', 'beefs' => 'beef', 'brothers' => 'brother') */ $irregularSingular = array_flip($irregularPlural); ?>