<?xml version="1.0" encoding="utf-8"?>
<!-- generator="Joomla! - Open Source Content Management" -->
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Livros - RibaFS Portal</title>
		<description><![CDATA[Servidores linux, Programação web (PHP, Joomla, CakePHP, Laravel), Programação Mobile (Phaser, PhoneGap, Monaca, Unity, etc) entre outros.]]></description>
		<link>http://backup/portal/curriculo/livros/cakephp.html</link>
		<lastBuildDate>Sat, 07 Sep 2019 19:23:03 -0300</lastBuildDate>
		<generator>Joomla! - Open Source Content Management</generator>
		<atom:link rel="self" type="application/rss+xml" href="http://backup/portal/curriculo/livros/cakephp.feed?type=rss"/>
		<language>pt-br</language>
		<item>
			<title>Código Fonte</title>
			<link>http://backup/portal/curriculo/livros/cakephp/codigo-fonte.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/codigo-fonte.html</guid>
			<description><![CDATA[<h3>Criando Aplicativos e Extensões em CakePHP 3</h3>
<p> </p>
<p><strong>Código fonte dos capítulos</strong></p>
<p> </p>
<p><strong>Atenção:</strong> como estes arquivos foram criados no Linux, que usa UTF-8 por default, então abra em um editor que suporte UTF-8 como</p>
<p>o Noepad++ ou o Visual Studio Code</p>
<p> </p>
<p><a href="http://backup/portal/down/livros/CakePHPCodigoFonte.zip">Download</a></p>
<p> </p>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 16:46:21 -0300</pubDate>
		</item>
		<item>
			<title>20 – Apêndice A - Dicas sobre o Composer</title>
			<link>http://backup/portal/curriculo/livros/cakephp/20-apendice-a-dicas-sobre-o-composer.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/20-apendice-a-dicas-sobre-o-composer.html</guid>
			<description><![CDATA[<h3>20 – Apêndice A - Dicas sobre o Composer<br /> </h3>
<p>Site oficial <br /><a href="https://getcomposer.org">https://getcomposer.org</a>  <br /><br />Documentação<br /><a href="https://getcomposer.org/doc/">https://getcomposer.org/doc/ </a> <br /><br />É um gerenciador de dependências para PHP, com bons recursos para instalar, atualizar e gerenciar módulos em PHP. Ele checa quais as dependências de um pacote e as instala, usando as versões indicadas.<br /><br /><strong>Pré-requisitos para sua instalação:</strong><br />- PHP 5.3.2 ou superior<br />- curl<br />- php-cli<br />- php-mbstring<br />- git<br />- unzip<br /><br /><strong>Para Windows</strong><br />https://getcomposer.org/doc/00-intro.md#using-the-installer<br /><br /><strong>Para Linux</strong><br />sudo apt install composer<br /><br /><strong>Testando</strong><br /><br />composer list<br /><br /><strong>Instalando uma dependência/pacote em um projeto</strong><br /><br />cd projeto<br />composer require vendor_nome/pacote_nome<br /><br /><strong>Instalar um determinado release</strong><br /><br />composer require ribafs/admin-br:1.30<br /><br /><strong>Instalar a versão atual em desenvolvimento</strong><br /><br />composer require ribafs/admin-br:dev-master<br /><br />Ele criará a pasta vendor no diretório atual com as dependências dentro.<br /><br /><strong>Ajuda</strong><br /><br />composer help require<br /><br /><strong>Arquivos importantes:</strong><br /><br />composer.json<br />composer.lock<br />autoload.php<br /><br />composer.json<br /><br /><a href="https://getcomposer.org/doc/04-schema.md">https://getcomposer.org/doc/04-schema.md</a>  <br /><br /><strong>Criando um pacote com o composer</strong><br /><br />mkdir projeto<br />cd projeto<br /><br />composer init<br /><br /><strong>Opções:</strong><br />    --name: Name of the package.<br />    --description: Description of the package.<br />    --author: Autor no formato: Nome &lt;autor@email.com&gt;<br />    --type: Type of package.<br />    --homepage: Homepage of the package.<br />    --require: Pacote para o require com uma versão. No formato vendor/pacote:1.0.0.<br />    --require-dev: Requisitos de desenvolvimento. Vide --require.<br />    --stability (-s): Valor para o campo minimum-stability.<br />    --license (-l): Licença do package.<br />    --repository: Provide one (or more) custom repositories. They will be stored in the generated composer.json, and used for auto-completion when prompting for the list of requires. Every repository can be either an HTTP URL pointing to a composer repository or a JSON string which similar to what the repositories key accepts.<br /> <br /><strong>Publicando projeto para ser instalado com composer:</strong><br /><br />- Hospedar o projeto no GitHub ou similar<br />- Publicar no Packagist e configurar a atualização automática<br />- Instalar com o composer<br /><br /><strong>Dicas:</strong><br /><br />- Adicione composer.lock no .gitignore em libraries<br />- Ordene os pacotes no require ou require-dev pelo nome<br />- Validar o composer.json:<br />    composer validate --no-check-all --strict<br />- Especificando duas versões do PHP:<br />"require": {<br />    "php": "7.1.* || 7.2.*"<br />},<br />- Configurar autoload-dev para testes:<br />"autoload": {<br />    "psr-4": {<br />        "Acme\\": "src/"<br />    }<br />},<br />"autoload-dev": {<br />    "psr-4": {<br />        "Acme\\": "tests/"<br />    }<br />},<br /><br />composer install - instalar dependêncis<br />composer update - atualizar dependências<br />composer clear-cache - limpar cache<br /><br /><strong>Desinstalar plugin</strong><br /><br />composer remove packageauthor/packagename --update-with-dependencies<br /><br /><strong>Após cada alteração no composer.json:</strong><br /><br />composer dump-autoload<br /><br /><br /><strong>O Packagist.org é o principal repositório de pacotes para o Composer</strong></p>
<p>https://packagist.org/</p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 15:38:13 -0300</pubDate>
		</item>
		<item>
			<title>19 - Conclusão</title>
			<link>http://backup/portal/curriculo/livros/cakephp/19-conclusao.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/19-conclusao.html</guid>
			<description><![CDATA[<h3>19 – Conclusão</h3>
<p><br /><strong>Importante</strong>: Podemos levar um minuto para aprender algo, mas muitos anos ou a vida inteira para dominar.</p>
<p><br />Gostaria de destacar alguns capítulos:<br /><br />3 – <strong>Convenções</strong> – Este é muito importante para que se tire o maior proveito do Cake.<br /><br />5 – <strong>Gerando CRUD com o bake e muito mais</strong> – O bake é uma ferramenta que facilita muito o trabalho na criação de aplicativos, plugins, componentes, etc<br /><br />9 – <strong>Validações</strong> – Muito importantes para melhorar a segurança dos aplicativos<br /><br />12 – <strong>Plugins</strong> – Com plugins estendemos muito as funcionalidades do Cake e podemos tornar o trabalho com ele mais agradável e simples. Exemplo: o plugin cake-acl-br<br /><br />14 – <strong>Aplicativos de Exemplo</strong> – Vários aplicativos úteis<br /><br />15 – <strong>Codificação no CakePHP 3</strong> – Aqui muitas informações úteis para customizar manualmente o código de aplicativos.<br /><br />Faço sinceros votos de que este livro venha a tornar seu trabalho com o CakePHP 3 mais produtivo e prazeroso.<br /><br /><em><strong>Feliz codificação!</strong></em></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 15:01:50 -0300</pubDate>
		</item>
		<item>
			<title>18 - Algo sobre o novo CakePHP 4</title>
			<link>http://backup/portal/curriculo/livros/cakephp/18-algo-sobre-o-novo-cakephp-4.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/18-algo-sobre-o-novo-cakephp-4.html</guid>
			<description><![CDATA[<h3>18 – Algo sobre o novo CakePHP 4</h3>
<p style="text-align: right;"><br /><em><strong>Quando você quer alguma coisa, todo o universo conspira para que você realize o seu desejo.</strong></em></p>
<p><br /><strong>Algumas novidades na próxima versão do CakePHP:</strong><br /><br />- Removerá todos os métodos deprecateds<br />- Removerá todos os métodos não-estáticos de Cake\Database\Type e moverá os métodos de instância comuns para um trait.<br />- Exigirá pelo menos PHP 7.1<br />- Usa novas características do PHP 7.1<br />- Implementa a PSR-16 (https://github.com/cakephp/cakephp/issues/9507)<br />- Suporte para a PSR-15 (https://github.com/cakephp/cakephp/pull/12907)<br />- Atualização da documentação. Remoção de todos os "prior to..."<br />- Atualização dos plugins do core<br />- Publicação de documentação de novos plugins<br />- A documentação sobre plugins será movida para plugin-docs tools<br />- Não será compatível com aplicativos da versão 3.x. Antes de atualizar para a versão 4, atualize para a 3.8 e resolva os deprecateds warnings<br /><br /><strong>Exemplo de aviso de código deprecated:</strong><br />deprecationWarning('TableSchema::columnType() is deprecated. Use TableSchema::setColumnType() or TableSchema::getColumnType() instead.');<br /><br /><strong>Para desabilitar estes avisos, mudar no config/app.php:</strong><br /><br />'errorLevel' =&gt; E_ALL,<br /><br />por<br />'errorLevel' =&gt; E_ALL &amp; ~E_USER_DEPRECATED,<br /><br /><strong>Para atualizar para a versão 4.0.x execute:</strong><br />php composer.phar require --update-with-dependencies "cakephp/cakephp:4.0.*"<br /><br />Consulte<br /><a href="https://book.cakephp.org/4.0/en/appendices/4-0-migration-guide.html">https://book.cakephp.org/4.0/en/appendices/4-0-migration-guide.html</a>  <br /><br />Deprecated no 3.7<br /><br />Cake\Core\Plugin::load() and loadAll() are deprecated. Instead you should use Application::addPlugin().<br /><br />Trocar<br />    Plugin::load('Bake');<br /><br />Por<br />    $this-&gt;addPlugin('Bake');<br />    $this-&gt;addPlugin('Migrations');<br /><br />bin/cake plugin load AdminlBr --bootstrap<br /><br />Gera no src/Application.php (surgiu a partir da versão 3.6):<br /><br />    $this-&gt;addPlugin('AdminBr', ['bootstrap' =&gt; true]);<br /><br /><strong>Antes da versão 3.6 usava-se</strong><br />Plugin::load('NomePlugin');<br /><br />A adicionava-se manualmente no config/bootstrap.php<br /><br /><strong>A partir da versão 3.6 o comando</strong><br /><br />bin/cake plugin load NomePlugin<br /><br />Adiciona uma linha não mais em config/bootstrap.php, mas em<br />src/Application.php<br /><br />Algo como:<br />    $this-&gt;addPlugin('CakeAclBr', ['bootstrap' =&gt; true, 'routes' =&gt; true]);<br /><br />// Desabilitar rotas para o plugin ContactManager:<br />$this-&gt;addPlugin(ContactManagerPlugin::class, ['routes' =&gt; false]);<br /><br /><br /><strong>Detalhes em</strong></p>
<p><br /><a href="https://book.cakephp.org/4.0/pt/index.html">https://book.cakephp.org/4.0/pt/index.html </a> <br /><a href="https://github.com/cakephp/cakephp/wiki/4.0-Roadmap">https://github.com/cakephp/cakephp/wiki/4.0-Roadmap </a> <br />https://github.com/cakephp/cakephp/wiki/4.1-Roadmap </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:59:51 -0300</pubDate>
		</item>
		<item>
			<title>17 - Referências</title>
			<link>http://backup/portal/curriculo/livros/cakephp/17-referencias.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/17-referencias.html</guid>
			<description><![CDATA[<h3>17 - Referências</h3>
<p> </p>
<p align="right"><em><strong>Eu faço da dificuldade a minha motivação. A volta por cima vem na continuação. Charlie Brown Jr</strong></em></p>
<p> </p>
<p>Criação de Aplicativos (boa fonte de informações práticas)</p>
<p align="left"><a href="https://book.cakephp.org/3.0/pt/quickstart.html">https://book.cakephp.org/3.0/pt/quickstart.html</a></p>
<p align="left"><a href="https://book.cakephp.org/3.0/pt/tutorials-and-examples.html">https://book.cakephp.org/3.0/pt/tutorials-and-examples.html</a></p>
<p align="left"><a href="https://book.cakephp.org/3.0/en/tutorials-and-examples/cms/installation.html">https://book.cakephp.org/3.0/en/tutorials-and-examples/cms/installation.html</a></p>
<p align="left"> </p>
<p align="left">Comunidade brasileira</p>
<p align="left"><a href="https://www.cakephpbrasil.com.br/">https://www.cakephpbrasil.com.br/</a></p>
<p align="left"><a href="https://pt-br.facebook.com/groups/cakebrasil/">https://pt-br.facebook.com/groups/cakebrasil/</a></p>
<p align="left"><a href="https://pt.stackoverflow.com/questions/tagged/cakephp">https://pt.stackoverflow.com/questions/tagged/cakephp</a></p>
<p align="left"><a href="https://www.meetup.com/pt-BR/topics/cakephp/br/">https://www.meetup.com/pt-BR/topics/cakephp/br/</a></p>
<p align="left"><a href="https://groups.google.com/forum/?hl=pt-Pt#!forum/cakephp-pt">https://groups.google.com/forum/?hl=pt-Pt#!forum/cakephp-pt</a></p>
<p align="left"> </p>
<p align="left">Internacional</p>
<p align="left"><a href="https://discourse.cakephp.org/">https://discourse.cakephp.org/</a></p>
<p align="left"><a href="https://www.facebook.com/CakePHP/">https://www.facebook.com/CakePHP/</a></p>
<p align="left"><a href="http://cakesf.herokuapp.com/">http://cakesf.herokuapp.com/</a></p>
<p align="left"><a href="https://stackoverflow.com/questions/tagged/cakephp">https://stackoverflow.com/questions/tagged/cakephp</a></p>
<p align="left"> </p>
<p align="left">Outras Boas Referências</p>
<p align="left"><a href="https://www.youtube.com/watch?v=DJh5eHD1dJM&amp;list=PL83b6tjXNFHe-OVRROawG3YdIN_-Kbc6j">https://www.youtube.com/watch?v=DJh5eHD1dJM&amp;list=PL83b6tjXNFHe-OVRROawG3YdIN_-Kbc6j</a> – Canal com 12 aulas</p>
<p align="left"><a href="https://www.youtube.com/playlist?list=PLmY5AEiqDWwBYKoUhTXqoMICoHc6Zd_Qe">https://www.youtube.com/playlist?list=PLmY5AEiqDWwBYKoUhTXqoMICoHc6Zd_Qe</a> – 6 aulas</p>
<p align="left"><a href="http://www.naidim.org/cakephp">http://www.naidim.org/cakephp</a></p>
<p align="left"><a href="https://www.startutorial.com/articles">https://www.startutorial.com/articles</a></p>
<p align="left"><a href="https://www.sanisoft.com/blog/">https://www.sanisoft.com/blog/</a></p>
<p align="left"><a href="https://getawesomeness.herokuapp.com/get/cakephp">https://getawesomeness.herokuapp.com/get/cakephp</a> (grande referência)</p>
<p align="left"><a href="https://github.com/FriendsOfCake/awesome-cakephp">https://github.com/FriendsOfCake/awesome-cakephp</a> (outra impressionante referência)</p>
<p align="left"><a href="https://github.com/ziadoz/awesome-php">https://github.com/ziadoz/awesome-php</a> (esta é de PHP)</p>
<p align="left"><a href="http://www.naidim.org/cakephp">http://www.naidim.org/cakephp</a></p>
<p align="left"><a href="https://www.tutorialspoint.com/cakephp/">https://www.tutorialspoint.com/cakephp/</a></p>
<p align="left"><a href="https://www.codexworld.com/cakephp-3-x-tutorial-for-beginners/">https://www.codexworld.com/cakephp-3-x-tutorial-for-beginners/</a></p>
<p align="left"><a href="https://riptutorial.com/cakephp-3-0">https://riptutorial.com/cakephp-3-0</a></p>
<p align="left"><a href="https://www.startutorial.com/series/view/3">https://www.startutorial.com/series/view/3</a></p>
<p align="left"><a href="https://dev.to/northgoingzax/cakephp-3-bake-by-example-40pp">https://dev.to/northgoingzax/cakephp-3-bake-by-example-40pp</a></p>
<p align="left"><a href="https://www.devsaran.com/blog/10-resources-learn-cakephp">https://www.devsaran.com/blog/10-resources-learn-cakephp</a></p>
<p align="left"><a href="https://waltherlalk.com/blog/cakephp-3-tutorial-part-1">https://waltherlalk.com/blog/cakephp-3-tutorial-part-1</a></p>
<p align="left"><a href="https://www.dereuromark.de/">https://www.dereuromark.de/</a></p>
<p align="left"><a href="https://www.toptal.com/cakephp/most-common-cakephp-mistakes">https://www.toptal.com/cakephp/most-common-cakephp-mistakes</a></p>
<p align="left"><a href="https://www.scoop.it/topic/cakephp-reporter">https://www.scoop.it/topic/cakephp-reporter</a></p>
<p align="left"><a href="http://backup/portal/../">https://ribafs.org/</a> (Seção CakePHP 3)</p>
<p align="left"> </p>
<p align="left">Referências sobre Temas</p>
<p align="left">Nice Admin bake theme for CakePHPs Bake plugin - <a href="https://github.com/davidyell/CakePHP-NiceAdminBakeScripts">https://github.com/davidyell/CakePHP-NiceAdminBakeScripts</a></p>
<p align="left">CakePHP3: Transparently use Bootstrap</p>
<p align="left"><a href="https://github.com/friendsofcake/bootstrap-ui">https://github.com/friendsofcake/bootstrap-ui</a></p>
<p align="left">Plugin to Implement ACL in CakePHP 3 applications with web interface, twitter bootstrap and others - <a href="https://github.com/ribafs/cakephp-admin-en-bs">https://github.com/ribafs/cakephp-admin-en-bs</a></p>
<p align="left">Implementando Twitter BootStrap em Aplicativo do CakePHP 3 existente ou novo</p>
<p align="left"><a href="https://github.com/ribafs/cakephp-app-bs">https://github.com/ribafs/cakephp-app-bs</a></p>
<p align="left">Plugin para implementar o framework Bootstrap em aplicativos do CakePHP 3 e bake em português</p>
<p align="left"><a href="https://github.com/ribafs/cake-bs-br">https://github.com/ribafs/cake-bs-br</a></p>
<p align="left">Implementando ACL em aplicativos do CakePHP 3 usando Bootstrap com administração via interface web - <a href="https://github.com/ribafs/admin-br">https://github.com/ribafs/admin-br</a></p>
<p align="left">Plugin to add twitter bootstrap in applications with CakePHP 3</p>
<p align="left"><a href="https://github.com/ribafs/twbs-cake-css">https://github.com/ribafs/twbs-cake-css</a></p>
<p align="left">CakePHP 3.x helpers for the Bootstrap 3 HTML, CSS &amp; JS framework by @Holt59.</p>
<p align="left"><a href="https://holt59.github.io/cakephp3-bootstrap-helpers/">https://holt59.github.io/cakephp3-bootstrap-helpers/</a></p>
<p align="left">CakePHP 3: Bake by example</p>
<p align="left"><a href="https://dev.to/northgoingzax/cakephp-3-bake-by-example-40pp">https://dev.to/northgoingzax/cakephp-3-bake-by-example-40pp</a></p>
<p align="left">Code Generation with Bake</p>
<p align="left"><a href="https://book.cakephp.org/bake/1.x/en/usage.html">https://book.cakephp.org/bake/1.x/en/usage.html</a></p>
<p align="left">CakePHP 3 tutorial part 3 - Baking a little cake</p>
<p align="left"><a href="https://waltherlalk.com/blog/cakephp-3-tutorial-part-3">https://waltherlalk.com/blog/cakephp-3-tutorial-part-3</a></p>
<p align="left">CakePHP AdminLTE Theme</p>
<p align="left"><a href="https://github.com/maiconpinto/cakephp-adminlte-theme">https://github.com/maiconpinto/cakephp-adminlte-theme</a></p>
<p align="left">CakePHP Gentelella Theme</p>
<p align="left"><a href="https://github.com/backstageel/cakephp-gentelella-theme">https://github.com/backstageel/cakephp-gentelella-theme</a></p>
<p align="left"><a href="https://colorlib.com/polygon/gentelella/index.html">https://colorlib.com/polygon/gentelella/index.html</a></p>
<p align="left">cakephp3-bootstrap-theme</p>
<p align="left"><a href="https://github.com/alaxos/cakephp3-bootstrap-theme">https://github.com/alaxos/cakephp3-bootstrap-theme</a></p>
<p align="left">Integrate theme in Cakephp 3.x</p>
<p align="left"><a href="http://findnerd.com/list/view/Integrate-theme-in-Cakephp-3-x/28722/">http://findnerd.com/list/view/Integrate-theme-in-Cakephp-3-x/28722/</a></p>
<p align="left">Configurar o CakePHP para usar o Twitter Bootstrap automaticamente</p>
<p align="left"><a href="https://www.webdevbr.com.br/configurar-o-cakephp-para-usar-o-twitter-bootstrap-automaticamente">https://www.webdevbr.com.br/configurar-o-cakephp-para-usar-o-twitter-bootstrap-automaticamente</a></p>
<p align="left">Theming our CMS</p>
<p align="left"><a href="http://josediazgonzalez.com/2016/12/15/theming-our-cms/">http://josediazgonzalez.com/2016/12/15/theming-our-cms/</a></p>
<p align="left">Free Templates That can Fit with Cakephp</p>
<p align="left"><a href="https://www.cakephpexpert.com/blog/free-cakephp-templates">https://www.cakephpexpert.com/blog/free-cakephp-templates</a></p>
<p align="left">Cakeswatch is adaptation of Bootswatch for CakePHP 3.x themes</p>
<p align="left"><a href="https://sherwinrobles.blogspot.com/2016/03/cakeswatch-is-adaptation-of-bootswatch.html">https://sherwinrobles.blogspot.com/2016/03/cakeswatch-is-adaptation-of-bootswatch.html</a></p>
<p align="left">Using themes in CakePHP 3</p>
<p align="left"><a href="http://tariquesani.net/blog/2014/07/21/using-themes-cakephp-3/">http://tariquesani.net/blog/2014/07/21/using-themes-cakephp-3/</a></p>
<p> </p>
<p>Livros sobre CakePHP 2.x</p>
<p><a href="https://whatpixel.com/best-cakephp-books/">https://whatpixel.com/best-cakephp-books/</a></p>
<p><a href="http://josediazgonzalez.com/cakephp-book/">http://josediazgonzalez.com/cakephp-book/</a></p>
<p><a href="https://www.amazon.com.br/Cakephp-Application-Cookbook-James-Watts/dp/1782160086">https://www.amazon.com.br/Cakephp-Application-Cookbook-James-Watts/dp/1782160086</a></p>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:57:27 -0300</pubDate>
		</item>
		<item>
			<title>16 - Ambiente de Desenvolvimento</title>
			<link>http://backup/portal/curriculo/livros/cakephp/16-ambiente-de-desenvolvimento.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/16-ambiente-de-desenvolvimento.html</guid>
			<description><![CDATA[<h3>16 – Ambiente de Desenvolvimento</h3>
<p style="text-align: right;"><br /><em><strong>Sonha como se vivesses para sempre; vive como se fosses morrer hoje. (James Dean)</strong> </em><br /><br /></p>
<p><br />A meu ver, o trabalho com programação web, especialmente para o backend (php, mysql e cia), deve ser executado num computador com Linux. Veja meus motivos:<br /><br />- Como estas ferramentas nasceram no Linux<br />- Como o linux é menos vulnerável a virus, mawares, etc<br />- Especialmente como a maioria dos servidores usa Linux<br />- Como o linux atualmente está muito amigável para uso em desktop (Exemplo maior (para mim): Linux Mint)<br />- Como a instalação dos pacotes básicos deixa a atualização dos mesmo automática<br />Acho que é suficiente para dizer que o Linux ou similar é o sistema operacional ideal para ser usado como sistema desktop pelos programadores backend.<br /><br /><strong>Ferramentas que tornem mais produtivo o trabalho</strong><br /><br /><strong>Editores de código</strong><br /><br />- Bem leve: Xed no Linux Mint (já vem na distribuição)<br />- Bons recursos: Visual Studio Code (https://code.visualstudio.com)<br /><br /><strong>Gerenciador de bancos de Dados</strong><br /><br />- Adminer (https://adminer.org)<br /><br /><strong>Ambiente de Desenvolvimento com Vagrant</strong><br /><br />Para o trabalho e mesmo para trabalhar sozinho, a adoção do Vagrant é bastante recomendada, pois podemos criar um ambiente similar ao do servidor com que estamos trabalhando para evitar conflitos. E sempre que mudarmos de projeto podemos criar uma nova box similar ao noso servidor. Cria-se uma box, similar ao servidor, com o mesmo sistema operacional, mesma versão, mesmas extensões e configurações e quando pronto exportamos e passamos uma cópia para cada integrante da equipe.<br /><br />Inspirado por este livro eu instalei uma box com Ubuntu 18.04 e adicionei todos os softwares que geralmente uso:<br />- Apache2<br />- PHP 7.2<br />- MySQL 5.7<br />- PostgreSQL 10.8<br />- Adminer<br />- Diversas extensões para o PHP<br />- mod_rewrite<br />- composer<br />- git<br />Instalei o CakePHP 3.7.7 e criei dois aplicativos, um deles com o plugin admin-br.<br />Entre outros.<br />Tudo configurado como eu geralmente faço.<br /><br />Depois de pronta e testada eu exportei e enviei para a nuuvem, no site do vagrant, além de criar um repositório no GitHub e documentar o processo de criação, juntamente com outras informações úteis. <br /><br />Veja aqui:<br />https://github.com/ribafs/cake-vagrant e <a href="https://ribafs.github.io/cake-vagrant">https://ribafs.github.io/cake-vagrant</a> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:55:07 -0300</pubDate>
		</item>
		<item>
			<title>15.4 - Resumindo Migrations</title>
			<link>http://backup/portal/curriculo/livros/cakephp/15-4-resumindo-migrations.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/15-4-resumindo-migrations.html</guid>
			<description><![CDATA[<h3>15.4 - Resumindo Migrations</h3>
<p style="margin-bottom: 0cm; line-height: 100%;" align="right"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="right"><i><b>Você nunca sabe que resultados virão da sua ação. Mas se você não fizer nada, não existirão resultados. (Mahatma Gandhi)</b></i></p>
<p><br /><br /><strong>Gerando um backup do banco juntamente com os dados em Migrations:</strong><br /><br />    Exportar banco de dados existente para uma Migration (apenas a estrutura das tabelas)<br /><br />bin/cake bake migration_snapshot NomeBanco<br /><br /><strong>Gera a migration para todo o banco em config/Migrations/20190520132718_NomeBanco.php</strong><br /><br />    Exportar uma tabela juntamente com seus registros<br /><br />bin/cake bake seed --data users<br /><br />Gera o arquivo config/Seeds/UsersSeed.php<br /><br /><br /><strong>Limpar todo o banco com rollback</strong><br /><br />Para remover todas as tabelas do banco execute:<br /><br />bin/cake migrations rollback<br /><br /><br /><strong>Restaurar todas as tabelas com seus dados</strong><br /><br />Trazer de volta a estrutura das tabelas e os registros, após ter feito a migration e seeds.<br /><br />bin/cake migrations migrate<br />bin/cake migrations seed<br /><br /><br /><strong>Vantagem Extra</strong><br /><br />Obs.: os arquivos de migrations tem mais uma vantagem. São independentes de SGBD. Funcionam em todos os SGBD suportados pelo CakePHP.<br /><br /><br /><strong>Atualizar aplicativo para a versão atual (3.7.7)</strong><br /><br />cd aplicativo<br />composer require --update-with-dependencies "cakephp/cakephp:3.7.*"<br /><br /><br /><br /><strong>Mudando de SGBD</strong><br /><br />Imagina só, você criou seu aplicativo com o MySQL então precisa mudar para o PostgreSQL. Basta exportar as migrations e as seeds no MySQL, depois criar o banco no PostgreSQL e importar as migrations e seeds. Uma beleza!<br /><br /><br /><strong>Mais detalhes</strong><br /><br /><a href="https://book.cakephp.org/3.0/pt/appendices/3-0-migration-guide.html">https://book.cakephp.org/3.0/pt/appendices/3-0-migration-guide.html</a>  <br /><a href="https://book.cakephp.org/3.0/en/upgrade-tool.html">https://book.cakephp.org/3.0/en/upgrade-tool.html</a> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:51:16 -0300</pubDate>
		</item>
		<item>
			<title>15.3 - Exemplos de uso da Faker</title>
			<link>http://backup/portal/curriculo/livros/cakephp/15-3-exemplos-de-uso-da-faker.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/15-3-exemplos-de-uso-da-faker.html</guid>
			<description><![CDATA[<h3>15.3 - Exemplos de uso da Faker</h3>
<p style="text-align: right;"><br /><em><strong>Como tive dificuldade de encontrar alguns exemplos de uso da Faker, então seguem alguns exenplos que colecionei.</strong></em></p>
<p><br />$faker = Faker\Factory::create('pt_BR');<br /><br />$cpf = $faker-&gt;numberBetween($min = 10000000000, $max = 99999999999);<br />$nome = addslashes($faker-&gt;name);<br />$credito_liberado = $faker-&gt;regexify('[sn]');<br />$nascimento = $faker-&gt;date;<br />$email = $faker-&gt;email;<br />$user_id = $faker-&gt;numberBetween($min = 1, $max = 4);<br />$quantidade = $faker-&gt;randomNumber($nbDigits = NULL, $strict = false);<br />$preco_venda = $faker-&gt;numberBetween($min = 20, $max = 1200);<br /><br />randomNumber($nbDigits = NULL, $strict = false) // 79907610<br />randomFloat($nbMaxDecimals = NULL, $min = 0, $max = NULL) // 48.8932<br />numberBetween($min = 1000, $max = 9000) // 8567<br /><br />$faker-&gt;regexify('[sn]'); // s ou n<br />$faker-&gt;randomElement($array = array ('s','n'));<br />$faker-&gt;randomLetter;<br />$faker-&gt;regexify('[A-Z]+[a-z]{2,5}'); // 2 a 5 letras<br />$faker-&gt;regexify('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'); // sm0@y8k96a.ej<br />$faker-&gt;randomElement($array = array ('a','b','c')); // 'b'<br />print $faker-&gt;sentence($nbWords = 3, $variableNbWords = true);<br />$faker-&gt;sentence($nbWords = 6, $variableNbWords = true);<br />$faker-&gt;address; // rua, número e cep<br />$faker-&gt;text; // Para grandes quantidades de texto<br />$faker-&gt;sentence($nbWords = 6, $variableNbWords = true);<br />$faker-&gt;text($maxNbChars = 200);<br />$faker-&gt;title($gender = null|'male'|'female');     // 'Ms.'<br />$faker-&gt;name($gender = null|'male'|'female');      // 'Dr. Zane Stroman'<br />$faker-&gt;cityPrefix;<br />$faker-&gt;state;<br />$faker-&gt;stateAbbr;<br />$faker-&gt;buildingNumber;<br />$faker-&gt;city;<br />$faker-&gt;streetName;<br />$faker-&gt;streetAddress;<br />$faker-&gt;postcode;<br />$faker-&gt;country;<br />$faker-&gt;PhoneNumber;<br />$faker-&gt;company;<br />$faker-&gt;date($format = 'Y-m-d', $max = 'now');<br />$faker-&gt;time($format = 'H:i:s', $max = 'now');<br />$faker-&gt;freeEmail;<br />$faker-&gt;password;<br />$faker-&gt;domainName;<br />$faker-&gt;url;<br />$faker-&gt;ipv4;<br />$faker-&gt;macAddress;<br />$faker-&gt;creditCardType;<br />$faker-&gt;creditCardNumber;<br />$faker-&gt;creditCardExpirationDateString;<br />$faker-&gt;hexcolor;<br />$faker-&gt;colorName;<br />$faker-&gt;fileExtension;<br />$faker-&gt;mimeType;<br />$faker-&gt;locale;<br />$faker-&gt;countryCode;<br />$faker-&gt;randomHtml(2,3);<br /><br /><br />A partir da versão 1.5.5 do plugin, você pode usar a shell de migrations para popular seu banco de dados. Essa função é oferecida graças ao recurso de seed da biblioteca Phinx. Por padrão, arquivos seed ficarão no diretório config/Seeds de sua aplicação. Por favor, tenha certeza de seguir as instruções do Phinx para construir seus arquivos de seed.<br /><br /><strong>Podemos especificar um plugin</strong><br /><br />bin/cake bake seed Articles --plugin PluginName<br /><br />As opções --data, --limit e --fields foram adicionadas para exportar dados da sua base de dados.<br />A partir da versão 16.4, o comando bake seed permite que você crie um arquivo de seed com dados exportados da sua base de dados com o uso da flag --data:<br /><br />Exportando a tabela Articles juntamente com seus dados:<br /><br />bin/cake bake seed --data Articles<br /><br />Por padrão, esse comando exportará todas as linhas encontradas na sua tabela. Você pode limitar o número de linhas a exportar usando a opção --limit:<br /><br />Exportar apenas os 10 primeiros registros encontradas<br /><br />bin/cake bake seed --data --limit 10 Articles<br /><br />Para popular seu banco de dados, você pode usar o subcomando seed:<br /><br />bin/cake migrations seed<br /><br />Para plugins<br /><br />bin/cake migrations seed -p MeuPlugin<br /><br /><br />Você pode especificar apenas um seeder para rodar usando a opção --seed:<br /><br />bin/cake migrations seed --seed ArticlesSeed<br /><br /><strong>Limpar o cache</strong><br /><br />Se você usa o plugin ao fazer o deploy de sua aplicação, garanta que o cache ORM seja limpo para renovar os metadados das colunas de suas tabelas.<br /><br />bin/cake orm_cache clear<br /><br /><br /><strong>Migrando somente uma migration</strong><br /><br />bin/cake migrations migrate -p CakeDC/Users<br />bin/cake migrations migrate -p Acl<br /><br /></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:38:54 -0300</pubDate>
		</item>
		<item>
			<title>15.2 - Seed - inserindo registros nas tabelas</title>
			<link>http://backup/portal/curriculo/livros/cakephp/15-2-seed-inserindo-registros-nas-tabelas.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/15-2-seed-inserindo-registros-nas-tabelas.html</guid>
			<description><![CDATA[<h3>15.2 - Seed - inserindo registros nas tabelas</h3>
<p style="text-align: right;"><br /><em><strong>Diante de uma dificuldade substitua o eu não consigo pelo vou tentar outra vez.</strong></em></p>
<p><br />bin/cake bake seed Posts<br /><br />Ele gera um esqueleto de classe.<br /><br />Editar config/Seeds/Posts e adicionar os registros diretamente como abaixo ou usando o Faker</p>
<pre class="language-php"><code>&lt;?php
use Phinx\Seed\AbstractSeed;

class PostsSeed extends AbstractSeed
{
    public function run()
    {
        $data = [
            [
                'body'    =&gt; 'foo',
                'created' =&gt; date('Y-m-d H:i:s'),
            ],
            [
                'body'    =&gt; 'bar',
                'created' =&gt; date('Y-m-d H:i:s'),
            ]
        ];

        $posts = $this-&gt;table('posts');
        $posts-&gt;insert($data)
              -&gt;save();
    }
}</code></pre>
<p><strong>Integrando seed com a biblioeca faker</strong><br /><br /><strong>Instalar a Faker</strong><br /><br />composer require fzaninotto/faker<br /><br /><strong>Detalhes de uso</strong>:<br />https://github.com/fzaninotto/Faker <br /><br /><strong>Criar um novo seed</strong><br /><br />bin/cake bake seed Despesas<br /><br /><strong>Então usar na classe gerada</strong></p>
<pre class="language-php"><code>&lt;?php

use Phinx\Seed\AbstractSeed;

class DespesasSeed extends AbstractSeed
{
    public function run()
    {
        $faker = Faker\Factory::create('pt_BR');
        $data = [];
        for ($i = 0; $i &lt; 20; $i++) {
            $data[] = [
                'descricao'     =&gt; $faker-&gt;userName,
                'valor'         =&gt; $faker-&gt;numberBetween($min = 0, $max = 9000),
                'mes'           =&gt; $faker-&gt;regexify('0[1-9]\/2019|1[1-2]\/2019'),
                'receita_id'    =&gt; $faker-&gt;numberBetween($min = 1, $max = 2),
                'created'       =&gt; date('Y-m-d H:i:s'),
            ];
        }

        $table = $this-&gt;table('despesas');
        $table-&gt;insert($data)-&gt;save();
    }
}
</code></pre>
<p>Adicionar os registros do Seed no banco<br /><br />bin/cake migrations seed</p>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:36:40 -0300</pubDate>
		</item>
		<item>
			<title>15.1 - Migrate</title>
			<link>http://backup/portal/curriculo/livros/cakephp/15-1-migrate.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/15-1-migrate.html</guid>
			<description><![CDATA[<h3>15.1 - Migrate</h3>
<p style="text-align: right;"><br /><em><strong>Não se preocupe com falhas, preocupe-se com as chances que você perde quando não tenta. (Jack Canfield)</strong></em></p>
<p><br />Aqui segue um exemplo de migração:</p>
<p> </p>
<pre class="language-php"><code>&lt;?php
use Migrations\AbstractMigration;

class CreateProducts extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-change-method
     * @return void
     */
    public function change()
    {
        $table = $this-&gt;table('products');
        $table-&gt;addColumn('name', 'string', [
            'default' =&gt; null,
            'limit' =&gt; 255,
            'null' =&gt; false,
        ]);
        $table-&gt;addColumn('description', 'text', [
            'default' =&gt; null,
            'null' =&gt; false,
        ]);
        $table-&gt;addColumn('created', 'datetime', [
            'default' =&gt; null,
            'null' =&gt; false,
        ]);
        $table-&gt;addColumn('modified', 'datetime', [
            'default' =&gt; null,
            'null' =&gt; false,
        ]);
        $table-&gt;create();
    }
}</code></pre>
<p><strong>Salvar em</strong><br />config/Migrations/20190519085224_Products.php<br /><br />Veja o formato: YYYYMMDDHHMMSS_Products.php<br /><br /><br /><strong>Também podemos criar a migration usando o bake:</strong><br /><br />bin/cake bake migration CreateProducts name:string description:text created modified<br /><br />Você pode criar um arquivo de migração vazio caso deseje ter um controle total do que precisa ser executado. Para isto, apenas omita a definição das colunas:<br /><br />bin/cake migrations create MyCustomMigration<br /><br /><strong>Criar a tabela ou as tabelas do(s) Migration(s)</strong><br /><br />bin/cake migrations migrate<br /><br /><strong>Limpar todo o banco, excluindo todas as tabelas</strong><br /><br />bin/cake migrations rollback<br /><br /><br /><strong>Nomes de campos e tipos</strong><br /><br />fieldName:fieldType[length]:indexType:indexName<br /><br /><strong>Por exemplo, veja formas válidas de especificar um campo de e-mail:</strong><br />    • email:string:unique <br />    • email:string:unique:EMAIL_INDEX <br />    • email:string[120]:unique:EMAIL_INDEX <br />O parâmetro length para o fieldType é opcional e deve sempre ser escrito entre colchetes<br />Os campos created e modified serão automaticamente definidos como datetime.<br />Os tipos de campos são genericamente disponibilizados pela biblioteca Phinx. Eles podem ser:<br />    • string <br />    • text <br />    • integer <br />    • biginteger <br />    • float <br />    • decimal <br />    • datetime <br />    • timestamp <br />    • time <br />    • date <br />    • binary <br />    • boolean <br />    • uuid <br /><br />Há algumas heurísticas para a escolha de tipos de campos que não são especificados ou são definidos com valor inválido. O tipo de campo padrão é string;<br />    • id: integer <br />    • created, modified, updated: datetime <br /><br /><br /><strong>Adicionando colunas a uma tabela existente</strong><br /><br />Se o nome da migração na linha de comando estiver na forma "AddXXXToYYY" e for seguido por uma lista de nomes de colunas e tipos, então o arquivo de migração com o código para criar as colunas será gerado:</p>
<p><br />bin/cake bake migration AddPriceToProducts price:decimal<br /><br />A linha de comando acima irá gerar um arquivo com o seguinte conteúdo:</p>
<p><br />&lt;?php<br />use Migrations\AbstractMigration;<br /><br />class AddPriceToProducts extends AbstractMigration<br />{<br />    public function change()<br />    {<br />        $table = $this-&gt;table('products');<br />        $table-&gt;addColumn('price', 'decimal')<br />              -&gt;update();<br />    }<br />}<br /><br /><br /><strong>Especificando o tamanho do campo</strong><br /><br />Se você precisar especificar o tamanho do campo, você pode fazer isto entre colchetes logo após o tipo do campo, ex.:<br /><br />bin/cake bake migration AddFullDescriptionToProducts full_description:string[60]<br /><br /><strong>Executar o comando acima irá gerar:</strong><br /><br />&lt;?php<br />use Migrations\AbstractMigration;<br /><br />class AddFullDescriptionToProducts extends AbstractMigration<br />{<br />    public function change()<br />    {<br />        $table = $this-&gt;table('products');<br />        $table-&gt;addColumn('full_description', 'string', [<br />            'default' =&gt; null,<br />            'limit' =&gt; 60,<br />            'null' =&gt; false,<br />        ])<br />        -&gt;update();<br />    }<br />}<br /><br />Se o tamanho não for especificado, os seguintes padrões serão utilizados:<br />    • string: 255 <br />    • integer: 11 <br />    • biginteger: 20 <br /><br /><strong>Removendo uma coluna de uma tabela</strong><br /><br />Da mesma forma, você pode gerar uma migração para remover uma coluna utilizando a linha de comando, se o nome da migração estiver na forma "RemoveXXXFromYYY":<br /><br />bin/cake bake migration RemovePriceFromProducts price<br /><br /><strong>Cria o arquivo:</strong><br />&lt;?php<br />use Migrations\AbstractMigration;<br /><br />class RemovePriceFromProducts extends AbstractMigration<br />{<br />    public function change()<br />    {<br />        $table = $this-&gt;table('products');<br />        $table-&gt;removeColumn('price');<br />    }<br />}<br /><br /><strong>Gerando migrações a partir de uma base de dados existente</strong><br /><br />Se você está trabalhando com um banco de dados pré-existente e quer começar a usar migrações, ou para versionar o schema inicial da base de dados da sua aplicação, você pode executar o comando migration_snapshot:<br /><br />bin/cake bake migration_snapshot Financas<br /><br />Ele gerará um arquivo de migrations com todas as tabelas do banco, mas somente as estruturas, sem os registros:<br /><br />YYYYMMDDHHMMSS_Financas.php<br /><br /><br />Migrações também podem ser executadas para plugins. Simplesmente utilize a opção <br />``--plugin`` ou ``-p``<br /><br />bin/cake migrations migrate -p MyAwesomePlugin<br /><br /><strong>Lista das migrações</strong><br /><br />bin/cake migrations status<br /><br /></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:19:29 -0300</pubDate>
		</item>
		<item>
			<title>15 - Migrations</title>
			<link>http://backup/portal/curriculo/livros/cakephp/15-migrations.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/15-migrations.html</guid>
			<description><![CDATA[<h3>15 - Migrations</h3>
<p style="text-align: right;"><em><strong>Quem não evita as pequenas faltas, pouco a pouco cai nas grandes. (T. Kempis)</strong></em></p>
<p><br /><br />Migrations é um plugin suportado pela equipe oficial do CakePHP que ajuda você a fazer mudanças no schema do banco de dados utilizando arquivos PHP, que podem ser versionados utilizando um sistema de controle de versão.<br /><br />Ele permite que você atualize suas tabelas ao longo do tempo. Ao invés de escrever modificações de schema via SQL, este plugin permite que você utilize um conjunto intuitivo de métodos para fazer mudanças no seu banco de dados.<br /><br />Esse plugin é um wrapper para a biblioteca Phinx(https://phinx.org/).<br /><br />Uma migração é basicamente um arquivo PHP que descreve as mudanças a serem feitas no banco de dados. Um arquivo de migração pode criar ou excluir tabelas, adicionar ou remover colunas, criar índices e até mesmo inserir dados em seu banco de dados.<br /><br />Uma migração é basicamente um arquivo PHP que descreve as mudanças a serem feitas no banco de dados. Um arquivo de migração pode criar ou excluir tabelas, adicionar ou remover colunas, criar índices e até mesmo inserir dados em seu banco de dados.<br /><br />Muito útil para quando desejamos distribuir um plugin ou aplicativo do CakePHP, já incluindo os arquivos de migration e/ou seed quando o usuário apenas executa o comando para criar as tabelas e adicionar os registros.</p>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:16:53 -0300</pubDate>
		</item>
		<item>
			<title>14.4 - Comunicação entre Model e Controller</title>
			<link>http://backup/portal/curriculo/livros/cakephp/14-4-comunicacao-entre-model-e-controller.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/14-4-comunicacao-entre-model-e-controller.html</guid>
			<description><![CDATA[<h3>14.4 - Comunicação entre Model e Controller</h3>
<p style="text-align: right;"><br /><em><strong>Habilidade é o que você é capaz de fazer. Motivação determina o que você faz. Atitude determina o quão bem você faz. (Lou Holtz)</strong></em></p>
<p><br />Criar function abaixo no model ArticlesTable.php:</p>
<pre class="language-php"><code>	public function teste()
	{
		return 'Funciona';
	}

Chamar no ArticlesController.php :

use Cake\ORM\TableRegistry;

		$articles = TableRegistry::get('Articles');
		$func=$articles-&gt;teste();// Redebe do Model

//dd($func);
		$this-&gt;set('func',$func); // Envia para a view</code></pre>
<p><strong>Na view</strong><br /><br />print $func<br />ou<br />debug($func)<br /><br /><br /><strong>Redirecionamento para outras páginas</strong><br /><br />controller/action<br /><br />$this-&gt;redirect(['controller' =&gt; 'Clientes', 'action' =&gt; 'index'])<br /><br />URL<br /><br />$this-&gt;redirect('http://ribafs.org')<br /><br /><strong>Action do controller atual</strong><br /><br />$this-&gt;redirect(['action' =&gt; 'edit', $id]);<br /><br /><strong>Para o próprio link de onde veio</strong><br /><br />$this-&gt;redirect($this-&gt;referer());<br /><br /><strong>Carregar model que não é o default em Controller</strong><br /><br />$this-&gt;LoadModel('Clientes');<br />Upload de arquivos com o CakePHP 3<br /><br />http://www.naidim.org/cakephp-3-tutorial-12-file-uploads <br /><br /><br /><strong>Como integrar o login do Facebook com o CakePHP 3</strong><br /><br /><a href="https://www.startutorial.com/articles/view/how-to-integrate-facebook-login-with-cakephp-3">https://www.startutorial.com/articles/view/how-to-integrate-facebook-login-with-cakephp-3</a> <br /><br /><br /><strong>Instalando o Wordpress em um aplicativo CakePHP 3</strong><br /><br /><a href="https://stackoverflow.com/questions/42891150/installing-wordpress-inside-cakephp-3">https://stackoverflow.com/questions/42891150/installing-wordpress-inside-cakephp-3</a> <br /><a href="https://www.startutorial.com/articles/view/installing-wordpress-in-a-cakephp-application">https://www.startutorial.com/articles/view/installing-wordpress-in-a-cakephp-application</a> <br /><br /></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:15:21 -0300</pubDate>
		</item>
		<item>
			<title>14.3 - Trabalhando com session no CakePHP</title>
			<link>http://backup/portal/curriculo/livros/cakephp/14-3-trabalhando-com-session-no-cakephp.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/14-3-trabalhando-com-session-no-cakephp.html</guid>
			<description><![CDATA[<h3>14.3 - Trabalhando com session no CakePHP</h3>
<p style="text-align: right;"><br /><em><strong>Nossa maior fraqueza está em desistir. A maneira certa de ter sucesso é tentar apenas mais uma vez</strong></em>. (Thomas Edison)</p>
<p><br /><strong>Mudando o session de php para database</strong><br /><br />Primeiro configurar em <strong>config/app.php</strong><br /><br />Ao final:<br /><br />    'Session' =&gt; [<br />        'defaults' =&gt; 'php',<br />    ],<br /><br />Mudar para<br /><br />    'Session' =&gt; [<br />        'defaults' =&gt; 'database',<br />    ],<br /><br /><strong>Veja que as alternativas são:</strong><br /><br />     * - 'php' - Uses settings defined in your php.ini.<br />     * - 'cake' - Saves session files in CakePHP's /tmp directory.<br />     * - 'database' - Uses CakePHP's database sessions.<br />     * - 'cache' - Use the Cache class to save sessions.<br /><br /><strong>E existem várias opções:</strong><br /><br />     * - `cookie` - The name of the cookie to use. Defaults to 'CAKEPHP'. Avoid using `.` in cookie names,<br />     *   as PHP will drop sessions from cookies with `.` in the name.<br />     * - `cookiePath` - The url path for which session cookie is set. Maps to the<br />     *   `session.cookie_path` php.ini config. Defaults to base path of app.<br />     * - `timeout` - The time in minutes the session should be valid for.<br />     *    Pass 0 to disable checking timeout.<br />     *    Please note that php.ini's session.gc_maxlifetime must be equal to or greater<br />     *    than the largest Session['timeout'] in all served websites for it to have the<br />     *    desired effect.<br />     * - `defaults` - The default configuration set to use as a basis for your session.<br />     *    There are four built-in options: php, cake, cache, database.<br />     * - `handler` - Can be used to enable a custom session handler. Expects an<br />     *    array with at least the `engine` key, being the name of the Session engine<br />     *    class to use for managing the session. CakePHP bundles the `CacheSession`<br />     *    and `DatabaseSession` engines.<br />     * - `ini` - An associative array of additional ini values to set.<br /><br /><br /><strong>Exemplo:</strong><br /><br />'Session' =&gt; [<br />    'defaults' =&gt; 'php',<br />    'timeout' =&gt; 12 * 60, //in minutes<br />    'cookie' =&gt; 'application-name',<br />],<br /><br />Configurar por quanto tempo o usuário ficará conectado no aplicativo.<br /><br />Em config/app.php:<br /><br /> 'Session' =&gt; [<br />    'defaults' =&gt; 'php',<br />    'timeout'=&gt;24*60, //minutos, que dá 24horas <br />    'cookie' =&gt; 'CAKEPHP',<br />],<br /><br /><strong>Sempre que alterar o cache limpe o cache e arquivos temporários.</strong><br /><br />Após efetuar as alterações immporte o script de:<br /><br />config/schema/session.sql para seu banco de dados<br /><br /><br /><strong>Algumas funções nativas e globais do CakePHP 3</strong><br /><br />__(string $string_id[, $formatArgs]) - Manipula localizações nas aplicações do CakePHP. Usada por padrão nas views geradas pelo bake para mostrar strings. Exemplo:<br />&lt;?= __('Ações') ?&gt;<br /><br />debug(mixed $var, boolean $showHtml = null, $showFrom = true)<br /><br />dd(mixed $var, boolean $showHtml = null) - semelhante a debug() mas também encerra o processamento ao final<br /><br />pr(mixed $var) - Encapsula print_r(), com a adição de tags &lt;pre&gt; ao redor da saída.<br /><br />pj(mixed $var) - semelhante a pr() mas para saída em json<br /><br />h(string $text, boolean $double = true, string $charset = null) - Encapsulamento da função htmlspecialchars(). Importante nas views. Usar h() quando mosrando informações para prevenir problemas de HTML injection.<br /><br /><br /><br /><strong>Algumas Constantes do Core</strong><br /><br />APP - Path para o diretório da aplicação. Retorna /var/www/html/nomeApp/src<br />CAKE - path do diretório dos arquivos do Cake. No caso este: vendor/cakephp/cakephp/src/<br />CORE_PATH - Path para este diretório: vendor/cakephp/cakephp/, com a barra final<br />DS - Retorna a barra "/"<br />ROOT - Retorna /var/www/html/nomeApp<br />TMP -  Retorna /var/www/html/nomeApp/tmp/<br />VENDORS - Retorna /var/www/html/nomeApp/config/<br />WWW_ROOT - Retorna /var/www/html/nomeApp/webroot/<br /><br />TIME_START -  Unix timestamp em microsegundoss como um float desde que a aplicação iniciou.<br /><br />SECOND - 1<br />MINUTE - 60<br />HOUR - 3600<br />DAY<br />WEEK<br />MONTH<br />YEAR - 31536000 (segundos)<br /><br /><strong>Mais detalhes em:</strong><br /><a href="https://book.cakephp.org/3.0/en/core-libraries/global-constants-and-functions.html">https://book.cakephp.org/3.0/en/core-libraries/global-constants-and-functions.html </a> <br /><br /><strong>Exemplo de uso:</strong><br /><br />Em um controller, adicione a linha abaixo no action/método index()<br /><br />dd(TIME_START);<br /><br /><br /><strong>Enviar informações do controller para uma view:</strong><br /><br />$this-&gt;set('valores', $valores);<br /><br /><strong>Enviar informações da view para o controller</strong><br /><br />Na view search.tcp:<br /><br />   $this-&gt;Form-&gt;create('Model', array('type' =&gt; 'get', 'action' =&gt; 'search'));<br />   $this-&gt;Form-&gt;input('select_tfield_id', array('type' =&gt; 'select'));<br />   $this-&gt;Form-&gt;input('value'));<br />   $this-&gt;Form-&gt;end('submit');<br /><br />No controller:<br />   function search() {<br />       $url = $this-&gt;params['url'];<br />       $id = $url['select_tfield_id'];<br />       $value = $url['value'];<br />   }</p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:10:09 -0300</pubDate>
		</item>
		<item>
			<title>14.2 - Conhecendo o CSS default do CakePHP 3</title>
			<link>http://backup/portal/curriculo/livros/cakephp/14-2-conhecendo-o-css-default-do-cakephp-3.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/14-2-conhecendo-o-css-default-do-cakephp-3.html</guid>
			<description><![CDATA[<h3>14.2 - Conhecendo o CSS default do CakePHP 3</h3>
<p style="text-align: right;"><br /><br /><em><strong>A lógica pode levar de um ponto A a um ponto B. A imaginação pode levar a qualquer lugar.</strong></em> (Albert Einstein)</p>
<p><br />A tela principal do aplicativo Customers mostrando a view index.ctp</p>
<p><img src="http://backup/portal/images/livrocake1.png" alt="" /></p>
<p> </p>
<p>Agora mostrarei par cada região da tela, o respectivo código e mais abaixo as classes usadas no CSS default do CakePHP 3 para estas regiões.<br /><br />No layout default.ctp<br /><br />Quase todas as classes das 4 views defaults criadas pelo bake e do layout.ctp estão abaixo<br /><br />layout.ctp (as imagens abaixo do código):<br /><br />&lt;nav class="top-bar expanded" data-topbar role="navigation"&gt;</p>
<p><img src="http://backup/portal/images/livrocake2.png" alt="" /></p>
<p>        &lt;ul class="title-area large-3 medium-4 columns"&gt;<br />            &lt;li class="name"&gt;<br />                &lt;h1&gt;&lt;a href="http://backup/portal/"&gt;&lt;?= $this-&gt;fetch('title') ?&gt;&lt;/a&gt;&lt;/h1&gt;<br />            &lt;/li&gt;<br />        &lt;/ul&gt;</p>
<p><img src="http://backup/portal/images/livrocake3.png" alt="" /></p>
<p>        &lt;div class="top-bar-section"&gt;<br />            &lt;ul class="right"&gt;<br />                &lt;li&gt;&lt;a target="_blank" href="https://book.cakephp.org/3.0/"&gt;Documentation&lt;/a&gt;&lt;/li&gt;<br />                &lt;li&gt;&lt;a target="_blank" href="https://api.cakephp.org/3.0/"&gt;API&lt;/a&gt;&lt;/li&gt;<br />            &lt;/ul&gt;<br />        &lt;/div&gt;</p>
<p><img src="http://backup/portal/images/livrocake4.png" alt="" /></p>
<p>Aqui embaixo o Cake joga o conteúdo da view/template atual:<br /><br />    &lt;div class="container clearfix"&gt;<br />        &lt;?= $this-&gt;fetch('content') ?&gt; &lt;!-- Aqui ficará o código da view atual --&gt;<br />    &lt;/div&gt;<br /><br />index.ctp:<br /><br />&lt;nav class="large-3 medium-4 columns" id="actions-sidebar"&gt;</p>
<p><img src="http://backup/portal/images/livrocake5.png" alt="" /></p>
<p>    &lt;ul class=<strong>"side-nav</strong>"&gt;<br />        &lt;li class="<strong>heading</strong>"&gt;&lt;?= __('Actions') ?&gt;&lt;/li&gt;</p>
<p><img src="http://backup/portal/images/livrocake6.png" alt="" /></p>
<p style="margin-bottom: 0cm; line-height: 100%;">&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('New Customer'), ['action' =&gt; 'add']) ?&gt;&lt;/li&gt;</p>
<p style="margin-bottom: 0cm; line-height: 100%;">&lt;/ul&gt;</p>
<p style="margin-bottom: 0cm; line-height: 100%;"><img src="http://backup/portal/images/livrocake7.png" alt="" /></p>
<p style="margin-bottom: 0cm; line-height: 100%;">&lt;/nav&gt;</p>
<p style="margin-bottom: 0cm; line-height: 100%;">&lt;div class="<b>customers index large-9 medium-8 columns content</b>"&gt;</p>
<p style="margin-bottom: 0cm; line-height: 100%;"><img src="http://backup/portal/images/livrocake8.png" alt="" /></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><b>As classes em negrito acima estão no style.css ou no base.css citadas abaixo:</b></p>
<pre class="language-css"><code>.disabled a,
a.disabled {
    pointer-events: none;
}
.top-bar-section {
    margin-top: 2.8125rem;
    z-index: 98
}
.right {
    float: right !important
}

.top-bar {
    background: #333;
    height: 2.8125rem;
    line-height: 2.8125rem;
    margin-bottom: 0;
    overflow: hidden;
    position: relative
}

top-bar e title-area
.top-bar.expanded .title-area {
    background: #01545b;
}

.top-bar.expanded, .top-bar,.top-bar-section ul li,.top-bar-section li:not(.has-form) a:not(.button) {
    background: #116d76;
}

div.message {
    text-align: center;
    cursor: pointer;
    display: block;
    font-weight: normal;
    padding: 0 1.5rem 0 1.5rem;
    transition: height 300ms ease-out 0s;
    background-color: #a0d3e8;
    color: #626262;
    top: 15px;
    right: 15px;
    z-index: 999;
    overflow: hidden;
    height: 50px;
    line-height: 2.5em;
}
div.message.error {
    background-color: #C3232D;
    color: #FFF;
}
.content {
    padding: 2rem;
}

.container {
    overflow: hidden;
    min-height: 92%; /* full height almost always */
}
.column,
.columns {
    position: relative;
    padding-left: 0.9375rem;
    padding-right: 0.9375rem;
    float: left
}
...
.large-3 {
    width: 25%
}
...
.large-9 {
    width: 75%
}
...
#actions-sidebar {
    background: #fafafa;
}
.side-nav {
    display: block;
    font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
    list-style-position: outside;
    list-style-type: none;
    margin: 0;
    padding: 0.875rem 0
}

.side-nav li {
    font-size: 0.875rem;
    font-weight: normal;
    margin: 0 0 0.4375rem 0
}

.side-nav li.heading {
    color: #008CBA;
    font-size: 0.875rem;
    font-weight: bold;
    text-transform: uppercase
}</code></pre>
<p>A finalidade deste trabalho é oferecer informações que ajudem a trocar o template default do Cake para um framework como o BootStrap, o foundation, o Materialize ou outro e mesmo para um criado com o CSS puro.<br /><br /><br /><strong>Implementando BootStrap 3 em aplicativos do CakePHP 3</strong><br /><br />Uma forma bem simples de implementar o BootStrap 3 em aplicativos do CakePHP 3 é criar um aplicativo com o CakePHP 3 atual, instalar e habilitar o plugin admin-br atual e então gerar o código com o bake usando o plugin admin-br.<br /><br /><strong>O código gerado tem o BootStrap 3 implementado.</strong><br /><br />Basta então ver o código gerado no src/Template para qualquer das tabelas e adaptar para seu aplicativo.<br /><br /><strong>Informação recebida do Admad no fórum oficial do CakePHP:</strong><br />O css default usado no CakePHP é um subconjunto do framework Foundation v5.</p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 14:01:46 -0300</pubDate>
		</item>
		<item>
			<title>14.1 - Repassando Informações Entre Controllers</title>
			<link>http://backup/portal/curriculo/livros/cakephp/14-1-repassando-informacoes-entre-controllers.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/14-1-repassando-informacoes-entre-controllers.html</guid>
			<description><![CDATA[<h3>14.1 - Repassando Informações Entre Controllers</h3>
<p style="text-align: right;"><br /><em><strong>Um dos mais importantes ingredientes na fórmula do sucesso é saber como lidar com as pessoas.</strong></em></p>
<p><br /><strong>Como faço para repassar informações entre dois controllers.</strong></p>
<p>Exemplo:<br /><br />Eu tenho no meu banco de dados duas tabelas, uma de usuários e outra de livros, aí eu seleciono um livro que está na tabela livros, pego seu id e tenho que atualizar essa informação na tabela do usuário..<br /><br /><strong>Eu tenho dois controllers, um de usuários e outro de livros, eu tenho que repassar o id do livro para o controller de usuários..</strong><br /><br />    Como passo essa informação entre controllers<br />    Como seleciono o id do usuário logado no sistema<br />    Qual o jeito correto de fazer essa atualização<br /><br /><br />Alguns actions típicos:</p>
<p><strong>Autenticação de e-mail</strong><br /><br />Crédito:<br /><a href="https://www.youtube.com/watch?v=cEwf9PpbMcQ">https://www.youtube.com/watch?v=cEwf9PpbMcQ </a> <br /><br />config/app.php</p>
<p> </p>
<pre class="language-php"><code>...
    'EmailTransport' =&gt; [
        'default' =&gt; [
            'className' =&gt; 'Mail',
            // The following keys are used in SMTP transports
            'host' =&gt; 'localhost',
            'port' =&gt; 25,
            'timeout' =&gt; 30,
            'username' =&gt; 'user',
            'password' =&gt; 'secret',
            'client' =&gt; null,
            'tls' =&gt; null,
            'url' =&gt; env('EMAIL_TRANSPORT_DEFAULT_URL', null),
        ],
		'gmail' =&gt; [
			'className' =&gt; 'Smtp',
			'host' =&gt; 'ssl://smtp.gmail.com',
			'port' =&gt; 465,
			'timeout' =&gt; 30,
			'username' =&gt; 'ribafs@gmail.com',
			'password' =&gt; 'zmxn1029g',
			'client' =&gt; null,
			'tls' =&gt; null,
			'url' =&gt; env('EMAIL_TRANSPORT_DEFAULT_URL', null)
    ],

Profile

'Email' =&gt; [
        'default' =&gt; [
            'transport' =&gt; 'default',
            'from' =&gt; 'you@localhost',
            //'charset' =&gt; 'utf-8',
            //'headerCharset' =&gt; 'utf-8',
        ],
		'ribaportal' =&gt; [
			'transport' =&gt; 'gmail',
			'from' =&gt; ['ribafs@gmail.com'=&gt;'Portal do RibaFS'],
		],
    ],</code></pre>
<p><strong>Criar classe mailler usando o bake</strong><br /><br />bin/cake bake mailer user<br /><br /><strong>Criar classes no controller e no model</strong><br /><br />Abrir src/Controller/Mailer/UserMailer.php<br /><br />Adicionar após a linha <br />static ...</p>
<pre class="language-php"><code>	public function welcome($user)
	{
		$this-&gt;to($user-&gt;email)
		-&gt;profile('ribaportal')
		-&gt;emailFormat('html')
		-&gt;template('welcome_email_template')
		-&gt;layout('default')
		-&gt;viewVars(['nome' =&gt; $user-&gt;name])
		-&gt;subject(sprintf('Bem vindo, %s', $user-&gt;name));
	}</code></pre>
<p><strong>Criar o template para o e-mail</strong><br /><br />src/Template/Email/html/welcome_email_template.ctp<br /><br />&lt;h1&gt;Seja bem-vindo(a), &lt;?php echo $nome;?&gt;&lt;/h1&gt;<br />&lt;p&gt;<br />    Apenas um teste de envio de e-mail pelo CakePHP.<br />&lt;/p&gt;<br /><br /><strong>Para testar crie um novo usuário e veja se ele enviou o e-mail.</strong><br /><br /><br /><strong>Recuperação de senha</strong><br /><br /><a href="https://www.youtube.com/watch?v=cEwf9PpbMcQ">https://www.youtube.com/watch?v=cEwf9PpbMcQ </a> <br /><br /><strong>Capturar numa view dados do user logado:</strong><br /><br />Capturar o group_id:<br /><br />$gi=$this-&gt;request-&gt;session()-&gt;read('Auth.User.group_id');<br /><br />dd($gi);<br /><br /><br /><strong>Campos Virtuais</strong><br /><br />São campos que não vêm de tabelas e existem apenas nos formulários. Um bom exemplo é o de confirmação de senha.<br /><br />Também podemos criar um para calcular a idade de alguém ou para efetuar consultas a bancos de dados no model.<br /><br />Crédito e Detalhes:<br /><a href="http://www.naidim.org/cakephp-3-tutorial-11-virtual-fields">http://www.naidim.org/cakephp-3-tutorial-11-virtual-fields</a> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 13:39:15 -0300</pubDate>
		</item>
		<item>
			<title>14 - Trabalhando com o Código do CakePHP 3</title>
			<link>http://backup/portal/curriculo/livros/cakephp/14-trabalhando-com-o-codigo-do-cakephp-3.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/14-trabalhando-com-o-codigo-do-cakephp-3.html</guid>
			<description><![CDATA[<h3>14 - Trabalhando com o Código do CakePHP 3</h3>
<p style="text-align: right;"><br /><em><strong>Sorte é o que acontece quando a preparação encontra a oportunidade.</strong></em></p>
<p><br /><br /><strong>Fluxo de Informações entre controllers, models e view/templates</strong><br /><br />Supondo que temos no aplicativo cliente, com apenas as tabelas users, groups e customers:<br /><br />Controller/CustomersController.php<br />Model/CustomersTable.php<br />Template/Customers/index.ctp<br /><br /><br /><strong>Criar em src/Model/CustomersTable.php a função:</strong></p>
<pre class="language-php"><code>	public function teste(){
		$query = $this-&gt;find('all', [
			'order' =&gt; ['Customers.id' =&gt; 'ASC']
		]);
		$row = $query-&gt;first(); // Ou -&gt;last()
		print "Model&lt;br&gt;";
		return $row-&gt;name;
	}</code></pre>
<p><strong>Chamar no index() do src/Controller/CustomersController.php:</strong></p>
<pre class="language-php"><code>    public function index()
    {
		// Adionar as 3 linhas abaixo
		print "Controller&lt;br&gt;";
		
		// Mostrar o primeiro name:		
  		print $this-&gt;Customers-&gt;teste();exit;

        $customers = $this-&gt;paginate($this-&gt;Customers);

        $this-&gt;set(compact('customers'));
    }</code></pre>
<p><strong>Chamar pela web</strong> <br /><br />http://localhost/clientes/users/index<br /><br />Mostrará, pois primeiro foi ao controller, depois foi ao model, voltou ao controller e mostrou na view:<br /><br />Controller<br />Model<br />Nome de um customer<br /><br /><br /><strong>Listagem de Users</strong><br /><br />View<br /><br /><strong>Veja a ordem:</strong><br /><br />1) O controller recebe a requisição do usuário para mostrar o customer:<br />http://localhost/clientes/customers/index<br /><br />2) O Controller envia para o Model pedindo o primeiro name <br /><br />3) O Model processa e devolve<br /><br />4) Então o controller envia para a view o primeiro name de customer<br /><br /><br /><strong>Para receber strings com segurança nos forms, usar a função h():</strong><br /><br />&lt;!-- File: src/Template/Articles/view.ctp --&gt;<br /><br />&lt;h1&gt;&lt;?= h($article-&gt;title) ?&gt;&lt;/h1&gt;<br />&lt;p&gt;&lt;?= h($article-&gt;body) ?&gt;&lt;/p&gt;<br /><br /><br /><strong>Testar se uma requisição é realmente post:</strong><br /><br />if ($this-&gt;request-&gt;is('post')) {<br /><br /><br /><strong>Debugar</strong><br /><br />dd($variavel);<br /><br /><strong>Carregar model que não é o default mas associado a este controller</strong><br />$cliente=$this-&gt;LoadModel('Clientes');<br /><br /><strong>Recebendo o nome da action atual</strong><br />$action=$this-&gt;request-&gt;getParam('action');<br />print $action;<br /><br />ou<br />use Cake\Routing\Router;<br />echo Router::getRequest()-&gt;params['action'];<br /><br /><strong>Recebendo nome do Controller atual</strong><br />$controller = $this-&gt;request-&gt;getParam('controller');<br />print $controller;<br />echo ucfirst(Router::getRequest()→params['controller']).'/'.Router::getRequest()→params['action'];<br /><br />ou<br />use Cake\Routing\Router;<br />print Router::getRequest()-&gt;params['controller'];<br /><br />Usando:<br />&lt;?php echo $title_for_layout .' - '. ucfirst(Router::getRequest()-&gt;params['controller']).'/'.Router::getRequest()-&gt;params['action']; ?&gt;<br /><br />$title_for_layout é definida no beforeFilter().<br /><br /><strong>Capturar nome do action atual:</strong><br />$this-&gt;request-&gt;action<br /><br /><strong>Capturar nome do controller:</strong><br />$this-&gt;request-&gt;controller<br /><br /><strong>Componente Flash</strong><br />Uma forma eficiente de enviar mensagens do controller para as views<br /><br />$this-&gt;Flash-&gt;msg    <br /><br />msg = success, set, error<br /><br />public function index()<br />{<br />$controller = $this-&gt;request-&gt;getParam('controller');<br />$this-&gt;Flash-&gt;success(__('O nome deste controller é: '.$controller));<br /><br /><br /><strong>Acesso a Banco de Dados</strong><br /><br />O trabalho com bancos de dados no Cake é feito com dois objetos Tables (lida com coleções da dados, tabela, por exemplo) e Entities (lida com apenas um registro).<br /><br /><br /><strong>Para trabalhar com Tabelas num controller</strong><br /><br />Carregar o objeto Table<br /><br />use Cake\ORM\TableRegistry;<br /><br />Carregar o respectivo objeto<br /><br />$clientes = TableRegistry::get('Clientes');<br /><br />Agora pode trabalhar com seu conteúdo.</p>
<pre class="language-php"><code>use Cake\Datasource\ConnectionManager;

$dsn = 'mysql://root:password@localhost/my_database';
ConnectionManager::config('default', ['url' =&gt; $dsn]);
$conn = ConnectionManager::get('default');

$results = $conn-&gt;execute('SELECT * FROM articles')-&gt;fetchall('assoc');</code></pre>
<p>Também podemos usar query builder.<br /><br /><strong>Redirecionamento para outras páginas</strong><br /><br />controller/action<br /><br />$this-&gt;redirect(['controller' =&gt; 'Clientes', 'action' =&gt; 'index'])<br /><br /><strong>URL</strong><br /><br />$this-&gt;redirect('http://ribafs.org')<br /><br />Action do controller atual<br /><br />$this-&gt;redirect(['action' =&gt; 'edit', $id]);<br /><br />ou<br />$this-&gt;setAction('index')<br /><br /><strong>Para o próprio link de onde veio</strong><br /><br />$this-&gt;redirect($this-&gt;referer());<br /><br /><br /><strong>Datasource</strong><br /><br />Se você precisar de mais controle sobre suas consultas, você pode fazer uso de instruções preparadas. Isso permite que você se comunique diretamente com o driver de banco de dados e enviar qualquer consulta personalizada que você queira:</p>
<pre class="language-php"><code>$db = $this-&gt;getDataSource();
$db-&gt;fetchAll(
    'SELECT * from users where username = ? AND password = ?',
    array('jhon', '12345')
);
$db-&gt;fetchAll(
    'SELECT * from users where username = :username AND password = :password',
    array('username' =&gt; 'jhon','password' =&gt; '12345')
);


Outro exemplo:

$query = "SELECT * FROM user WHERE id=:user_id"
$data = $this-&gt;getDataSource()-&gt;fetchAll($query, array("usery_id" =&gt; $user_id), array("cache" =&gt; false));

Retornando os nomes de todas as tabelas do banco atual

	$conn = ConnectionManager::get('default');
	$driver = $conn-&gt;config()['driver'];

	if($driver == 'Cake\Database\Driver\Postgres'){
		$tables = $conn-&gt;execute("SELECT relname FROM pg_class WHERE relname !~ '^(pg_|sql_)' AND relkind = 'r';")-&gt;fetchAll();		
	}elseif($driver=='Cake\Database\Driver\Mysql'){
		$tables = $conn-&gt;execute("SHOW tables")-&gt;fetchAll();
	}
print $tables;


Identificar SGBD (mysql ou postgres):

Add ao início

use Cake\Datasource\ConnectionManager;

		$conn = ConnectionManager::get('default');
		$driver = $conn-&gt;config()['driver']; // Outros: database, etc.		
		if($driver == 'Cake\Database\Driver\Postgres'){
		    $this-&gt;paginate = [
		        'contain' =&gt; ['Users'],
		        'conditions' =&gt; ['or' =&gt; [
		            'Customers.name ilike' =&gt; '%' . $this-&gt;request-&gt;getQuery('search') . '%',
		            'Customers.phone ilike' =&gt; '%' . $this-&gt;request-&gt;getQuery('search') . '%'
		        ]],
		        'order' =&gt; ['Customers.id' =&gt; 'DESC' ]
		    ];
		}elseif($driver=='Cake\Database\Driver\Mysql'){
		    $this-&gt;paginate = [
		        'contain' =&gt; ['Users'],
		        'conditions' =&gt; ['or' =&gt; [
		            'Customers.name like' =&gt; '%' . $this-&gt;request-&gt;getQuery('search') . '%',
		            'Customers.phone like' =&gt; '%' . $this-&gt;request-&gt;getQuery('search') . '%'
		        ]],
		        'order' =&gt; ['Customers.id' =&gt; 'DESC' ]
		    ];
		}else{
			print '&lt;h2&gt;Driver database dont supported!';
			exit;
		}</code></pre>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 13:28:08 -0300</pubDate>
		</item>
		<item>
			<title>13.8 - Autenticação e Autorização Simples</title>
			<link>http://backup/portal/curriculo/livros/cakephp/13-8-autenticacao-e-autorizacao-simples.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/13-8-autenticacao-e-autorizacao-simples.html</guid>
			<description><![CDATA[<h3>13.8 – Autenticação e Autorização Simples</h3>
<p style="text-align: right;"><br /><em><strong>O sucesso não consiste em não errar, mas em não cometer os</strong> mesmos<strong> equívocos mais de uma vez</strong></em>. (George Bernard Shaw)</p>
<p><br /><br /><strong>Criar um aplicativo tipo blog com CakePHP 3 e autenticação simples</strong><br /><br />Tomando como ponto de partida o exemplo de aplicativo blog do site oficial do CakePHP:<br /><a href="https://book.cakephp.org/3.0/pt/tutorials-and-examples/blog/blog.html">https://book.cakephp.org/3.0/pt/tutorials-and-examples/blog/blog.html</a> </p>
<p><br /><strong>Basicamente esta parte:</strong><br /><a href="https://book.cakephp.org/3.0/pt/tutorials-and-examples/blog-auth-example/auth.html">https://book.cakephp.org/3.0/pt/tutorials-and-examples/blog-auth-example/auth.html</a>  <br /><br /><strong>Banco</strong></p>
<pre class="language-php"><code>-- Primeiro, criamos a tabela articles
CREATE TABLE articles (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(50),
    body TEXT,
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL
);

-- Então inserimos articles para testes
INSERT INTO articles (title,body,created)
    VALUES ('The title', 'This is the article body.', NOW());
INSERT INTO articles (title,body,created)
    VALUES ('A title once again', 'And the article body follows.', NOW());
INSERT INTO articles (title,body,created)
    VALUES ('Title strikes back', 'This is really exciting! Not.', NOW());

CREATE TABLE users (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50),
    password VARCHAR(255),
    role VARCHAR(20),
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL
);
</code></pre>
<p><strong>Criar aplicativo</strong><br /><br />cd varwww/html<br />cacomposer.phar create-project --prefer-dist cakephp/app blog<br /><br />Configurar o banco em config/app.php<br />Configurar as rotas em config/routes.php para Users/login<br /><br /><br /><strong>Gerar o código</strong><br /><br />bin/cake bake all articles<br />bin/cake bake all users</p>
<p><strong>Adicionar ao src/Controller/UsersController.php</strong><br /><br />use Cake\Event\Event;<br /><br />    public function beforeFilter(Event $event)<br />    {<br />        parent::beforeFilter($event);<br />        $this-&gt;Auth-&gt;allow('add');<br />    }<br /><br />Alterar o src/Template/Users/login.ctp, apenas a linha do username para que receba o foco automaticamente ao ser aberta:<br /><br />        &lt;?= $this-&gt;Form-&gt;input('username', ['autofocus' =&gt; true]) ?&gt;<br /><br />Adicione ao src/Controller/AppController.php, logo ao final do initialize():</p>
<pre class="language-php"><code>        $this-&gt;loadComponent('Auth', [
            'loginRedirect' =&gt; [
                'controller' =&gt; 'Articles',
                'action' =&gt; 'index'
            ],
            'logoutRedirect' =&gt; [
                'controller' =&gt; 'Pages',
                'action' =&gt; 'display',
                'home'
            ]
        ]);

Ao final da classe:
    public function beforeFilter(Event $event)
    {
        $this-&gt;Auth-&gt;allow(['index', 'view', 'display']);
    }

Adicione ao início do src/Controller/UsersController.php

    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
        // Permitir aos usuários se registrarem e efetuar logout.
        // Você não deve adicionar a ação de "login" a lista de permissões.
        // Isto pode causar problemas com o funcionamento normal do AuthComponent.
        $this-&gt;Auth-&gt;allow(['add', 'logout']);
    }

    public function login()
    {
        if ($this-&gt;request-&gt;is('post')) {
            $user = $this-&gt;Auth-&gt;identify();
            if ($user) {
                $this-&gt;Auth-&gt;setUser($user);
                return $this-&gt;redirect($this-&gt;Auth-&gt;redirectUrl());
            }
            $this-&gt;Flash-&gt;error(__('Usuário ou senha ínvalido, tente novamente'));
        }
    }

    public function logout()
    {
        return $this-&gt;redirect($this-&gt;Auth-&gt;logout());
    }

Adicionar o suporte ao bcrypt para o hash das senhas

Editar src/Model/Entity/User.php e adicionar:

use Cake\Auth\DefaultPasswordHasher;

    protected function _setPassword($password)
    {
        if (strlen($password) &gt; 0) {
            return (new DefaultPasswordHasher)-&gt;hash($password);
        }
    }

Criar o src/Template/Users/login.ctp contendo:

&lt;div class="users form"&gt;
&lt;?= $this-&gt;Flash-&gt;render('auth') ?&gt;
&lt;?= $this-&gt;Form-&gt;create() ?&gt;
    &lt;fieldset&gt;
        &lt;legend&gt;&lt;?= __('Por favor informe seu usuário e senha') ?&gt;&lt;/legend&gt;
        &lt;?= $this-&gt;Form-&gt;input('username') ?&gt;
        &lt;?= $this-&gt;Form-&gt;input('password') ?&gt;
    &lt;/fieldset&gt;
&lt;?= $this-&gt;Form-&gt;button(__('Login')); ?&gt;
&lt;?= $this-&gt;Form-&gt;end() ?&gt;
&lt;/div&gt;</code></pre>
<pre class="language-php"><code>Execute no mysql
ALTER TABLE articles ADD COLUMN user_id INT(11);

Edite o AppController.php e mude o Auth para:

    $this-&gt;loadComponent('Auth', [
        'authorize' =&gt; ['Controller'], // Adicione está linha
        'loginRedirect' =&gt; [
            'controller' =&gt; 'Articles',
            'action' =&gt; 'index'
        ],
        'logoutRedirect' =&gt; [
            'controller' =&gt; 'Pages',
            'action' =&gt; 'display',
            'home'
        ]
    ]);

Logo ao final:

public function isAuthorized($user)
{
    // Admin pode acessar todas as actions
    if (isset($user['role']) &amp;&amp; $user['role'] === 'admin') {
        return true;
    }

    // Bloqueia acesso por padrão
    return false;
}

Adicione ao início do src/Controller/ArticlesController.php

    public function isAuthorized($user)
    {
        // Todos os usuários registrados podem adicionar artigos
        if ($this-&gt;request-&gt;getParam('action') === 'add') {
            return true;
        }

        // Apenas o proprietário do artigo pode editar e excluí
        if (in_array($this-&gt;request-&gt;getParam('action'), ['edit', 'delete'])) {
            $articleId = (int)$this-&gt;request-&gt;getParam('pass.0');
            if ($this-&gt;Articles-&gt;isOwnedBy($articleId, $user['id'])) {
                return true;
            }
        }

        return parent::isAuthorized($user);
    }

Adicione ao src/Model/Table/ArticlesTable.php

    public function isOwnedBy($articleId, $userId)
    {
        return $this-&gt;exists(['id' =&gt; $articleId, 'user_id' =&gt; $userId]);
    }</code></pre>
<p><strong>Acesse</strong><br /><br />http://localhost/auth_blog/users/add<br /><br /><strong>Adicione um usuário</strong><br /><br />Faça login com ele<br />http://localhost/auth_blog<br /><br />Faça logout<br />http://localhost/auth_blog/users/logout<br /><br /><strong>Veja que ele volta para a home do controller Pages.</strong><br /><br />Vamos mudar isso para que volte para o Users/login<br /><br /><strong>Altere estas linhas no AppController:</strong><br /><br />            'logoutRedirect' =&gt; [<br />                'controller' =&gt; 'Users',<br />                'action' =&gt; 'login',<br />                'home'<br />            ]<br /><br />Caso já tenhamos cadastrado todos os usuários do aplicativo devemos remover o add de:<br /><br />    public function beforeFilter(Event $event)<br />    {<br />        parent::beforeFilter($event);<br />        $this-&gt;Auth-&gt;allow(['logout']);<br />    }<br /><br /><strong>Pronto. Nosso aplicativo agora somente será acessado por quem autorizarmos.</strong><br /><br /><br /><strong>Bom exemplo:</strong><br /><br /><a href="https://lornajane.net/posts/2016/simple-access-control-cakephp3">https://lornajane.net/posts/2016/simple-access-control-cakephp3</a></p>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 13:19:36 -0300</pubDate>
		</item>
		<item>
			<title>13.7 - Aplicativo com uma área restrita</title>
			<link>http://backup/portal/curriculo/livros/cakephp/13-7-aplicativo-com-uma-area-restrita.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/13-7-aplicativo-com-uma-area-restrita.html</guid>
			<description><![CDATA[<h3>13.7 - Aplicativo com uma área restrita/administrativa</h3>
<p> </p>
<p style="text-align: right;"><em><strong>Daqui a vinte anos, você não vai se arrepender das coisas que fez, mas das que deixou de fazer. Por isso, veleje longe do seu porto seguro. Pegue os ventos. Explore. Sonhe.</strong> <strong>Descubra.</strong></em> (Mark Twain)</p>
<p><br /><strong>Criar um aplicativo com uma área restrita/administrativa para o CakePHP 3</strong><br /><br /><strong>Adaptado do vídeo abaixo:</strong><br /><br /><a href="https://www.youtube.com/watch?v=eWu6r5aO1Jc&amp;index=6&amp;list=PL83b6tjXNFHe-OVRROawG3YdIN_-Kbc6j" target="_blank" rel="noopener noreferrer">https://www.youtube.com/watch?v=eWu6r5aO1Jc&amp;index=6&amp;list=PL83b6tjXNFHe-OVRROawG3YdIN_-Kbc6j </a> <br /><br />Criar um aplicativo chamado admin_area.<br /><br />Banco admin_area</p>
<pre class="language-php"><code>CREATE TABLE `customers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(55) COLLATE utf8mb4_unicode_ci NOT NULL,
  `birthday` date DEFAULT NULL,
  `phone` varchar(14) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `observation` text COLLATE utf8mb4_unicode_ci,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO `customers` (`id`, `name`, `birthday`, `phone`, `observation`, `created`, `modified`) VALUES
(1,	'Brennan G. Wilcox',	'2016-04-15',	'(851) 190-1314',	'ante. Maecenas mi felis, adipiscing',	NULL,	NULL),
(2,	'Chase Summers',	'2016-08-27',	'(846) 297-4733',	'Sed molestie. Sed id risus',	NULL,	NULL),
(3,	'Sonia L. Mckay',	'2015-12-02',	'(131) 453-1690',	'fermentum vel, mauris. Integer sem',	NULL,	NULL),
(4,	'Isadora L. Bowers',	'2015-10-24',	'(939) 798-4625',	'consequat, lectus sit amet luctus',	NULL,	NULL),
(5,	'Sophia Cochran',	'2017-06-15',	'(811) 687-0491',	'Aliquam tincidunt, nunc ac mattis',	NULL,	NULL),
(6,	'Maxwell T. Burton',	'2016-01-12',	'(147) 962-3265',	'at arcu. Vestibulum ante ipsum',	NULL,	NULL),
(7,	'Desiree Y. Henry',	'2017-07-21',	'(148) 711-3747',	'vitae dolor. Donec fringilla. Donec',	NULL,	NULL),
(8,	'Asher Key',	'2015-11-07',	'(355) 668-5871',	'a, aliquet vel, vulputate eu,',	NULL,	NULL),
(9,	'Tyler Castro',	'2016-08-31',	'(567) 793-5061',	'nec tempus mauris erat eget',	NULL,	NULL),
(10,	'Rudyard Weber',	'2015-10-26',	'(445) 457-4552',	'Morbi vehicula. Pellentesque tincidunt tempus',	NULL,	NULL),
(11,	'Allen Austin',	'2016-04-15',	'(758) 867-2179',	'ipsum. Phasellus vitae mauris sit',	NULL,	NULL),
(12,	'Octavius Cooper',	'2015-10-13',	'(101) 625-3985',	'ipsum non arcu. Vivamus sit',	NULL,	NULL),
(13,	'Dustin M. Oneill',	'2016-04-24',	'(276) 722-0976',	'magnis dis parturient montes, nascetur',	NULL,	NULL),
(14,	'Giacomo K. Horton',	'2016-07-03',	'(773) 532-7468',	'neque. Sed eget lacus. Mauris',	NULL,	NULL),
(15,	'Signe T. Weaver',	'2016-06-17',	'(210) 895-3664',	'dui nec urna suscipit nonummy.',	NULL,	NULL),
(16,	'Avram O. Delaney',	'2016-08-05',	'(609) 552-7572',	'Donec luctus aliquet odio. Etiam',	NULL,	NULL),
(17,	'Cara Parker',	'2016-07-24',	'(854) 169-4797',	'ornare lectus justo eu arcu.',	NULL,	NULL),
(18,	'Chelsea Mcclain',	'2016-08-06',	'(363) 636-1560',	'mollis lectus pede et risus.',	NULL,	NULL),
(19,	'Wesley Garner',	'2016-06-11',	'(578) 231-2389',	'Fusce feugiat. Lorem ipsum dolor',	NULL,	NULL),
(20,	'Irene P. Arnold',	'2016-02-12',	'(253) 631-9830',	'accumsan laoreet ipsum. Curabitur consequat,',	NULL,	NULL),
(21,	'Austin S. Wall',	'2016-01-21',	'(225) 694-9511',	'Sed eget lacus. Mauris non',	NULL,	NULL);

DROP TABLE IF EXISTS `groups`;
CREATE TABLE `groups` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `groups` (`id`, `name`, `created`, `modified`) VALUES
(1,	'Supers',	'2016-08-30 21:15:01',	'2016-08-30 21:15:01'),
(2,	'Admins',	'2016-08-30 21:15:01',	'2016-08-30 21:15:01'),
(3,	'Managers',	'2016-08-30 21:15:01',	'2016-08-30 21:15:01'),
(4,	'Users',	'2016-08-30 21:15:01',	'2016-08-30 21:15:01');

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(55) COLLATE utf8mb4_unicode_ci NOT NULL,
  `password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `group_id` int(11) NOT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  KEY `group_id` (`group_id`),
  CONSTRAINT `users_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);


INSERT INTO `users` (`id`, `username`, `password`, `group_id`, `created`, `modified`) VALUES
(1,	'super',	'$2y$10$zlIAsTubGNqvhn3pS76jN.QeF6msHGYGcTIJ7KgzS757vDsioA3xa',	1,	'2016-09-15 15:57:16',	'2019-06-12 19:03:49'),
(2, 'admin', '$2y$10$f26.qAgF5Jnl7b3zIdRlQuKTBkrxM2d1xtrLlIee0EKULfSKgejqm', 2, '2016-09-15 15:57:16',	'2019-06-12 19:03:49'),
(3, 'manager', '$2y$10$fx0/o/XU3WPO5.nnP7cnCeSuFsFjxCMkk72DciLqABzHp50cOFnre', 3, '2016-09-15 15:57:16',	'2019-06-12 19:03:49');</code></pre>
<p><strong>Três usuários usando o hash bcrypt:</strong><br /><br />Login - super<br />Senha - abc123S@<br /><br />Login - admin<br />Senha - abc123A@<br /><br />Login - manager<br />Senha - abc123M@<br /><br /><br /><strong>Configurar o banco em config/app.php</strong><br /><br />Configurar a rota default em config/routes.php para Customers/index<br /><br /><strong>Gerar o código com o bake</strong><br /><br />bin/cake bake all customers<br />bin/cake bake model Users<br />bin/cake bake model Groups<br /><br />bin/cake bake controller Users --prefix admin<br />bin/cake bake template Users --prefix admin<br /><br />bin/cake bake controller Groups --prefix admin<br />bin/cake bake template Groups --prefix admin<br /><br /><strong>Adicionar ao webroot/css/style.css</strong><br /><br />.emlinha{<br />    display: inline;<br />    padding: 10px;<br />    text-align: center;<br />}<br />li a{<br />    color: #fff;<br />}<br /><br /><br /><strong>Crie um arquivo src/Template/Element/menu.ctp contendo:</strong><br /><br />&lt;div&gt;<br />    &lt;ul&gt;<br />        &lt;li class="emlinha"&gt;&lt;?= $this-&gt;Html-&gt;link(__('Customers'), '/customers/index') ?&gt;&lt;/li&gt;<br />        &lt;li class="emlinha"&gt;&lt;?= $this-&gt;Html-&gt;link(__('Groups'), '/admin/groups/index') ?&gt;&lt;/li&gt;<br />        &lt;li class="emlinha"&gt;&lt;?= $this-&gt;Html-&gt;link(__('Users'), '/admin/users/index') ?&gt;&lt;/li&gt;<br />        &lt;li class="emlinha"&gt;&lt;?= $this-&gt;Html-&gt;link(__('Login'), '/admin/users/login') ?&gt;&lt;/li&gt;<br />        &lt;li class="emlinha"&gt;&lt;?= $this-&gt;Html-&gt;link(__('Sair'), '/admin/users/logout') ?&gt;&lt;/li&gt;<br />    &lt;/ul&gt;<br />&lt;/div&gt;<br /><br /><br /><strong>Edite o src/Template/Layout/default.ctp</strong><br /><br />E sobrescreva o código entre<br />&lt;nav&gt;<br />e<br />&lt;/nav&gt;<br /><br />Com este abaixo, logo abaixo de &lt;body&gt;:</p>
<pre class="language-php"><code>    &lt;nav class="top-bar expanded" data-topbar role="navigation"&gt;
&lt;?php
    if($loguser){
?&gt;
        &lt;h2 align="center"&gt;&lt;?= $titulo ?&gt;&lt;?php echo $this-&gt;element('menu') ?&gt;&lt;/h2&gt;
        &lt;div align="center"&gt;&lt;?= $this-&gt;fetch('title') ?&gt;&lt;/div&gt;
        &lt;div class="right"&gt;Logado como: &lt;strong&gt;&lt;?=__($loguser) ?&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt; 
&lt;?php
    }else{
        echo '&lt;h3 class="titulo" align="center"&gt;Acesso ao Sistema&lt;/h3&gt;';
    }
?&gt;
    &lt;/nav&gt;</code></pre>
<p>Somente customers poderá ser acessado livremente, groups e users serão restritos<br /><br /><strong>Criar a rota admin em config/routes.php</strong><br /><br />Router::prefix('admin', function ($routes) {<br />    $routes-&gt;fallbacks(DashedRoute::class);<br />});<br /><br /><strong>Obs.:</strong><br />Veja que na pasta src/Controller/Admin os controllers tem o namespace para Admin<br /><br />namespace App\Controller\Admin;<br /><br /><strong>Adicionar os actions login e logout para src/Controller/Admin/UsersController.php:</strong></p>
<pre class="language-php"><code>    public function login()
    {
        if ($this-&gt;request-&gt;is('post')) {
            $user = $this-&gt;Auth-&gt;identify();
            if ($user) {
                $this-&gt;Auth-&gt;setUser($user);
                return $this-&gt;redirect($this-&gt;Auth-&gt;redirectUrl());
            }
            $this-&gt;Flash-&gt;error(__('Usuário ou senha ínvalido, tente novamente'));
        }
    }

    public function logout()
    {
        return $this-&gt;redirect($this-&gt;Auth-&gt;logout());
    }
</code></pre>
<p>Adicionar o login.ctp para src/Template/Admin/Users:</p>
<pre class="language-php"><code>&lt;div class="users form"&gt;
&lt;?= $this-&gt;Flash-&gt;render('auth') ?&gt;
&lt;?= $this-&gt;Form-&gt;create() ?&gt;
    &lt;fieldset&gt;
        &lt;legend&gt;&lt;?= __('Por favor informe seu usuário e senha') ?&gt;&lt;/legend&gt;
        &lt;?= $this-&gt;Form-&gt;input('username', ['autofocus' =&gt; true]) ?&gt;
        &lt;?= $this-&gt;Form-&gt;input('password') ?&gt;
    &lt;/fieldset&gt;
&lt;?= $this-&gt;Form-&gt;button(__('Login')); ?&gt;
&lt;?= $this-&gt;Form-&gt;end() ?&gt;
&lt;/div&gt;</code></pre>
<p><strong>Para acessar customers:</strong><br />http://localhost/admin_area<br /><br />Ainda não podemos acessar users e groups e o acesso integral de customers é permitido.<br /><br /><strong>Implementar a Auenticação</strong><br />Para controlar o acesso ao aplicativo<br /><br /><strong>Adicionar suporte para bcrypt ao login:</strong><br /><br />Adicionar ao início do src/Model/Entity/User.php:<br /><br />use Cake\Auth\DefaultPasswordHasher;<br /><br />Ao final:<br /><br />    protected function _setPassword($password)<br />    {<br />        if (strlen($password) &gt; 0) {<br />            return (new DefaultPasswordHasher)-&gt;hash($password);<br />        }<br />    }<br /><br /><br /><strong>Implementar a autenticação</strong><br /><br />Adicione ao initialize() do AppController, logo abaixo do carregamento do componente Flash::</p>
<pre class="language-php"><code>        $this-&gt;loadComponent('Auth', [
            'authorize' =&gt; ['Controller'],
            'logoutRedirect' =&gt; [
                'controller' =&gt; 'Users',
                'action' =&gt; 'login',
                'home'
            ],
            //'unauthorizedRedirect' =&gt; $this-&gt;referer()
		    'unauthorizedRedirect' =&gt; [
		    'controller' =&gt; 'Users',
		    'action' =&gt; 'login',
		    'prefix' =&gt; false
	       ],
	        'authError' =&gt; 'Você não tem permissão para acessar esta área!',
                  'flash' =&gt; [
                      'element' =&gt; 'error'
           ]
        ]);

        $this-&gt;set('titulo', 'Aplicativo para área Admin Restrita');	   
		$user = $this-&gt;request-&gt;getSession()-&gt;read('Auth.User');
		$loguser = $user['username'];
		$this-&gt;set('loguser',$loguser);
</code></pre>
<p><strong>Restringindo acesso com o Authorization através do callback isAuthorized().</strong><br /><br />Agora que os usuários podem se conectar, nós vamos querer limitar os bookmarks que podem ver para aqueles que fizeram. Nós vamos fazer isso usando um adaptador de ‘autorização’. Sendo os nossos requisitos bastante simples, podemos escrever um código em nossa BookmarksController. Mas antes de fazer isso, vamos querer dizer ao AuthComponent como nossa aplicação vai autorizar ações. Em seu AppController adicione o seguinte:<br /><br />Ao final, abaixo do initialize():</p>
<pre class="language-php"><code>    public function isAuthorized($user = null)
    {
        // Any registered user can access public functions
        if (!$this-&gt;request-&gt;getParam('prefix')) {
            return true;
        }

        // Only admins can access admin functions
        if ($this-&gt;request-&gt;getParam('prefix') === 'admin') {
            return (bool)($user['group_id'] === 1 || $user['group_id'] === 2);
        }

        // Default deny
        return false;
    }
</code></pre>
<p>Observe que os usuários dos grupos 1 (super) e 2 (admin), têm direito a acessar tudo. Aqui podemos customizar mais este comportamento. Mas caso precise de algo mais flexível recomendo o uso de um dos plugins sugeridos ao final.<br /><br /><strong>Abaixo do isAuthorized() adicione:</strong><br /><br />    public function beforeFilter(Event $event)<br />    {<br />        $this-&gt;Auth-&gt;allow(['customers'=&gt;'index', 'customers'=&gt;'view']);<br />        // Negar acesso para todos os actions do controller Customers para usuários comuns<br />        //$this-&gt;Auth-&gt;deny('customers');<br />    }<br /><br /><strong>Também podemos negar acesso:</strong><br />Obs.: Não se aplica para os usuários dos grupos 1 e 2, que podem tudo e já foram previamente autorizados.<br /><br />As regras abaixo aplicam-se somente para os usuários dos grupos 3 em diante.</p>
<pre class="language-php"><code>// Negar acesso a qualquer parte do aplicativo:
$this-&gt;Auth-&gt;deny();

// Negar apenas para o action add
$this-&gt;Auth-&gt;deny('add');

// Negar para um grupo de actions
$this-&gt;Auth-&gt;deny(['add', 'edit']);

// Negar para um controller
$this-&gt;Auth-&gt;deny('customers');</code></pre>
<p>Observe que são públicos apenas os actions index e view do controller Customers.</p>
<p><br />Isto indica a que estamos garantindo acesso completo em todos os controllers:<br />        $this-&gt;Auth-&gt;allow(['index', 'view']);<br /><br /><strong>Podemos controlar o acesso por este método acima.</strong><br /><br />Para que um controller permita o acesso completo adicione ao seu início:<br /><br />use Cake\Event\Event;<br /><br />public function beforeFilter(Event $event)<br />{<br />    $this-&gt;Auth-&gt;allow();<br />}<br /><br /><br /><strong>Testar o acesso para áreas restritas:</strong><br /><br />http://localhost/admin_area/admin/users/add<br /><br />ou<br /><br />http://localhost/admin_area/customers/add<br /><br /><strong>Veja que ele pede o controller Users no src. Então lhe daremos:</strong><br /><br />E crie o src/Controller/UsersController.php com apenas:<br /><br />&lt;?php<br />namespace App\Controller;<br />use App\Controller\AppController;<br /><br />class UsersController extends AppController<br />{<br /><br />    public function login()<br />    {<br />        return $this-&gt;redirect('/admin/users/login');<br />    }<br />}<br /><br /><strong>Agora experimente acessar</strong><br /><br />http://localhost/admin_area/customers/add<br /><br /><strong>Será redirecionado para o login.</strong><br /><br />Acesse com os logins citados no início. Veja que super e admin têm acesso completo e manager tem acesso somente a customers.<br /><br /><strong>Sugestão de Plugins</strong><br /><br />Para um maior controle e mais recursos use um dos plugins abaixo:<br /><br /><strong>Acl da equipe do Cake, via terminal/prompt:</strong><br /><a href="https://github.com/cakephp/acl" target="_blank" rel="noopener noreferrer">https://github.com/cakephp/acl</a>  <br />Um ótimo exemplo de uso<br /><a href="https://github.com/mattmemmesheimer/cakephp-3-acl-example" target="_blank" rel="noopener noreferrer">https://github.com/mattmemmesheimer/cakephp-3-acl-example</a> <br /><br /><strong>Plugim com administração via interface web</strong><br /><a href="https://github.com/ribafs/admin-br" target="_blank" rel="noopener noreferrer">https://github.com/ribafs/admin-br</a> <br /><br /><strong>Mais detalhes em:</strong></p>
<p><br /><a href="https://book.cakephp.org/3.0/en/controllers/components/authentication.html">https://book.cakephp.org/3.0/en/controllers/components/authentication.html</a>  <br /><a href="https://book.cakephp.org/3.0/en/tutorials-and-examples/cms/authentication.html">https://book.cakephp.org/3.0/en/tutorials-and-examples/cms/authentication.html</a>  <br /><a href="https://book.cakephp.org/3.0/pt/tutorials-and-examples/blog-auth-example/auth.html">https://book.cakephp.org/3.0/pt/tutorials-and-examples/blog-auth-example/auth.html</a> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 13:07:28 -0300</pubDate>
		</item>
		<item>
			<title>13.6 - Aplicativo usando o Plugin admin-br</title>
			<link>http://backup/portal/curriculo/livros/cakephp/13-6-aplicativo-usando-o-plugin-admin-br.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/13-6-aplicativo-usando-o-plugin-admin-br.html</guid>
			<description><![CDATA[<h3>13.6 – Aplicativo usando o Plugin admin-br</h3>
<p style="text-align: right;"><br /><br /><em><strong>Não falta quem faça planos, mas para a história apenas ficam aqueles que os concretizaram.</strong></em></p>
<p><br />Para não me tornar repetitivo e evitar conteúdo desatualizado apenas o remeterei para o projeto admin-br, que está sendo atualizado com frequência:</p>
<p><br /><a href="https://github.com/ribafs/admin-br" target="_blank" rel="noopener noreferrer">https://github.com/ribafs/admin-br</a> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 12:51:29 -0300</pubDate>
		</item>
		<item>
			<title>13.5 - Aplicativo Finanças Pessoais</title>
			<link>http://backup/portal/curriculo/livros/cakephp/13-5-aplicativo-financas-pessoais.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/13-5-aplicativo-financas-pessoais.html</guid>
			<description><![CDATA[<h3>13.5 - Aplicativo Finanças Pessoais<br /><br /></h3>
<p style="text-align: right;"><em><strong>Cada um de nós tem um fogo no coração para alguma coisa. É nossa meta na vida encontrá-lo e mantê-lo aceso. (Mary Lou Retton)</strong></em></p>
<p><br /><strong>Este aplicativo tem como objetivo principal efetuar operações entre os elementos do MVC (Controller, Model e View) para um simplificada aplicação de controle de receitas e despesas pessoais.</strong><br /><br />Procurarei simplificar outras operações, focando apenas na codificação.<br /><br />Versão com CakePHP 3.6.1<br /><br />- Criar um Aplicativo com o CakePHP 3.6.1<br />- Para gerenciamento de finanças pessoais.<br />- Apenas com as tabelas despesas e receitas<br /><br /><strong>Importante:</strong> este código customizado funciona apenas no CakePHP 3.6 ou superior<br />Criando behaviors para executar o código da camada de negócios nos models<br />Criando components para executar o código da camada de negócios nos controllers<br /><br /><strong>- Criar o aplicativo</strong><br /><br />cd /var/www/html<br />composer create-project --prefer-dist cakephp/app financas<br /><br /><strong>- Criar o banco de dados</strong><br /><br />Usaremos como SGBD o MySQL<br /><br />Criar o banco financas contendo:</p>
<pre class="language-php"><code>CREATE TABLE `despesas` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `descricao` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  `valor` int(11) DEFAULT NULL,
  `mes` char(8) COLLATE utf8_unicode_ci DEFAULT NULL,
  `created` date DEFAULT NULL,
  `modified` date DEFAULT NULL,
  `receita_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `despesas` (`id`, `descricao`, `valor`, `mes`, `created`, `modified`, `receita_id`) VALUES
(1,	'Mercantil',	500,	'05/2017',	'2017-05-11',	'2017-05-15',	1),
(2,	'Condomínio',	100,	'05/2017',	'2017-05-11',	'2017-05-15',	1),
(3,	'Teste',	300,	'06/2017',	'2017-05-11',	'2017-05-11',	2);

CREATE TABLE `receitas` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `descricao` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  `mes` char(7) COLLATE utf8_unicode_ci DEFAULT NULL,
  `valor` int(11) DEFAULT NULL,
  `created` date DEFAULT NULL,
  `modified` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `receitas` (`id`, `descricao`, `mes`, `valor`, `created`, `modified`) VALUES
(1,	'Salário',	'05/2017',	3000,	'2017-05-11',	'2017-05-15'),
(2,	'Extra',	'05/2017',	100,	'2017-05-11',	'2017-05-15');</code></pre>
<p>Observe acima que o mês é tipo texto para que seja inserido algo com mes/ano<br /><br />- Configurar o banco de dados em config/app.php<br />e o <br />config/routes.php para Despesas/index<br /><br /><br /><strong>Gerar o código dos dois CRUDs com o Bake</strong><br /><br />cd /var/www/html/financas<br />bin/cake bake all despesas<br />bin/cake bake all receitas<br /><br /><br /><strong>Veja pelo navegador</strong><br /><br />http://localhost/financas<br /><br /><strong>Já temos um CRUD básico para as despesas e para as receitas</strong><br /><br />Mas o importante de um aplicativo deste tipo são o código personalidado, chamado de lógica de negócio, que é por exemplo somar todas as despesas de um mês e subtrair as receitas do mês do total de despesas. Isso o CakePHP não faz e precisamos fazer. Também precisamos criar código nos tempaltes adicionando um formulário<br /><br /><br /><strong>Agora a parte interessante</strong><br /><br />O código da camada de negócios<br />Observe que o mês tem um formato próprio, texto sendo dia/ano (dd/aaaa).<br /><br /><br /><strong>Vamos criar uma função em DespesasTable.php, que retorne a soma das despesas do mês:</strong><br /><br />Adicionar ao início:</p>
<pre class="language-php"><code>use Cake\ORM\TableRegistry;

Adicionar:

	public function despesasMes($mes){

		$despesas = TableRegistry::get('Despesas')-&gt;find();
		$res = $despesas-&gt;select(['total_sum' =&gt;$despesas-&gt;func()-&gt;sum('Despesas.valor')])
		-&gt;where(['Despesas.mes' =&gt; $mes])-&gt;first();
		$total = $res-&gt;total_sum;

		return $total;
	}</code></pre>
<p><strong>Criar duas funções no DespesasController.php, que retornem o resultado das funções acima:</strong><br /><br />Adicionar ao início do DespesasController<br /><br />use Cake\ORM\TableRegistry;<br /><br />Mais abaixo</p>
<pre class="language-php"><code>	public function despesasMes()
	{
		$mes = $this-&gt;request-&gt;data('mes');
		$despesas = TableRegistry::get('Despesas');
		$total = $despesas-&gt;despesasMes($mes);
		$this-&gt;set('total',$total); 
		$this-&gt;set('mes',$mes);
	}

	public function saldoMes()
	{
		$mes = $this-&gt;request-&gt;data('mes');
		$this-&gt;LoadModel('Receitas');
		$receitas = $this-&gt;Receitas-&gt;receitaMes($mes);

		$despesas = TableRegistry::get('Despesas');
		$total = $despesas-&gt;despesasMes($mes);

		$saldo = $receitas - $total;
		$this-&gt;set('saldo',$saldo); 
		$this-&gt;set('mes',$mes);
	}


Agora criaremos uma função no ReceitasTable.php, que retorne a soma das receitas do mês:

Adicionar ao início:

use Cake\ORM\TableRegistry;

Mais abaixo:

	public function receitaMes($mes){
		$receitas = TableRegistry::get('Receitas')-&gt;find();
		$res = $receitas-&gt;select(['total_sum' =&gt;$receitas-&gt;func()-&gt;sum('Receitas.valor')])
		-&gt;where(['Receitas.mes' =&gt; $mes])
		-&gt;first(); //perform the sum operation 
		$total = $res-&gt;total_sum;

		return $total;
	}

Veja que existe grande semelhança entre esta e a das despesas.


Vamos customizar a src/Template/Despesas e criar duas views novas:

src/Template/Despesas/despesas_mes.ctp:

&lt;?php ?&gt;
&lt;nav class="large-3 medium-4 columns" id="actions-sidebar"&gt;
    &lt;ul class="side-nav"&gt;
    &lt;h3&gt;&lt;?= __('Despesas') ?&gt;&lt;/h3&gt;
&lt;?php
print '&lt;b&gt;Mês: &lt;/b&gt;'.$mes. '&lt;br&gt;&lt;b&gt;Total: &lt;/b&gt;'. $total;
?&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('Voltar'), ['action' =&gt; 'index']) ?&gt;&lt;/li&gt;

&lt;/nav&gt;

src/Template/Despesas/saldo_mes.ctp:

&lt;?php ?&gt;
&lt;nav class="large-3 medium-4 columns" id="actions-sidebar"&gt;
    &lt;ul class="side-nav"&gt;
    &lt;h3&gt;&lt;?= __('Despesas') ?&gt;&lt;/h3&gt;
&lt;?php
print '&lt;b&gt;Mês: &lt;/b&gt;'.$mes. '&lt;br&gt;&lt;b&gt;Saldol: &lt;/b&gt;'. $saldo;
?&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('Voltar'), ['action' =&gt; 'index']) ?&gt;&lt;/li&gt;
&lt;/nav&gt;

Agora vejamos a customização do index.ctp

Logo abaixo da linha:

&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('New Receita'), ['controller' =&gt; 'Receitas', 'action' =&gt; 'add']) ?&gt;&lt;/li&gt;

Adicione os dois pequenos forms:

        &lt;b&gt;Despesas de um mês&lt;/b&gt;
        &lt;?php
           echo $this-&gt;Form-&gt;create("Despesas",['url'=&gt;'/despesas/despesas_mes']);
           echo $this-&gt;Form-&gt;input('mes');
           echo $this-&gt;Form-&gt;button('Submit');
           echo $this-&gt;Form-&gt;end();
        ?&gt;
        &lt;b&gt;Saldo de um mês&lt;/b&gt;
        &lt;?php
           echo $this-&gt;Form-&gt;create("Saldo",['url'=&gt;'/despesas/saldo_mes']);
           echo $this-&gt;Form-&gt;input('mes');
           echo $this-&gt;Form-&gt;button('Submit');
           echo $this-&gt;Form-&gt;end();
        ?&gt;
</code></pre>
<p><strong>Depois de pronto podemos efetuar as operações através dos pequenos forms.</strong><br /><br />- O form chama o action do controller<br />- O controller chama o model para que devolva o resultado de uma função<br />- Recebendo o resultado o controller devolve para a view/template respectiva<br /><br /><br /><strong>Testando</strong><br /><br />Agora acesse pela web<br />http://localhost/financas<br /><br />Pesquise o total das despesas do mês de 05/2017 ou outro que você tenha cadastrado.<br />Pesquise qual o saldo de um mês<br /><br />Isso dá para começar a mexer no código e ir em frente.<br /><br /><br /><br /><strong>Fluxo das informações</strong><br /><br />- O usuário acessa o aplicativo pela URL:<br />http://localhost/financas<br />- Então ele cai em (pela configuração do routes):<br />http://localhost/financas/despesas/index<br /><br />- Na view Despesas/index.ctp ele consulta a despesa total de um certo mês pelo formulário Despesas de um mês<br /><br />- Este form o direciona para o action DespesasController/despesasMes() através do comando do form: $this-&gt;Form-&gt;create("Despesas",['url'=&gt;'/despesas/despesas_mes'])<br /><br />- O controller então registra o DespesasTable e chama através do seu método despesasMes() para saber o total das despesas do referido mês<br /><br />- O DespesasTable, através do seu método despesasMes() prepara uma consulta e a envia ao banco de dados.<br /><br />- O banco de dados retorna o resultado para o método despesasMes() do DespesasTable.<br /><br />- O método do DespesasTable retorna o valor para o DespesasController, em seu método despesasMes()<br /><br />- O método despesasMes() do DespesasController envia através do método set() o mês e o total de despesas do referido mês para a view com o mesmo nome dele, que é a Despesas/despesas_mes.ctp<br /><br />- Finalmente o usuário é redirecionado para a view despesas_mes.ctp onde recebe o resultado de sua consulta<br /><a href="http://localhost/financas/despesas/despesas_mes">http://localhost/financas/despesas/despesas_mes </a></p>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 12:47:18 -0300</pubDate>
		</item>
		<item>
			<title>13.4 - Aplicativo via Código</title>
			<link>http://backup/portal/curriculo/livros/cakephp/13-4-aplicativo-via-codigo.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/13-4-aplicativo-via-codigo.html</guid>
			<description><![CDATA[<h3>13.4 – Aplicativo via Código</h3>
<p style="text-align: right;"><br /><br /><em><strong>Você não precisa estar um passo à frente dos outros, desde que ca dada dia esteja à frente de você mesmo ontem.</strong></em></p>
<p><br /><br /><strong>Criar um aplicativo para exemplo de interação do codigo do CakePHP entre controllers, models e templates.</strong><br /><br />cake3_app_code<br /><br /></p>
<p>Criar um banco no postgresql com duas tabelas relacionadas<br /><br />groups e users<br /><br /></p>
<p>Configurar o banco no app.php e a rota para apontar para Users e index<br /><br />Testar<br /><br />http://localhost/cake3_app_code<br /><br /><br />Criar um novo método com apenas uma mensagem/string<br /><br />Criar o src/Model/Table/UsersTable.php com apenas o método abaixo</p>
<p> </p>
<pre class="language-php"><code>&lt;?php
namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

class UsersTable extends Table
{
    public function olaModel(){
        return "Olá model do CakePHP3";
    }
}
</code></pre>
<p>No UsersController adicione ao início<br /><br />use Cake\ORM\TableRegistry;<br /><br />E crie o método ola, deixando assim:</p>
<pre class="language-php"><code>&lt;?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\ORM\TableRegistry;

class UsersController extends AppController
{
	public function ola()
	{
		$msg = TableRegistry::get('Users');
		$ola = $msg-&gt;olaModel();
		$this-&gt;set('ola',$ola); 
	}
}

No Template Users cria o arquivo ola.ctp contendo:

&lt;b&gt;A mensagem abaixo foi criada no método olaModel do Model UsersTable.php&lt;br&gt;
e enviada para a view ola.ctp pelo action ola() do Controller UsersController.php&lt;/b&gt;
&lt;br&gt;&lt;br&gt;
&lt;?= $ola ?&gt;</code></pre>
<p><strong>Chamar pelo navegador assim:</strong><br /><br />http://localhost/cake3_app_code/users/ola<br /><br /></p>
<p>Alternativamente criar o action index() no UsersController vazio, assim:<br /><br />public function index(){<br />}<br /><br /></p>
<p><strong>E criar a index.ctp contendo:</strong><br /><br />&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('Olá'), ['controller' =&gt; 'Users', 'action' =&gt; 'ola']) ?&gt;&lt;/li&gt;<br /><br /></p>
<p><strong>Criar um método que pega um registro da tabela users</strong><br /><br />No UsersTable.php:<br /><br />Adicione ao início</p>
<pre class="language-php"><code>   use Cake\ORM\TableRegistry;

	public function umUser()
	{
        $users = TableRegistry::get('Users');
        $query = $users-&gt;find();
        $user=$query-&gt;where(['username' =&gt; 'super']);
        return $user;
	}


No UsersController.php
	public function umUser()
	{
		$user = TableRegistry::get('Users');
		$super = $user-&gt;umUser();
		$this-&gt;set('super',$super); 
	}

No Template/Users criar um_user.ctp contendo:

&lt;?php
//
?&gt;
&lt;h3&gt;Usuário recebido do model através do controller&lt;/h3&gt;
&lt;?php
foreach($super as $campos){
    print ' ID - '.$campos-&gt;id.'&lt;br&gt;';
    print ' Grupo - '.$campos-&gt;group_id.'&lt;br&gt;';
    print ' Username - '.$campos-&gt;username.'&lt;br&gt;';
}</code></pre>
<p><strong>Testar</strong><br />http://localhost/cake3_app_code/users/um_user<br /><br /></p>
<p>Adicionar o link abaixo para o action um_user na index.ctp<br /><br />&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('Um usuário'), ['controller' =&gt; 'Users', 'action' =&gt; 'um_user']) ?&gt;&lt;/li&gt;<br /><br /></p>
<p><strong>Sugestões</strong><br /><br />Existe muita informação importante na documentação do CakePHP 3 online assim também como podemos aprender muito estudando o código gerado pelo bake.<br /><br />Em português<br /><a href="https://book.cakephp.org/3.0/pt/index.html">https://book.cakephp.org/3.0/pt/index.html</a> <br /><br />Aqui<br /><a href="https://book.cakephp.org/3.0/en/index.html">https://book.cakephp.org/3.0/en/index.html </a></p>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 12:37:20 -0300</pubDate>
		</item>
		<item>
			<title>13.3 - Aplicativo com Bootstrap</title>
			<link>http://backup/portal/curriculo/livros/cakephp/13-3-aplicativo-com-bootstrap.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/13-3-aplicativo-com-bootstrap.html</guid>
			<description><![CDATA[<h3>13.3 – Aplicativo com Bootstrap</h3>
<p> </p>
<p align="right"><em><strong>Uma mente ousada está sempre mais preparada para desafiar a sorte e atingir o sucesso!</strong></em></p>
<p> </p>
<p><strong>Criação de Layouts</strong></p>
<p>Esta versão cria 3 novos layouts e os aplica respectivamente aos usuários:</p>
<p>super</p>
<p>admin</p>
<p>manager</p>
<p> </p>
<p><strong>- Baixei os arquivos:</strong></p>
<p>bootstrap.css, jquery.min.js e bootstrap.css</p>
<p> </p>
<p>Alterei o plugin TwitterBootstrap para usar offline</p>
<p><a href="https://github.com/CakePHPBrasil/TwitterBootstrap">https://github.com/CakePHPBrasil/TwitterBootstrap</a></p>
<p>composer require cakephp-brasil/twitter-bootstrap</p>
<p>bin/cake plugin load CakephpBrasil</p>
<p>Em src/View/AppView.php adicionar dentro de initialize(), desta forma:</p>
<pre class="language-php"><code>public function initialize()
{
    $this-&gt;loadHelper('Form', ['className' =&gt; 'TwitterBootstrap.Form']);
}

No AppController.php

$this-&gt;viewBuilder()-&gt;theme('TwitterBootstrap');

$this-&gt;set('project_name', 'Título que você quer');</code></pre>
<p><strong>Para alterar o menu superior direito</strong><br /><br />Crie um arquivo<br />src/Template/Element/nav-bar-right.ctp <br /><br />Você pode copiar o modelo dentro de <br />vendor/cakephp-brasil/twitter-bootstrap/src/Template/Element<br /><br /><strong>Para alterar o menu superior esquerdo</strong><br /><br />Crie um arquivo<br />src/Template/Element/nav-bar-left.ctp<br /><br /><br />Você pode copiar o modelo dentro de <br />vendor/cakephp-brasil/twitter-bootstrap/src/Template/Element<br /><br /><strong>Gerar o código</strong><br />bin\cake bake all MyModel --theme TwitterBootstrap<br /><br /><strong>Para testar:</strong><br /><br />$ cd path-to-project<br />$ bin/cake TwitterBootstrap.publish<br /><br />Ou:<br /><br />$ cd path-to-project<br />$ bin/cake TwitterBootstrap.publish all<br /><br /><br />- Copia do arquivo app/webroot/css/bootstrap.css para bootstrap.super.css, bootstrap.admin.css e<br />bootstrap.manager.css (todos no webroot/css)<br /><br />Editei cada um dos que criei e apenas alterei a cor de fundo do body na linha do background-color abaixo:<br /><br />body {<br />  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;<br />  font-size: 14px;<br />  line-height: 1.42857143;<br />  color: #333;<br />  background-color: #B78999;<br />}<br /><br />- Copiei o arquivo <br />/vendor/cakephp-brasil/twitter-bootstrap/src/Template/Layout/default.ctp<br />para super.ctp, admin.ctp e manager.ctp<br /><br />- Editei cada um dos 3 criados (super.ctp, admin.ctp e manager.ctp) e alterei a linha:</p>
<pre class="language-php"><code>	&lt;?= $this-&gt;Html-&gt;css('bootstrap');?&gt;

para
	&lt;?= $this-&gt;Html-&gt;css('bootstrap.super');?&gt;
	&lt;?= $this-&gt;Html-&gt;css('bootstrap.admin');?&gt;
	&lt;?= $this-&gt;Html-&gt;css('bootstrap.manager');?&gt;

- Adicionei ao initialize() do AppController.php:

		$this-&gt;set('project_name', 'Título do Aplicativo');
		if($loguser == 'super'){
			//$this-&gt;viewBuilder()-&gt;theme('TwitterBootstrap');
			$this-&gt;viewBuilder()-&gt;layout('TwitterBootstrap.super');
		}elseif($loguser == 'admin'){
			$this-&gt;viewBuilder()-&gt;layout('TwitterBootstrap.admin');
		}elseif($loguser=='manager'){
			$this-&gt;viewBuilder()-&gt;layout('TwitterBootstrap.manager');
		}elseif($loguser=='user'){
			$this-&gt;viewBuilder()-&gt;layout('TwitterBootstrap.default');
		}</code></pre>
<p>Assim, ao logar cada usuário terá seu próprio ambiente.<br />Claro que falta fazer um bom acabamento nos layouts, nas cores.<br /><br /><br />Veja também um tutorial similar que mostra a implementação do Bootstrap no CakePHP 3:<br /><a href="https://github.com/ribafs/cakephp-app-bs">https://github.com/ribafs/cakephp-app-bs</a></p>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 12:31:38 -0300</pubDate>
		</item>
		<item>
			<title>13.2 – Aplicativo Blog</title>
			<link>http://backup/portal/curriculo/livros/cakephp/13-2-aplicativo-blog.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/13-2-aplicativo-blog.html</guid>
			<description><![CDATA[<h3>13.2 – Aplicativo Blog</h3>
<p> </p>
<p align="right"><em><strong>Só fracassa quem desiste de lutar, quem para de tentar, por isso quando cair lembre-se que reerguer-se já é uma vitória.</strong></em></p>
<p> </p>
<p><strong>Criando um Blog Simples em CakePHP 3</strong></p>
<p><strong>Pré-Requisitos</strong></p>
<p>PHP 5.5.9 com pdo_mysql, intl e mbstring (no terminal digite php -v)</p>
<p>Apache 2</p>
<p>MySQL 5</p>
<p> </p>
<p><strong>Caso tenha o cRUL instalado use:</strong></p>
<p>curl -s https://getcomposer.org/installer | php</p>
<p>sudo mv composer.phar /usr/local/bin/composer</p>
<p> </p>
<p><strong>Instalar no Windows</strong></p>
<p><a href="http://book.cakephp.org/3.0/en/installation.html">http://book.cakephp.org/3.0/en/installation.html</a></p>
<p> </p>
<p><strong>Criar uma nova aplicação do Cake:</strong></p>
<p><em>composer create-project --prefer-dist cakephp/app cakeblog</em></p>
<p> </p>
<p>O comando acima criou a estrutura de arquivos e diretórios básicos de um aplicativo chamado cakeblog.</p>
<p>Criar o banco cake_blog</p>
<p>Configurar o banco em config/app.php</p>
<p>Configure seu Apache para que tenha suporte ao mod_rewrite.</p>
<p><strong>Model</strong></p>
<p>Após criar um model (modelo) no CakePHP, nós teremos a base necessária para interagirmos com o banco de dados e executar operações.</p>
<p>Os arquivos de classes, correspondentes aos models, no CakePHP estão divididos entre os objetos Table e Entity. Objetos Table provêm acesso à coleção de entidades armazenada em uma tabela e são alocados em src/Model/Table. Entity em src/Model/Entity.</p>
<p> </p>
<p><strong>Configurando rotas:</strong></p>
<p>config/routes.php</p>
<p>$routes-&gt;connect('/', ['controller' =&gt; 'Articles', 'action' =&gt; 'index']);</p>
<p> </p>
<p><strong>Gerando código com bake:</strong></p>
<p>bin/cake bake all Articles</p>
<p> </p>
<p><strong>Executar para criar um arquivo de migração:</strong></p>
<p>bin/cake bake migration CreateArticles title:string body:text category_id:integer created modified</p>
<p> </p>
<p><strong>Criar uma tabela de categorias:</strong></p>
<p>bin/cake bake migration CreateCategories parent_id:integer lft:integer[10] rght:integer[10] name:string[100] description:string created modified</p>
<p> </p>
<p><strong>Criar as tabelas</strong></p>
<p>bin/cake migrations migrate</p>
<p> </p>
<p>Abra o arquivo src/Model/Table/ArticlesTable.php e adicione o seguinte:</p>
<pre class="language-php"><code>// src/Model/Table/ArticlesTable.php
namespace App\Model\Table;
use Cake\ORM\Table;

class ArticlesTable extends Table
{
    public function initialize(array $config)
    {
        $this-&gt;addBehavior('Timestamp');
        // ADICIONE AS 3 LINHAS ABAIXO PARA RELACIONAR AS DUAS TABELAS
        $this-&gt;belongsTo('Categories', [
            'foreignKey' =&gt; 'category_id',
        ]);
    }
}

</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Para Gerar código</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">bin/cake bake all Categories</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Acesse</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="http://localhost/cakeblog">http://localhost/cakeblog</a></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Adicione alguns registros e veja como funciona.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><strong><span style="font-family: Times New Roman, serif;">Acesse</span></strong></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="http://localhost/cakeblog/categories">http://localhost/cakeblog/categories</a> </span></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 12:23:56 -0300</pubDate>
		</item>
		<item>
			<title>13 - Aplicativos de Exemplo</title>
			<link>http://backup/portal/curriculo/livros/cakephp/13-aplicativos-de-exemplo.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/13-aplicativos-de-exemplo.html</guid>
			<description><![CDATA[<h3>13 - Aplicativos de Exemplo</h3>
<p> </p>
<p align="right"><em><strong>Às vezes desistir parece a saída mais fácil, mas é a alternativa mais dolorosa de todas as tentativas de superação!</strong></em></p>
<p> </p>
<h4><a name="__RefHeading___Toc38942_2227385112"></a><strong><span style="font-family: Times New Roman, serif;">13.1 - CakePHP Hello World</span></strong></h4>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Instalação e Teste de Aplicativo Mínimo no CakePHP 3.1.6</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Criar a estrutura básica do aplicativo (de dentro do diretório web)</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">cd /backup/www/cake</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">composer create-project --prefer-dist cakephp/app ola</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Obs.: dessa forma, com o composer, é mais prático para a criação da estrutura básica.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Ainda mais prático que fazendo o download manual e descompactando no diretório web.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Chamar pelo navegador</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">http://localhost/cake/ola</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Classes customizadas:</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Controller</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Ola</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">src/Controller/OlaController.php:</span></p>
<pre class="language-php"><code>    $routes-&gt;connect('/', ['controller' =&gt; 'Ola', 'action' =&gt; 'index']);

&lt;?php
namespace App\Controller;
use App\Controller\AppController;

class OlaController extends AppController
{
    public function index()
    {

    }
}</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>View</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Template/OlaController/index.ctp:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;h1&gt;Olá Mundo do Cake&lt;/h1&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Configurações</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">config/routes.php Ajustar o controller inicial para:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>$routes-&gt;connect('/', ['controller' =&gt; 'OlasController', 'action' =&gt; 'index']);</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Este action diz que quando o usuário chamar o aplicativo pelo raiz o action index do OlasController será chamado.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">config/app.php</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Customizando as views</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Mudando o CSS</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Edite o base.css ou cake.css em webroot/css inserindo no início:</span></p>
<pre class="language-css"><code>#menu-box{
	width:150px;
	float:left;
	border-right:1px solid #CCCCCC;
}
#content-box{
	margin-left:10px;
	width:700px;
	float:left;
	border:1px solid #CCCCCC;
	padding:10px;
	background-color:#F3F3F3;
}
</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Na view troque as classes pelo nosso id, assim:</span></p>
<pre class="language-php"><code>&lt;div id="menu-box"&gt;
    &lt;ul class="side-nav"&gt;
        &lt;li class="heading"&gt;&lt;?= __('Actions') ?&gt;&lt;/li&gt;
        &lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('New Cliente'), ['action' =&gt; 'add']) ?&gt;&lt;/li&gt;
        &lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('List Pedidos'), ['controller' =&gt; 'Pedidos', 'action' =&gt; 'index']) ?&gt;&lt;/li&gt;
        &lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('New Pedido'), ['controller' =&gt; 'Pedidos', 'action' =&gt; 'add']) ?&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;</code></pre>
<p> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 12:19:16 -0300</pubDate>
		</item>
		<item>
			<title>12 - Dicas de CakePHP 3</title>
			<link>http://backup/portal/curriculo/livros/cakephp/12-dicas-de-cakephp-3.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/12-dicas-de-cakephp-3.html</guid>
			<description><![CDATA[<h3>12 - Dicas de CakePHP 3</h3>
<p align="left"> </p>
<p align="right"><em><strong>Não importa se seu sonho vai se realizar hoje ou amanhã, mas sim que você trabalhe para o alcançar todos os dias.</strong></em></p>
<p align="right"> </p>
<p><strong>Foco com HTML5</strong></p>
<p>Foco automático em um campo</p>
<p>echo $this-&gt;Form-&gt;input('grupo',['style'=&gt;'width: 100px', 'type'=&gt;'text', 'autofocus']);</p>
<p align="left"> </p>
<p><strong>Passando argumentos pela URL</strong></p>
<p>Adicionar a linha ao routes.php:</p>
<p>$routes-&gt;connect('tests/:arg1/:arg2', ['controller' =&gt; 'Tests', 'action' =&gt;'index'],['pass' =&gt; ['arg1', 'arg2']]);</p>
<p> </p>
<p>Visite:</p>
<p>http:/localhost/exemplos/tests/value1/value2</p>
<p align="left"> </p>
<p><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Customizando a </b><b>Paginação </b><b>no Controller </b><b>Customers</b></span></span></p>
<pre class="language-php"><code>class CustomersController extends AppController
{
    public $paginate = [
        'fields' =&gt; ['Customers.id', 'Customers.name','Customers.birthday','Customers.cpf', 'Customers.created','Customers.modified'],
        'limit' =&gt; 12,
        'order' =&gt; [
            'Customers.id' =&gt; 'asc'
        ]
    ];

    public function index()
    {
        $customers = $this-&gt;paginate($this-&gt;Customers);

        $this-&gt;set(compact('customers'));
    }

action index resumido

public function index()
{
	$this-&gt;set('customers', $this-&gt;paginate($this-&gt;Posts));
}

ou
$this-&gt;set('customers', $this-&gt;Despesas-&gt;find('all'));

action view
public function view($id = null)
{
	$post = $this-&gt;Posts-&gt;get($id);
	$this-&gt;set('posts', $posts);
}

action add

    function add() {
        if (!empty($this-&gt;data)) {
            if ($this-&gt;Category-&gt;save($this-&gt;data)) {
                $this-&gt;Session-&gt;setFlash('Your category has been saved.');
                $this-&gt;redirect(array('action' =&gt; 'index'));
            }
        }
    }
</code></pre>
<p><strong>Implementação do displayField()</strong></p>
<p>Tenho duas tabelas relacionadas: users e clientes.</p>
<p>Clientes tem um campo user_id</p>
<p>Em</p>
<p>src/Model/Table/UsersTable.php</p>
<p> </p>
<p><strong>Mude o displayField para mostrar não o id mas o username</strong></p>
<p>$this-&gt;displayField('username');</p>
<p> </p>
<p><strong>Aproveite e torne requerido o campo user_id em clientes</strong></p>
<p>src/Model/Table/ClientesTable.php</p>
<p>Adicione</p>
<p>$validator-&gt;notBlank('user_id');</p>
<p>No Clientes/index.ctp no valor do user_id:</p>
<p>&lt;td&gt;&lt;?= $cliente-&gt;has('user') ? $this-&gt;Html-&gt;link($cliente-&gt;user-&gt;id, ['controller' =&gt; 'Users', 'action' =&gt; 'view', $cliente-&gt;user-&gt;id]) : '' ?&gt;&lt;/td&gt;</p>
<p align="left"> </p>
<p><strong>Atualização de Aplicativo</strong></p>
<p>Após instalar um aplicativo podemos atualizar o cake e algum plugin com:</p>
<p>Acessar o diretório e executar:</p>
<p>composer update</p>
<p> </p>
<p><strong>Implementando Busca com paginação em Forms do CakePHP 3</strong></p>
<p>Adaptação de:</p>
<p><a href="http://www.tayron.com.br/blog/121/criando-um-formulario-de-pesquisa-com-cakephp3">http://www.tayron.com.br/blog/121/criando-um-formulario-de-pesquisa-com-cakephp3</a></p>
<p>O exemplo aqui apresentado foi com um aplicativo criado através do bake.</p>
<p>Apenas duas tabelas:</p>
<pre class="language-php"><code>CREATE TABLE IF NOT EXISTS `groups` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `password` char(255) NOT NULL,
  `group_id` int(11) NOT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
);</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Banco - busca</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Diretório - busca</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Os dados do formulário deve ser enviado via query string (get).</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">E a action do formulário deve sempre apontas para o método index, exemplo: </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="http://www.site.com.br/users/index">www.site.com.br/users/index</a>. </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%; page-break-before: always;"><span style="font-family: Times New Roman, serif;"><b>View Users/index.ctp</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Entendidas as duas regras acima vamos criar nosso formulário na nossa view</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">antes da tag &lt;table&gt;:</span></p>
<pre class="language-php"><code>&lt;?php
    echo $this-&gt;Form-&gt;create(null, ['type' =&gt; 'get']);
   
    echo $this-&gt;Form-&gt;input('search', 
	['class' =&gt; 'form-control', 'label' =&gt; false, 
	'placeholder' =&gt; 'Digite o username', 
	'value' =&gt; $this-&gt;request-&gt;query('search')]);
	    
    echo $this-&gt;Form-&gt;button('Pesquisar');
    echo $this-&gt;Form-&gt;end();
?&gt;
&lt;hr /&gt;

Substitua o método index() existente do Controller/UserController.php por:

public function index()
{
    $this-&gt;paginate = [
        'contain' =&gt; ['Groups'],
        'conditions' =&gt; ['and' =&gt; [
            //'Users.people like' =&gt; '%' . $this-&gt;request-&gt;query('search') . '%',
            'Users.username like' =&gt; '%' . $this-&gt;request-&gt;query('search') . '%'
        ]],
        'order' =&gt; ['Users.id' =&gt; 'DESC' ]
    ];
        
    $this-&gt;set('users', $this-&gt;paginate($this-&gt;Users));
    $this-&gt;set('_serialize', ['users']);
}

&lt;?php
namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

class UsersTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this-&gt;table('users'); // Name of the table in the database, if absent convention assumes lowercase version of file prefix
        $this-&gt;displayField('full_name'); // field or virtual field used for default display in associated models, if absent 'id' is assumed
        $this-&gt;primaryKey('id'); // Primary key field(s) in table, if absent convention assumes 'id' field

        $this-&gt;addBehavior('Timestamp'); // Allows your model to timestamp records on creation/modification
    }
}</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Resumo do CakePHP</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Geralmente controller são usados para gerenciar a lógica de um único model.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Controllers são classes que estendem a classe AppController. AppController deve conter métodos que são compartilhados entre todos os controllers de sua aplicação.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Os controllers fornecem uma série de métodos que lidam com requisições. Estes são chamados de actions.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Components - são a melhor alternativa sobre código usado por muitos controllers.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Os controllers e componentes contam com um método initilize() que é invocado ao final do construtor do controller.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Qualquer trecho de código ou componente:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">- No AppController fica acessível por todos os controllers.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">- Num certo controller fica acessível somente para este</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Deployment/Implantação</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="https://book.cakephp.org/3.0/pt/deployment.html">https://book.cakephp.org/3.0/pt/deployment.html</a> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Antes de implantar um aplicativo em produção faça as seguintes verificações/alterações:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">- Atualizar o arquivo config/core.php</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">debug = false;</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Ao desabilitar o debug altera o seguinte:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Mensagens de depuração criadas com pr() e debug() serão desabilitadas.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">O cache interno do CakePHP será descartado após 999 dias ao invés de ser a cada 10 segundos como em desenvolvimento.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Views de erros serão menos informativas, retornando mensagens de erros genéricas.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Erros do PHP não serão mostrados.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">O rastreamento de stack traces (conjunto de exceções) será desabilitado.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>- Checar a segurança:</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Observe que atualmente (3.7.7) o Cake já traz o componente security no AppController:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">No método initialize()</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">// $this-&gt;loadComponent('Security');</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Para ter seus recursos disponíveis no nosso aplicativo basta descomentar e usar o formHelper para criar os formulários. Isso pode prevenir diversos tipos de adulteração de formulários e reduzir a possibilidade de overdose de requisições.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Certifique-se que seus models possuem as regras de validação habilitadas.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Verifique se apenas o seu diretório webroot é visível publicamente, e que seus segredos (como seu app salt, e qualquer chave de segurança) são privados e únicos também.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">- Aprimorar a performance do aplicativo</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Execute</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">composer dumpautoload -o</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Corrigir error no código com composer</b></span></span></p>
<pre class="western" style="font-weight: normal; text-align: left;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><code class="western">composer cs-fix<br /><br /></code></span></span></pre>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 12:14:51 -0300</pubDate>
		</item>
		<item>
			<title>11.3 - Criação do plugin cake-acl-br</title>
			<link>http://backup/portal/curriculo/livros/cakephp/11-3-criacao-do-plugin-cake-acl-br.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/11-3-criacao-do-plugin-cake-acl-br.html</guid>
			<description><![CDATA[<h3>11.3 - Criação do plugin cake-acl-br</h3>
<p> </p>
<p align="right"><em><strong>Não importa se seu sonho vai se realizar hoje ou amanhã, mas sim que você trabalhe para o alcançar todos os dias.</strong></em></p>
<p> </p>
<p><strong>O plugin cake-acl-br foi criado vindo de outros 3 plugins.</strong></p>
<p>Primeito criei o twbs-cake-css - <a href="https://github.com/ribafs/twbs-cake-css">https://github.com/ribafs/twbs-cake-css</a>, depois criei o cake-control, que já removi do GitHub, depois o cake-control-br - <a href="https://github.com/ribafs/cake-control-br">https://github.com/ribafs/cake-control-br</a> e finalmente este, o cake-acl-br, que já está no release 1.30, ou seja, já o atualizei 30 vezes.</p>
<p> </p>
<p><strong>Seus recursos principais são:</strong></p>
<p>• Menu de topo com o element topmenu <br />• Uso do framework Bootstrap<br />• Busca com paginação <br />• Senhas criptografadas com Bcrypt <br />• Controle de Acesso tipo ACL com administração web <br />• Dois Layouts: admin e default com cor de fundo que os diferencia<br />• Datas formatadas para pt-br (veja em Customers)<br />• Tradução do template do Bake para pt-br<br />• Customização do bootstrap_cli adicionando os campos login e logout na geração do Bake<br />• Validação via frontend no login com pattern e minlenght, para exigir senha forte, com pelo menos 8 dígitos, uma maiúscula, uma minúscula e um símbolo. Também com recomendações para validação semelhante pelo CakePHP no<br />UsersTable.php</p>
<p>Geralmente quando vou criar um novo aplicativo eu uso o cake-acl-br, pois o considero muito útil.</p>
<p>Vou esquecer a criação dos plugins do qual ele deriva e me focar apenas na criação do cake-acl-br – <a href="https://github.com/ribafs/cake-acl-br">https://github.com/ribafs/cake-acl-br</a>.</p>
<p> </p>
<p><strong>Um pouco de como implementei os recursos</strong></p>
<p align="justify">- Framework bootstrap juntamente com o template do bake para implementar o Bootstrap no código, especialmente nas views. Estes recursos vieram do plugin <a href="https://github.com/elboletaire/twbs-cake-plugin">https://github.com/elboletaire/twbs-cake-plugin</a></p>
<p>- Busca com Paginação. Este veio do Tayron:</p>
<p><a href="http://www.tayron.com.br/blog/121/criando-um-formulario-de-pesquisa-com-cakephp3">http://www.tayron.com.br/blog/121/criando-um-formulario-de-pesquisa-com-cakephp3</a>. O código para implantar a busca encontra-se no plugin, mas comentado. Para habilitar basta descomentar no action e na view.</p>
<p align="justify">- Depois resolvi traduzir as strings do template do bake para que ele gerasse o código traduzido. Esta tradução encontra-se basicamente nos arquivos da pasta src/Template/Bake</p>
<p align="justify">- Também adicionei no docs/bootstrap_cli.php código para que ao gerar o código com bake já seja gerado o código para login e logout</p>
<p align="left">- Criei um element (topmenu) com um menu de topo e já o incorporei ao plugin em src/Template/Element/topmenu.ctp</p>
<p align="left">- Implementei a criptografia com Bcrypt e incorporei ao plugin em src/Template/Bake/Model/entity.ctp</p>
<p align="justify">- Criei um componente para controlar o acesso do aplicativo, que faz o principal trabalho de ACL (ControlComponent) e inseri em</p>
<p>src/Controller/Component/ControlComponent.php</p>
<p>- Criei um segundo layout, o primeiro para usuários administradores e o outro para os dois restantes e adicionei em</p>
<p>src/Template/Layout</p>
<p>- Adicionei ao código do componente ControlComponent suporte para MySQL e PostgreSQL e já ofereci dois scripts .sql para cada um</p>
<p>- Criei um tratamento de erro para o PDO em docs/pdo_error.ctp e deve ser copiado para o aplicativo/src/Tempalte/Error</p>
<p>- Criei um pequeno estilo em CSS para ajustes no CSS do BootStrap, que está em docs/custom.css e deve ser copiado para webroot/css</p>
<p align="justify">- A parte mais trabalhosa foi encontrar o código correto para lidar com o componente Auth no AppController. Neste controller tem muito código importante para o plugin.</p>
<p align="justify">- Finalmente adicionei validação ao login. No frontend com HTML5 e no backend com validação no model, de forma que exija senhas com pelo menos um caratere maiúsculo, um minúsculo, um número, um símbolo e 8 dígitos.</p>
<p> </p>
<p><strong>Começando pra valer</strong></p>
<p>Irei começar do plugin cake-control-br, esquecendo que iniciei com o twbs-cake-plugin.</p>
<p>Fazendo o download do cake-acl-br:</p>
<p><a href="https://github.com/ribafs/cake-acl-br">https://github.com/ribafs/cake-</a><a href="https://github.com/ribafs/cake-acl-br">ac</a><a href="https://github.com/ribafs/cake-acl-br">l-br</a></p>
<p> </p>
<p>Não vou mostrar detalhes do php na construção do componente, mas apenas detalhes do CakePHP na criação do plugin, que considero relevantes.</p>
<p> </p>
<p><strong>Detalhes</strong></p>
<p><a href="https://github.com/ribafs/cake-acl-br">https://github.com/ribafs/cake-acl-br</a></p>
<p> </p>
<p><strong>Observação importante</strong></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;">O pluigin cake-acl-br
foi descontinuado e <a title="https://github.com/ribafs/admin-br" href="https://github.com/ribafs/admin-br" target="_blank" rel="noopener noreferrer">admin-br</a> continua de onde cake-acl-br parou.</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"></code></p>
<p style="margin-bottom: 0cm; line-height: 100%; page-break-before: always;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>A
estrutura de diretórios ficou assim:</b></span></code></p>
<pre class="language-markup"><code>/config
	bootstrap.php	
/docs
	 /dicas
    AppController.php
    bootstrap_cli.php
    cake-acl-br-my.sql
    cake-acl-br-pg.sql
    custom.css
    pdo_error.ctp	
/src
	/Controller
		/Component
			ControlComponent.php
	/Template
		/Bake
			/Element
				/Controller
					 add.ctp
                delete.ctp
                edit.ctp
                index.ctp
                login.ctp
                logout.ctp
                view.ctp
				form.ctp
			/Model
				entity.ctp
			/Template
		                add.ctp
		                edit.ctp
		                index.ctp
		                login.ctp
		                view.ctp                
		/Element
			topmenu.ctp
		/Layout
			admin.ctp
			default.ctp
/webroot
	/css
		bootstrap.min.css
		bootstrap.min.css.map		
	/fonts
		glyphicons-halflings-regular.ttf
	/js
		bootstrap.min.js
		jquery.min.js
composer.json
LICENSE
README.md</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>Detalhando
alguns arquivos</b></span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>config/bootstrap.php</b></span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;">Neste
arquivo são chamados o BootstrapUI e o código que lida com a
formatação das datas:</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"></code></p>
<pre class="language-php"><code>&lt;?php
use Cake\Core\Plugin;

Plugin::load('BootstrapUI');

// Habilita o parseamento de datas localizadas
date_default_timezone_set('America/Fortaleza');

/**
 * Locale Formats
 */
\Cake\I18n\Time::setToStringFormat([IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT]);
\Cake\I18n\Time::setToStringFormat('dd/MM/YYYY HH:mm');

\Cake\Database\Type::build('date')
    -&gt;useLocaleParser()
    -&gt;setLocaleFormat('dd/MM/yyyy');

\Cake\Database\Type::build('datetime')
    -&gt;useLocaleParser()
    -&gt;setLocaleFormat('dd/MM/yyyy HH:mm');

\Cake\Database\Type::build('timestamp')
    -&gt;useLocaleParser()
    -&gt;setLocaleFormat('dd/MM/yyyy HH:mm');

\Cake\Database\Type::build('decimal')
    -&gt;useLocaleParser();

\Cake\Database\Type::build('float')
    -&gt;useLocaleParser();

ini_set('intl.default_locale', 'pt_BR');

/**
 * Default formats
 */
\Cake\I18n\Time::setToStringFormat('dd/MM/yyyy HH:mm:ss');
\Cake\I18n\Date::setToStringFormat('dd/MM/yyyy');
\Cake\I18n\FrozenTime::setToStringFormat('dd/MM/yyyy HH:mm:ss');
\Cake\I18n\FrozenDate::setToStringFormat('dd/MM/yyyy');


docs/AppController.php (resumido)

&lt;?php
namespace App\Controller;

use Cake\Controller\Controller;
use Cake\Event\Event;

class AppController extends Controller
{
	// Controller default para usuários não admins em 
	protected $noAdmins = 'Customers';
		
	public $helpers = [
		'BootstrapUI.Form',
		'BootstrapUI.Html',
		'BootstrapUI.Flash',
		'BootstrapUI.Paginator'
	];	

    public function initialize()
    {
        parent::initialize();

        $this-&gt;loadComponent('RequestHandler');
        $this-&gt;loadComponent('Flash');
		$this-&gt;loadComponent('CakeAclBr.Control');
        $this-&gt;loadComponent('Auth', [
            'loginRedirect' =&gt; [
                'controller' =&gt; 'Permissions',
                'action' =&gt; 'index',
				'base' =&gt; false
            ],
            'loginAction' =&gt; [
                'plugin' =&gt; false,
                'controller' =&gt; 'Users',
                'action' =&gt; 'login'
            ],                    
            'logoutRedirect' =&gt; [
                'controller' =&gt; 'Users',
                'action' =&gt; 'login'
            ],
    		'unauthorizedRedirect' =&gt; [
    		'controller' =&gt; 'Users',
    		'action' =&gt; 'login',
    		'prefix' =&gt; false
    	   ],
    	    'authError' =&gt; 'Sem permissão para acessar esta área!',
              'flash' =&gt; [
                  'element' =&gt; 'error'
              ]
        ]);		

        $this-&gt;set('titulo', 'Título do Aplicativo');
	    
			$user = $this-&gt;request-&gt;getSession()-&gt;read('Auth.User');
			$loguser = $user['username'];
			$this-&gt;set('loguser',$loguser);
		
			$group=$user['group_id'];
			$this-&gt;set('group',$group);
		
			$controller = $this-&gt;request-&gt;getParam('controller');
			$this-&gt;set('controller',$controller);	   
		
			$action = $this-&gt;request-&gt;getParam('action');
		// Via url: users/login?temp=default
		// $layout=$this-&gt;request-&gt;query('temp');
    	// $this-&gt;set('template',$layout);

		if($loguser == 'user' || $loguser == 'manager'){
			$this-&gt;viewBuilder()-&gt;setLayout('CakeAclBr.default');
		}else{
			$this-&gt;viewBuilder()-&gt;setLayout('CakeAclBr.admin');
		}

		// Descomente para acesso total aos actions abaixo
//		$this-&gt;Auth-&gt;allow(['index','add','edit']);
		
		if(isset($group)){
			// Popula a tabela permissions
			// Após o primeiro login pode comentar as 3 linhas abaixo
			$this-&gt;Control-&gt;populate(1);// Full permissions in all tables to users from Supers group			
			$this-&gt;Control-&gt;populate(2);// Full only in groups, users and permissions tables to users from Admins group			
			$this-&gt;Control-&gt;populate(3);// All in all tables that are not groups, users and permissions to all users from group Managers

			// Enviar o controller atual para o element topmenu.ctp
			$this-&gt;set('supers',$this-&gt;Control-&gt;tables($controller,$action,1));
			$this-&gt;set('admins',$this-&gt;Control-&gt;tables($controller,$action,2));
			$this-&gt;set('managers',$this-&gt;Control-&gt;tables($controller,$action,3));
			$this-&gt;set('users',$this-&gt;Control-&gt;tables($controller,$action,4));
		}

		if($action != 'login' &amp;&amp; $action != 'logout'){
			if(isset($group) &amp;&amp; $this-&gt;Control-&gt;access($controller,$action,$group)==false){	
				$this-&gt;Flash-&gt;error(__('Como usuário "'.$user['username'].'", você não tem permissão de acesso a '.$controller.'/'.$action));
				return $this-&gt;redirect($this-&gt;referer());
			}
		}
    }

	public function isAuthorized($user)
	{
		$requestedUserId=$this-&gt;request-&gt;pass[0];

		if ($user['group_id']==1){
		    return true;
		} else if ($user['group_id']!=1 || $user['group_id']!=2) {
			if (!($this-&gt;request-&gt;action == 'index')) {
				if($userid==$user['id']) {
				    return true;
				}
			}
	    	return false;
		}
		return parent::isAuthorized($user);
	}

    public function beforeRender(Event $event)
    {	    
        if (!array_key_exists('_serialize', $this-&gt;viewVars) &amp;&amp; in_array($this-&gt;response-&gt;getType(), ['application/json', 'application/xml'])) {
            $this-&gt;set('_serialize', true);
        }
    }
}


Um arquivo vital do plugin é o de configuração:

composer.json

{
    "name": "ribafs/cake-acl-br",
    "authors": [
        {
            "name": "Ribamar FS",
            "email": "ribafs@gmail.com",
            "homepage": "http://ribafs.org",
            "role": "Developer"
        }
    ],
    "description": "Plugin para implementar controle de acesso com bons recursos: busca, bcrypt, template do bake em português, bootstrap",
    "type": "cakephp-plugin",
    "keywords": ["cakephp", "acl","bootstrap", "plugin", "busca", "admin", "painel", "bcrypt", "portugues", "controle de acesso"],
    "license": "MIT",
    "require": {
        "php": "&gt;=7.0",
        "cakephp/cakephp": "~3.0",
        "friendsofcake/bootstrap-ui": "1.4.1"        
    },
    "autoload": {
        "psr-4": {
            "CakeAclBr\\": "src"
        }
    }
}</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;" align="justify"><code class="western"><span style="font-family: Times New Roman, serif;">Veja
que este arquivo contém diversas informações importantes sobre o
plugin: nome do plugin, autor, descrição, dependências, licença,
autoload, etc.</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>Outro
arquivo importante é o README.md</b></span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;">Como
o README.md deste plugin é bem grande, não o incluirei aqui, mas
veja em:</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><a href="https://github.com/ribafs/cake-acl-br"><span style="font-family: Times New Roman, serif;">https://github.com/ribafs/cake-acl-br</span></a></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;">Após
concluir empacotei tudo no formato zip.</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>Envio
para o GitHib e publicação no Packagist</b></span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="justify"><code class="western"><span style="font-family: Times New Roman, serif;">Como
em casa uso internet tipo ADSL, não posso enviar o código para o
GitHub usando Git e SSH na porta 22, que é a usada no GitHub. Então
procurei uma alternativa: enviar para a minha hospedagem, onde tenho
acesso SSH e de lá enviar via Git para o GitHub. Ou usar algum outro
servidor free que tenha suporte ao Git. Minhas alternativas são o
Google Cloud (<a href="https://cloud.google.com/">https://cloud.google.com</a>),
mas neste somente usando o Google Chrome. Ou usando o CodeAnyWhere
(<a href="https://codeanywhere.com/">https://codeanywhere.com/</a>).</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;">Depois
disso cadastrar o repositório no Packagist (<a href="https://packagist.org/">https://packagist.org/</a>).</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;">Caso
precise de ajuda para criar o repositório no GitHub e publicar no
Packagist, para que possa instalar localmente via composer, então
confira o tutorial:</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><a href="http://backup/portal/cakephp-3/tutoriais/projeto-no-github.html"><span style="font-family: Times New Roman, serif;">https://ribafs.org/portal/cakephp-3/tutoriais/projeto-no-github.html</span></a></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%; page-break-before: always;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>Remover
plugin</b></span></code></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><code class="western"><span style="font-family: Times New Roman, serif;">composer
remove ribafs/cake-acl-br</span></code></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>Instalar
a versão em desenvolvimento</b></span></code></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><code class="western"><span style="font-family: Times New Roman, serif;">composer
require ribafs/cake-acl-br:dev-</span></code><code class="western"><span style="font-family: Times New Roman, serif;">master</span></code></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>Instalar
uma certa versão</b></span></code></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><code class="western"><span style="font-family: Times New Roman, serif;">composer
require ribafs/cake-acl-br:1.30</span></code></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>Carga
de Plugins </b></span></code><code class="western"><span style="font-family: Times New Roman, serif;"><b>(exemplo)</b></span></code></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;">$this-&gt;addPlugin(</span></code><code class="western"><span style="font-family: Times New Roman, serif;">'autoload'
=&gt; true, 'bootstrap' =&gt; false, 'routes' =&gt; true</span></code><code class="western"><span style="font-family: Times New Roman, serif;">);</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;"><b>Recomendações
para o README de plugins</b></span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"><span style="font-family: Times New Roman, serif;"><a href="https://gist.github.com/josegonzalez/903066">https://gist.github.com/josegonzalez/903066</a>
</span></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"></code></p>
<p style="margin-bottom: 0cm; line-height: 100%; page-break-before: always;"><code class="western"></code></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><code class="western"></code></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 11:50:57 -0300</pubDate>
		</item>
		<item>
			<title>11.2 - Plugin DebugKit</title>
			<link>http://backup/portal/curriculo/livros/cakephp/11-2-plugin-debugkit.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/11-2-plugin-debugkit.html</guid>
			<description><![CDATA[<h3>11.2 - Plugin DebugKit</h3>
<p> </p>
<p align="right"><em><strong>Aquele que tentou e não conseguiu, é superior àquele que não tentou.</strong></em></p>
<p><a href="https://book.cakephp.org/3.0/pt/debug-kit.html">https://book.cakephp.org/3.0/pt/debug-kit.html</a></p>
<p> </p>
<p>DebugKit é um plugin suportado pelo time principal do CakePHP que oferece uma barra de ferramentas para auxiliar na depuração de aplicações do CakePHP.</p>
<p>Já vem instalado por default no CakePHP 3</p>
<p>Para usar clique no botão abaixo e à direita no aplicativo (no rodapé).</p>
<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAvCAIAAAD4sNTGAAAAA3NCSVQICAjb4U/gAAAFZElEQVRYR+1YW08bRxT27H1tg43NNZiAgSQQRCgVgV7UVqr6GkVKpUp9aP9aH/pUqVXVqlIf2hQ1TVHTNgVKaBQKmHsDvhuvveu99RvbGIPx4gTU8sBqHtazM2e++eac75wxySR3XBfgYS4ABgrhouDgSnys3/n4/yXmovBxieOoH1zyccmHkzKU9cNpiPM3liEs6yKMi5DyQMu0TdNlWs7zjn19ERyEMLLMeNysx82IEpFEhucZt5uRRMJzLoalpi3LNgwrr5o5xWWYeLE01crlzaxiqSq+1gPXAI7i8lyLnwu0iD0hobtL6OriggEuEGC9HkaSiChQSphi6Nk2cNhaAauaimLEE2iF57uF7R1ta9uIxY1U2srlMOzF+CCiKHS0yzeHmqZuu0eG+a7Oehsq9xNCeB6N8Xq41qDYe7UyXn++m3vy1/6j33KLT/VozAY9VY8THzDnGR0JfnCvaXLChR2f7eE7O3ydHc1vv5n9Yy7xxVfZx7O2rldMOuGQrw8G7t1ten3qbACOzCaC0PTaJFgz9/dBTOWbk54KoZDUd0jsOaLhOzrEcF+1QScctmlUU3eOOKhlw2gUBw3C4359TmBg96hpJz4OpemcVj80Q0XvQPeKvU5+SjieEfgGMViKYu5noWms33/qFMJy5KhlJxxGIqHH4kJP6FS7GKBtbqfvTxvJtBTuFbqvCFe6EKhsc9OJc810Wt/bq/7khENdWU1/Pw3FlAb7oSUnWqx0go/80nJuYVEpKi/UlmsNiKEQ395GW0c75/eDA7ugq5FIevqBurTcKA4jkcw8nDEyGe/4mDQ4AEXnWlrK+l0LimUJxyG+9L0oGv1OCM0GrUE+GOTagsgJeDHS6dyfi8rCEyOZahQHxlEoP83knz6Th2/IgwPi1R5QzXq9yHalzMIIAqQWKagWGCIC09FUF906/IYPBiBfejxem42dzqVs2jT13T20zIOfOb8Ppw6SYZFtbmabvBSTKIJwI55E8pOuDZjpDBzWyuePITNTKbTDToRMVeiS0r3yxPsL7DJuGQvQDFnnwVnQxMZx8s0b/vfexUHAS7T1zcLWFvItzfhKzlLz1QSgVIADwVGqXdWJD88rtzzjY8rjuezsnJVVjilgCRjN8kVltFQN1r2TE96p2+hBrGlrG2pkXVuNaOsbNN3n85ZWoLlz/BYcDnCT33xb2Z0TDpQdSPfeiVelH37c/+XXwuaWpeu2joX12gOmJB/wDHr49nY0wMJKZmYfUPLPlsATzrT5jSmgUSNr1RQ74cAOwKo0EG776MPg+3fVv1eQIfPLK9rGprEXxeZs1Ffl5e2SLoEJgoKoVBMdrAPXdo+OoFUWVpdXcGSN4qDljCiURuNQ3WOjaKWf8Dg9GkcswP/NXA4OhHNRV+kW5eGhevJVWRhKjQKgURwIV2V+QQh1V08ovReDpdkO9xb5QJ+NkbHPPt/75FPW75MG+lG7yEPX5WuDcJpaydEia7n5hUZxFHb+iX/5NXbse+et4xVhkXlS9bcFFVzbVXRGDWyhBGRkiXXLqDOkvl4crtTfD02D/yL+U9/dh/FGcUActZVILJHMPvodpwspk8J9cDQ6v3JLODBGA7hEtWWhTHehZE+5UPdhPWV2nsaq3wduULjD33Ggx6LPyU8p3YjAaExJphCB3MMZzucDMXxbK80gLX4qYrhJoF7nBT0aRYqp3mLpnV4dAAtV+9Y2OCtebczaYafgKE2gaOJxNPwE24zHQ5d3y4xAlRSXBjQcH24GtQsc9uBKUSjUG9AQjurJ5f3Vs/ey/Sflp5e1dZZ5lziOsnfJxyUfTvF0UfyDhMNhJ5z/1bd/AbOhfrejP95LAAAAAElFTkSuQmCC" /></p>
<p>Então aparecerá a barra do plugin ocupando toda a região do rodapé.</p>
<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABVEAAAArCAIAAAD+A1+EAAAAA3NCSVQICAjb4U/gAAAgAElEQVR4Xu2dC1RU2ZmoTz0BqxDqgEUhVtlI2VFMK87ykaWSi0OGHlo72GZsydWYiHZEc8UkTWe11VnTeNdYzmox0+JNi3davasjMyoJNll2mDChQwY1UZwWTQQ7FiKFSqFSvKqgOEVV3X3qAfU4Z59z6gEUbhbLJfvs/e////a/9z77eXh/XvcNLNiffiuRKBIHm5pMF7qEUHKPXNqZalfkiE03yagEJ7NEEO3JoY04R4LzjKQ6I43yLv0Zb2AYXR2xGoeJUATnVy8ytxfZduQtwRGIXCp+5EQjyYgAIoAIIAKIACKACCACiAAigAggAogAIjCFBNCYfwrho6wRAUQAEUAEEAFEABFABBABRAARQAQQgQgSQGP+CMJFohEBRAARQAQQAUQAEUAEEAFEABFABBCBKSSAxvxTCB9ljQggAogAIoAIIAKIACKACCACiAAigAhEkAAa80cQLhKNCCACiAAigAggAogAIoAIIAKIACKACEwhATTmn0L4KGtEABFABBABRAARQAQQAUQAEUAEEAFEIIIE0Jg/gnCRaEQAEUAEEAFEABFABBABRAARQAQQAURgCgkIpzBvlDUigAggAogAIoAIIAKIACKACCACiAAigAjQEuDxeEIhxuNhfM+CvcOB2e2OsTEM/IfFDxrzs4CEoiACiAAigAggAogAIoAIIAKIACKACCACESbAE4sFUgl/1ix+XCw/Nhb8yY8R8+PiwH/Ikb/rx2azE4R9eNg+SjjAfywW8tc8bDMPO0ZHAxVEY/5AJigEEUAEEAFEABFABBABRAARQAQQAUQAEZgkAryYGGFigiBhtjhtbsy8NLFCIZQni3BcMDseDPjBsJ8nEmMCzzq/DSzyW+2WUfvIiG1wyGo0jj3vJboNxBMD0fVobGBgrK/fe/CPxvyTVIoom0kgYMOwp5jD5HBYeNS5xTowKY+XitE8pk6EQhGB4Akw+mTwoj0pkVePMwwj7SilykggSu1yFfHMti70pgBJQASCJsBYuSglR3V7QmkRCgyaAKMLvQjewgjBhfcVjOI2PZ5IJMRlcS+rpatWSJZ+VTwvDSzpMxSHgM8TxAhiYsAcgUiREusVe/Rh5/Cf7w798fpI+wMwEeAgrOAhGvMz8ESPo4UAqGkPHHZytE8/ogdPLc5JgYU8ivoWLZYiPaOFABufDN0W5NUuhuGlHY1U2RCIRrvYl2/0Whd6O4AkIAJBE2DTdFAKRzWOEssLGMjGhWa8t7CBQOsbAkFsRnrS5oLEvFxMIKCNxvpBzEvzwW/CN/526Oofe2t+PdJ2Dxz7pxn54EsTt+RJcNayaSPK4vLfkGWl0D5HDxCBMBEAK/zkgJ/FD4jWjbG67oKFMBQFEaAlwN4naUWwfoC8OhK0o4sqewLRZZerEsxs61hXdBQREQg/AfaVizLvaGxPKA1BgUETYO9CM9hb2EMI5ByjnIdv+mZifl5YBvzj8sFdAAnfWI8XbIjJSAeBlGN+ZZL2UMpyYtQYqBXXkD7r0DJ5+XvJahHXlCg+IsCJAFi9Zx+fU2T2YlFMRMCbwCS72SRnN93KOkLmR0hsJOhxUpVT5Ehoy1UmJ4U5ReaqCYqPCMwwAqHXl9AlzDCkL5o5nByAU+QoIhmKXaI5yXGLFkbI2BiVMkapBMIDx/yi2D2aFPzqY23jWDgyH7ty9HGDTF62O47pVEI4ckMyXlwCLBf5XYA4RX5xmSLLQyMwyW42ydmFxib8qSNkfoTEht9+DOOkKqfIkdCWq0xOCnOKzFUTFB8RmGEEQq8voUuYYUhfNHM4OQCnyFFEMhS7HDab68h9JOwFu/odNnJM73+en5+1T7lFbCw9bjKFK1+z6dhh45ljyrebdUdu2oOSylOswLdtTly9OCZVig0ZRltvGs980tfaF5Qw70SSxPKLSdeL2qt7QhbFWYCooOIrpYsnko2aCH2bqfb8s7o7VoKztGmRYJVmcWnfwzdPjri1mVS8DocDfLqSJQcQGXLsn40Q/+IbT3PraGtJfXB+7pQxqdDYWBpkHH9nCFLMeDIAfGH+7+8XXyLvIfH5WaS4eExcsUl/BTxhTS/c6vkr5fybk09SSuAUGBavpoHMSRFRvPZTRWfJ/VPtnJJ5RZYklF9M5tgyR4h26FSBXfTeGywhqnScCIRuF9kG7se6t5f0Gqi0wVKSKs+kEh/dK/mMaf3Au9rSOs8kW+cqNZ8+GsPsvbrB6pOGqjtMFlEC8Q5k3VIxSpoeEQI7RHuv3txwuvvUNWKav8+Euy+IOIpwKww8iFPlovS40NsTIFaYtUG+faM0UyWOB3XNaGm9Zjx3vj8Mr/qUKoPAaVQNQ7OdttkERs643oc0dn427TLykHZTZx02hYM7Om9jCAejEkcIQwe4dCDcTgr3HfNL18wty7OfLelpCXivhouDPyXu9ZR9MqvynblNxY+ucB6oC9eVpmvW2po+eVp2csRg4uFKSW6hvKJy9onSztoueM7T/Kn9/scPSi67OkS+FI9Zska27ZC6oLELzLmE4WDFlFtPWG81m7uneYcfPCXv4huX4iDMHM4YUGQ+w6FRWBzOIEQvnDSRLESAgUDMYnlJzoCGYlegMPeAfIkYu8UgwPl4+lZb30ZeLFSvkZceWqA6HPQCBhscURrHj5VAtWxOyTsZ2pO60vqwvlBGAR6EIohC4q/TLNAozadOPtS2jxEYH1fGLX91jrY8pnRXjy4IeWySTJeWZypsZ8NnesaxDpVtah2/0D5z78IyqeHNo0NuZQmHCbQ3ougbfZBrlmyXLTkXDCmbFO495pclaA7E6z9qr2oPbdBCoYxDd6HrxEq15p3EIk0/9ZoARSoQxFNvnV+2bKQMTBZ4luKNff26O4PX96ZrvhPfoB0K234EagUiG0oQNpPZNbFjN5nHDBfMTddk2gplmU5X8ln0d5NWc1WZObIEp1S6V/GFT4+ZDi18pKgkIXpUVFAYIhAZAvZuHZG1K2VV8+Mbvi29dEXK/sXEfUMMq3yncbX1aeTNRMtnj0rFC87txat2Pdezsu0FiuTLyt7a+ESDic7tnZP1+yfhXUaa/kwRCs5llCIrWjt2tuhxrftV3266N6S/N9Qg4UXwJX+atDxTYjvnEppGCQir3fnlOfKH/M/ESMqj5DQpWQ7MeAIBL4Z280KgIGvPUxAolCUyf88PDKWFIvAhQDL+uCBxwXtzM9ueFH0WoWVZa+3hJ6sr55a9MVx8iXUWsoTiQmHD4QfjA36PuvaWkw+2Yw6XIGlGwrbvJGVnCMVinthENF3oPlFv8cqDp1oj31mYsDoD7Beydt4eqjptqGv33kIBzg4k7dmBrwYSTJaGk4+ONY7vRuMp1iTtKcRXK8GXE+yG2wNVv3ja4JM2sCRCCiG6+rQfJ17cMSerfrybpNcBbEw6N/vT7d1YYer2NbG4FJhvabrQc6re4m4lyZ1LCQ3bH3fnzS0tlBLndUUXABh6gaTuMFz0qOP2nHxpi1oQQ6T/Js9BXO3aVG4K2Dc1zlksJgjd7YHq008bupwTTE496zbp768EJTV7SYoQF4/d+ORR2aURdxEvStq/G1+eApybR/SMNNQYzk6UESVwvipnpeYH89VSm6FFV/HB7RucN5hQimUdCLNIvO1kxvJL90vrvTeICvPLyW3VJY3SifMmdMXndleOGF0qvdnVnaMo3ixV4UKx0Vx1vKvqjh1fkbx/hwxglxJO/782Pt9E7yowA6mcgTW5kCL6btWTUrsNnXoM/ulVjx7d2piWevpLTaNPM5J1YGEp0bV9/GyLvyXB+KSq8O/PLG597X0960bTP9cg/4aVr0skrKHwyVSZfKZSUvVmZ4PXsDDzwMvloievgVaC/OFnbkgtLpydifNMhhHQgJ+66qc1vR/CzItdtXtlyaup86VYr/5R1YfN1W3k8Y8tJ75ZkulJRnQezL92BaOMCRMd7mf0vufko85TFG+Nz1IICKPlek3PicvYznMp+pIH0FNpwfgbV7uM9YaqtaqSHcaik+62mpQgitu5d7b+Y33Tq/OzPRLp+46gd9hOhoGBQAxtw8bdsxaKML0VgxlFpmRdRzAMXzG34oCoWqOv7XIwiWX0B1h9oWkVAw0NQ4ixzaSXJizEsRb3QA6mGIkrR168NTFLJcCMoy2NTyvOO3aeketcfs7cjMCE01hN1xeEwXY/ERQo6PpxmKU2ihctp6dB3lRpbGe0UZS5L1eDNW//qJeMKorP/cHKPeuTcbHN0Np59sMvGrrCuhE5JQbHxroDNriafDZOBmkmLQHfFwYSI12hMHeIjDzpI7CzHVY76GWzeEJvNZmYsbWhzGFqGucJVbxLNgKvvgGjKkoIJD3WIxHb0BDxxBCbsYBOlF/4YNPV4bv3RMlJ4rRUcdpcsSJFmJzEj4ujTG593jv2nKzH7jE/WE5X7k8ZKnt/IKDGUaYPKrBvQHtUeuaQcs+dB6fYbSWQrkzIMg2U3KTcd+Ae8GMi6f4DCfpPuopuksfgpYuStUfStdj4gIqXuWtBeZ699qR++9VRkzRm1ebU0ooM9du6E/fcYtWblflKouqjhyd6MFVemvYdpb69vYo8NQCwpJfnEWePPjhyb4wQ8dUr5aXajKzD7cfuhLWx88VpbOxr2SfPVmEt5GlYJh3EMdsPzeusN2h2jYCyky6Svf1OeuViffFxs2dyVJC1Q1kgGqwofdKqB4NMuEAoLhjqkVN72275nef3sYunfiO9YgdWd7yrqNliFMdkb07dX7FAfbDj1D0XTMGqfelbJH2V7+sO9TmkSxWVR+btuXP/BICQklR+KOHW++1vOmNKldKCrbKs5h6/lSWf3DJe0f5odt27l0p04lU/yin76eD2tzsi6NvUFYLOIqLusmXbxgRFvdc52JSEAqX5HMUW2YDiCxojqaRg3d758V3PtMVPDFZ+1t708kNzTScd2UvNlQfv68w81QZVxTtzW4s668gpErirkNJoiozRGah5hTmU1m0o1WP2T+96JCWSz2xOUDT2TexaEkkL1tjqSj2XWQQaMy18MlAtSAhd+ZK+wdiuQuT6PuJnHcgoXzNWfbyjrHmUwGflFqZql1q95rsZ/ZA6KzxvTdl6y7Ef/7KhS6DeuKb8n7/W/T+brmBJy1V9lf+rsc5dcjbQTlLHnLwtSnDfA/U0ozwH8OnUOvlkF8q17xBAbYZ15knyN6Lu+LOCitSCyw+qPUftVJvn5hPPiuuJ1a96igbWd1AXH3PoJBnorwiuisGNo93k9tFQ3z3GReNr0ir2Cl0DfiaxjP4ArS+0raK/mWH5W6yMVRCEZyAHVczZ3VQUYg0n9UVXLeBVLSsnRXsII8QYu33dUOG0VlP2BWEx3V+IPwqGftw/uedvSoWDs50uC2c4OcJfe/B1mfFX7miqb619e/FTzfc+b+kTZe3LLf+p+u6ev3LZtAvNDjxsN7cSaUW7pbqPTQbqTa7Bmklb+n4qwdthEBnSITJZB3/OzvYQagcke7jVjK0NjeQpapxptCHLLryvvr6jKvpsOXAgHncP/O5zQVzcrKVf5YmZP3UH1vlNN5rBPRrCxERREi6QJYrlc8RzU4Vz5oDxP/gKgGB2PMbnOyyWkS/vD/6hyfKgA+jpGvOLZhVsjjM0Pr4S4bcc083eBoM6/w3J2XITm2UrVUYM1t7P0OJbTUdKJvb+mO49Lz+fcOYNz4AqQ67ZjFWVPHQfWOizXDn9UN8sEY9f2ieOW53yvFgz4Gq8jBceV+Woc1eIqrqsGEhb6Dhb/Mi918hq110zlJj4595RZBVFcq+aebTbJExN4WFgZgSuA+lpQuPljiOesaLpXt8hDVZRmbbzt/fdkxriWcuxjqJyzxQAXKAKiguOmt7tySfKJM1uQd34VIvZ0nD64X1T+pn35E1FhlYQQTxrtaRzu+ewhunO8+o2vGCFGGsnpMuk6q4+jXtqADN1marcy4O0WWa9ni69eg0s6xGY9cq/tur+TZ2b0gFdE6MVRf+Av2TfV5r2+TzvPK/bftriDqK3yNj4vGW3oiCjd/ySM/VGHL/2hJzFkPhm6Fd8IWAk5YpnLbF2bL9gdtY+e8snvS0b5+3JeeQ5cePQf/a0oTA9exmvrpGF79EbSA8tlCf8JbvVv9kRIEHMi8codv9xcxsWYL3rkam+t2WHvCCjb7wEpWvx5V29J+hvGGHyydj8Ixv2Y19sPwgmp+K3nMgraG8q/pDcvIXh8p2HXilYJcGMz+s+vHai2QIW/8uXPb+rmL9a2q393rVItduQ8mVsVwNKiTYgY05pHlZd8tA9Edxjrj3+8O7W9Eox1uBKA2+yqN8OndikloZ/ve1cjLLrLv/11lsrlquwK2J5JmHDCrPz1bGE/vGZD7+4QhezjVblMD+A+55qTulGuzefOiefM+t516F6MPkbNDGXh0RXb3m9rHxvYoOmn5xXTUksLeTXHezVW4Wrx+WE0nfQKDNpBnrnDxYMNbtm6c53k30W3CjWdUSRM69il6DKucJP5sUglskfoPVFx70zpcHPHCxVJrx9IMF4+cENVyWFKtaiSNLs8HlDuHKhUwfeEJYxZ0TGgAqfTKsp1fVHAa/ylCIggeG3PXHP/81Z3faXs1e+WuDJV3++ftOvnBuqRQJwlJowhvuqafOA9n2h5oDyXJ5N12a+22y+1WZuuWed6NqDNZPtmwBjoUA6REjpsHnEaDvQLZTaAdEBbvW0730glvk8Cverr8+oil4JLp0UWOcfav5v25BJ+tf7seoFMfPmgXV7nkjoOocfmAe5pZ/Pt/cPEEMmousRiABChEm4CJcJ5XPALEDMfJVg9myiu3v4zl+GW+/ZBgZBHNe3+qzmU0f7xBvT9mRE7AIBUmEwS5e2RdpffprVgB8kIAjKFf5A431C9O0WAo9ROMPUObMVt3trfbYVOPR3TLo+j2SCqPuFe8DvTEHc73LgKnIuxJnWWOd7pT9x53mtKT7f6759n7zD/QcLHYhbbb53CPf0X2wW5L46y60LMVpbM77mz2AUMy5fA71Rw01X58lUbc+qPHsrnJEd+ppnN6QJbpjEaN0F79sZxroNDlwBjlRgpnazHgwMtiZkpgR+W5Iy29hUpdjQ6hrZYlifudMkUbscgjJ6kIH2ux99mf13f/H+nRjwA5n0FmFm08VGfu5GiXsxUyQpyMEaLnsU9tbHr/hCwEhKJUZ9cjFbu032lsve/m/V92CgyQBxmX0PYmCQSOHJ7PdrHm4vuu/3W/R+fzdVOk5uw8Y/vesRZh682MgD05ee5Whh7sbY1ppB+r0kjD5pqfuguUW9rDRHoi782k6pTvvzp67XnZjMFLz+v9785qWSX2H5P/mqa1t6apbM8OF/bP/+F7DdLlRYOITRly/XhgKSKSmq7Vm1bxOtu2xs8cwKM/shjXRdzbVjje5pbOlK1RKs/5YeUyxOBgdYbtX8qfTH16r7Ust+tiJLhFHGpJEa/mC476lIPr1+fPRefGgUYvQ3mnTBBDtaP+m+npGyfw1on/nrdqWomrvP+jT1FELZ9x0UicmgyTHQOc94abH797PMT4/gxPmHpTTnE7m9e5BW8BR5YGuVuHZ8wE9lrbdYRn+A1xdOrSKVLpCwAFblyVhNZ+lp90FLuGLOWvDc9w0BMzT26disDjH1VpG0mhIIEwrGfpxSKk0gHGxQtg9W//jXRR/o7vqsApIDfnzj//jNr984tp6o+riTvrOjUZQp2HSnV7OrbVPJ43NXx8TLZMVHvlJ3KeP9DXFSZ8KgzWRJAN4OkxrQd4hMljE/Z7A9tNoByR5uNWNrQyN5chpnmswpg8P96uvzNkiZIxnIlYN9yGS6+cWzf7/4/MKven99uf93n5tu/PdIa9top9769Kmtf8A+MkJ+z89mIy/hB1fx+/44CMLabRi+2zb4+//q/eWnz86df/ZvF56f/+XQn5pBWldcz3l+080n2svqck3q9eJIrWCLF6WUgZmqg0/YX92vbxslcuLU2AA5p0774/yS38bZ4NAmQdjBXQ7dBLgHwb3WCkYvJqPXTCGFEJvRd42QFOKcCwFp45cpzv0ixT8R2GyGgwgR294vAZ8kHOvsIcuTQQfqT2E5DD1j0gwhaCidltm9P5UDF8iEC4ban5Lv36Rkg9W/k7BaO42ChQAmaYjdvyBIws5Bfvvz4mJL/sbEorIUNe7QNw/WXe6tuwf5WpJACuahJ8wG/xVIXf0GXMswP6W3CHO0XO4ntLJVH5nBF+akK2XZfc+LqUvTv/iCx0ha56cSEO4Y8plZI7NzjWPhrsJQZGEm6RZHGMeMfQHlbqKpiVzcho1/+n5yytFSYzRWJGWfNJPH1JWJBSlDFc00mpDqs/DJPn35z+ef+dHflWOWqh//udWzgj3a8uWpq+R0mO73ev1baakS7D6GjbZ2VN82+1eoMGOndWCmhoKDHtTksYnejMEPWbTD4oyXtT+R3/2X/yQ3RJz/j9d+5bz1B8Pq/uWLrF+uKVj1RctVd8H5xORgREhRqQl42kbyaVdAy+nFhyZvFv5GkzKYYLPpxGnLub2KVQRWstJyqijwW7/B9x00+kyOgeQ8Y2nN+GYSu6nP7jUIhRnFoo7wMzertqzAdHpRNrm1cFwwk1ioPzDUlztcO1Ma/BTB3qz4qw+k7xf3nrg00UbBFXPWAiKwQWM35Gd6U4qg1RQgQD/r5TbUKGD9OMe7h+BgsWBstxtpdDBe/sNrl0WZm7PBUanOyGwxM3WZr4DfzwBYcJJ8btmBl8rM90sbx4I3k92bALwdnpwXHojtodQOSh91BcKtJp9CWxsayZPTONNkTh0c5ldfdh8g5cwBXK3vcIDxuenGTfDLl0rEKXKRXC6ckwQ28INRjEAq4c+aBW7jc63/g+0A1p5nYGuA3Wx2WP33PILN/657/kgirg+Zg4MA43gcLR93nV26QHNgsKg8sMOmpsghVCJ9+z2cqOk4weUkPNFsbDqg3J7z1PeuLFe2PKnEYTJjYJq8cuvYibLOY+4LRfiqDcpcz34wMEKQLhbhGBbYlzAqD9KOtj0D254p9g0zJg4hAp4jyzKazjkPazLo4NwHPv7JCk+e/PlKIRgdUaoNF6jOgOGCo4ZbTBZEhsgzDeGJKxIpcFuvETJScsckeky1p8Ev2PouylorLzmyIOvw/SPUFz2AJATYSSIWgz0CrkogFott5PnXafXTbqztUW9ay7/SyM/eKGmtecLmaFyIGDkBgLuK/xkETqInKzJ7twkGbFd/dducLXmihktWMFkubuyC3k3NyieNV7+8/oPc1wytPheFmiacF7wBu3cWmEam0KO5tavkpBLf7z5asci9p8wpSoxjtPMXDH7I5EuKtSu0P0y+++Hnx666J4LH7/sFm6j1BsFqGVCNfBQYk0l2eJ7DfY/6KXPOrPyNWQzrGMb67rMb1eAAtu5jnfM2EJ+fUPoOf1nuvyfJQOp5RqcOcKOY64g4ZvXiQQ34NDIuqyifuOeIWWxgT+rFiLG+sG8VacjTBnuzqjvek3sGbP0YPHTN3b/DFSPfPaB2YUzNCPxtLXJWU+JgREFh7PjrENTSwOzgYEH8cNtuba35S8O3c3Kz+Fc8s6WBWoUjxK6rf1yxYpE2J07cOBSKmWwIULe0rN9Rw2Gvtwx/2ykcJhxZwq2mfsqc7yQ1zsyKBBWDwdP8jt/CsuDEARy/F+Kysd4+sMnfJRR8zc1i6rC0k+fw3T88HnmRuUjIEwqT/+EN+bZvE0+fgl0Ao51d4Io+m9lsHx4GewHsI54Txs5k/HipSCazDQ+DON57pa2WKm2PYW2aJmdiJmAiq5D+J8x9Jy23r6fstNfVvmwEWk2nTg9n7lUWKP0OHZCXjZ2rnJslEi7Pk+hrerxuELUbemzjsnX1ffrFc7Yt8kmuWJqwSsm8S9yZFs9X+igqTpGsygg7n4ksxEqZZnds6/lnrvEDsw7iuPzNEp81bCW+ZaW9qXGYEjBcIBQXA2rK7CYKonHQsCxpm+/hEdXGOdmmoVpO52bN1pb6J2eaBUuWQb4CZe3sGlGoZ7tzl0nmS806NkNquA1hfmqtqzGrwU1+5O19pk/Z9Z26cGFkYQvcVVgImE5RmNwmKLBjDTWDio24mjyaYau97NPKBhjPxif5md9dmW3obMJf0Wxk7lhYroAFaBKGAGhDESDfOGbARGrvhlSW8OZa9x01JPnFyTuX+jTI0mXxas8kQQh+yM8s/NvKfXG179Yfu+rapSpa95PXKwsT3SqKwNcriG5yfTUwZoAVEQuA+57eWeULfFtObz40erHxN5qkQQYTtcd7bjT3lF8OdMyQ+g4adSbfQD9FGIxiriPESNXRnhbgmOBjPafH8jWpWWSlZxDL6A8c6gtTq0hDnl1wX3/FJ9bsvQpwdsb1A1dM1zgU8IbAU+XhWeOThfBmhP3bWkStpmQTiALej0MtDcwBDtYnfvC2850tZ7xbGnmknyDodtgFqsgiRJyRkJsR+FrOixfzTCZyc014zKQnAG+HWVgQfBRm2xlrR7CZw61mbG1osp3yxplGL3bBHDyNQSAnDrHqjORvv5mw/uvgTD7tHX7gyr7RUTAXQO7V5/Nj1emy115V7H1L+Y/vzvvpTxTfL8ILNsZ/bXVsRrooVSFITACbAoC0hK+vS9ryhiSLXAv3q2JdvdqTlqwDYIzNYAqnx4oNaW8vI04c7nUuXXP7MdZ3aWr4eyrU72+Nz1QKpTKhamnCNo26ElwId9TQYh2732ZVr09QefoVaUbi/sJZGPhonysEWPSJLf9I+v6cWFzCk8pi121VVRySZwds2KdQC6Q9j23TqgoWCZ39Dk+xNFlbnpbPJi2FOKogUk/XLx9Xxq3bOq+yIhVv7Cr7zLNLg1EHYlQvkWtLZVlKvlgkVK1ILi+XK5oNp+jWwOECYbiYUJP3L9jxxZJMmXga/ZEAAAyJSURBVFCxKG68RNxmtz/V1mAF2pf2gG8KApNBQexKr9gtqD1qGN/DTAWIxA6u9a44kJgJLjV0/kgX4ZuW2W41j9LEJ4Nbf/vYtP6r2xaLMJFk3VuZ6taOJt97GSBpOTyaKL7xcuT5rWdCpJmuGq8rk0sO4NLGXvctR5DYrkfBY2QUHRAB7ioB0f0CYM7AlDYczxncxl+9oMASN3vrsMSiA0mru4wNTA7G6JPixVma14mzH1zTftCpeGt1QRjbmXAA9ZEBayjI7TWjmHDhIrFUIpSCdthqbrotyN8hc7UJeEbi+4fw3qvDYMcCWVlI8vbcQ+kHN0hVMiGeEpcLmujviI0mPvj4KJlpsH6I52Rrv2Wr+qcvmoxiXBYLfqWYtbVlUPWtV/LBnC9oGX7wN9lGcETCThUz7MjADg2vVsLd7DubC7jvOZ+CbmjbCjE5tysSZeallW0UMV6Kw+hvYbeQaO/VlPXq/HcYgnyY+44JZfych17LyTfQVxcmo+B1xClrfIOoof5xeXu85kC8lJEVoz/A6gtDq0gPO5gn+stPqonE0h2x7j4RphhZC8rr+Vs8bwhS0A7sVZVkEBPn+eHNCEw4g9X+fUEwtjKk8UcBr/JwSwNftEKwnUHvicf21hug5fybAiX5TrXqrWXZRn0t9Mwta8nuiLgyfmf5wsrS5PwVsQoZXyoCr8SS3L3z968crb7kXMEK0kyG0p/QE14oXO3hEp/Zduba4dvnBuY+03ufQIuDD4F5Gjep1J2UKD5rbaAcfkyM5JUlKXt2yb+3XbI8Swgu3o+P58XGgiV96mv87PbxE/1gbB/z0vzZ678uL9ox7x/fnf/B4bTSA0nf2gRmEOTf3SbfsW3WkkyekLweLWDFGvQ92hUZZZrkuyXPqTrvQEWZQpRJZftiW462u2+/Z4oe8NzeeqFj+23ZtkJ5WWEMLnaYDJZb156WFg20OjcQ6k4/1O6dW1aJE31jJsLW2z5QffgxUa7atJJ34xrYU+rQXego6kraU6g69w6YmrQa2oaqDj6q9VwCH5CddwCZthik3bdgj1JAEDZwY3z14Qe1sJPkUHn+D8FFLy837HaF2keNY7o2U93h+7XOjw56fhh1sN/6Ref1DHlJ2ULP15v1xRdM9GcZ4AJhuJhQY62XnreUySvOyU36wVPaR3ofJRytpx8Ut8mLQUG8RxaE/vbAiZKnPnuY/fm4/na0fNR1cfOc4jK5CifHAIRxpOF4x9k7/vdX+KRuayn7+UrN/35jp9RmbO0o+6dILPN7F99E5t017W/SfqHd10KrqbqRd3bzWMVx+BKxd6qgMVLDhYbCXQWaFEy7+DkD/YX2DIKCfMzgNgHqBQfWUl1DXPyhpOn9Lvoa5zEA7pOipD0/STf9ez35wbOu2+VXN5T99OVb+/8apPURTwZrKDDMXFszWrbv5U93j1QfbD91b6zuaJf6vbmVF+VgxcbY1nfu6MMbstTVh/BsianB7CTfDr7LnXZmnwAzge9y92pLzUveW7AlL/YUWZWC88PELd+dm4RjJf/nmyVuGiOf/vjTY/XXNPjXSn72D29LbYYWXdm7t3VY4h7KmLfDC5G6uRj6bcdr5WZo2wj4dJR0KYr3pu9UCAij5frlp+VHBaXnkhn0g/sbQ+IwP2bsO7zy83Meek2m2kAmo+B1xM+usSvHH62unKfJadcwvdIw+QOsvgTTmdKXAMMTq+Xs8f7cI3ML6l3fcYQpRn5H5nh7iT61ZG/6lvd4JsNI04XusquxZevB0UzXD0MzAnlbg1sd0BcwmBXM4wAU0CoPtzSwb4WBhdvO3hZj47VS/GulP3ujVGrrbOnQvvsF02oNe9lkTEPjo6Lbcbmbk/J34ftVwngxNmq06toGT5Q8a3Df8BqkmawJBPcOwM1MytgsbGesHfBm84XufSiZQwNhngZNGPCQspNSLSj9qX37Br/I9tFRsKtfrJyHb3od/FraH4y0fQk+swe27hPdBhs4cm+zOewOz9V9DgyM4cFlfjY7xud5TwqAOQIRuLdfPke6asV4FtY7f7FbyHEG78/rvhGgpUTyduX85dc6ik7Ct+L3W4lEEXxZUxS3pyI9t11Pc0cACwkB2kVDwGTZJUksv5h0vag93F+hiwbG/jrecdjAURf/UJq/wQaZpTxy0ovuZ7JKkC7/Fys8immLV8y7eMCuKXpC9QLEySdDL/IX3KsjRHtaUpXJKs7Jmooe+Lb8nAjA7ZqGVTKM1oG6Ng0NDKEFoPaHEAT6JJ06VuQbDn7d38/DZVcQcqYORRDKckjCqXJRyo269oTSikgERsxnpqp2ULc2nFxopnrLn1ncKQx8jJ/1wyUtFX7OBoboqT/4fsyC9EAnBFf0WXvJG6zB9/ach/bBiX1wgT8BBvazXlkiTlXwYiBnnUl5YPrgeXXNwH9+HrDOTz41m08U31fg0HXUQK2oQ6x1Wl21YdpdoEatLApFBBABRIADAWHu5nhTYzvVgJ+DFBQVEaAlIJNuWTlWW+/+4JkrGr5ytto4XMl0nIRWJnoQvQSQP0Rv2SHNEYHoIoBam0iUlyRliQFr8Zc8+lA/+Mfrc6jG/OTW/di4mLS5DvCJPvBDDs4dPR//v56zv3BYRkVzFXHqBeA6gLivvBwzXwXuAvQXjWHDrW0jrfdAOOWYH2yfNlv1Pl/mDBTBLsQ6pp/sPb3sFEOxZhoB9ov8wHJOkWcaKWRPmAjw8BXyncssVccDLy1z5TDJbjbJ2YWJYtjERMj8CIllbTbhUGydX5HRU3EeHGdzYCJh5np56d6YpqOPA47TclKVU2TW2kYwIieFOUWOoNLhF83BH8Kf+VRIFODgHgs0vRVZ9KHXl9AlRNbCGSo9wrWDQ2vDyQE4RZ5xRWfurjqf7H+bHmbt7e3/TT348J7s7/NiXlL5WA22MAvIXcw8wcT2ZPDFPvB9PnAcwP7AQjx+MvSnm/y4WHDzPxj2xy5Ij02fD27yAzcCjHY9Hvj9HwY+/4Pru300Y/4ZxxgZNOMJxDowC9ut/RiIjLGOPOPRIQODIaDepa7czGv5WF9H+z7KySeD0cE3zQvu1RGiPdVUwba7ks783SmllakqcKkhMaZvM9Ue1FFdScOJwFTbxdnfZ7Z1rHFw8AfWMqdtRPPw9XZ+QU7sqXb2V95MW2Oms2KcKhelIVHXnlBaEVWBk1A7OLQ2nFxopnoLJwj+zmazjT5+PPbZb4db7sRlLp61ZDG4li8mLZXct091bJkPrvdzhoORP/gFl/mD/4OT/5YHHabrN/mz4oSyRDAFAIb6xJPusYFB8vA/zXl+f03o/g79mEroEuh0m9rwmWrX1FKF596NOZ47t7yw+UnGeKnQQT8qQTYYwxVnptLm5JOhw3zBvTpCtKOIKicCcLumYZUMo3Wgrk1DA0NvASIkAbEaBztTUXCqXJRuFnXtCaUVkQicqT7jx4qTC81Ub2EP4ZWAdf4Jnjwe2J8vlMnAv2JFimjOHGGSjPwzPh6M5MFiPljh54vE4Hx+f/3vbINDtE7L57v2AmCuEwHOeGidnxYXehBdBOQYz+RwsFnqB1NxqVTTZtFlL9J2+hNg75Oh24K8OhK0o4sqewLRZZerdsxs60JvAZAERCBoAuwrF2UW0dieUBqCAoMmwN6FZrC3sIcA4+xwkHf1gZV5cPfevb+Cw/wCcqgfx4+N4YnF4Fp+coc/nz+q7wKX+cHkgI/5jfp/0xyN+WHE0LMoIgCOuSzk8cE0G2TkD9oaKY+HBvxRVKxRrSobnwzdQOTVLobhpR2NVNkQiEa72Jdv9FoXejuAJCACQRNg03RQCkc1jhLLCxjIxoVmvLewgcDJN8Dl/Dbw29/PKRUkMhrzQ+CgR9FHgNyxD1nDR2f4o69Io15jBp8M3T7k1V4Mw0Y7aqkyEIhau1yFPLOtC70xQBIQgaAJMFQuSrlR3p5Q2oQCgybA4EIvhrcwQAgabjgS8sMhBMlABBABRAARQAQQAUQAEUAEEAFEABFABBCBaUcAjfmnXZEghRABRAARQAQQAUQAEUAEEAFEABFABBCBsBBAY/6wYERCEAFEABFABBABRAARQAQQAUQAEUAEEIFpRwCN+addkSCFEAFEABFABBABRAARQAQQAUQAEUAEEIGwEEBj/rBgREIQAUQAEUAEEAFEABFABBABRAARQAQQgWlHAI35p12RIIUQAUQAEUAEEAFEABFABBABRAARQAQQgbAQQGP+sGBEQhABRAARQAQQAUQAEUAEEAFEABFABBCBaUfg/wNkm0h1AqQPOgAAAABJRU5ErkJggg==" /></p>
<p><strong>Clique numa opção para ver detalhes</strong></p>
<p>Exemplo: Sql log, mostra as consultas que levaram ao que aparece na tela</p>
<p> </p>
<p><strong>No CakePHP 3 temos duas opções de plugin, que ficam em:</strong></p>
<p>aplicativo/plugins</p>
<p>aplicativo/vendor/vendorname/plugin</p>
<p> </p>
<p><strong>Instalando um plugin pelo composer</strong></p>
<p>cd aplicativo</p>
<p><em>composer require vendorname/plugin-name</em></p>
<p> </p>
<p>Exemplo:</p>
<p>composer require ribafs/cake-acl-br</p>
<p> </p>
<p><strong>Criação de Plugins no CakePHP</strong></p>
<p>Execute:</p>
<p>bin/cake bake plugin Ola</p>
<p> </p>
<p><strong>Ele criará toda a estrutura, mas vazia.</strong></p>
<p>Vamos adicionar conteúdo apenas para mostrar como funciona.</p>
<p> </p>
<p><strong>Habilitar/Carregar o Plugin</strong></p>
<p>bin/cake plugin load CakeAclBr</p>
<p> </p>
<p><strong>Descarregar plugin</strong></p>
<pre>bin/cake plugin unload CakeAclBr</pre>
<p> </p>
<p><strong>Funções para debugar o código</strong></p>
<p>Citando duas delas abaixo:</p>
<p>Para verificar o código, use a função debug, cujo retorno ajuda a debugar:</p>
<p> </p>
<p>debug($variavel_objeto_array);</p>
<p>exit;</p>
<p> </p>
<p>A função dd() é ainda mais prática, pois já tem o exit() embutido e não precisamos digitá-lo:</p>
<p>dd($variavel_objeto_array);</p>
<p> </p>
<p><strong>Mais detalhes</strong></p>
<p><a href="https://book.cakephp.org/debugkit/">https://book.cakephp.org/debugkit/</a></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 11:44:33 -0300</pubDate>
		</item>
		<item>
			<title>11.1 - Criação de Plugin para o CakePHP 3</title>
			<link>http://backup/portal/curriculo/livros/cakephp/11-1-criacao-de-plugin-para-o-cakephp-3.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/11-1-criacao-de-plugin-para-o-cakephp-3.html</guid>
			<description><![CDATA[<h3>11.1 - Criação de Plugin para o CakePHP 3</h3>
<p> </p>
<p align="right"><em><strong>A melhor maneira de melhorar o padrão de vida está em melhorar o padrão de pensamento. - U. S. Andersen</strong></em></p>
<p align="right"> </p>
<p><strong>Irei relatar detalhadamente como criei o plugin twbs-cake-css:</strong></p>
<p><a href="https://github.com/ribafs/twbs-cake-css">https://github.com/ribafs/twbs-cake-css</a></p>
<p> </p>
<p><strong>Veja o restante neste artigo:</strong></p>
<p><a href="http://backup/portal/cakephp-3/tutoriais/criacao-plugin-cakephp.html">https://ribafs.org/portal/cakephp-3/tutoriais/criacao-plugin-cakephp.html</a></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 11:36:25 -0300</pubDate>
		</item>
		<item>
			<title>11 - Plugins</title>
			<link>http://backup/portal/curriculo/livros/cakephp/11-plugins.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/11-plugins.html</guid>
			<description><![CDATA[<h3>11 – Plugins</h3>
<p align="right"> </p>
<p align="right"><em><strong>Teste os seus limites, enfrente os seus medos e não deixe que nada impeça você de pelo menos tentar!</strong></em></p>
<p> </p>
<p><strong>Publicação de Plugins no site do CakePHP:</strong></p>
<p><a href="https://plugins.cakephp.org/">https://plugins.cakephp.org/</a></p>
<p> </p>
<p>No CakePHP 3 o plugin é a forma mais adequada de reutilizar código e compartilhar com a comunidade nossos melhores recursos para o Cake.</p>
<p>Basicamente um plugin pode conter um apliicativo a ser usado dentro do Cake como um mini ou sub aplicativo.</p>
<p> </p>
<p>Ele pode conter</p>
<p>Controllers</p>
<p>Models</p>
<p>Views/Templates</p>
<p>Entre outros</p>
<p> </p>
<p>E dentro destes:</p>
<p>Componentes, Helpers, Behaviors, etc</p>
<p> </p>
<p>Então é um super recurso do Cake.</p>
<p>Empacotamos nosso código, hospedamos no GitHub gratuitamente e publicamos no Packagist para que possa ser usado por nós e por toda a comunidade com grande facilidade.</p>
<p>Depois podemos atualizar via git ou no próprio GitHub com os ótimos recursos do mesmo.</p>
<p> </p>
<p><strong>Plugin Assets</strong></p>
<p>Os recursos da web de um plugin (mas não arquivos PHP) podem ser atendidos através do plugin no diretório webroot, assim como os assets da aplicação principal:</p>
<p>/vendor/meuVendor/NomePlugin/webroot/</p>
<p>css/</p>
<p>js/</p>
<p>img/</p>
<p>flash/</p>
<p>pdf/</p>
<p> </p>
<p><strong>Linkando para Assets em Plugins</strong></p>
<p>Você pode usar o sintaxe plugin ao vincular aos recursos do plugin usando o View\Helper\HtmlHelper script, image ou css methods:</p>
<p>// Gera a URL /contact_manager/css/styles.css</p>
<p>echo $this-&gt;Html-&gt;css('ContactManager.styles');</p>
<p> </p>
<p>// Gera a URL /contact_manager/js/widget.js</p>
<p>echo $this-&gt;Html-&gt;script('ContactManager.widget');</p>
<p> </p>
<p>// Gera a URL /contact_manager/img/logo.jpg</p>
<p>echo $this-&gt;Html-&gt;image('ContactManager.logo');</p>
<p> </p>
<p><strong>Chamar Element no layout do plugin</strong></p>
<p>/vendor/ribafs/cake-control-br/src/Template/Layout/default.ctp</p>
<p>$this-&gt;element('CakeControlBr.topmenu');</p>
<p> </p>
<p><strong>Habilitar o plugin</strong></p>
<p>Execute a seguinte linha:</p>
<p>bin/cake plugin load ContactManager</p>
<p> </p>
<p>Isso colocará o plugin Plugin::load('ContactManager'); no src/Application.php.</p>
<p> </p>
<p><strong>Autoloading Plugin Classes</strong></p>
<p align="justify">Ao usar bake para criar um plugin ou quando instalar um plugin usando o Composer, você normalmente não precisa fazer alterações em seu aplicativo para faça com que o CakePHP reconheça as classes que vivem dentro dele.</p>
<p>Em qualquer outro caso, você precisará modificar o arquivo do composer.json do seu aplicativo. Para conter as seguintes informações:</p>
<p>"autoload": {</p>
<p>    "psr-4": {</p>
<p>        "CakeAclBr\\": "src"</p>
<p>    }</p>
<p>}</p>
<p> </p>
<p><strong>Atualizar plugin após alterar composer.json</strong></p>
<p>Sempre que alterar o composer.json execute:</p>
<p>composer update</p>
<p> </p>
<p><strong>Mais detalhes</strong></p>
<p><a href="https://book.cakephp.org/authorization/1.1/en/index.html">https://book.cakephp.org/authorization/1.1/en/index.html</a></p>
<p><a href="https://book.cakephp.org/authentication/1.1/en/index.html">https://book.cakephp.org/authentication/1.1/en/index.html</a></p>
<p><a href="https://book.cakephp.org/debugkit/3.x/en/index.html">https://book.cakephp.org/debugkit/3.x/en/index.html</a></p>
<p><a href="https://book.cakephp.org/migrations/2.x/en/index.html">https://book.cakephp.org/migrations/2.x/en/index.html</a></p>
<p><a href="https://book.cakephp.org/3.0/en/upgrade-tool.html">https://book.cakephp.org/3.0/en/upgrade-tool.html</a></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 00:29:57 -0300</pubDate>
		</item>
		<item>
			<title>10.1 - Components</title>
			<link>http://backup/portal/curriculo/livros/cakephp/10-1-components.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/10-1-components.html</guid>
			<description><![CDATA[<h3>10.1 - Componentes</h3>
<p align="right"> </p>
<p align="right"><em><strong>Nunca desista porque encontrou um obstáculo! Os desafios são o tempero da vida!</strong></em></p>
<p> </p>
<p><a name="o-que-é-um-component-segundo-a-doc-do-cakephp"></a> <span style="font-family: Times New Roman, serif;"><b>O que é um Component segundo a documentação do CakePHP:</b></span></p>
<p align="justify"><span style="font-family: Times New Roman, serif;">Os componentes são pacotes de lógica que são compartilhados entre controllers. O CakePHP vem com um conjunto fantástico de componentes que você pode usar para ajudar em várias tarefas comuns. Você também pode criar seus próprios componentes. Se você copia e cola parte de código entre controllers, você deve considerar criar seu próprio Component para conter essa funcionalidade. A criação de Componentes no CakePHP mantém o código dos controllers mais limpos e permite que você reutilize código entre controllers diferentes.</span></p>
<p><span style="font-family: Times New Roman, serif;">Documentação: <a href="https://book.cakephp.org/3.0/en/controllers/components.html#components">https://book.cakephp.org/3.0/en/controllers/components.html#components</a></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;">Os Components podem ser considerados como formas de criar pedaços reutilizáveis de código relacionado a controllers com uma característica específica ou conceito.</p>
<p style="margin-bottom: 0cm; line-height: 100%;">O CakePHP conta com vários componentes nativos:</p>
<p style="margin-bottom: 0cm;"><a href="https://book.cakephp.org/3.0/en/controllers/components/authentication.html">AuthComponent</a></p>
<p style="margin-bottom: 0cm;"><a href="https://book.cakephp.org/3.0/en/controllers/components/cookie.html">Cookie</a></p>
<p style="margin-bottom: 0cm;"><a href="https://book.cakephp.org/3.0/en/controllers/components/csrf.html">Cross Site Request Forgery</a></p>
<p style="margin-bottom: 0cm;"><a href="https://book.cakephp.org/3.0/en/controllers/components/flash.html">Flash</a></p>
<p style="margin-bottom: 0cm;"><a href="https://book.cakephp.org/3.0/en/controllers/components/security.html">Security</a></p>
<p style="margin-bottom: 0cm;"><a href="https://book.cakephp.org/3.0/en/controllers/components/pagination.html">Pagination</a></p>
<p><a href="https://book.cakephp.org/3.0/en/controllers/components/request-handling.html">Request Handling</a></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><b>FlashComponent</b>, são usados nos controllers para criar mensagens flash para o <code class="western">$_SESSION</code>, para serem renderizadas em uma View usando <a href="https://book.cakephp.org/3.0/en/views/helpers/flash.html">FlashHelper</a>.</p>
<p style="margin-bottom: 0cm; line-height: 100%;">Criando uma mensagem flash:</p>
<p style="margin-bottom: 0cm; line-height: 100%;">// Uses src/Template/Element/Flash/success.ctp</p>
<p style="margin-bottom: 0cm; line-height: 100%;">$this-&gt;Flash-&gt;success('This was successful');</p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Usamos os métodos </span><code class="western"><span style="font-family: Times New Roman, serif;">success()</span></code><span style="font-family: Times New Roman, serif;"> e </span><code class="western"><span style="font-family: Times New Roman, serif;">error()</span></code><span style="font-family: Times New Roman, serif;"> do </span><code class="western"><span style="font-family: Times New Roman, serif;">FlashComponent</span></code><span style="font-family: Times New Roman, serif;"> para definir uma mensagem que será armazenada numa variável de sessão. </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><b>Mensagem em texto plano</b></p>
<p style="margin-bottom: 0cm; line-height: 100%;">Também podemos criar uma mensagem em texto plano no controller através do método set que será recebida na view respectiva com:</p>
<p style="margin-bottom: 0cm; line-height: 100%;">$this-&gt;Flash-&gt;set('Isto é uma mensagem somente texto');</p>
<p style="margin-bottom: 0cm; line-height: 100%;"><a name="criando-um-component"></a> <span style="font-family: Times New Roman, serif;"><b>Criando um Component</b></span></p>
<p><span style="font-family: Times New Roman, serif;">Para nosso exemplo, vamos criar um Component para criação de senhas com caracteres aleatórios. Para isso precisamos criar uma classe no diretório </span></p>
<p align="justify"><code class="western"><span style="font-family: Times New Roman, serif;">src/Controller/Component/</span></code><span style="font-family: Times New Roman, serif;">, um nome de component seguindo a convenção do cake seria algo como: </span><code class="western"><span style="font-family: Times New Roman, serif;">MinhaClasseComponent.php</span></code><span style="font-family: Times New Roman, serif;"> que extende da classe </span><code class="western"><span style="font-family: Times New Roman, serif;">Component</span></code><span style="font-family: Times New Roman, serif;">. Como umas das filosofias do nosso Framework favorito é facilitar o trabalho, podemos usar o PHP CLI(command line inteface) ou vulgarmente conhecido como Bake.</span></p>
<p><span style="font-family: Times New Roman, serif;">Para executar o console do cake, precisamos simplesmente executar o código abaixo.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Carregar componentes</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">No método initialize() de um controller</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>$this-&gt;loadComponent('Flash');</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>$this -&gt;loadComponent('Auth');</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Criação de um Componente</b></span></span></p>
<p><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Criar o arquivo</span></span></p>
<pre class="language-php"><code>src/Controller/Component/CalcularComponent.php, contendo:

&lt;?php
namespace App\Controller\Component;

use Cake\Controller\Component;

class CalcularComponent extends Component
{
    public function soma($valor1, $valor2)
    {
        $s =$valor1 + $valor2;
		return $s;
    }
}</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Adicionar uma chamada no método initialize() do src/Controller/AppController</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Executar num action</b>, como o src/Controller/ClientesController.php</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>public function index()</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>{</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> print 'Componente Soma: '.$this-&gt;Calcular-&gt;soma(2,3);</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Estando no AppController ele será visto por todos os demais controllers e seus métodos estarão disponíveis logo que cada controller seja executado.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Caso queira que apenas um controller tenha acesso ao mesmo, insira o método initialize() no início deste controller assim :</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>public function initialize()</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>{</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>parent::initialize();</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> $this-&gt;loadComponent('Calcular');</i></span></span></p>
<p><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>}</i></span></span></p>
<p><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Exemplos de Componentes Simples</b></span></span></p>
<pre class="language-php"><code>&lt;?php
/**
 * Component Calculo
 * For CakePHP 3.x
 * Autor: Ribamar FS
 *
 * This component allow access control to each action from application with web interface.
 *
 * Licenced with The MIT License
 * Redistributions require keep copyright below.
 *
 * @copyright     Copyright (c) Ribamar FS (http://ribafs.org)
 * @link          http://ribafs.org
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */

namespace App\Controller\Component;
use Cake\Controller\Component;

class CalculoComponent extends Component{

	private $um;
	private $dois;

	public function soma($um,$dois){
		return ($um + $dois);
	}

	public function subtracao($um,$dois){
		return ($um - $dois);
	}
	
	public function multiplicacao($um,$dois){
		return ($um * $dois);
	}	

	public function divisao($um,$dois){
		return ($um / $dois);
	}
	
}
</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%; page-break-before: always;"><span style="font-family: Times New Roman, serif;"><b>Exemplos Práticos com o CakePHP 3</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="https://www.tutorialspoint.com/cakephp/index.htm">https://www.tutorialspoint.com/cakephp/index.htm</a> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Bom exemplo de criação de plugin</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><a href="https://www.cakephpbrasil.com.br/tutorial/2017/03/07/criando-components-no-cakephp-3/">https://www.cakephpbrasil.com.br/tutorial/2017/03/07/criando-components-no-cakephp-3/</a> </span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Padrões para a criação de um bom plugin para o CakePHP 3</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><a href="https://www.cakedc.com/plugin-standard">https://www.cakedc.com/plugin-standard</a></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Mais detalhes</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><a href="https://book.cakephp.org/3.0/en/controllers/components.html">https://book.cakephp.org/3.0/en/controllers/components.html</a></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 00:25:52 -0300</pubDate>
		</item>
		<item>
			<title>10 - Detalhes sobre Controllers</title>
			<link>http://backup/portal/curriculo/livros/cakephp/10-detalhes-sobre-controllers.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/10-detalhes-sobre-controllers.html</guid>
			<description><![CDATA[<h3>10 – Detalhes sobre Controllers</h3>
<p align="right"> </p>
<p align="right"><em><strong>Já experimentou acreditar em você? Tente! Você não faz ideia do que é capaz.</strong></em></p>
<p align="justify"> </p>
<p align="justify">Os controllers correspondem ao ‘C’ no padrão MVC. Após o roteamento ter sido aplicado e o controller correto encontrado, a ação do controller é chamada. Seu controller deve lidar com a interpretação dos dados de uma requisição, certificando-se que os models corretos são chamados e a resposta ou view esperada seja exibida. Os controllers podem ser vistos como intermediários entre a camada Model e View. Você vai querer manter seus controllers magros e seus Models gordos. Isso lhe ajudará a reutilizar seu código e testá-los mais facilmente.</p>
<p align="justify">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 RecipesController e um IngredientsController gerenciando suas receitas e seus ingredientes. No CakePHP, controllers são nomeados de acordo com o model que manipulam. É também absolutamente possível ter controllers que usam mais de um model.</p>
<p align="justify">Os controllers da sua aplicação são classes que estendem a classe CakePHP AppController, a qual por sua vez estende a classe Controller do CakePHP. A classe AppController pode ser definida em /app/Controller/AppController.php e deve conter métodos que são compartilhados entre todos os seus controllers.</p>
<p align="justify">Os controllers fornecem uma série de métodos que são chamados de ações. Ações são métodos em um controller que manipulam requisições. Por padrão, todos os métodos públicos em um controller são ações e acessíveis por urls.</p>
<p align="justify">Os atributos e métodos criados em AppController vão estar disponíveis para todos os controllers da sua aplicação. Este é o lugar ideal para criar códigos que são comuns para todos os seus controllers. Componentes (que você vai aprender mais tarde) são a melhor alternativa para códigos que são usados por muitos (mas não obrigatoriamente em todos) controllers.</p>
<p align="justify">Enquanto regras normais de herança de classes orientadas à objetos são aplicadas, o CakePHP também faz um pequeno trabalho extra quando se trata de atributos especiais do controller. A lista de componentes (components) e helpers usados no controller são tratados diferentemente. Nestes casos, as cadeias de valores do AppController são mescladas com os valores de seus controllers filhos. Os valores dos controllers filhos sempre sobrescreveram os do AppController.</p>
<p>O CakePHP mescla as seguintes variáveis do AppController em controllers da sua aplicação:</p>
<p>$components</p>
<p>$helpers</p>
<p>$uses</p>
<p> </p>
<p>Lembre-se de adicionar os helpers Html e Form padrões se você incluiu o atributo $helpers em seu AppController.</p>
<p>Também lembre de fazer as chamadas de callbacks do AppController nos controllers filhos para obter melhores resultados:</p>
<p>function beforeFilter() {</p>
<p>parent::beforeFilter();</p>
<p>}</p>
<p>No CakePHP nós gostamos de manter os nossos actions do controller enxutos, e colocar a maior parte da lógica de negócio de nossa aplicação nos modelos.</p>
<p><strong>Exemplo de Controller Comentado</strong></p>
<pre class="language-php"><code>&lt;?php
// O comando abaixo faz o include da classe AppController que encontra-se na pasta app/Controller
App::uses('AppController', 'Controller');
// Observe que o controller PostsController extende a classe AppController
class PostsController extends AppController {

A propriedade recursive define qual a profundidade que o CakePHP deve ir para procurar modelos associados de dados via métodos find() e read().

Imagine uma aplicação com Groups e cada Group contém muitos Users que por sua vez, cada User tem muitos Articles. Você pode setar $recursive para vários valores baseado no total de dados que você deseja de volta de uma chamada $this-&gt;Group-&gt;find():

    -1 Cake busca somente dados de Group, sem joins.
    0 Cake busca dados de Group e seu domínio
    1 Cake busca um Group, seu domínio e seus Users associados
    2 Cake busca um Group, seu domínio, seus Users associados e os Articles assoaiados aos Users

Não defina $recursive mais do que você precisa. Quando você tem dados buscados pelo CakePHP você não vai deixar sua aplicação lenta desnecessariamente. Observe também que o nível recursivo padrão é 1.

*/
		$this-&gt;Post-&gt;recursive = 0;
/*

O método set() tem como objetivo enviar informações para a View.
Com a linha abaixo a view index.ctp poderá chamar o array $posts, que contém todos os posts paginados.

*/
		$this-&gt;set('posts', $this-&gt;paginate());
	}
/**
 * view method
 *
 * @throws NotFoundException
 * @param string $id
 * @return void
 */
	public function view($id = null) {
		// Verifica com o model Post, se existe o $id recebido
		if (!$this-&gt;Post-&gt;exists($id)) {
			throw new NotFoundException(__('Invalid post'));
		}
		// Opções para filtrar o model Post que tem o $id como chave primária
		$options = array('conditions' =&gt; array('Post.' . $this-&gt;Post-&gt;primaryKey =&gt; $id));
		// Passa para a view a variável $post com o primeiro Post encontrado
		$this-&gt;set('post', $this-&gt;Post-&gt;find('first', $options));
	}

	public function add() {
		// Verifica se a requisição é do tipo POST
		if ($this-&gt;request-&gt;is('post')) {
			// Cake PHP recomenda chamar a função create() para re-inicializar um model antes de salvar
			// um novo registro. Criar - create(). Salvar/Atualizar - save().
			$this-&gt;Post-&gt;create();
			// O método save() salva o registro e também valida
			if ($this-&gt;Post-&gt;save($this-&gt;request-&gt;data)) {
				// setFlash mostra uma mensagem
				$this-&gt;Session-&gt;setFlash(__('The post has been saved'));
				// redirect redireciona para o action index. Também existem outros parâmetros
				$this-&gt;redirect(array('action' =&gt; 'index'));
			} else {
				$this-&gt;Session-&gt;setFlash(__('The post could not be saved. Please, try again.'));
			}
		}
	}
	public function edit($id = null) {
		// Verifica se existe o $id no model Post
		if (!$this-&gt;Post-&gt;exists($id)) {
			throw new NotFoundException(__('Invalid post'));
		}
	//echo 'CONTROLLER - Enviando para o Model';
	//exit;
		// Verifica se houve requisição do tipo POST ou PUT
		if ($this-&gt;request-&gt;is('post') || $this-&gt;request-&gt;is('put')) {
			if ($this-&gt;Post-&gt;save($this-&gt;request-&gt;data)) {
	//echo 'CONTROLLER - Vindo do Model';
	//exit;
				$this-&gt;Session-&gt;setFlash(__('The post has been saved'));
				$this-&gt;redirect(array('action' =&gt; 'index'));
			} else {
				$this-&gt;Session-&gt;setFlash(__('The post could not be saved. Please, try again.'));
			}
		} else {
			$options = array('conditions' =&gt; array('Post.' . $this-&gt;Post-&gt;primaryKey =&gt; $id));
			$this-&gt;request-&gt;data = $this-&gt;Post-&gt;find('first', $options);
		}
	}
	public function delete($id = null) {
		// Guarda em $this-&gt;Post-&gt;id o $id passado via parâmetro
		$this-&gt;Post-&gt;id = $id;
		if (!$this-&gt;Post-&gt;exists()) {
			throw new NotFoundException(__('Invalid post'));
		}
		// CakeRequest::onlyAllow($methods) - adicionado no Cake 2.3. Substituiu o método 
		// requireDelete() das versões anteriores.
		$this-&gt;request-&gt;onlyAllow('post', 'delete');
		// Exclui o registro
		if ($this-&gt;Post-&gt;delete()) {
			$this-&gt;Session-&gt;setFlash(__('Post deleted'));
			$this-&gt;redirect(array('action' =&gt; 'index'));
		}
		$this-&gt;Session-&gt;setFlash(__('Post was not deleted'));
		$this-&gt;redirect(array('action' =&gt; 'index'));
	}
}</code></pre>
<p style="font-style: normal;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Permitir que registros sejam deletados usando requisições GET é perigoso, pois rastreadores na web podem acidentalmente deletar todo o seu conteúdo.</span></span></p>
<p style="font-style: normal;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Mais detalhes</b></span></span></p>
<p style="font-style: normal;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><a href="https://book.cakephp.org/3.0/en/controllers.html">https://book.cakephp.org/3.0/en/controllers.html</a></span></span></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 00:22:09 -0300</pubDate>
		</item>
		<item>
			<title>9.3.4 - flashHelper e Flash Component</title>
			<link>http://backup/portal/curriculo/livros/cakephp/9-3-4-flashhelper-e-flash-component.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/9-3-4-flashhelper-e-flash-component.html</guid>
			<description><![CDATA[<h3>9.3.4 - flashHelper e Flash Component</h3>
<p> </p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="right"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i><b>Não sei qual é o segredo do sucesso, mas o segredo do fracasso é tentar agradar a todo mundo.</b></i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="right"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Bill Cosby</span></span></p>
<p>FlashComponent fornece duas maneiras de definir mensagens flash: seu método mágico __call() e seu método set(). Para fornecer seu aplicativo com verbosidade, o método mágico __call() do FlashComponent permite usar um nome de método que mapeia para um elemento localizado no diretório src/Template/Element/Flash. Por convenção, os métodos camelcased serão mapeados para o nome do elemento em minúsculas e sublinhado:</p>
<p>// Use em src/Template/Element/Flash/success.ctp</p>
<p>$this-&gt;Flash-&gt;success('This was successful');</p>
<p>// Use em src/Template/Element/Flash/great_success.ctp</p>
<p>$this-&gt;Flash-&gt;greatSuccess('This was greatly successful');</p>
<p><strong>Renderizar em texto plano</strong></p>
<p>$this-&gt;Flash-&gt;set('This is a message');</p>
<p> </p>
<p><strong>Renderizar em HTML</strong></p>
<p>$this-&gt;Flash-&gt;info(sprintf('&lt;b&gt;%s&lt;/b&gt; %s', h($highlight), h($message)), ['escape' =&gt; false]);</p>
<p> </p>
<p><strong>Código para mensagens em Flash</strong></p>
<p>&lt;dic class="message error" onclick="thisClasslist.add('hidden');"&gt;Você não tem permissão para acessar esta área&lt;/div&gt;</p>
<p> </p>
<p><strong>Em action/template</strong></p>
<p>&lt;?= $this-&gt;Flash-&gt;render() ?&gt;</p>
<p>// wm seu Controller</p>
<p>$this-&gt;Flash-&gt;set('The user has been saved.', [</p>
<p>'element' =&gt; 'success'</p>
<p>]);</p>
<p> </p>
<p>// Em seu arquivo de template: Irá usar great_success.ctp ao invés de succcess.ctp</p>
<p>&lt;?= $this-&gt;Flash-&gt;render('flash', [</p>
<p>'element' =&gt; 'great_success'</p>
<p>]);</p>
<p><strong>Detalhes sobre o FlashHelper</strong></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/flash.html">https://book.cakephp.org/3.0/en/views/helpers/flash.html</a></p>
<p><a href="https://book.cakephp.org/3.0/en/controllers/components/flash.html">https://book.cakephp.org/3.0/en/controllers/components/flash.html</a></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 00:18:57 -0300</pubDate>
		</item>
		<item>
			<title>9.3.3 - TimeHelper</title>
			<link>http://backup/portal/curriculo/livros/cakephp/9-3-3-timehelper.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/9-3-3-timehelper.html</guid>
			<description><![CDATA[<h3>9.3.3 – TimeHelper</h3>
<p align="right"><strong>Há dias que você tem que ir para a frente só com o que você tem na mão, não dá para esperar pela motivação.</strong></p>
<p><strong>Data e Hora com CakePHP 3</strong></p>
<p>class Cake\I18n\Time</p>
<p> </p>
<p>Se você precisa das funcionalidades do TimeHelper fora de uma View, então use a classe Time:</p>
<pre class="language-php"><code>use Cake\I18n\Time;

class UsersController extends AppController
{
    public function initialize()
    {
        parent::initialize();
        $this-&gt;loadComponent('Auth');
    }

    public function afterLogin()
    {
        $time = new Time($this-&gt;Auth-&gt;user('date_of_birth'));
        if ($time-&gt;isToday()) {
            // Greet user with a happy birthday message
            $this-&gt;Flash-&gt;success(__('Happy birthday to you...'));
        }
    }
}</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Criando Instâncias de Time</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Existem algumas maneiras de criar instâncias de Time:</span></span></p>
<pre class="language-php"><code>use Cake\I18n\Time;
// Create from a string datetime.
$time = Time::createFromFormat(
    'Y-m-d H:i:s',
    $datetime,
    'America/Fortaleza'
);
// Create from a timestamp
$time = Time::createFromTimestamp($ts);

// Get the current time.
$time = Time::now();
$time = new Time('2014-01-10 11:11', 'America/Fortaleza');
$time = new Time('2 hours ago');

Mais:
$now = new Time('2014-04-12 12:22:30');
Time::setTestNow($now);

// Retorna '2014-04-12 12:22:30'
$now = Time::now();

// Retorna '2014-04-12 12:22:30'
$now = Time::parse('now');</code></pre>
<p><strong>Manipulação</strong></p>
<p>Depois de criada a instância podemos manipular as instâncias de Time usando métodos setters.</p>
<p>$now = Time::now();</p>
<p>$now-&gt;year(2016)</p>
<p>-&gt;month(08)</p>
<p>-&gt;day(31);</p>
<p>Também podemos usar os métodos providos pelo PHP embutidos na classe DateTime:</p>
<p>$now-&gt;setDate(2016, 08, 31);</p>
<p>Datas podem ser modificdas através da subtração e adição de seus componentes:</p>
<p>$now = Time::now();</p>
<p>$now-&gt;subDays(5);</p>
<p>$now-&gt;addMonth(1);</p>
<p> </p>
<p>// Usando strtotime strings.</p>
<p>$now-&gt;modify('+5 days');</p>
<p>Você pode receber os componentes internos da data acessando suas propriedades:</p>
<p>$now = Time::now();</p>
<p>echo $now-&gt;year; // 2014</p>
<p>echo $now-&gt;month; // 5</p>
<p>echo $now-&gt;day; // 10</p>
<p>echo $now-&gt;timezone; // America/Fortaleza</p>
<p> </p>
<p>Também é permitido assinalar diretamente essas propriedades para modificar a data:</p>
<p>$time-&gt;year = 2015;</p>
<p>$time-&gt;timezone = 'Europe/Paris';</p>
<p> </p>
<p>Formatando</p>
<p>static Cake\I18n\Time::setJsonEncodeFormat($format)</p>
<p>O método configura o formato default usado quando convertendo um objeto para json:</p>
<p>Time::setJsonEncodeFormat('yyyy-MM-dd HH:mm:ss');</p>
<p> </p>
<p>Este método precisa ser chamado estaticamente.</p>
<p>Cake\I18n\Time::i18nFormat($format = null, $timezone = null, $locale = null)</p>
<p>Algo bem comum a fazer com instâncias de Time é imprimir as datas formatadas. Veja:</p>
<p>$now = Time::parse('2014-10-31');</p>
<p>// Prints a localized datetime stamp.</p>
<p>echo $now;</p>
<p>// Outputs '10/31/14, 12:00 AM' for the en-US locale</p>
<p>$now-&gt;i18nFormat();</p>
<p> </p>
<p>// Use the full date and time format</p>
<p>$now-&gt;i18nFormat(\IntlDateFormatter::FULL);</p>
<p>// Use full date but short time format</p>
<p>$now-&gt;i18nFormat([\IntlDateFormatter::FULL, \IntlDateFormatter::SHORT]);</p>
<p>// Outputs '2014-10-31 00:00:00'</p>
<p>$now-&gt;i18nFormat('yyyy-MM-dd HH:mm:ss');</p>
<p>Configurando o Locale Padrão e o Formato de String</p>
<p>// The same method exists on Date, FrozenDate, and FrozenTime</p>
<p>Time::setDefaultLocale('pt-BR');</p>
<p> </p>
<p>Datas</p>
<p>A classe Date no CakePHP implementa a mesma API e métodos que o Time\ I18n\. A principal diferença entre hora e data é que Data não acompanha componentes de tempo, e está sempre em UTC. Como um exemplo:</p>
<pre class="language-php"><code>use Cake\I18n\Date;
$date = new Date('2015-06-15');

$date-&gt;modify('+2 hours');
// Outputs 2015-06-15 00:00:00
echo $date-&gt;format('Y-m-d H:i:s');

$date-&gt;modify('+36 hours');
// Outputs 2015-06-15 00:00:00
echo $date-&gt;format('Y-m-d H:i:s');

Dicas sobre data e hora

Num controller

use Cake\I18n\Time;
use Cake\I18n\Date;

    public function index()
    {
        $time = new Time($this-&gt;Auth-&gt;user('birtday'));
        if ($time-&gt;isToday()) {
            // Greet user with a happy birthday message
            $this-&gt;Flash-&gt;error(__('Hoje é seu aniversário. Meus parabéns...'));
        }

        $this-&gt;paginate = [
            'contain' =&gt; ['Groups']
        ];
        $permissions = $this-&gt;paginate($this-&gt;Permissions);

        $this-&gt;set(compact('permissions'));
    }

Outras formas:

$now = Time::now();
$now-&gt;year(2013)
    -&gt;month(10)
    -&gt;day(31);

dd($now);

$now = Time::parse('2014-10-31');

$now = Time::parse('2014-10-31');

// Outputs 'Oct 31, 2014 12:00 AM' in en-US
Time::setDefaultLocale('pt-BR');
echo $now;
exit;

$time = new Time($this-&gt;Auth-&gt;user('modified'));
Time::setDefaultLocale('pt-BR'); // ou Date::setDefaultLocale('pt-BR');
echo $time;
exit;

$time = new Time($this-&gt;Auth-&gt;user('modified'));
Time::setToStringFormat('dd/MM/yyyy');
echo $time;
exit;

src/Template/Clientes/add.ctp ou edit.ctp
</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Por padrão o Cake mostra apenas os anos de 2011 até 2021 na combo Ano.</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Vamos alterar para que o ano mínimo seja 13 anos antes do atual e máximo seja 100 anos antes do atual, ou seja, como estou em 2016, que mostre de 1916 até 2003, mas isso deve ser pensado para atender ao requisito da tabela/aplicativo. No nosso caso, do DNOCS, devemos usar 18 anos antes, ou mais para o primeiro?</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">E 100 anos antes do atual ou mais para o segundo.</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Precisamos saber da legislação e usar a favor da segurança, deixando uma margem.</span></span></p>
<pre class="language-php"><code>		echo $this-&gt;Form-&gt;input('nascimento',['label' =&gt; 'Nascimento',
	        'dateFormat'    =&gt; 'DMY',
	        'minYear'       =&gt; date('Y') - 100,
	        'maxYear'       =&gt; date('Y') - 13,
	        'empty'         =&gt; [
	            'day'       =&gt; 'Dia',
	            'month'     =&gt; 'Mês',
	            'year'      =&gt; 'Ano'
            ]
        ]);</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Mais em:</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">CakePHP usa Chronos para dar poder ao seu utilitário Timer. Qualquer coisa que você possa fazer com Chronos e DateTime você pode fazer com Time e Date:</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><span style="font-family: Times New Roman, serif;"><a href="https://github.com/cakephp/chronos">https://github.com/cakephp/chronos</a> </span></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><span style="font-family: Times New Roman, serif;"><a href="http://api.cakephp.org/chronos/1.0/">http://api.cakephp.org/chronos/1.0/</a> </span></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Antes da versão 3.2 o CakePHP usava Carbon:</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><span style="font-family: Times New Roman, serif;"><a href="https://github.com/briannesbitt/Carbon">https://github.com/briannesbitt/Carbon</a> </span></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><a href="http://book.cakephp.org/3.0/en/views/helpers/time.html"><span style="font-family: Times New Roman, serif;">http://book.cakephp.org/3.0/en/views/helpers/time.html</span></a></span></span></p>
<p style="margin-bottom: 0cm; font-weight: normal; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><span style="font-family: Times New Roman, serif;"><a href="https://book.cakephp.org/3.0/en/core-libraries/time.html">https://book.cakephp.org/3.0/en/core-libraries/time.html</a> </span></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Arial, serif;"><span style="font-size: medium;"><span style="font-family: Times New Roman, serif;"><a href="http://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html#parsing-localized-dates">http://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html#parsing-localized-dates</a> </span></span></span></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 00:14:52 -0300</pubDate>
		</item>
		<item>
			<title>9.3.2 - htmlHelper</title>
			<link>http://backup/portal/curriculo/livros/cakephp/9-3-2-htmlhelper.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/9-3-2-htmlhelper.html</guid>
			<description><![CDATA[<h3>9.3.2 – htmlHelper</h3>
<p align="right"><em><strong>Não perca a motivação só porque as coisas não estão correndo como o previsto. Adversidade gera sabedoria e é isso que levará você ao sucesso.</strong></em><br /> </p>
<p>class <tt>Cake\View\Helper\HtmlHelper</tt>(View $view, array $config =[])</p>
<p lang="pt-PT"><a name="result_box7"></a> <span style="font-family: Times New Roman, serif;">O papel do HtmlHelper no CakePHP é fazer opções relacionados a HTML mais fácil, mais rápido e mais resistente à mudança. Usando este helper permitirá que sua aplicação seja mais luz em seus pés, e mais flexível de onde ele é colocado em relação à raiz de um domínio.</span></p>
<p><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">Você deve ter notado o uso de um objeto chamado </span></span><code class="western"><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">$this-&gt;Html</span></span></code><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">, uma instância da classe </span></span><code class="western"><a href="https://book.cakephp.org/3.0/pt/views/helpers/html.html#Cake%5CView%5CHelper%5CHtmlHelper"><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">Cake\View\Helper\HtmlHelper</span></span></a></code><span style="font-family: Times New Roman, serif;"><span lang="pt-PT"> do CakePHP. O CakePHP vem com um conjunto de view helpers que simplificam tarefas como gerar links e formulários. Você pode aprender como usá-los em </span></span><a href="https://book.cakephp.org/3.0/pt/views/helpers.html">Helpers (Facilitadores)</a><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">, mas aqui é importante notar que o método </span></span><code class="western"><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">link()</span></span></code><span style="font-family: Times New Roman, serif;"><span lang="pt-PT"> irá gerar um link HTML com o referido título (primeiro parâmetro) e URL (segundo parâmetro).</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT"><br /> <br /> Muitos métodos HtmlHelper incluem um parâmetro $at</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">t</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">ribut</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">es</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">, que lhe permitem aderência em quaisquer atributo extras em suas tags. Aqui estão alguns exemplos de como usar o </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">parâmetro </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">$at</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">t</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">ribut</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">te</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">s:</span></span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Desired attributes: &lt;tag class="someClass" /&gt;</i></span></span>
<span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Array parameter: ['class' =&gt; 'someClass']</i></span></span>

<span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Desired attributes: &lt;tag name="foo" value="bar" /&gt;</i></span></span>
<span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Array parameter:  ['name' =&gt; 'foo', 'value' =&gt; 'bar']</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Inserindo Elementos Bem Formatados</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><a name="result_box12"></a> <span style="font-family: Times New Roman, serif;"><span lang="pt-PT">A tarefa mais importante que o HtmlHelper realiza é a criação de marcação bem formado. Esta seção irá cobrir alguns dos métodos do HtmlHelper e como usá-los.</span> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Criando a tag Charset</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><tt class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Cake\View\Helper\HtmlHelper::charset</i></span></span></tt><span style="font-family: Times New Roman, serif;"><span style="font-size: large;"><i>(</i></span></span><em><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>$charset=null</i></span></span></em><span style="font-family: Times New Roman, serif;"><span style="font-size: large;"><i>)</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Usado para criar a meta tag especificando o charset do documento. O default valor é UTF-8. Veja um exemplo:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Html-&gt;charset();</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Uma alternativa:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Html-&gt;charset('ISO-8859-1');</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Linkando para Arquivos CSS</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><tt class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Cake\View\Helper\HtmlHelper::css</i></span></span></tt><span style="font-family: Times New Roman, serif;"><span style="font-size: large;"><i>(</i></span></span><em><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>mixed $path</i></span></span></em><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>, </i></span></span><em><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>array $options =</i></span></span></em><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>[]</i></span></span><span style="font-family: Times New Roman, serif;"><span style="font-size: large;"><i>)</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Cria um link para um CSS. Caso o bloco option seja configurado para true, a tag link é adicionada para o bloco CSS que você pode imprimir dentro da tag head do documento.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Este método de inclusão do CSS assume que o CSS especificado reside dentro do webroot/css e não inicia com '/':</span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Html-&gt;css('forms');</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Deve gerar:</span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;link rel="stylesheet" href="http://backup/portal//css/forms.css" /&gt;</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">O primeiro parâmetro deve ser um array para incluir múltiplos arquivos:</span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Html-&gt;css(['forms', 'tables', 'menu']);</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Saída:</span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;link rel="stylesheet" href="http://backup/portal//css/forms.css" /&gt;</i></span></span>
<span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;link rel="stylesheet" href="http://backup/portal//css/tables.css" /&gt;</i></span></span>
<span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;link rel="stylesheet" href="http://backup/portal//css/menu.css" /&gt;</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Adicionando CSS de um Plugin:</span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Html-&gt;css('DebugKit.toolbar.css');</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Criando Meta tags</b></span></p>
<pre class="language-php"><code>&lt;?= $this-&gt;Html-&gt;meta(
    'favicon.ico',
    '/favicon.ico',
    ['type' =&gt; 'icon']
);
?&gt;
&lt;?= $this-&gt;Html-&gt;meta(
    'keywords',
    'enter any meta keyword here'
);
?&gt;
&lt;?= $this-&gt;Html-&gt;meta(
    'description',
    'enter any meta description here'
);
?&gt;</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Linkando para Imagens</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><tt class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Cake\View\Helper\HtmlHelper::image</i></span></span></tt><span style="font-family: Times New Roman, serif;"><span style="font-size: large;"><i>(</i></span></span><em><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>string $path</i></span></span></em><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>, </i></span></span><em><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>array $options =</i></span></span></em><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>[]</i></span></span><span style="font-family: Times New Roman, serif;"><span style="font-size: large;"><i>)</i></span></span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Html-&gt;image('cake_logo.png', ['alt' =&gt; 'CakePHP']);</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Gera:</i></span></span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;img src="http://backup/portal//img/cake_logo.png" alt="CakePHP" /&gt;</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Html-&gt;image("recipes/6.jpg", [</i></span></span>
    <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>"alt" =&gt; "Brownies",</i></span></span>
    <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>'url' =&gt; ['controller' =&gt; 'Recipes', 'action' =&gt; 'view', 6]</i></span></span>
<span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>]);</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><strong><span style="font-family: Times New Roman, serif;">Plugin:</span></strong></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Html-&gt;image('DebugKit.icon.png');</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Criando Links</b></span></p>
<pre class="language-php"><code>echo $this-&gt;Html-&gt;link(
    'Enter',
    '/pages/home',
    ['class' =&gt; 'button', 'target' =&gt; '_blank']
);
echo $this-&gt;Html-&gt;link(
    'Dashboard',
    ['controller' =&gt; 'Dashboards', 'action' =&gt; 'index', '_full' =&gt; true]
);
echo $this-&gt;Html-&gt;link(
    'Delete',
    ['controller' =&gt; 'Recipes', 'action' =&gt; 'delete', 6],
    ['confirm' =&gt; 'Are you sure you wish to delete this recipe?'],
);
echo $this-&gt;Html-&gt;link('View image', [
    'controller' =&gt; 'Images',
    'action' =&gt; 'view',
    1,
    '?' =&gt; ['height' =&gt; 400, 'width' =&gt; 500]
]);
</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%; page-break-before: always;"><span style="font-family: Times New Roman, serif;"><b>Linkando Vídeos</b></span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;?= $this-&gt;Html-&gt;media('audio.mp3') ?&gt;</i></span></span>
 <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>// Output</i></span></span>
 <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;audio src="http://backup/portal//files/audio.mp3"&gt;&lt;/audio&gt;</i></span></span>

 <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;?= $this-&gt;Html-&gt;media('video.mp4', [</i></span></span>
     <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>'fullBase' =&gt; true,</i></span></span>
     <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>'text' =&gt; 'Fallback text'</i></span></span>
 <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>]) ?&gt;</i></span></span>
<span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;?= $this-&gt;Html-&gt;media(</i></span></span>
     <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>['video.mp4', ['src' =&gt; 'video.ogg', 'type' =&gt; "video/ogg; codecs='theora, vorbis'"]],</i></span></span>
     <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>['autoplay']</i></span></span>
 <span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>) ?&gt;</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Link para Imagens</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Cake\View\Helper\HtmlHelper::image(string $path, array $options = [])</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>Creates a formatted image tag. The path supplied should be relative to webroot/img/.</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Html-&gt;image('cake_logo.png', ['alt' =&gt; 'CakePHP']);</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Irá mostrar:</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;img src="http://backup/portal//img/cake_logo.png" alt="CakePHP" /&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>CSS </b><b>CakePHP</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Customizar CSS do bootstrap numa view</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Form-&gt;input('grupo',['style'=&gt;'width: 200px']);</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Tipos de Campos</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>input[type="text"],</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>input[type="password"],</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>input[type="email"],</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>input[type="tel"],</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>input[type="select"] {</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>max-width: 280px;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>}</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%; page-break-before: always;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Usando num template login.ctp</b></span></span></p>
<pre class="language-markup"><code>&lt;div class="users form"&gt;
&lt;?= $this-&gt;Flash-&gt;render('auth') ?&gt;    
    &lt;?= $this-&gt;Form-&gt;create() ?&gt;
    &lt;div align="center"&gt;
    &lt;fieldset&gt;
        &lt;legend&gt;&lt;?= __('&lt;h3&gt;&lt;b&gt;Favor entrar seu com login e senha&lt;/b&gt;&lt;/h3&gt;') ?&gt;&lt;/legend&gt;
        &lt;?= $this-&gt;Form-&gt;input('username', ['label'=&gt;'Login', 'class'=&gt;'col4']) ?&gt;
        &lt;?= $this-&gt;Form-&gt;input('password',['label'=&gt;'Senha', 'class'=&gt;'col4']) ?&gt;
    &lt;/fieldset&gt;
    &lt;?= $this-&gt;Form-&gt;button(__('Acessar')); ?&gt;
    &lt;?= $this-&gt;Form-&gt;end() ?&gt;
    &lt;/div&gt;
&lt;/div&gt;


No arquivo  webroot/css/custom.css

/* Para a customização da largura dos campos de form: echo $this-&gt;Form-&gt;input('grupo',['class'=&gt;'col2']); */
.col1{
    width:50px;
}

.col2{
    width:100px;
}

.col3{
    width:150px;
}

.col4{
    width:200px;
}

.col5{
    width:250px;
}

.col6{
    width:300px;
}

.col7{
    width:350px;
}

.col8{
    width:400px;
}

.col9{
    width:950px;
}

JavaScript em View/Template

&lt;div class="actions columns col-lg-2 col-md-3"&gt;
    &lt;h3&gt;&lt;?= __('Ações') ?&gt;&lt;/h3&gt;
    &lt;ul class="nav nav-stacked nav-pills"&gt;
        &lt;li class="active disabled"&gt;&lt;?= $this-&gt;Html-&gt;link(__('Novo Materiai'), ['action' =&gt; 'add']) ?&gt;&lt;/li&gt;
        &lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('Listar Materiais'), ['action' =&gt; 'index']) ?&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;

&lt;script type="text/javascript"&gt;

function grupoFocus() { 
    // conta_grupo receber o valor da combo grupo
    var elt = document.getElementById('grupo');
    var selection=elt.options[elt.selectedIndex].innerHTML;
    document.getElementById('conta').value = selection;
    // Foco na descrição
    document.getElementById('descricao').focus();
}
&lt;/script&gt;

&lt;div class="materiais form col-lg-10 col-md-9 columns"&gt;
    &lt;?= $this-&gt;Form-&gt;create($materiai); ?&gt;
    &lt;fieldset&gt;
        &lt;legend&gt;&lt;?= __('Add Materiai') ?&gt;&lt;/legend&gt;
        &lt;?php
            echo $this-&gt;Form-&gt;input('codigo', ['autofocus'=&gt;'autofocus']);
            echo $this-&gt;Form-&gt;input('grupo', ['label'=&gt;'','id'=&gt;'grupo','readonly' =&gt; true,'options' =&gt; $grupos, 'empty'=&gt;'Selecione o grupo', 'onchange'=&gt;'grupoFocus()']);
            echo $this-&gt;Form-&gt;input('conta_grupo',['id'=&gt;'conta', 'readonly'=&gt;true]);
            echo $this-&gt;Form-&gt;input('descricao',['id'=&gt;'descricao']);
            echo $this-&gt;Form-&gt;input('uid_inclusao');
            echo $this-&gt;Form-&gt;input('uid_data_inclusao');
            echo $this-&gt;Form-&gt;input('uid_alteracao');
            echo $this-&gt;Form-&gt;input('uid_data_alteracao');
            echo $this-&gt;Form-&gt;input('status');
        ?&gt;
    &lt;/fieldset&gt;
    &lt;?= $this-&gt;Form-&gt;button(__('Enviar'), ['class' =&gt; 'btn-success']) ?&gt;
    &lt;?= $this-&gt;Form-&gt;end() ?&gt;
&lt;/div&gt;</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Mais detalhes em:</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="http://book.cakephp.org/3.0/en/views/helpers/html.html">http://book.cakephp.org/3.0/en/views/helpers/html.html</a> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><a href="http://book.cakephp.org/3.0/en/views/helpers/paginator.html"><span style="font-family: Times New Roman, serif;">http://book.cakephp.org/3.0/en/views/helpers/paginator.html</span></a></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><a href="http://book.cakephp.org/3.0/en/views/helpers/form.html"><span style="font-family: Times New Roman, serif;">http://book.cakephp.org/3.0/en/views/helpers/form.html</span></a></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><a href="http://book.cakephp.org/3.0/en/views.html"><span style="font-family: Times New Roman, serif;">http://book.cakephp.org/3.0/en/views.html</span></a></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><a href="http://book.cakephp.org/3.0/en/core-libraries/form.html"><span style="font-family: Times New Roman, serif;">http://book.cakephp.org/3.0/en/core-libraries/form.html</span></a></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><a href="http://book.cakephp.org/3.0/en/core-libraries/email.html"><span style="font-family: Times New Roman, serif;">http://book.cakephp.org/3.0/en/core-libraries/email.html</span></a></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><a href="http://book.cakephp.org/3.0/en/views/helpers.html"><span style="font-family: Times New Roman, serif;">http://book.cakephp.org/3.0/en/views/helpers.html</span></a></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 00:07:14 -0300</pubDate>
		</item>
		<item>
			<title>9.3.1 - formHelper</title>
			<link>http://backup/portal/curriculo/livros/cakephp/9-3-1-formhelper.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/9-3-1-formhelper.html</guid>
			<description><![CDATA[<h3>9.3.1 – formHelper</h3>
<p align="right">Você nunca sabe a força que tem, até que a sua única alternativa é ser forte.</p>
<p align="right">Johnny Depp</p>
<p> </p>
<p><strong>Tradução simplificada e resumida do original em:</strong></p>
<p><a href="http://book.cakephp.org/3.0/en/views/helpers/form.html">http://book.cakephp.org/3.0/en/views/helpers/form.html</a></p>
<p>class <tt>Cake\View\Helper\FormHelper</tt>(View $view, array $config =[])</p>
<p align="justify"><a name="result_box6"></a> <span style="font-family: Times New Roman, serif;"><span lang="pt-PT">O FormHelper faz a maior parte do trabalho pesado na criação de formulários. O FormHelper foca na criação de formulários de forma rápida, de uma forma que irá agilizar a validação, re-po</span><span lang="pt-PT">pulação</span><span lang="pt-PT"> e layout. O FormHelper também é flexível - ele vai fazer quase tudo p</span><span lang="pt-PT">or</span><span lang="pt-PT"> você, utilizando convenções, ou você pode usar métodos específicos para obter apenas o que você precisa.</span> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Iniciando um Formulário</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><tt class="western"><span style="font-family: Times New Roman, serif;">Cake\View\Helper\FormHelper::create</span></tt><span style="font-family: Times New Roman, serif;"><span style="font-size: large;">(</span></span><em><span style="font-family: Times New Roman, serif;">mixed $model = null</span></em><span style="font-family: Times New Roman, serif;">, </span><em><span style="font-family: Times New Roman, serif;">array $options =</span></em><span style="font-family: Times New Roman, serif;">[]</span><span style="font-family: Times New Roman, serif;"><span style="font-size: large;">)</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="justify"><span style="font-family: Times New Roman, serif;">O primeiro método que você deve usar para tirar vantagem do FormHelper é o create(). Este método mostra uma tag de abertura de formulário.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="justify"><span style="font-family: Times New Roman, serif;">Todos os parâmetros são opcionais. Caso create() seja chamado sem nenhum parâmetro, ele assume que você está construindo um form que submete para o controller atual, via URL atual. O método default para a submissão do form é o POST. Caso você chame o create dentro da view para UsersController::add(), com <code class="western">$this-&gt;Form-&gt;create()</code><code class="western">
</code>você deve ver a seguinte saída na view renderizada:</span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: xx-small;"><i>/<span style="font-size: medium;">&lt;form method="post" action="/users/add"&gt;</span></i></span></span></pre>
<p align="justify"><span style="font-family: Times New Roman, serif;">Se <code class="western">create()</code> é chamado sem parâmetros fornecidos, assume-se a construção de um formulário que submete dados via POST para a action <code class="western">add()</code> (ou <code class="western">edit()</code> no caso de um <code class="western">id</code> estar incluído nos dados do formulário).</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="justify"><a name="result_box11"></a> <span style="font-family: Times New Roman, serif;">O argumento $model é usado como forma de contexto. <span lang="pt-PT">Existem vários contextos </span><span lang="pt-PT">embutidos para </span><span lang="pt-PT">formulário e você pode adicionar seu próprio, o que nós vamos cobrir na próxima seção. O provedores internos map</span><span lang="pt-PT">eiam</span><span lang="pt-PT"> para os seguintes valores de</span> $model:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="justify"><a name="result_box21"></a> <span style="font-family: Times New Roman, serif;">- <span lang="pt-PT">Uma instância de entidade ou um mapa de itera</span><span lang="pt-PT">t</span><span lang="pt-PT">or para o EntityContext, neste contexto permite FormHelper trabalhar com os resultados do ORM embutido.</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="justify"><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">- Um </span><span lang="pt-PT">array</span><span lang="pt-PT"> que contém a chave de esquema, mapeia para ArrayContext que permite a criação de estruturas de dados simples para construir forms </span><span lang="pt-PT">contra</span><span lang="pt-PT">.</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="justify"><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">- </span><span lang="pt-PT">null</span> <span lang="pt-PT">e</span><span lang="pt-PT"> fals</span><span lang="pt-PT">e</span> <span lang="pt-PT">mapeiam para </span><span lang="pt-PT">o NullContext, esta classe de contexto simplesmente satisfizer a interface </span><span lang="pt-PT">que a </span><span lang="pt-PT">FormHelper requer. </span><span lang="pt-PT">E</span><span lang="pt-PT">ste contexto é útil se você quiser construir um pequeno formulário que não requer persistência </span><span lang="pt-PT">ORM</span><span lang="pt-PT">.</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Para criar um form para uma entity faça o seguinte:</span></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">// Se você está em /articles/add</span></span>
<span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">// $article deve ser uma entidade vazia de Article.</span></span>
<span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;Form-&gt;create($article);</i></span></span></pre>
<p style="margin-bottom: 0cm; line-height: 100%;" align="justify"><a name="result_box41"></a><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">Isto irá postar os dados do formulário para </span><span lang="pt-PT">o action</span><span lang="pt-PT"> add () de ArticlesController. No entanto, você também pode usar a mesma lógica para criar um formulário de edição. O FormHelper utiliza o objeto de entidade para detectar automaticamente se criar</span><span lang="pt-PT">á</span><span lang="pt-PT"> um form de adicionar ou editar. Se a entidade fornecido não é "novo", o formulário será criado como um formulário de edição. </span><span lang="pt-PT">Se for novo será add.</span> </span></p>
<p><span style="font-family: Times New Roman, serif;">Por exemplo, se navegar para</span><br /> </p>
<p><strong><span style="font-family: Times New Roman, serif;">http://example.org/articles/edit/5</span></strong><span style="font-family: Times New Roman, serif;">, nós devemos fazer o seguinte:</span></p>
<pre class="language-php"><code>// src/Controller/ArticlesController.php:

public function edit($id = null)
{
    if (empty($id)) {
        throw new NotFoundException;
    }
    $article = $this-&gt;Articles-&gt;get($id);
    // Save logic goes here
    $this-&gt;set('article', $article);
}

// View/Articles/edit.ctp:
// Since $article-&gt;isNew() is false, we will get an edit form

&lt;?= $this-&gt;Form-&gt;create($article) ?&gt;</code></pre>
<p><strong>Mudando o Método para o Form</strong></p>
<pre>echo $this-&gt;Form-&gt;create($article, ['type' =&gt; 'get']);</pre>
<p>Quando existir algum campo do tipo file, precisará ser assim:</p>
<pre>echo $this-&gt;Form-&gt;create($article, ['type' =&gt; 'file']);</pre>
<p><strong>Configurando a URL para o Form</strong></p>
<pre>echo $this-&gt;Form-&gt;create($article, ['url' =&gt; ['action' =&gt; 'login']]);</pre>
<p>Caso o desejado form action não seja do controller atual, podemos especificar a completa URL para a action do form:</p>
<pre>echo $this-&gt;Form-&gt;create(null, [
    'url' =&gt; ['controller' =&gt; 'Articles', 'action' =&gt; 'publish']
]);</pre>
<p><strong>Ou pode apontar para uma URL externa:</strong></p>
<pre>echo $this-&gt;Form-&gt;create(null, [
    'url' =&gt; 'http://www.google.com/search',
    'type' =&gt; 'get'
]);</pre>
<p><strong>Criando Controles para Forms</strong></p>
<p><a name="Cake\View\Helper\FormHelper::control"></a><code class="western"><span style="font-family: Times New Roman, serif;"><i>Cake\View\Helper\FormHelper::control</i></span></code><span style="font-family: Times New Roman, serif;"><i>(</i></span><em><span style="font-family: Times New Roman, serif;"><i>string $fieldName</i></span></em><span style="font-family: Times New Roman, serif;"><i>, </i></span><em><span style="font-family: Times New Roman, serif;"><i>array $options = []</i></span></em><span style="font-family: Times New Roman, serif;"><i>) </i></span></p>
<p style="margin-bottom: 0cm;"><code class="western">$fieldName</code> – O nome do campo do form <code class="western">'Modelname.fieldname'</code>.</p>
<p><code class="western">$options</code> - Um array opcional que pode incluir ambos <a href="https://book.cakephp.org/3.0/en/views/helpers/form.html#control-specific-options">Options for Control</a>, e options dos outros métodos (que o <code class="western">control()</code> emprega internamente para gerar vários elementos HTML) como também atributos HTML válidos.</p>
<p>Em versões anteriores o Cake usava $this-&gt;form-&gt;input(), agora usa $this-&gt;form-&gt;control().</p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">O método control() permite gerar </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">todos os </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">controles/</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">inputs</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT"> d</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">o</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT"> formulário. Esses controles incluirão um</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">a</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT"> div </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">para</span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT"> quebra automática, </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">um </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">rótulo, </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">um </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">widget de controle e </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">validação de </span></span><span style="font-family: Times New Roman, serif;"><span lang="pt-PT">erro, se necessário. Usando os metadados no contexto do formulário, esse método escolherá um tipo de controle apropriado para cada campo. Internamente control() usa os outros métodos do FormHelper.</span></span></p>
<p lang="pt-PT">Observe que enquanto os campos gerados pelo método control() são chamados genericamente de “inputs” nesta página, tecnicamente falando, o método control() pode gerar não apenas todos os elementos de tipo input do HTML, mas também outros elementos de formulário HTML (por exemplo, selects, button, textarea).</p>
<p>Por default o método <code class="western"><span style="font-family: Times New Roman, serif;">control()
</span></code><code class="western"><span style="font-family: Times New Roman, serif;">deve
empregar os </span></code><code class="western"><span style="font-family: Times New Roman, serif;">s</span></code><code class="western"><span style="font-family: Times New Roman, serif;">eguintes
widget </span></code>templates:</p>
<pre class="western">'inputContainer' =&gt; '&lt;div class="input {{type}}{{required}}"&gt;{{content}}&lt;/div&gt;'
'input' =&gt; '&lt;input type="{{type}}" name="{{name}}"{{attrs}}/&gt;'</pre>
<p>Em caso de validação de erros ele também usa:</p>
<pre class="western" style="margin-bottom: 0.5cm;">'inputContainerError' =&gt; '&lt;div class="input {{type}}{{required}} error"&gt;{{content}}{{error}}&lt;/div&gt;'</pre>
<p><span style="font-family: Times New Roman, serif;">O tipo de controle criado (quando nós não provemos nenhum options adicional para especificar o tipo de elemento gerado) é inferido via introspecção do model e depende do tipo de dados do campo:</span></p>
<dl>
<dt><b>Column Type - </b>Resulting Form Field</dt>
<dt>string, uuid (char, varchar, etc.) - text</dt>
<dt>boolean, tinyint(1) - checkbox</dt>
<dt>decimal - number</dt>
<dt>float - number</dt>
<dt>integer - number</dt>
<dt>text - textarea</dt>
<dt>text, with name of password, passwd - password</dt>
<dt>text, with name of email - email</dt>
<dt>text, with name of tel, telephone, or phone - tel</dt>
<dt>date - day, month, and year selects</dt>
<dt>datetime, timestamp - day, month, year, hour, minute, and meridian selects</dt>
<dt>time - hour, minute, and meridian selects</dt>
<dt>binary - file</dt>
</dl>
<p>O parâmetro <code class="western">$options</code> segue sua escolha de um controle específico tipo caso necessite:</p>
<pre class="western" style="margin-bottom: 0.5cm;">echo $this-&gt;Form-&gt;control('published', ['type' =&gt; 'checkbox']);</pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Exemplo de form:</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Crie uma nova view em um template, chamada form.ctp, contendo</span></p>
<pre class="language-php"><code>&lt;?php
	echo $this-&gt;Form-&gt;create($user);
	// The following generates a Text input
	echo $this-&gt;Form-&gt;control('username');
	// The following generates a Password input
	echo $this-&gt;Form-&gt;control('password');
	// Assuming 'approved' is a datetime or timestamp field the following
	//generates: Day, Month, Year, Hour, Minute
	echo $this-&gt;Form-&gt;control('approved');
	// The following generates a Textarea element
	echo $this-&gt;Form-&gt;control('quote');
	echo $this-&gt;Form-&gt;button('Add');
	echo $this-&gt;Form-&gt;end();
?&gt;</code></pre>
<p><strong>Adicione um action ao controller correspondente, assim:</strong></p>
<p>public function form()</p>
<p>{</p>
<p>$customers =$this-&gt;Customers;</p>
<p>$this-&gt;set(compact('customers'));</p>
<p>}</p>
<p>Então chame pelo navegador assim:</p>
<p><a href="http://localhost/controllerNome/form">http://localhost/</a><a href="http://localhost/controllerNome/form">clientes/</a><a href="http://localhost/controllerNome/form">controllerNome/form</a></p>
<p>Podemos especificar qualquer opção para o tipo do input e qualquer atributo HTML.</p>
<p> </p>
<p><strong>Criar um Select</strong></p>
<p>Se você deseja criar um campo select enquanto usando uma relação belogTo ou hasOne você pode adicionar o seguinte para seu UsersController (assumindo que User belongTo Group):</p>
<pre>$this-&gt;set('groups', $this-&gt;Users-&gt;Groups-&gt;find('list'));</pre>
<p>Então na view do Template:</p>
<pre>echo $this-&gt;Form-&gt;input('group_id', ['options' =&gt; $groups]);</pre>
<p> </p>
<p>Para um select em uma associação belongsToMany Groups você pode adicionar o seguinte para seu UsersController:</p>
<pre>$this-&gt;set('groups', $this-&gt;Users-&gt;Groups-&gt;find('list'));</pre>
<p>Na view:</p>
<pre>echo $this-&gt;Form-&gt;input('groups._ids', ['options' =&gt; $groups]);</pre>
<p><a name="result_box31"></a> <span style="font-family: Times New Roman, serif;"><span lang="pt-PT">Se o nome do model consiste em duas ou mais palavras, por exemplo, "UserGroup", ao passar os dados usando set() você deve nomear os seus dados </span><span lang="pt-PT">com</span><span lang="pt-PT"> um formato pluralizado e camelCase como se segue:</span></span></p>
<pre class="western" lang="pt-PT"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>$this-&gt;set('userGroups', $this-&gt;UserGroups-&gt;find('list'));</i></span></span></pre>
<p lang="pt-PT" style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Não usar input() para gerar submits</b></span></p>
<p lang="pt-PT" style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Para isso usar o método \View\Helper\FormHelper::submit().</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Options do Input</b></span></p>
<pre class="language-php"><code>$options['type']

echo $this-&gt;Form-&gt;input('field', ['type' =&gt; 'file']);
echo $this-&gt;Form-&gt;input('email', ['type' =&gt; 'email']);
$options['label']

echo $this-&gt;Form-&gt;input('name', [
    'label' =&gt; 'The User Alias'
]);
Outros:
echo $this-&gt;Form-&gt;input('name', [
    'label' =&gt; [
        'class' =&gt; 'thingy',
        'text' =&gt; 'The User Alias'
    ]
]);</code></pre>
<p> </p>
<pre class="language-php"><code>Tipo select:
$sizes = ['s' =&gt; 'Small', 'm' =&gt; 'Medium', 'l' =&gt; 'Large'];
echo $this-&gt;Form-&gt;select('size', $sizes, ['default' =&gt; 'm']);
$options['value']
echo $this-&gt;Form-&gt;time('close_time', [
    'value' =&gt; '13:30:00'
]);
echo $this-&gt;Form-&gt;select('rooms', [
    'multiple' =&gt; true,
    // options with values 1 and 3 will be selected as default
    'default' =&gt; [1, 3]
]);
$options['empty']
echo $this-&gt;Form-&gt;select(
    'field',
    [1, 2, 3, 4, 5],
    ['empty' =&gt; '(choose one)']
);
$options['datetime']
echo $this-&gt;Form-&gt;input('time', [
    'type' =&gt; 'time',
    'interval' =&gt; 15
]);
</code></pre>
<p><strong>Criando dois selects estáticos para os campos controller e action em Permissions/add.ctp</strong></p>
<p>$options = ['Customers'=&gt;'Customers','Groups'=&gt;'Groups','Users'=&gt;'Users','Permissions'=&gt;'Permissions','Products'=&gt;'Products','ProductItems'=&gt;'ProductItems','value'=&gt;'Selecione'];</p>
<p>echo $this-&gt;Form-&gt;input('controller',['options'=&gt;$options,'required'=&gt;'false', 'class'=&gt;'col-md-12','empty'=&gt;'Selecione']); </p>
<p>$options2 = ['index'=&gt;'index','add'=&gt;'add','edit'=&gt;'edit','view'=&gt;'view','delete'=&gt;'delete'];</p>
<p>echo $this-&gt;Form-&gt;input('action', ['options'=&gt;$options2,'required'=&gt;'false', 'class'=&gt;'col-md-12', 'empty'=&gt;'Selecione']);</p>
<p> </p>
<p>São estáticos, portanto sempre que precisar adicionar um novo controller ou action, precisa alterar este código.</p>
<p> </p>
<p><strong>Para que Html-&gt;Link permita CSS:</strong></p>
<p>&lt;?= $this-&gt;Html-&gt;Link('&lt;span class="glyphicon glyphicon-plus"&gt;&lt;/span&gt; Novo', ['controller'=&gt;'Bookmaarks','action'=&gt;'add'],</p>
<p>['class'=&gt;'btn tbn-primary pull-right']);</p>
<p> </p>
<p>Assim ele mostrará o código &lt;span...&lt;/span&gt;</p>
<p><strong>Para que permita o CSS, use:</strong></p>
<p>&lt;?= $this-&gt;Html-&gt;link('&lt;span class="glyphicon glyphicon-plus"&gt;&lt;/span&gt; Novo', ['controller'=&gt;'Bookmaarks','action'=&gt;'add'],</p>
<p>['class'=&gt;'btn tbn-primary pull-right', 'escape'=&gt;false]);</p>
<p> </p>
<p><strong>Observação:</strong></p>
<p>classe Html, método link. Classe com inicial maiúscula e método tudo em minúsculas.</p>
<p> </p>
<p><strong>Mudar o tipo de um campo</strong></p>
<p>O Cake gerou um campo com o tipo textarea em um form.</p>
<p>Para mudar podemos fazer isso:</p>
<p>print $this-&gt;Form-&gt;input('url',['label', 'URL']);</p>
<p> </p>
<p>Mudar para tipo text (campo texto) assim:</p>
<p>print $this-&gt;Form-&gt;input('url',['type'=&gt;'text','label', 'URL']);</p>
<p> </p>
<p><strong>Pegando os Erros do Formulário</strong></p>
<p>Uma vez sido validado, o formulário pode recuperar seus próprios erros:</p>
<p>$errors = $form-&gt;errors();</p>
<p>/* $errors contains</p>
<p>[</p>
<p>'email' =&gt; ['A valid email address is required']</p>
<p>]</p>
<p>*/</p>
<p> </p>
<p><strong>Form Helper</strong></p>
<p>Form</p>
<p>$this-&gt;Form-&gt;control() - usado para criar elementos com o mesmo nome. Tem dois parâmetros:</p>
<p>Primeiro - nome do campo</p>
<p>Segundo - opcional, permite usar arrays com múltiplas opções</p>
<p> </p>
<p>Para o CakePHP os campos do tipo data, datatime ou timestamp obrigatoriamente devem usar DEFAULT NULL:</p>
<p>nascimento date DEFAULT NULL</p>
<p>E também não podemos alterar sua validação para exigir preenchimento com notEmpty ou notBlank. Caso contrário o Cake não reconhece e não adiciona o registro.</p>
<p>src/Template/Clientes/add.ctp ou edit.ctp</p>
<p> </p>
<p>Ano mínimo sendo 13 anos antes do atual e máximo sendo 100 anos antes do atual, ou seja, como estou em 2016 de 1916 até 2003</p>
<p>Select múltiplo (permite selecionar várias opções)</p>
<pre class="language-php"><code>	print $this-&gt;Form-&gt;input('pilot_ratings',[
		'type' =&gt; 'select',
		'class' =&gt; 'listbox',
		'size' =&gt; 5,
		'id' =&gt; 'pilot_ratings',
		'multiple' =&gt; 'multiple',
		'options' =&gt; [
		    ['name' =&gt; 'Habilitación de Vuelo Nocturno Local', 'value' =&gt; '1'],
		    ['name' =&gt; 'Habilitación Cat. II / Cat. III', 'value' =&gt; '2'],
		    ['name' =&gt; 'Habilitación de Remolque de Planeador', 'value' =&gt; '5']
		]
	]);</code></pre>
<p>src/Template/Clientes/add.ctp ou edit.ctp</p>
<p> </p>
<p><strong>Dicas sobre data e hora</strong></p>
<p>Para o CakePHP os campos do tipo data, datatime ou timestamp obrigatoriamente devem usar DEFAULT NULL:</p>
<p>nascimento date DEFAULT NULL</p>
<p> </p>
<p>E também não podemos alterar sua validação para exigir preenchimento com notEmpty ou notBlank. Caso contrário</p>
<p>o Cake não reconhece e não adiciona o registro.</p>
<p>src/Template/Clientes/add.ctp ou edit.ctp</p>
<p>Por padrão o Cake mostra apenas os anos de 2011 até 2021 na combo Ano.</p>
<p>Vamos alterar para que o ano mínimo seja 13 anos antes do atual</p>
<p>e máximo seja 100 anos antes do atual, ou seja, como estou em 2016,</p>
<p>que mostre de 1916 até 2003, mas isso deve ser pensado para atender ao requisito</p>
<p>da tabela/aplicativo. No nosso caso, do DNOCS, devemos usar 18 anos antes,</p>
<p>ou mais para o primeiro?</p>
<p><strong>Criar o select controller e o action</strong></p>
<pre class="language-php"><code>&lt;?php
            $controls = ['Groups'=&gt;'Groups', 'Users'=&gt;'Users', 'Permissions'=&gt;'Permissions', 'Customers'=&gt;'Customers'];			
            $actions = ['index'=&gt;'index','add'=&gt;'add','edit'=&gt;'edit','delete'=&gt;'delete'];
            echo $this-&gt;Form-&gt;input('group_id', ['options' =&gt; $groups, 'empty'=&gt;'Grupo','class'=&gt;'col2']);
            echo $this-&gt;Form-&gt;input('controller', ['options'=&gt;$controls,'class'=&gt;'col2','empty'=&gt;'Controller']);
            echo $this-&gt;Form-&gt;input('action', ['options'=&gt;$actions,'class'=&gt;'col2','empty'=&gt;'Action']);
        ?&gt;
</code></pre>
<p><strong>Actions em form</strong></p>
<p>echo $form-&gt;create('Post', ['action' =&gt; 'whatever']);</p>
<p>echo $form-&gt;create('Post', ['url' =&gt; '/controller_name/action_name']);</p>
<p>echo $this-&gt;Form-&gt;create("Despesas",['url'=&gt;'/despesas/despesas_mes']);</p>
<p> </p>
<p>Quando usamos o método set() em nosso controller, definimos variáveis específicas para serem enviadas para a view/tempalte correspondente. A view/template fará com que todas as variáveis passadas estejam disponíveis no escopo do template como variáveis locais.</p>
<p> </p>
<p><strong>Mudando largura de campos</strong></p>
<p>echo $this-&gt;Form-&gt;input['Busca',['type'=&gt;'text','maxlength'=&gt;'8','style'=&gt;'width:50px; height:20px;']];</p>
<p> </p>
<p><strong>Criando link com o HtmlHelper:</strong></p>
<p>Para o controller atual</p>
<p>&lt;?= $this-&gt;Html-&gt;link(__('Lista de Usuário'), ['action' =&gt; 'index']) ?&gt;</p>
<p> </p>
<p><strong>Para outro controller</strong></p>
<p>&lt;?= $this-&gt;Html-&gt;link(__('Lista de Usuário'), ['controller'=&gt;'Users','action' =&gt; 'index']) ?&gt;</p>
<p> </p>
<p><strong>Criando formulário com o FormHelper</strong></p>
<p>&lt;?= $this-&gt;Form-&gt;create($user) ?&gt;</p>
<p>&lt;legend&gt;&lt;?= __('Editar Usuário') ?&gt;&lt;/legend&gt;</p>
<p>&lt;?php</p>
<p>echo $this-&gt;Form-&gt;input('username');</p>
<p>echo $this-&gt;Form-&gt;input('password');</p>
<p>echo $this-&gt;Form-&gt;input('role', ['admin'=&gt;'Administrador','user'=&gt;'Usuário']);</p>
<p>?&gt;</p>
<p>&lt;?= $this-&gt;Form-&gt;button(__('Submit')) ?&gt;</p>
<p>&lt;?= $this-&gt;Form-&gt;end() ?&gt;</p>
<p>Campo input simular select em FormHelper e mudando o label:</p>
<p> </p>
<p>echo $this-&gt;Form-&gt;label('Tipo'); // Criando o Label</p>
<p>echo $this-&gt;Form-&gt;select('role', ['user'=&gt;'Usuário','admin'=&gt;'Administrador'], ['default' =&gt; 'admin']);</p>
<p> </p>
<p><strong>Mais detalhes em:</strong></p>
<p><a href="http://book.cakephp.org/3.0/en/views/helpers/form.html">http://book.cakephp.org/3.0/en/views/helpers/form.html</a></p>
<p><a href="https://book.cakephp.org/3.0/pt/core-libraries/form.html">https://book.cakephp.org/3.0/pt/core-libraries/form.html</a></p>
<h3 class="western"> </h3>]]></description>
			<category>CakePHP</category>
			<pubDate>Wed, 03 Jul 2019 00:01:54 -0300</pubDate>
		</item>
		<item>
			<title>9.3 - Helper</title>
			<link>http://backup/portal/curriculo/livros/cakephp/9-3-helper.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/9-3-helper.html</guid>
			<description><![CDATA[<h3>9.3 – Helper</h3>
<p align="right"><em><strong>Você não pode mudar o vento, mas pode ajustar as velas do barco para chegar onde quer</strong></em></p>
<p align="right">Confúcio</p>
<p align="justify">Os helpers contém código de apresentação que são compartilhados entre muitas views, elements ou layouts.</p>
<p align="justify"><strong>Veja a relação de helper nativos do CakePHP 3:</strong></p>
<p align="justify"><a href="https://book.cakephp.org/3.0/en/views/helpers/breadcrumbs.html">Breadcrumbs</a></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/form.html">Form</a></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/html.html">Html</a></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/number.html">Number</a></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/paginator.html">Paginator</a></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/rss.html">Rss</a></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/session.html">Session</a></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/text.html">Text</a></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/time.html">Time</a></p>
<p><a href="https://book.cakephp.org/3.0/en/views/helpers/url.html">Url</a></p>
<p> </p>
<p>Carregamos Helpers no Cake declarando em classes views.</p>
<p>src\View</p>
<pre class="language-php"><code>Class AppView extends View
{
	public function initialize()
	{
		parent::initialize();
		$this-&gt;loadHelper('Html');
		$this-&gt;loadHelper('Form');
		$this-&gt;loadHelper('Flash');
	}
}
</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Usando o helper</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Também podemos usar o método beforeRender() dos controllers para carregar Helpers.</span></p>
<pre class="language-php"><code>class ArticlesController extends AppController
{
    public function beforeRender(Event $event)
    {
        parent::beforeRender($event);
        $this-&gt;viewBuilder()-&gt;helpers(['MeuHelper']);
    }
}</code></pre>
<p><strong>Criando Helpers</strong></p>
<p>Podemos criar classes Helper para usar em aplicações ou em plugins.</p>
<p>Os Helpers têm algumas convenções que nos ajuda se as seguirmos:</p>
<p>- Arquivos de classe Helper devem ficar em src/View/Helper. Exemplo:</p>
<p>src/View/Helper/MeuHelper.php</p>
<p>- Classes helpers devem ser sufixadas com Helper. Exemplo:</p>
<p> </p>
<p>MeuHelper</p>
<p>- Quando referenciar classes helper deve omitir o sufixo Helper:</p>
<p>$this-&gt;loadHelper('Meu');</p>
<p>Criando o esqueleto de um Helper chamado Mensagem com o bake:</p>
<p>cd /var/www/html/cliente</p>
<p>bin/cake bake helper Mensagem</p>
<p> </p>
<p>Editar o src\View\Helper\MensagemHelper.php e adicionar a função msg(), assim:</p>
<pre class="language-php"><code>&lt;?php
namespace App\View\Helper;

use Cake\View\Helper;
use Cake\View\View;

class MensagemHelper extends Helper
{
	protected $_defaultConfig = [];
	
	public function msg($msg)
	{
		return '&lt;h2&gt;'.$msg.'&lt;/h2&gt;';
	}
}</code></pre>
<p><strong>Usando o Helper</strong></p>
<p>Editar a view index.ctp e adicionar em algum lugar:</p>
<p>&lt;?=$this-&gt;Mensagem-&gt;msg('Minha Mensagem Helper') ?&gt;</p>
<p>Ao chamar no navegador verá a mensagem com título h2.</p>
<p>Um helper bem simples para mostrar o caminho das pedras.</p>
<p><strong>Máscaras no CakePHP</strong></p>
<p>- Máscara na view index para o campo CPF</p>
<p>Enquanto não descubro uma função do Cake que faz isso...</p>
<p> </p>
<p>O CPF é um campo texto mas constituido somente de números. A listagem (index.ctp) mostra a relação de números sem nenhuma formatação. Ajudaria se formatassemos usando uma máscara adequada para CPF, ajudaria a visualizar.</p>
<p>Vamos fazer isso agora para a view Clientes/index.ctp:</p>
<p>Substitua a linha</p>
<p>&lt;td&gt;&lt;?php echo h($cliente['Cliente']['cpf']); ?&gt;&amp;nbsp;&lt;/td&gt;</p>
<p>Por este código:</p>
<pre class="language-php"><code>        &lt;tbody&gt;
            &lt;?php foreach ($customers as $customer): ?&gt;
&lt;?php 
$cpfmask1 = substr($customer-&gt;cpf, 0,3);
$cpfmask2 = substr($customer-&gt;cpf, 3,3);
$cpfmask3 = substr($customer-&gt;cpf, 6,3);
$cpfmask4 = substr($customer-&gt;cpf, 9,2);
$cpfmask = $cpfmask1.'.'.$cpfmask2.'.'.$cpfmask3.'-'.$cpfmask4;
?&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;?= $this-&gt;Number-&gt;format($customer-&gt;id) ?&gt;&lt;/td&gt;
                &lt;td&gt;&lt;?= h($customer-&gt;name) ?&gt;&lt;/td&gt;
                &lt;td&gt;&lt;?= h($customer-&gt;birthday) ?&gt;&lt;/td&gt;
        		&lt;td&gt;&lt;?= h($cpfmask) ?&gt;&lt;/td&gt;</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Com isso a listagem mostrará o CPF com a sua máscara.</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Caso existam registros eles não serão alterados, apenas os novos.</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Dicas sobre data e hora</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Ano mínimo sendo 16 anos antes do atual e máximo sendo 100 anos antes do atual em actions add e edit</span></span></p>
<pre class="language-php"><code>		echo $this-&gt;Form-&gt;input('nascimento',['label' =&gt; 'Nascimento',
	        'dateFormat'    =&gt; 'DMY',
	        'minYear'       =&gt; date('Y') - 100,
	        'maxYear'       =&gt; date('Y') - 16,
	        'empty'         =&gt; [
	            'day'       =&gt; 'Dia',
	            'month'     =&gt; 'Mês',
	            'year'      =&gt; 'Ano'
            ]
        ]);</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Detalhes em:</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="http://book.cakephp.org/3.0/en/views/helpers.html">http://book.cakephp.org/3.0/en/views/helpers.html</a> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 23:48:54 -0300</pubDate>
		</item>
		<item>
			<title>9.2 - Layout</title>
			<link>http://backup/portal/curriculo/livros/cakephp/9-2-layout.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/9-2-layout.html</guid>
			<description><![CDATA[<h3>9.2 – Layout</h3>
<p align="right"><em><strong>A grande glória da vida não está em nunca cair, mas em se levantar a cada vez que cair.</strong></em></p>
<p align="right">Nelson Mandela</p>
<p align="justify">Layout contém código de apresentação que é incorporado na view. Qualquer coisa que você deseje ver em todas as suas views deve ser colocada em um layout.</p>
<p>No CakePHP 3 o arquivo default de layout fica em</p>
<p>src\Template\Layout\default.ctp</p>
<p align="justify">Se você deseja mudar a aparência da sua aplicação (cores, fontes e posições, imagens, etc) então o layout é o lugar para mexer.</p>
<p>Outros arquivos de layout devem ser criados em</p>
<p>src\Template\Layout\</p>
<p>Aqui está o layout default.ctp do CakePKP 3.8.0 com leves modificações:</p>
<pre class="language-php"><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;?= $this-&gt;Html-&gt;charset() ?&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;
        &lt;?= $this-&gt;fetch('title') ?&gt;
    &lt;/title&gt;
    &lt;?= $this-&gt;Html-&gt;meta('icon') ?&gt;

    &lt;?= $this-&gt;Html-&gt;css('base.css') ?&gt;
    &lt;?= $this-&gt;Html-&gt;css('style.css') ?&gt;

    &lt;?= $this-&gt;fetch('meta') ?&gt;
    &lt;?= $this-&gt;fetch('css') ?&gt;
    &lt;?= $this-&gt;fetch('script') ?&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;nav class="top-bar expanded" data-topbar role="navigation"&gt;
        &lt;ul class="title-area large-3 medium-4 columns"&gt;
            &lt;li class="name"&gt;
                &lt;h1&gt;&lt;a href="http://backup/portal/"&gt;&lt;?= $this-&gt;fetch('title') ?&gt;&lt;/a&gt;&lt;/h1&gt;
            &lt;/li&gt;
        &lt;/ul&gt;
    &lt;/nav&gt;
    &lt;?= $this-&gt;Flash-&gt;render() ?&gt;
    &lt;div class="container clearfix"&gt;
        &lt;?= $this-&gt;fetch('content') ?&gt;
    &lt;/div&gt;
    &lt;footer&gt;
    &lt;/footer&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>Podemos criar tantos layouts quantos desejarmos. Apenas os crie em:</p>
<p>src\Template\Layout\</p>
<p> </p>
<p>E chame no action respectivo com:</p>
<p>$this-&gt;viewBuilder()-&gt;layout('admin');</p>
<p> </p>
<p>Na view use:</p>
<p>$this-&gt;layout = 'loggedin';</p>
<p> </p>
<p>Veja no plugin <a href="https://github.com/ribafs/admin-br">admin-br</a> o uso de dois layouts e sua chamada no AppController.</p>
<p><strong>Carregando num controller</strong></p>
<p>public function initialize()</p>
<p>{</p>
<p>$this-viewBuilder()-&gt;setLayout('admin');</p>
<p>}</p>
<p> </p>
<p>Ou</p>
<p>if($loguser == 'user' || $loguser == 'manager'){</p>
<p>$this-&gt;viewBuilder()-&gt;setLayout('CakeAclBr.default');</p>
<p>}else{</p>
<p>$this-&gt;viewBuilder()-&gt;setLayout('CakeAclBr.admin');</p>
<p>}</p>
<p>Layout - contém código de apresentação da view. Tudo que vemos nas views está incorporado num layout.</p>
<p> </p>
<p>Estão em src/Template/Layout</p>
<p>O cake já vem com um layout padrão, que é o default.ctp.</p>
<p>Como setar outro layout no controller. Exemplo admin.ctp:</p>
<p>public function initialize()</p>
<p>{</p>
<p>$this-viewBuilder()-setLayout('admin');</p>
<p>// Para plugin</p>
<p>// $this-viewBuilder()-setLayout('AdminBr.admin');</p>
<p>}</p>
<p><strong>Detalhes</strong></p>
<p><a href="https://book.cakephp.org/3.0/en/views.html#layouts">https://book.cakephp.org/3.0/en/views.html#layouts</a></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 23:40:37 -0300</pubDate>
		</item>
		<item>
			<title>9.1 - Element</title>
			<link>http://backup/portal/curriculo/livros/cakephp/9-1-element.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/9-1-element.html</guid>
			<description><![CDATA[<h3>9.1 - Element</h3>
<p align="right"><em><strong>Creio muito na sorte. Quanto mais trabalho, mais sorte pareço ter.</strong></em></p>
<p align="right"><tt>Coleman Cox</tt></p>
<p><tt>Cake\View\View::element</tt>(string $elementPath, array $data, array $options =[])</p>
<p align="justify">Alguns aplicativos tem pequenos blocos de código de apresentação que se repetem de página para página, algumas vezes em diferentes lugares do layout. O CakePHP pode ajudar você a repetir partes do seu site que precisam ser reutilizadas. Estas partes reusáveis são chamadas de Elements. Ads, help boxes, navigational controls, extra menus, login forms e callouts são implementados em CakePHP como elements.</p>
<p align="justify"><a name="result_box5"></a> <span style="font-family: Times New Roman, serif;"><span lang="pt-PT">Um element é basicamente uma mini-view que pode ser incluída em outros pontos d</span><span lang="pt-PT">a</span><span lang="pt-PT"> vi</span><span lang="pt-PT">ew</span><span lang="pt-PT">, em layouts, e até mesmo dentro de outros elements. Os elements podem ser usados para fazer uma vi</span><span lang="pt-PT">ew</span><span lang="pt-PT"> mais legível, colocando a prestação de elements repetidos em seu próprio arquivo. Eles também podem ajudá-lo a reutilizar fragmentos de conteúdo em sua aplicação.</span> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><strong><span style="font-family: Times New Roman, serif;">Elements ficam na pasta</span></strong></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">src\Template\Element </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><strong><span style="font-family: Times New Roman, serif;">E tem extensão .ctp</span></strong></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><strong><span style="font-family: Times New Roman, serif;">Mostrando com o método element da view:</span></strong></p>
<pre class="western"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;element('helpbox');</i></span></span>
</pre>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Criando seu </b><b>Próprio Element</b><br /> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Criaremos um pequeno Element que adicionará um menu para a região &lt;nav&gt; do layout.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Criar o arquivo</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">src\Template\Element\topmenu.ctp</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Contendo:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;?php</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> echo $this-&gt;Html-&gt;link(__('Customers'), array('plugin'=&gt;null,'controller'=&gt;'Customers','action'=&gt;'index', 'class'=&gt;'a menu'));</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> echo '&amp;nbsp;'.$this-&gt;Html-&gt;link(__('Grupos'), array('plugin'=&gt;null,'controller'=&gt;'Groups','action'=&gt;'index'));</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> echo '&amp;nbsp;'.$this-&gt;Html-&gt;link(__('Usuários'), array('plugin'=&gt;null,'controller'=&gt;'Users','action'=&gt;'index'));</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>?&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Customizando o css para exibir melhor nosso menu:</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Mude a linha com a para:</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>a {</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>color: black;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>}</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Usando</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">Para usar adicione a linha no src/Template/Layout/default.ctp, como indicado abaixo:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;body&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;nav class="top-bar expanded" data-topbar role="navigation"&gt; </i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> &lt;?php echo $this-&gt;element('topmenu');?&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Veja que é um element bem simples mas pode usar o conhecimento e criatividade para fazer algo melhor. Também pode ver um exemplo mais interessante no plugin admin-br.</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Dicas sobre Element no Cake</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p align="justify">Muitas aplicações possuem pequenos blocos de código de apresentação que precisam ser repetidos a cada página, às vezes em diferentes lugares no layout. O CakePHP ajuda você a repetir partes do seu website que precisam ser reutilizados. Estas partes reutilizáveis são chamadas de Elements (ou Elementos). Propagandas, caixas de ajuda, controles de navegação, menus extras, formulários de login e chamadas geralmente são implementadas como elements. Um element é basicamente uma mini-view que pode ser incluída em outras views, layouts e até mesmo em outros elements. Elements podem ser usados para criar uma view mais legível, colocando o processamento de elementos repetidos em seu próprio arquivo. Eles também podem ajudá-lo a reusar conteúdos fragmentados pela sua aplicação.</p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Element</b> - são pequenos trechos de código que podem ser usados nas views para qualquer utilidade. </span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Um element pode ser acessado por qualquer view.</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">No local da view onde queremos que apareça o código do elemento inserimos: </span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">echo $this-&gt;element('espacos'); </span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Podemos passar informações para um element através do seu segundo parâmetro: </span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $this-&gt;element(’helpbox’, array( </i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>"textoajuda" =&gt; "Oh, this text is very helpful." </i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>)); </i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>echo $textoajuda; </i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">São blocos de código tipo view reutilizáveis que criamos uma vez usamos várias vezes e em qualquer lugar do site (geralmente aplicados no layout)</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Detalhes</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><a href="https://book.cakephp.org/3.0/en/views.html#elements">https://book.cakephp.org/3.0/en/views.html#elements</a> </span></span></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 23:37:26 -0300</pubDate>
		</item>
		<item>
			<title>9 - Detalhes sobre Views</title>
			<link>http://backup/portal/curriculo/livros/cakephp/9-detalhes-sobre-views.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/9-detalhes-sobre-views.html</guid>
			<description><![CDATA[<h3>9 – Detalhes sobre Views</h3>
<p align="right"><em><strong>Eu gosto do impossível porque lá a concorrência é menor.</strong></em></p>
<p align="right">Walt Disney</p>
<p align="justify">As Views representam o V de MVC. Elas são responsáveis por gerar a saída específica para a requisição do usuário. Geralmente a saída é em HTML, mas também pode ser em XML, JSON, PDF e outras.</p>
<p>O CakePHP conta com uma grande quantidade de classes embutidas para manipulação o mais comum dos cenários a renderizar:</p>
<p>- Para criar webservers XML ou JSON que podemos usar nas views</p>
<p>- Para servir arquivos protegidos, ou arquivos gerados dinamicamente</p>
<p>- Para criar múltiplas views com templates</p>
<p>A AppView</p>
<p>A classe AppView é a classe View default. Em si ela estende a classe View e é definida em src\View\AppView.php assim:</p>
<pre>&lt;?php
namespace App\View;

use Cake\View\View;

class AppView extends View
{
}</pre>
<p align="justify">Podemos usar AppView para carregar Helper (no método initialize()), mas geralmente os helpers criados e adicionados a src\View\Helper já ficam automaticamente disponíveis para as views dos templates.</p>
<p> </p>
<p><strong>Views Template</strong></p>
<p>A camada de views do CakePHP é a forma de nos comunicarmos com o usuário da aplicação.</p>
<p align="justify">A extensão default das views é .ctp (CakePHP Template) e utiliza uma sintaxe alternativa em PHP para estruturas de controle e saída. Estes arquivos contem a lógica necessária para preparar os dados recebidos do controller no formato de apresentação que está pronto para a nossa audiência.</p>
<p align="justify">O CakePHP espera que os nossos templates sigam a convenção de nomenclatura onde o nome do template é a versão minúscula e grifada do nome do respectivo action do controller.</p>
<p align="left"> </p>
<p><strong>Partes de uma View</strong></p>
<p align="justify">A camada View no CakePHP pode ser formada por algumas partes. Cada parte tem diferentes usos e será coberta neste tutorial:</p>
<p>- templates: Templates são a parte da página que é única para o action começar a rodar;</p>
<p><a name="result_box1"></a> <span style="font-family: Times New Roman, serif;"><span lang="pt-PT">Elas são a parte principal da resposta do aplicativo.</span> Arquivos de template do CakePHP são armazenados em <strong>src/Template</strong> dentro de uma pasta com o nome do controller correspondente e com extensão .ctp.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="https://book.cakephp.org/3.0/en/views.html#view-templates">https://book.cakephp.org/3.0/en/views.html#view-templates</a> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">- <b>elements</b>: pequenos, reusáveis pedaços de código da view. Elements geralmente são renderizados dentro da view. Documentação oficial:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="http://book.cakephp.org/3.0/en/views.html#elements">http://book.cakephp.org/3.0/en/views.html#elements</a> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">- <b>layouts</b>: são arquivos de templates que contém código de apresentação que envolve muitas interfaces na sua aplicação. Muitas views são renderizadas dentro de um layout. Os layouts incorporam templates: index, add, edit, login, etc.</span></p>
<p><span style="font-family: Times New Roman, serif;">Um layout é um conjunto de códigos encontrado ao redor das views. Múltiplos layouts podem ser definidos, e você pode alterar entre eles, mas agora, vamos usar o default, localziado em <strong>src/Template/Layout/default.ctp</strong>.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="http://book.cakephp.org/3.0/en/views.html#layouts">http://book.cakephp.org/3.0/en/views.html#layouts</a> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">- <b>helpers</b>: estas classes encapsulam lógica de views que são necessárias em muitos lugares na camada view. Entre outras coisas os helpers no CakePHP podem ajudar você a construir forms, criar funcionalidade AJAX, paginar modelo de dados, etc.</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="http://book.cakephp.org/3.0/en/views/helpers.html">http://book.cakephp.org/3.0/en/views/helpers.html</a> </span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;">- <b>cells</b>: estas classes oferecem uma miniatura tipo as características dos controllers para a criação de componentes UI auto contidos. Veja a documentação para mais informações:</span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><a href="http://book.cakephp.org/3.0/en/views/cells.html"><span style="font-family: Times New Roman, serif;">http://book.cakephp.org/3.0/en/views/cells.html</span></a></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Dicas sobre Views</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Título do Aplicativo</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">- Adicionar ao AppController.php:</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> function beforeFilter(Event $event){</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> $this-&gt;set('title_for_layout','Controle de Finanças Pessoais');</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> }</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">- Será usado no Layout/default.ctp, aqui assim:</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;title&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;?= $cakeDescription ?&gt;:</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;?php echo $title_for_layout;?&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;/title&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">E no body</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;">…</p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;li class="name"&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;h1&gt;&lt;a href="http://backup/portal/"&gt;&lt;?php echo $title_for_layout;?&gt;&lt;/a&gt;&lt;/h1&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>&lt;/li&gt;</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Isso mostrará no title do navegador a variável $title_for_layout definida no AppController e também no body, no h1.</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>T</b><b>rocando campo do tipo text por select:</b></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i>$options = array(''=&gt;'Selecione','colegioelias' =&gt; 'Colégio do Elias', 'eliasmesada'=&gt;'Elias Mesada','eliasmerenda'=&gt;'Elias Merenda','meire' =&gt; 'Meire Salário', 'coelce'=&gt;'COELCE', 'condominio'=&gt;'Condomínio Ferreira', 'gvt'=&gt;'GVT', 'carnes'=&gt;'Carnes','mercantil'=&gt;'Mercantil','almoco'=&gt;'Almoço Trabalho','passagens'=&gt;'Passagens','remedio'=&gt;'Remédio');</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"> </p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Usando o $options:</span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i> echo $this-&gt;Form-&gt;input('descricao', array('type'=&gt;'select','label' =&gt; 'Descrição da Despesa','options' =&gt; $options,'default'=&gt;'0'));</i></span></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Algumas views típicas:</b></span></p>
<pre class="language-php"><code>&lt;!-- File: src/Template/Articles/add.ctp --&gt;

&lt;h1&gt;Add Article&lt;/h1&gt;
&lt;?php
    echo $this-&gt;Form-&gt;create($article);
    echo $this-&gt;Form-&gt;control('title');
    echo $this-&gt;Form-&gt;control('body', ['rows' =&gt; '3']);
    echo $this-&gt;Form-&gt;button(__('Save Article'));
    echo $this-&gt;Form-&gt;end();
?&gt;

&lt;!-- File: src/Template/Articles/edit.ctp --&gt;

&lt;h1&gt;Edit Article&lt;/h1&gt;
&lt;?php
    echo $this-&gt;Form-&gt;create($article);
    echo $this-&gt;Form-&gt;control('title');
    echo $this-&gt;Form-&gt;control('body', ['rows' =&gt; '3']);
    echo $this-&gt;Form-&gt;button(__('Save Article'));
    echo $this-&gt;Form-&gt;end();
?&gt;

&lt;!-- File: src/Template/Articles/view.ctp --&gt;

&lt;h1&gt;&lt;?= h($article-&gt;title) ?&gt;&lt;/h1&gt;
&lt;p&gt;&lt;?= h($article-&gt;body) ?&gt;&lt;/p&gt;
&lt;p&gt;&lt;small&gt;Created: &lt;?= $article-&gt;created-&gt;format(DATE_RFC850) ?&gt;&lt;/small&gt;&lt;/p&gt;


&lt;!-- File: src/Template/Articles/index.ctp  (edit links added) --&gt;

&lt;!-- File: src/Template/Articles/index.ctp (delete links added) --&gt;

&lt;h1&gt;Blog articles&lt;/h1&gt;
&lt;p&gt;&lt;?= $this-&gt;Html-&gt;link('Add Article', ['action' =&gt; 'add']) ?&gt;&lt;/p&gt;
&lt;table&gt;
    &lt;tr&gt;
        &lt;th&gt;Id&lt;/th&gt;
        &lt;th&gt;Title&lt;/th&gt;
        &lt;th&gt;Created&lt;/th&gt;
        &lt;th&gt;Actions&lt;/th&gt;
    &lt;/tr&gt;

&lt;!-- Here's where we loop through our $articles query object, printing out article info --&gt;

    &lt;?php foreach ($articles as $article): ?&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;?= $article-&gt;id ?&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;?= $this-&gt;Html-&gt;link($article-&gt;title, ['action' =&gt; 'view', $article-&gt;id]) ?&gt;
        &lt;/td&gt;
        &lt;td&gt;
            &lt;?= $article-&gt;created-&gt;format(DATE_RFC850) ?&gt;
        &lt;/td&gt;
        &lt;td&gt;
            &lt;?= $this-&gt;Form-&gt;postLink(
                'Delete',
                ['action' =&gt; 'delete', $article-&gt;id],
                ['confirm' =&gt; 'Are you sure?'])
            ?&gt;
            &lt;?= $this-&gt;Html-&gt;link('Edit', ['action' =&gt; 'edit', $article-&gt;id]) ?&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;?php endforeach; ?&gt;

&lt;/table&gt;

&lt;!-- File: src/Template/Users/login.ctp --&gt;
&lt;div class="users form"&gt;
&lt;?= $this-&gt;Flash-&gt;render() ?&gt;
&lt;?= $this-&gt;Form-&gt;create() ?&gt;
    &lt;fieldset&gt;
        &lt;legend&gt;&lt;?= __('Please enter your username and password') ?&gt;&lt;/legend&gt;
        &lt;?= $this-&gt;Form-&gt;control('username') ?&gt;
        &lt;?= $this-&gt;Form-&gt;control('password') ?&gt;
    &lt;/fieldset&gt;
&lt;?= $this-&gt;Form-&gt;button(__('Login')); ?&gt;
&lt;?= $this-&gt;Form-&gt;end() ?&gt;
&lt;/div&gt;
</code></pre>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><b>Detalhes em</b></span></p>
<p style="margin-bottom: 0cm; line-height: 100%;"><span style="font-family: Times New Roman, serif;"><a href="http://book.cakephp.org/3.0/en/views.html">http://book.cakephp.org/3.0/en/views.html</a> </span></p>
<h2 class="western"> </h2>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 23:34:11 -0300</pubDate>
		</item>
		<item>
			<title>8.6- Behaviors</title>
			<link>http://backup/portal/curriculo/livros/cakephp/8-6-behaviors.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/8-6-behaviors.html</guid>
			<description><![CDATA[<h3>8.6 – Behaviors</h3>
<p style="margin-bottom: 0cm; line-height: 100%;" align="right"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><i><b>Seja muito bom, que eles não vão ter como ignorar você.</b></i></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="right"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Steve Martin</span></span></p>
<p align="left">Criar um aplicativo para controle de receitas e despesas pessoais no CakePHP 3</p>
<p align="left">usando dois behaviors, um para somar as despesas de um mês e outro para somar as receitas de um mês.</p>
<p align="left"> </p>
<p align="left"><strong>Criar o banco financas</strong></p>
<p align="left">Importar o script do capítulo 15.3</p>
<p align="left"> </p>
<p align="left">Criar o aplicativo padrão usando o composer na pasta financas</p>
<p align="left"> </p>
<p align="left"><strong>Configurar o banco em config/app.php</strong></p>
<p align="left">Configurar a rota default em config/routes.php para Despesas/index</p>
<p align="left"> </p>
<p align="left"><strong>Gerar o código com o bake</strong></p>
<p align="left">bin/cake bake all despesas</p>
<p align="left">bin/cake bake all receitas</p>
<p align="left"> </p>
<p align="left"><strong>Criar os dois behaviors:</strong></p>
<p align="left">bin/cake bake behavior Despesas</p>
<p align="left">bin/cake bake behavior Receitas</p>
<p align="left"> </p>
<p align="left"><strong>Editar o src/ModelBehavior/Despesas e deixar assim:</strong></p>
<pre class="language-php"><code>&lt;?php
namespace App\Model\Behavior;

use Cake\ORM\Behavior;
use Cake\ORM\Table;
use Cake\ORM\TableRegistry;

class DespesasBehavior extends Behavior
{
    protected $_defaultConfig = [];

	public function despesasMes($mes){

		$despesas = TableRegistry::get('Despesas')-&gt;find();
		$res = $despesas-&gt;select(['total_sum' =&gt;$despesas-&gt;func()-&gt;sum('Despesas.valor')])-&gt;where(['Despesas.mes' =&gt; $mes])-&gt;first();
		$total = $res-&gt;total_sum;
		return $total;
	}
}</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Agora edite o behavior Receitas e deixe assim:</span></span></p>
<pre class="language-php"><code>&lt;?php
namespace App\Model\Behavior;

use Cake\ORM\Behavior;
use Cake\ORM\Table;
use Cake\ORM\TableRegistry;

class ReceitasBehavior extends Behavior
{
    protected $_defaultConfig = [];

	public function receitaMes($mes){
		$receitas = TableRegistry::get('Receitas')-&gt;find();
		$res = $receitas-&gt;select(['total_sum' =&gt;$receitas-&gt;func()-&gt;sum('Receitas.valor')])-&gt;where(['Receitas.mes' =&gt; $mes])
		-&gt;first(); //perform the sum operation 
		$total = $res-&gt;total_sum;
		return $total;
	}
}</code></pre>
<p align="left">Edite o src/Model/Table/DespesasTable.php e adicione logo abaixo do behavior Timestamp:</p>
<p align="left">$this-&gt;addBehavior('Despesas');</p>
<p align="left">Também no ReceitasTable.php:</p>
<p align="left">$this-&gt;addBehavior('Receitas');</p>
<p align="left">Customizar o controller src/Controller/DespesasController.php, adicionando ao início do arquivo:</p>
<pre class="language-php"><code>use Cake\ORM\TableRegistry;

No início da classe:

	public function despesasMes()
	{
		$mes = $this-&gt;request-&gt;data('mes');
		$despesas = TableRegistry::get('Despesas');
		$total = $despesas-&gt;despesasMes($mes);
		$this-&gt;set('total',$total); 
		$this-&gt;set('mes',$mes);
	}

	public function saldoMes()
	{
		$mes = $this-&gt;request-&gt;data('mes');
		$this-&gt;LoadModel('Receitas');// Como não é o model relacionado com este controller, precisamos usar LoadModel para carregá-lo
		$receitas = $this-&gt;Receitas-&gt;receitaMes($mes);

		$despesas = TableRegistry::get('Despesas');
		$total = $despesas-&gt;despesasMes($mes);

		$saldo = $receitas - $total;
		$this-&gt;set('saldo',$saldo); 
		$this-&gt;set('mes',$mes);
	}
</code></pre>
<p align="left"> </p>
<pre class="language-php"><code>Adicionar ao src/Template/Despesas:

despesas_mes.ctp

&lt;?php ?&gt;
&lt;nav class="large-3 medium-4 columns" id="actions-sidebar"&gt;
    &lt;ul class="side-nav"&gt;
    &lt;h3&gt;&lt;?= __('Despesas') ?&gt;&lt;/h3&gt;
&lt;?php
print '&lt;b&gt;Mês: &lt;/b&gt;'.$mes. '&lt;br&gt;&lt;b&gt;Total: &lt;/b&gt;'. $total;
?&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('Voltar'), ['action' =&gt; 'index']) ?&gt;&lt;/li&gt;

&lt;/nav&gt;

saldo_mes.ctp

&lt;?php ?&gt;
&lt;nav class="large-3 medium-4 columns" id="actions-sidebar"&gt;
    &lt;ul class="side-nav"&gt;
    &lt;h3&gt;&lt;?= __('Despesas') ?&gt;&lt;/h3&gt;
&lt;?php
print '&lt;b&gt;Mês: &lt;/b&gt;'.$mes. '&lt;br&gt;&lt;b&gt;Saldol: &lt;/b&gt;'. $saldo;
?&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('Voltar'), ['action' =&gt; 'index']) ?&gt;&lt;/li&gt;
&lt;/nav&gt;

Altere o index.ctp, adicionando ao início:

...
&lt;nav class="large-3 medium-4 columns" id="actions-sidebar"&gt;
    &lt;ul class="side-nav"&gt;
        &lt;li class="heading"&gt;&lt;?= __('Actions') ?&gt;&lt;/li&gt;
        &lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('New Despesa'), ['action' =&gt; 'add']) ?&gt;&lt;/li&gt;
        &lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('List Receitas'), ['controller' =&gt; 'Receitas', 'action' =&gt; 'index']) ?&gt;&lt;/li&gt;
        &lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('New Receita'), ['controller' =&gt; 'Receitas', 'action' =&gt; 'add']) ?&gt;&lt;/li&gt;

        &lt;li&gt;&lt;b&gt;Despesas de um mês&lt;/b&gt;
        &lt;?php
           echo $this-&gt;Form-&gt;create("Despesas",['url'=&gt;'/despesas/despesas_mes']);
           echo $this-&gt;Form-&gt;input('mes');
           echo $this-&gt;Form-&gt;button('Submit');
           echo $this-&gt;Form-&gt;end();
        ?&gt;&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Saldo de um mês&lt;/b&gt;
        &lt;?php
           echo $this-&gt;Form-&gt;create("Saldo",['url'=&gt;'/despesas/saldo_mes']);
           echo $this-&gt;Form-&gt;input('mes');
           echo $this-&gt;Form-&gt;button('Submit');
           echo $this-&gt;Form-&gt;end();
        ?&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/nav&gt;
...</code></pre>
<p align="left">Chame pelo navegador:</p>
<p align="left">http://localhost/financas</p>
<p align="left"> </p>
<p align="left">Use o pequeno form da esquerda para cálculo das Despesas de um mês. Informe o mês '05/2017'</p>
<p align="left">Observe que o campo mẽs é do tipo string, com o formato mes/ano.</p>
<p align="left"> </p>
<p align="left">Também teste o Saldo de um mês.</p>
<p align="left"> </p>
<p align="left">Quando temos um model table com muitos métodos podemos criar behaviors para modular mais o código e mantê-lo mais organizado e de fácil manutenção.</p>
<p align="left"> </p>
<p align="left"><strong>Behavior Timestamp</strong></p>
<p align="left">O behavior Timestamp que irá preencher automaticamente os campos created e modified da nossa tabela.</p>
<p align="left"> </p>
<p align="left"><strong>Mais detalhes:</strong></p>
<p align="left"><a href="https://book.cakephp.org/3.0/pt/orm/behaviors.html">https://book.cakephp.org/3.0/pt/orm/behaviors.html</a></p>
<p align="left"><a href="https://book.cakephp.org/3.0/en/orm/behaviors.html">https://book.cakephp.org/3.0/en/orm/behaviors.html</a></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 23:30:31 -0300</pubDate>
		</item>
		<item>
			<title>8.5 - Query Builder</title>
			<link>http://backup/portal/curriculo/livros/cakephp/8-5-query-builder.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/8-5-query-builder.html</guid>
			<description><![CDATA[<h3>8.5 - Query Builder</h3>
<p align="left"> </p>
<p align="right"><em><strong>Dizem que a vida é para quem sabe viver, mas ninguém nasce pronto. A vida é para quem é corajoso o suficiente para se arriscar e humilde o bastante para aprender.</strong></em></p>
<p align="right">Clarice Lispector</p>
<p align="left">O Query Builder do ORM fornece uma interface fluente e simples de usar para criar e executar consultas. Ao compor consultas em conjunto, você pode criar consultas avançadas usando unions e subconsultas com facilidade.</p>
<p align="left">Por "baixo dos panos", o Query Builder usa instruções prepare do PDO que protegem contra ataques de injeção de SQL.</p>
<p align="left">A maneira mais fácil de criar um objeto Query é usar o método find () a partir de um objeto Table. Este método retornará uma consulta incompleta pronta para ser modificada. Você também pode usar o objeto de conexão de uma tabela para acessar o Query Builder de nível inferior que não inclui recursos de ORM, se necessário.</p>
<p align="left">Quando em um controller podemos usar Articles ao invés de $articles</p>
<pre class="language-php"><code>// Em ArticlesController.php

use Cake\ORM\TableRegistry;
$query = TableRegistry::getTableLocator()-&gt;get('Articles')-&gt;find();

foreach ($query as $article) {
    print $article-&gt;id .'-'.$article-&gt;title.'&lt;br&gt;';
}
exit;
</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-size: medium;"><strong><span style="font-family: Times New Roman, serif;">Veja pelo navegador</span></strong></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Sempre usar a linha abaixo em todos os exemplos</span></span></p>
<pre class="language-php"><code>use Cake\ORM\TableRegistry;

$articles = TableRegistry::getTableLocator()-&gt;get('Articles');
$resultsIteratorObject = $articles
    -&gt;find()
    -&gt;where(['id &gt;' =&gt; 1])
    -&gt;order(['id ASC'])
    -&gt;all();

foreach ($resultsIteratorObject as $article) {
    print $article-&gt;id.'-'.$article-&gt;title.'&lt;br&gt;';
}
exit;</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Veja no navegador</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Outro</span></span></p>
<pre class="language-php"><code>$articles = TableRegistry::getTableLocator()-&gt;get('Customers');
$resultsArray = $articles
    -&gt;find()
    -&gt;where(['id &gt;' =&gt; 1])
    -&gt;toList();

foreach ($resultsArray as $article) {
    print $article-&gt;id.'-'.$article-&gt;name.'&lt;br&gt;';
}

//debug($resultsArray[0]-&gt;title);
exit;</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-size: medium;"><strong><span style="font-family: Times New Roman, serif;">Mais detalhes:</span></strong></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><a href="https://book.cakephp.org/3.0/en/orm/query-builder.html">https://book.cakephp.org/3.0/en/orm/query-builder.html</a></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 23:22:00 -0300</pubDate>
		</item>
		<item>
			<title>8.4 - Table Objects</title>
			<link>http://backup/portal/curriculo/livros/cakephp/8-4-table-objects.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/8-4-table-objects.html</guid>
			<description><![CDATA[<h3>8.4 - Table Objects</h3>
<p> </p>
<p align="right"><em><strong>Tente uma, duas, três vezes e se possível tente a quarta, a quinta e quantas vezes for necessário. Só não desista nas primeiras tentativas, a persistência é amiga da conquista. Se você quer chegar onde a maioria não chega, faça o que a maioria não faz.</strong></em></p>
<p align="right">Bill Gates</p>
<p align="left">Provê acesso para a coleção de entities/registros armazenados em uma tabela específica. Para cada tabela de um aplicativo em CakePHP devemos ter uma classe Table associada a ela que é usada para interagir com a referida tabela.</p>
<p align="left">Antes de começar a usar Table Objects precisa garantir que tem configurada uma conexão com o banco de dados.</p>
<p align="left">A classe Table fica em src/Model/Table.</p>
<p align="left"> </p>
<p align="left">Por convenção objetos Table devem usar uma tabela que é idêntica a versão em minúsculas do nome da Table. Exemplos:</p>
<p align="left">ArticlesTable - artigos</p>
<p align="left">BlogPostsTable - blog_posts</p>
<p align="left"> </p>
<p align="left"><strong>Caso queira usar um nome de tabela que não segue esta convenção deve setar seu nome no método setTable() no método initialize() da classe Table:</strong></p>
<p align="left">$this-&gt;setTable('nomeTabela');</p>
<p align="left"> </p>
<p align="left">O ORM também espera que cada tabela tenha uma chave primária e que seu nome seja 'id'.<strong> Caso queira usar uma PK com nome diferente de “id” use o método setPrimaryKey() também no initialize() da Table.</strong></p>
<p align="left">$this-&gt;setPrimaryKey('cpf');</p>
<p align="left"> </p>
<p align="left"><strong>Classes Entity usadas em classe Table.</strong></p>
<p align="left">Por default table objects usam uma classe Entity baseada na convenção de nomes. Por exemplo, se uma Table tem nome ClientesTable então a entity respectiva será chamada de Cliente, no singular, visto que liga com apenas um registro por vez. Caso precise mudar esta convenção use o método setEntityClass() no initialize da Table:</p>
<p align="left"> </p>
<p align="left"><strong>Para Cake com versão anterior a 3.4.0:</strong></p>
<p align="left">$this-&gt;entityClass('App\Model\Entity\PO');</p>
<p align="left"> </p>
<p align="left"><strong>Superior a 3.4.0:</strong></p>
<p align="left">$this-&gt;setEntityClass('App\Model\Entity\PO');</p>
<p align="left"> </p>
<p align="left"><strong>Instância de uma Table:</strong></p>
<p align="left">Antes de começar a consultar uma tabela precisamos ter uma instância da mesma. Podemos fazer isso usando a classe TableRegistry:</p>
<p align="left"> </p>
<p align="left">// Em um método de controller ou de uma table adicione a linha</p>
<p align="left">use Cake\ORM\TableRegistry;</p>
<p align="left"> </p>
<p align="left"><strong>Lifecycle Callbacks/Eventos</strong></p>
<p align="left">Os eventos são úteis se você deseja conectar-se ao ORM e adicionar lógica sem subclassificar ou substituir métodos. Ouvintes de eventos podem ser definidos em Tables ou classes de Behavior. Você também pode usar o gerenciador de eventos de uma tabela para vincular os ouvintes. São semelhantes aos eventos dos controllers e componentes.</p>
<p align="left"> </p>
<p align="left"><strong>Lista de eventos</strong></p>
<p align="left">Model.initialize</p>
<p align="left">Model.beforeMarshal</p>
<p align="left">Model.beforeFind</p>
<p align="left">Model.buildValidator</p>
<p align="left">Model.buildRules</p>
<p align="left">Model.beforeRules</p>
<p align="left">Model.afterRules</p>
<p align="left">Model.beforeSave</p>
<p align="left">Model.afterSave</p>
<p align="left">Model.afterSaveCommit</p>
<p align="left">Model.beforeDelete</p>
<p align="left">Model.afterDelete</p>
<p align="left">Model.afterDeleteCommit</p>
<p align="left"> </p>
<p align="left"><strong>Alguns eventos</strong></p>
<p align="left">initialize()</p>
<p align="left">Cake\ORM\Table::initialize(Event $event, ArrayObject $data, ArrayObject $options)</p>
<p align="left">O evento Model.initialize é disparado após o método construtor.</p>
<p align="left"> </p>
<p align="left"><strong>beforeFind</strong></p>
<p align="left">Cake\ORM\Table::beforeFind(Event $event, Query $query, ArrayObject $options, $primary)</p>
<p align="left">The Model.beforeFind event is fired before each find operation. By stopping the event and supplying a return value you can bypass the find operation entirely.</p>
<p align="left"> </p>
<p align="left"><strong>buildValidator</strong></p>
<p align="left">Cake\ORM\Table::buildValidator(Event $event, Validator $validator, $name)</p>
<p align="left">O evento Model.buildValidator é disparado quando o $name validator é criado.</p>
<p align="left"> </p>
<p align="left"><strong>buildRules</strong></p>
<p align="left">Cake\ORM\Table::buildRules(Event $event, RulesChecker $rules)</p>
<p align="left">O evento Model.buildRules é disparado após uma instância de rules ser criada e após o método buildRules da Table ser chamado.</p>
<p align="left"> </p>
<p align="left"><strong>beforeRules</strong></p>
<p align="left">Cake\ORM\Table::beforeRules(Event $event, EntityInterface $entity, ArrayObject $options, $operation)</p>
<p align="left">O evento Model.beforeRules é disparado entes de uma entity ter a rules aplicada.</p>
<p align="left"> </p>
<p align="left"><strong>afterRules</strong></p>
<p align="left">Cake\ORM\Table::afterRules(Event $event, EntityInterface $entity, ArrayObject $options, $result, $operation)</p>
<p align="left">O evento Model.afterRules é disparado após uma entity ter a rules rules aplicada.</p>
<p align="left"> </p>
<p align="left"><strong>beforeSave</strong></p>
<p align="left">Cake\ORM\Table::beforeSave(Event $event, EntityInterface $entity, ArrayObject $options)</p>
<p align="left">O evento Model.beforeSave é disparado antes de cada entity ser salva.</p>
<p align="left"> </p>
<p align="left"><strong>afterSave</strong></p>
<p align="left">Cake\ORM\Table::afterSave(Event $event, EntityInterface $entity, ArrayObject $options)</p>
<p align="left">O evento Model.afterSave é disparado após uma entity ser salva.</p>
<p align="left"> </p>
<p align="left"><strong>afterSaveCommit</strong></p>
<p align="left">Cake\ORM\Table::afterSaveCommit(Event $event, EntityInterface $entity, ArrayObject $options)</p>
<p align="left">O evento Model.afterSaveCommit é disparado após a transação em que a operação save é embutida ser committed.</p>
<p align="left"> </p>
<p align="left"><strong>beforeDelete</strong></p>
<p align="left">Cake\ORM\Table::beforeDelete(Event $event, EntityInterface $entity, ArrayObject $options)</p>
<p align="left">O evento Model.beforeDelete é disparado antes que uma entity seja deletada.</p>
<p align="left"> </p>
<p align="left"><strong>afterDelete</strong></p>
<p align="left">Cake\ORM\Table::afterDelete(Event $event, EntityInterface $entity, ArrayObject $options)</p>
<p align="left">O evento Model.afterDelete é disparado após uma entity ser deletada.</p>
<p align="left"> </p>
<p align="left"><strong>afterDeleteCommit</strong></p>
<p align="left">Cake\ORM\Table::afterDeleteCommit(Event $event, EntityInterface $entity, ArrayObject $options)</p>
<p align="left">O evento Model.afterDeleteCommit é disparado após a transação em que a operação delete está embutida for committed.</p>
<p align="left"> </p>
<p align="left"><strong>Prioridades nos callbacks</strong></p>
<p align="left">Ao usar eventos em suas Tables e Behaviors, esteja ciente da prioridade a que os ouvintes de pedidos estão conectados. Eventos de Behaviors são anexados antes dos eventos da Tabela. Com as prioridades padrão, isso significa que retornos de chamada de Behavior são acionados antes do evento de Table com o mesmo nome.</p>
<p align="left">Por exemplo, se sua tabela estiver usando TreeBehavior, o método TreeBehavior::beforeDelete() será chamado antes do método beforeDelete() da sua Table, e você não poderá trabalhar com os nós filhos do registro que estão sendo excluídos no método da sua Table.</p>
<p align="left">Podemos gerenciar eventos de prioridades de uma das duas maneiras:</p>
<p align="left">Mude a prioridade de Behavior listeners usando a opção priority. Isto irá modificar a prioridade de todos os métodos callback no Behavior:</p>
<p align="left">// In a Table initialize() method</p>
<p align="left">$this-&gt;addBehavior('Tree', [</p>
<p align="left">// Default value is 10 and listeners are dispatched from the</p>
<p align="left">// lowest to highest priority.</p>
<p align="left">'priority' =&gt; 2,</p>
<p align="left">]);</p>
<p align="left"> </p>
<p align="left">Modifique a prioridade em sua classe Table usando o método Model.implementedEvents(). Isso permite que você atribua uma prioridade diferente por método callback:</p>
<p align="left">// In a Table class.</p>
<p align="left">public function implementedEvents()</p>
<p align="left">{</p>
<p align="left">$events = parent::implementedEvents();</p>
<p align="left">$events['Model.beforeDelete'] = [</p>
<p align="left">'callable' =&gt; 'beforeDelete',</p>
<p align="left">'priority' =&gt; 3</p>
<p align="left">];</p>
<p align="left">return $events;</p>
<p align="left">}</p>
<p align="left"> </p>
<p align="left"><strong>Sistema de Eventos</strong></p>
<p align="left">Criar aplicativos manuteníveis é uma ciência e uma arte. É bem conhecido que uma chave para ter um código de boa qualidade é tornar seus objetos fracamente acoplados e fortemente coesos ao mesmo tempo. Coesão significa que todos os métodos e propriedades de uma classe estão fortemente relacionados à própria classe e não está tentando fazer o trabalho que outros objetos deveriam estar fazendo, enquanto o acoplamento frouxo é a medida de quão pequena uma classe é conectada a objetos externos. e quanto essa classe depende deles.</p>
<p align="left"><strong>Mais detalhes em:</strong></p>
<p align="left"><a href="https://book.cakephp.org/3.0/en/core-libraries/events.html">https://book.cakephp.org/3.0/en/core-libraries/events.html</a></p>
<p align="left"><a href="https://book.cakephp.org/3.0/en/orm/table-objects.html">https://book.cakephp.org/3.0/en/orm/table-objects.html</a></p>
<p align="left"> </p>
<p align="left"> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 22:39:11 -0300</pubDate>
		</item>
		<item>
			<title>8.3 - Retornando dados do banco</title>
			<link>http://backup/portal/curriculo/livros/cakephp/8-3-retornando-dados-do-banco.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/8-3-retornando-dados-do-banco.html</guid>
			<description><![CDATA[<h3>8.3 - Retornando dados do banco</h3>
<p align="right"> </p>
<p align="right"><em><strong>No que diz respeito ao empenho, ao compromisso, ao esforço, à dedicação, não existe meio termo. Ou você faz uma coisa bem feita ou não faz.</strong></em></p>
<p align="right">Ayrton Senna</p>
<p align="left"><strong>class Cake\ORM\Table</strong></p>
<p align="left"> </p>
<p align="left">Enquanto os objetos Table fornecem uma abstração em torno de um "repositório" ou coleção de objetos, quando você consulta registros individuais, obtém objetos Entity.</p>
<p align="left">Quando o ORM foi implementado no CakePHP, era muito difícil depurar os resultados obtidos. Agora existem muitas formas fáceis de inspecionar os dados retornados pelo ORM.</p>
<p align="left">- debug($query) Mostra o SQL e os parâmetros incluídos, não mostra resultados.</p>
<p align="left">- debug($query-&gt;all()) Mostra a propriedade ResultSet retornado pelo ORM.</p>
<p align="left">- debug($query-&gt;toArray()) Um caminho mais fácil para mostrar todos os resultados.</p>
<p align="left">- debug(json_encode($query, JSON_PRETTY_PRINT)) Exemplo em JSON.</p>
<p align="left">- debug($query-&gt;first()) Primeiro resultado obtido na query.</p>
<p align="left">- debug((string)$query-&gt;first()) Mostra as propriedades de uma única entidade em JSON.</p>
<p align="left"> </p>
<p align="left"><strong>As opções suportadas por find() são:</strong></p>
<p align="left">- conditions provê acesso direto na cláusula Where.</p>
<p align="left">- limit Limite o número de resultados.</p>
<p align="left">- offset Uma página que você quer. Use page para cálculo simplificado.</p>
<p align="left">- contain defina uma associação para carregar.</p>
<p align="left">- fields Quais campos você deseja carregar somente? Quando carregar somente alguns campos o lembre-se dos plugins, callbacks.</p>
<p align="left">- group adicione um GROUP BY. muito usado para funçoes agregadas.</p>
<p align="left">- having adicionar HVAING.</p>
<p align="left">- join Defina um Join específico.</p>
<p align="left">- order Ordenar resultados por.</p>
<p align="left"> </p>
<p align="left">Outras opções fora dessa lista, serão passadas para o beforeFind ou outras funções de tratamento, onde podem ser usados para tratar a consulta a sua maneira. Pode usar o metódo getOptions() no objeto para retornar as opções utilizadas. Quando uma consulta for passada para o controller, recomendamos uma leitura sobre consultas personalizadas em Personalizando Metódos de Consulta. Usando metódos de consultas personalizados, você terá um melhor reuso de seu código, e ficará fácil para testar a sua maneira.</p>
<p align="left"> </p>
<p align="left"><strong>Detalhes</strong></p>
<p align="left"><a href="https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html">https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html</a></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 22:22:45 -0300</pubDate>
		</item>
		<item>
			<title>8.2 - O básico sobre o ORM</title>
			<link>http://backup/portal/curriculo/livros/cakephp/8-2-o-basico-sobre-o-orm.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/8-2-o-basico-sobre-o-orm.html</guid>
			<description><![CDATA[<h3>8.2 - O básico sobre o ORM</h3>
<p align="left"> </p>
<p align="right"><em><strong>Fazer as coisas certas é mais importante do que fazer bem feitas as coisas.</strong></em></p>
<p align="right">Peter Drucker</p>
<p align="left">Criar um novo aplicativo chamado cake_orm e um banco também cake_orm, com duas tabelas, relacionadas de acordo com a convenção do CakePHP: articles e comments para nossos testes, com o script abaixo:</p>
<pre class="language-markup"><code>-- Primeiro, criamos a tabela articles
CREATE TABLE articles (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(50),
    body TEXT,
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL
);

INSERT INTO `articles` (`id`, `title`, `body`, `created`, `modified`) VALUES
(1,	'Título1',	'Corpo do primeiro artigo',	'2019-06-01 10:07:39',	NULL),
(2,	'Título2',	'Corpo do segundo artigo.',	'2019-06-01 10:07:39',	NULL),
(3,	'Título3',	'Corpo do terceiro artigo.',	'2019-06-01 10:07:39',	NULL),
(4,	'Título4',	'Corpo do quarto artigo',	'2019-06-02 00:00:00',	NULL),
(5,	'Título4',	'Corpo do quarto artigo',	'2019-06-02 00:00:00',	NULL);

CREATE TABLE comments (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    comment VARCHAR(50),
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL,
    article_id int not null    
);

INSERT INTO comments (comment,created, article_id) VALUES ('Primeiro comantário', NOW(), 1),
 ('Segundo comantário', NOW(), 2),
 ('Terceiro comantário', NOW(), 3);</code></pre>
<p align="left">Configurar o aplicativo para este banco, setar o routes para Articles/index e</p>
<p align="left"> </p>
<p align="left"><strong>Gerar os CRUDs com o bake:</strong></p>
<p align="left">bin/cake bake all articles</p>
<p align="left">bin/cake bake all comments</p>
<p align="left"> </p>
<p align="left"><strong>Exemplo de uso do find()</strong></p>
<p align="left">Num método, pode ser o initialize() do model ArticlesTable.php</p>
<p align="left">list - retorna pares com chave e valor</p>
<p align="left">$rets = $this-&gt;find('list', ['order'=&gt;'id ASC']);</p>
<p align="left">foreach($rets as $id=&gt;$title){</p>
<p align="left">echo "$id : $title&lt;br&gt;";</p>
<p align="left">}</p>
<p align="left">exit;</p>
<p align="left">Num método, pode ser o index() do controller ArticlesController.php</p>
<p align="left">$rets = $this-&gt;Articles-&gt;find('list', ['order'=&gt;'id ASC']);</p>
<p align="left">foreach($rets as $id=&gt;$title){</p>
<p align="left">echo "$id : $title&lt;br&gt;";</p>
<p align="left">}</p>
<p align="left">exit;</p>
<p align="left">Obs.: observe que a diferença entre os usos no model ou no controller é que no controller precisamos usar Articles e no model não.</p>
<p align="left"> </p>
<p align="left"><strong>Recebendo a conexão default:</strong></p>
<p align="left">Abra o src/Model/Table/ArticlesTable.php</p>
<p align="left">Adicione ao início, abaixo dos existentes:</p>
<p align="left">use Cake\Datasource\ConnectionManager;</p>
<p align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Crie uma nova função:</span></span></p>
<pre class="language-php"><code>	public function artigos(){
		$conn = ConnectionManager::get('default');
		$artigos = $conn-&gt;execute("select * from articles")-&gt;fetchAll();
		return $artigos;
	}

Execute no initialize, ao final():

//debug($this-&gt;artigos()[0]);exit;
//debug($this-&gt;artigos()[0][2]);exit;
//debug($this-&gt;artigos()[0][2]);exit;
//debug($this-&gt;artigos()[2][2]);exit;

$arts = $this-&gt;artigos();


foreach($arts as $chave=&gt;$valor){
    print 'Artigo';
    foreach($valor as $val){
        print $val.'&lt;br&gt;';
    }
}
exit;</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Chame pelo navegador para ver o resultado</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">http://localhost/cake_orm</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Executar consultas SQL</b></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Sempre usar no início, para dar suporte</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">use Cake\Datasource\ConnectionManager;</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Execute o código abaixo no initialize() da ArticlesTable</span></span></p>
<pre class="language-php"><code>$conn = ConnectionManager::get('default');
$results = $conn
    -&gt;execute('SELECT * FROM articles WHERE id = :id', ['id' =&gt; 1])
    -&gt;fetchAll('assoc');
//debug($results);exit;
foreach($results as $chave=&gt;$valor){
    foreach($valor as $val){
        print $val.'&lt;br&gt;';
    }
}
exit;</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Chame pelo navegador para ver o resultado</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Mais um exemplo:</b></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Adicione ao final do initialize() do ArticlesTable</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<pre class="language-php"><code>$conn = ConnectionManager::get('default');
$results = $conn
    -&gt;execute(
        'SELECT * FROM articles WHERE title = :title', ['title'=&gt;'Título1']
    )
    -&gt;fetchAll('assoc');
debug($results);exit;
foreach($results as $chave=&gt;$valor){
    foreach($valor as $val){
        print $val.'&lt;br&gt;';
    }
}
exit;</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Sempre Chame pelo navegador para ver o resultado</span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Usando query builder</b></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Adicione ao final do initialize()</span></span></p>
<pre class="language-php"><code>$conn = ConnectionManager::get('default');
$results = $conn
    -&gt;newQuery()
    -&gt;select('*')
    -&gt;from('articles')
    -&gt;where(['title &gt;' =&gt; 'Título1'])
    -&gt;order(['title' =&gt; 'DESC'])
    -&gt;execute()
    -&gt;fetchAll('assoc');

//debug($results);exit;
foreach($results as $chave=&gt;$valor){
    foreach($valor as $val){
        print $val.'&lt;br&gt;';
    }
}
exit;</code></pre>
<p align="left">Chame pelo navegador</p>
<p align="left"> </p>
<p align="left"><strong>Insert</strong></p>
<p align="left">$connection = ConnectionManager::get('default');</p>
<p align="left">$connection-&gt;insert('articles', [</p>
<p align="left">'title' =&gt; 'Título4',</p>
<p align="left">'body' =&gt; 'Corpo do quarto artigo',</p>
<p align="left">'created' =&gt; '2019-06-02',</p>
<p align="left">], ['created' =&gt; 'datetime']);</p>
<p align="left"> </p>
<p align="left"><strong>Confira no banco de dados.</strong></p>
<p align="left"> </p>
<p align="left"><strong>Update</strong></p>
<p align="left">$connection = ConnectionManager::get('default');</p>
<p align="left">$connection-&gt;update('articles', ['title' =&gt; 'Título6'], ['id' =&gt; 6]);</p>
<p align="left">Confira no banco</p>
<p align="left"> </p>
<p align="left"><strong>Delete</strong></p>
<p align="left">use Cake\Datasource\ConnectionManager;</p>
<p align="left">$connection = ConnectionManager::get('default');</p>
<p align="left">$connection-&gt;delete('articles', ['id' =&gt; 5]);</p>
<p align="left">Confira no banco</p>
<p align="left"> </p>
<p align="left"><strong>Transações</strong></p>
<p align="left">$conn-&gt;begin();</p>
<p align="left">$conn-&gt;update('articles', ['title' =&gt; 'Título6'], ['id' =&gt; 1]);</p>
<p align="left">$conn-&gt;update('articles', ['title' =&gt; 'Título7'], ['id' =&gt; 1]);</p>
<p align="left">//...</p>
<p align="left">$conn-&gt;commit();</p>
<p align="left">Confira no banco</p>
<p align="left"> </p>
<p align="left"><strong>Outro</strong></p>
<p align="left">$conn = ConnectionManager::get('default');</p>
<p align="left">$conn-&gt;transactional(function ($conn) {</p>
<p align="left">$conn-&gt;execute('UPDATE articles SET created = "2019-06-01 10:07:39" WHERE id = 6');</p>
<p align="left">$conn-&gt;execute('UPDATE articles SET created = "2019-06-01 10:07:39" WHERE id = 4');</p>
<p align="left">});</p>
<p align="left">exit;</p>
<p align="left">Confira no banco</p>
<p align="left"> </p>
<p align="left"><strong>Executando consultas</strong></p>
<p align="left">Cake\Database\Connection::query($sql)</p>
<p align="left">Cake\Database\Connection::execute($sql, $params, $types)</p>
<p align="left"> </p>
<p align="left">$conn = ConnectionManager::get('default');</p>
<p align="left">$stmt = $conn-&gt;query('UPDATE articles SET created = "2019-06-05" WHERE id = 6');</p>
<p align="left">exit;</p>
<p align="left"> </p>
<p align="left">$conn = ConnectionManager::get('default');</p>
<p align="left">$stmt = $conn-&gt;execute(</p>
<p align="left">'UPDATE articles SET created = ? WHERE id = ?', ['2019-06-05', 2]</p>
<p align="left">);</p>
<p align="left">Confira no banco</p>
<p align="left"> </p>
<p align="left"><strong>Muito mais em:</strong></p>
<p align="left"><a href="https://book.cakephp.org/3.0/pt/orm/database-basics.html">https://book.cakephp.org/3.0/pt/orm/database-basics.html</a></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 22:20:59 -0300</pubDate>
		</item>
		<item>
			<title>8.1 - Validações</title>
			<link>http://backup/portal/curriculo/livros/cakephp/8-1-validacoes.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/8-1-validacoes.html</guid>
			<description><![CDATA[<h3>8.1 – Validações</h3>
<p align="left"> </p>
<p align="right"><em><strong>Escolhe um trabalho de que você goste e não terá que trabalhar nem um dia na sua vida.</strong></em></p>
<p align="right">Confúcio</p>
<p align="right"><strong>(Mas se não encontrar um de que você goste, empenhe-se no que você tem no momento e fique atento para encontrar um de que gosta)</strong></p>
<p align="right">Ribamar FS</p>
<p align="justify"><strong>A validação no Cake é feita no Model, mais especificamente na classe Table</strong></p>
<p align="left">Exemplo, o nosso aplicativo cliente:</p>
<pre class="language-php"><code>src\Model\Table\ClientesTable.php

…
    public function validationDefault(Validator $validator)
    {
        $validator
            -&gt;integer('id')
            -&gt;allowEmptyString('id', 'create');

        $validator
            -&gt;scalar('nome')
            -&gt;maxLength('nome', 45)
            -&gt;requirePresence('nome', 'create')
            -&gt;allowEmptyString('nome', false);

        $validator
            -&gt;email('email')
            -&gt;requirePresence('email', 'create')
            -&gt;allowEmptyString('email', false);

        $validator
            -&gt;date('data_nasc')
            -&gt;requirePresence('data_nasc', 'create')
            -&gt;allowEmptyDate('data_nasc', false);

        $validator
            -&gt;scalar('cpf')
            -&gt;maxLength('cpf', 11)
            -&gt;requirePresence('cpf', 'create')
            -&gt;allowEmptyString('cpf', false);

        return $validator;
    }

    /**
     * Returns a rules checker object that will be used for validating
     * application integrity.
     *
     * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
     * @return \Cake\ORM\RulesChecker
     */
    public function buildRules(RulesChecker $rules)
    {
        $rules-&gt;add($rules-&gt;isUnique(['email']));

        return $rules;
    }
…
</code></pre>
<p> </p>
<p align="left">O método validationDefault() diz ao CakePHP como validar seus dados quando o método save() no action no controller for solicitado.</p>
<p align="left"> </p>
<p align="left"><strong>Observações:</strong></p>
<p align="left">- Vejamos o campo nome:</p>
<p align="left">-&gt;maxLength('nome', 45)</p>
<p align="left">-&gt;requirePresence('nome', 'create')</p>
<p align="left">-&gt;allowEmptyString('nome', false);</p>
<p align="left"> </p>
<p align="left">De onde o Cake tirou este tamanho máximo de 45?</p>
<p align="left">Da nossa tabela. Veja que lá temos varchar(45).</p>
<p align="left"> </p>
<p align="left">De onde ele tirou que deve requerer a presença na criação de novos registros?</p>
<p align="justify">Também da tabela, onde viu NOT NULL, o que assegura a linha abaixo para não permitir vazio.</p>
<p align="justify"> </p>
<p align="justify">Desde que tenhamos usado o método Cake\View\Helper\FormHelper::input() do FormHelper para criar nossos elementos, nossas mensagens de alerta da validação serão exibidas automaticamente.</p>
<p align="left"> </p>
<p align="left"><strong>Validação para o CPF</strong></p>
<p align="left">Baixar o repositório para a validação de:</p>
<p align="left"><a href="https://github.com/gspaiva/cpfvalidator">https://github.com/gspaiva/cpfvalidator</a></p>
<p align="left">Ajustar num campo cujo nome seja "cpf" para que nossa ClientesModel seja:</p>
<pre class="language-php"><code>&lt;?php
namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class ClientesTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this-&gt;setTable('clientes');
        $this-&gt;setDisplayField('id');
        $this-&gt;setPrimaryKey('id');
    }

    public function validationDefault(Validator $validator)
    {
        $validator
            -&gt;integer('id')
            -&gt;allowEmptyString('id', 'create');

        $validator
            -&gt;scalar('nome')
            -&gt;maxLength('nome', 45)
            -&gt;requirePresence('nome', 'create')
            -&gt;allowEmptyString('nome', false);

        $validator
            -&gt;email('email')
            -&gt;requirePresence('email', 'create')
            -&gt;allowEmptyString('email', false);

        $validator
            -&gt;date('data_nasc')
            -&gt;requirePresence('data_nasc', 'create')
            -&gt;allowEmptyDate('data_nasc', false);

        $validator
            -&gt;scalar('cpf')
            -&gt;maxLength('cpf', 11)
            -&gt;requirePresence('cpf', 'create')
            -&gt;allowEmptyString('cpf', false);

       $validator
            -&gt;add('cpf','custom',
                ['rule'=&gt;
                    function($cpf)
                    {   
                         // Verifica se um número foi informado
                        if(empty($cpf)) {
                            return false;
                        }
                     
                        // Elimina possivel mascara
                        $cpf = preg_replace('[^0-9]', '', $cpf);
                        $cpf = str_pad($cpf, 11, '0', STR_PAD_LEFT);
                         
                        // Verifica se o numero de digitos informados é igual a 11 
                        if (strlen($cpf) != 11) {
                            return false;
                        }
                        // Verifica se nenhuma das sequências invalidas abaixo foi digitada
                        else if ($cpf == '00000000000' || 
                            $cpf == '11111111111' || 
                            $cpf == '22222222222' || 
                            $cpf == '33333333333' || 
                            $cpf == '44444444444' || 
                            $cpf == '55555555555' || 
                            $cpf == '66666666666' || 
                            $cpf == '77777777777' || 
                            $cpf == '88888888888' || 
                            $cpf == '99999999999') {
                            return false;
                         // Calcula os digitos verificadores para verificar se o cpf é valido
                         } else {   
                             
                            for ($t = 9; $t &lt; 11; $t++) {
                                 
                                for ($d = 0, $c = 0; $c &lt; $t; $c++) {
                                    $d += $cpf{$c} * (($t + 1) - $c);
                                }
                                $d = ((10 * $d) % 11) % 10;
                                if ($cpf{$c} != $d) {
                                    return false;
                                }
                            }
                     
                            return true;
                        }                        
                    },
                    // Caso retorne falso ele vai retornar uma mensagem falando que é inválido
                    'message'=&gt;'=== CPF INVÁLIDO ==='
                ]); 
        return $validator;
    }

    public function buildRules(RulesChecker $rules)
    {
        $rules-&gt;add($rules-&gt;isUnique(['email']));
        return $rules;
    }
}</code></pre>
<p align="left"><strong>Customizando as mensagens de erro do Cake</strong></p>
<p align="left">Caso ache necessário pode customizar o design das mensagens de erro.</p>
<p align="left">Edite o arquivo:</p>
<p align="left">webroot/css/style.css</p>
<p align="left">E altere o código de do seletor .form .error-message para este:</p>
<p align="left">.form .error-message {</p>
<p align="left">display: block;</p>
<p align="left">padding: 0.375rem 0.5625rem 0.5625rem;</p>
<p align="left">margin-top: -1px;</p>
<p align="left">margin-bottom: 1rem;</p>
<p align="left">font-size: 1rem;</p>
<p align="left">font-weight: normal;</p>
<p align="left">font-style: italic;</p>
<p align="left">color: #FF0000;</p>
<p align="left">}</p>
<p align="left"> </p>
<p align="left"><strong>Outras Validações Customizadas</strong></p>
<pre class="language-php"><code>$validator-&gt;add('nascimento',[
	        'notEmptyCheck'=&gt;[
    		    'rule'=&gt;[$this,'notEmptyNascimento'],
    		    'provider'=&gt;'table',
    		    'message'=&gt;'Favor selecionar uma data de nascimento'
    		 ]
         ]);

        return $validator;
    }

    public function notEmptyNascimento($value,$context){
        if(empty($context['data']['nascimento'])) {
            return false;
        } else {
            return true;
        }
    }</code></pre>
<p><strong>Validação nos Forms</strong></p>
<p>Para tirar proveito dos recursos de validação do Cake, você vai precisar usar o Form helper em suas views para criar formulários e nunca criar diretamente código HTML. O <a href="https://book.cakephp.org/3.0/pt/views/helpers/form.html#Cake%5CView%5CHelper%5CFormHelper">Cake\View\Helper\FormHelper</a> está disponível por padrão em todas as views pelo uso do $this-&gt;Form.</p>
<p>Basta usar $this-&gt;Form-&gt;...</p>
<p> </p>
<p align="left"><strong>Cuidados com o banco de dados</strong></p>
<p align="left">Uma preocupação com a segurança deve levar a um cuidado com a criação das tabelas no banco de dados com vários detalhes:</p>
<p align="left">- Relacionamentos sempre que for importante</p>
<p align="left">- Tipo de dados de cada campo selecionado com critério</p>
<p align="left">- Tamanho dos campos</p>
<p align="left">- Quantidade de campos</p>
<p align="left">- Constraints de cada campo</p>
<p align="left"> </p>
<p align="left"><strong>Criando nossas próprias regras de validação</strong></p>
<p align="left">O sistema de validação do Cake é rico e flexível e ainda permite que criemos nossas próprias regras de validação. Uma forma simples é usando Expressões Regulares.</p>
<p align="left">Desde que estejamos usando o método Cake\View\Helper\FormHelper::control() do FormHelper para criar os elementos do form, nossas mensagens de erro de validação serão mostradas automaticamente.</p>
<p align="left">Para tirar proveito dos recursos de validação do Cake, você vai precisar usar o Form helper em suas views.</p>
<p align="left"> </p>
<p align="left"><strong>Validações Customizadas</strong></p>
<p align="left"> </p>
<p align="left">Validação de senha:</p>
<pre class="language-php"><code>/**
     * Checks password for a single instance of each:
     * number, uppercase, lowercase, and special character
     *
     * @param type $password
     * @param array $context
     * @return boolean
     */
    public function checkCharacters($password, array $context)
    {
        // number
        if (!preg_match("#[0-9]#", $password)) {
            return false;
        }
        // Uppercase
        if (!preg_match("#[A-Z]#", $password)) {
            return false;
        }
        // lowercase
        if (!preg_match("#[a-z]#", $password)) {
            return false;
        }
        // special characters
        if (!preg_match("#\W+#", $password) ) {
            return false;
        }
        return true;
    }
        $validator
            -&gt;requirePresence('password', 'create')
            -&gt;notEmpty('password', 'You must enter a password', 'create')
                -&gt;add('password', [
                    'length' =&gt; [
                    'rule' =&gt; ['minLength', 8],
                    'message' =&gt; 'Passwords must be at least 8 characters long.',
                ]
            ])
            -&gt;add('password', 'custom', [
                'rule' =&gt; [$this, 'checkCharacters'],
                'message' =&gt; 'The password must contain 1 number, 1 uppercase, 1 lowercase, and 1 special character'
            ]);</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Validação Condicional</b></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"> </p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;">Baseado no Entity</span></span></p>
<pre class="language-php"><code>$rules-&gt;add(function ($entity, $options) use($rules) {
    if ($entity-&gt;role == 'admin') {
        $rule = $rules-&gt;existsIn('user_id', 'Admins');

        return $rule($entity, $options);
    }
    if ($entity-&gt;role == 'user') {
        $rule = $rules-&gt;existsIn('user_id', 'Users');

        return $rule($entity, $options);
    }

    return false;
}, 'userExists');</code></pre>
<p style="margin-bottom: 0cm; font-style: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><b>Detalhes em</b></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><a href="https://book.cakephp.org/3.0/en/orm/validation.html">https://book.cakephp.org/3.0/en/orm/validation.html</a></span></span></p>
<p style="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%;" align="left"><span style="font-family: Times New Roman, serif;"><span style="font-size: medium;"><a href="https://book.cakephp.org/3.0/pt/orm/validation.html">https://book.cakephp.org/3.0/pt/orm/validation.html</a></span></span></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 22:12:23 -0300</pubDate>
		</item>
		<item>
			<title>8 - Detalhes sobre Models</title>
			<link>http://backup/portal/curriculo/livros/cakephp/8-detalhes-sobre-models.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/8-detalhes-sobre-models.html</guid>
			<description><![CDATA[<h3>8 – Detalhes sobre Models</h3>
<p align="left"> </p>
<p align="right"><em><strong>Nas adversidades, uns desistem, enquanto outros batem recordes.</strong></em></p>
<p align="right">Ayrton Senna</p>
<p align="left"> </p>
<p><strong>O Model representa a primeira letra do MVC.</strong></p>
<p align="justify">Models (Modelos) são as classes que servem como camada de negócio na sua aplicação. Isso significa que eles devem ser responsáveis pela gestão de quase tudo o que acontece em relação a seus dados, sua validade, interações e evolução do fluxo de trabalho de informação no domínio do trabalho.</p>
<p align="justify">No CakePHP seu modelo de domínio da aplicação é dividido em 2 tipos de objetos principais. Os primeiros são repositories (repositórios) ou table objects (objetos de tabela). Estes objetos fornecem acesso a coleções de dados. Eles permitem a você salvar novos registros, modificar/deletar os que já existem, definir relacionamentos, e executar operações em massa. O segundo tipo de objetos são as entities (entidades). Entities representam registros individuais e permitem a você definir comportamento em nível de linha/registro e funcionalidades.</p>
<p align="justify"><strong>O ORM (MOR - Mapeamento Objeto-Relacional)</strong> nativo do CakePHP especializa-se em banco de dados relacionais, mas pode ser extendido para suportar fontes de dados alternativas.</p>
<p align="justify">O ORM do Cakephp toma emprestadas ideias e conceitos dos padrões ActiveRecord e Datamapper. Isso permite criar uma implementação híbrida que combina aspectos de ambos padrões para criar uma ORM rápida e simples de utilizar.</p>
<p align="justify">Objetos Table são usados para ser interface para coleções de objetos, ou seja, tabelas. O objeto Entity provê uma interface para um objeto individual, ou seja registros.</p>
<p> </p>
<p><strong>Atributos do Model</strong></p>
<p>Indicar nome de configuração do database</p>
<p>public $useDbConfig = 'alternate';</p>
<p> </p>
<p><strong>Prefixo das Tabelas</strong></p>
<p>public $tablePrefix = 'alternate_';</p>
<p> </p>
<p><strong>Nome do campo Primary Key</strong></p>
<p>public $primaryKey = 'example_id';</p>
<p> </p>
<p><strong>Display field</strong></p>
<p>Nomes de campos em tabelas para tabelas relacionadas</p>
<p>Convenção: title ou name</p>
<p>Se diferente indicar no model com:</p>
<p>public $displayField = 'nomedocampo';</p>
<p> </p>
<p><strong>Tabela Default</strong></p>
<p>public $useTable = 'users';</p>
<p>Caso receba a mensagem:</p>
<p>Erro: Table useres for model User was not found in datasource default.</p>
<p>Isso aconteceu comigo sempre que instalei o o plugin Cakept_br.</p>
<p> </p>
<p>Adicione a variável $use/Table contendo o nome da tabela ao model User</p>
<p>public $useTable = 'usuarios';</p>
<p> </p>
<p><strong>Método _setPassword()</strong> - este método cria um hash da senha do usuário antes que seja salva e antes que seja validada.</p>
<p> </p>
<p><strong>Lógica de negócios</strong></p>
<p>A codificação mostrada abaixo, neste capítulo, sobre os models e o ORM, que é o padrão que o CakePHP usa para lidar com bancos de dados, é muito importante para codificar a lógica de negócios de muitos aplicativos. As operações de CRUD, que são as mais básicas, podemos criar usando o bake, mas a lógica específica de alguns aplicativos somos nós que precisaremos criar. Então devemos criá-la no model, para que esteja disponível nos controllers e possa ser solicitada pelas views.</p>
<p>Um exemplo deste tipo de lógica é a usada no aplicativo de exemplo Finanças, no capítulo 13.5, onde temos que retornar a soma das despesas de um certo mês, somar as receitas do mesmo mês e devolver ambas e também o saldo. O bake não faz isso, somente faz as operações básicas de CRUD, somos nós que devemos fazer manualmente e sempre irá depender de cada aplicativo como faremos isso. Por isso é muito importante conhecer como o CakePHP lida com model, controller, view e cia além do CRUD. Me parece que o pontapé inicial recomendado é seguir os tutoriais de criação de aplicativos existentes no site oficial. Depois ir em frente devorando a documentação e todo o material deste livro foi elaborado para colaborar com esta empreitada.</p>
<p><strong>Detalhes</strong></p>
<p><a href="https://book.cakephp.org/3.0/en/orm.html">https://book.cakephp.org/3.0/en/orm.html</a></p>
<h1 class="western"> </h1>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 22:02:08 -0300</pubDate>
		</item>
		<item>
			<title>7 - Debug e Erros</title>
			<link>http://backup/portal/curriculo/livros/cakephp/7-debug-e-erros.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/7-debug-e-erros.html</guid>
			<description><![CDATA[<h3>7 – Debug e Erros</h3>
<p align="right"><em><strong>Só existe uma maneira de evitar críticas: não fazer nada, não dizer nada e não ser nada.</strong></em></p>
<p align="right">Aristóteles</p>
<p><strong>Debug/Depuração</strong></p>
<p align="justify">Depuração é uma etapa inevitável e importante de qualquer ciclo de desenvolvimento. Ainda que o CakePHP não forneça nenhuma ferramenta que se conecte com qualquer IDE ou editor de texto, este oferece várias ferramentas que auxiliam na depuração e exibição de tudo que está sendo executado "por baixo dos panos" na sua aplicação.</p>
<p> </p>
<p><strong>Depuração Básica</strong></p>
<p>Você pode usar as funções <a href="https://book.cakephp.org/3.0/pt/core-libraries/global-constants-and-functions.html#pr">pr()</a> ou <a href="https://book.cakephp.org/3.0/pt/core-libraries/global-constants-and-functions.html#debug">debug()</a> caso queira verificar erros em código ou apenas verificá-los.</p>
<p>debug(mixed $var, boolean $showHtml = null, $showFrom = true)</p>
<p> </p>
<p align="justify">A função debug() é uma função de escopo global que funciona de maneira similar a função do PHP, print_r(). A função debug() exibe os conteúdos de uma variável de diversas maneiras. Primeiramente, se você deseja exibir os dados no formato HTML, defina o segundo parâmetro como true. A função também exibe a linha e o arquivo de onde a mesma foi chamada.</p>
<p>A saída da função somente é exibida caso a variável $debug do core esteja definida com o valor true.</p>
<p>debug($query) Mostra o SQL e os parâmetros incluídos, não mostra resultados.</p>
<p>debug($query-&gt;all()) Mostra a propriedade ResultSet retornado pelo ORM.</p>
<p>debug($query-&gt;toArray()) Um caminho mais fácil para mostrar todos os resultados.</p>
<p>debug(json_encode($query, JSON_PRETTY_PRINT)) Exemplo em JSON.</p>
<p>debug($query-&gt;first()) Primeiro resultado obtido na query.</p>
<p>debug((string)$query-&gt;first()) Mostra as propriedades de uma única entidade em JSON.</p>
<p> </p>
<p>Tente isto na camada Controller: debug( $this-&gt;{EntidadeNome}-&gt;find()-&gt;all() );</p>
<p> </p>
<p><strong>Tratando erros</strong></p>
<p>Cada SGBD tem seus próprios códigos de erro que podem ser capturados pelo PDO.</p>
<p> </p>
<p><strong>Dicas sobre erros no PDO no Cake</strong></p>
<p>Criar o arquivo src/Template/Error/pdo_error.ctp, contendo</p>
<p> </p>
<pre class="language-php"><code>&lt;?php
use Cake\Utility\Debugger;
?&gt;

&lt;h2&gt;Erro no Cadastro&lt;/h2&gt;
&lt;p class="error"&gt;
&lt;strong&gt;Erro: Grupo não existe na tabela estrangeira&lt;br&gt;&lt;/strong&gt;

&lt;?php
if($error-&gt;getCode() == 23503){
print "Este grupo não existe na tabela estrangeira.&lt;br&gt;Caso tenha realmente digitado de forma correta&lt;br&gt;e queira adicionar cadastre-o na tabela estrangeira&lt;br&gt;primeiro e depois cadastre o material com ele!";
}

//print $message;
?&gt;
&lt;/p&gt;</code></pre>
<p> </p>
<p>Tratamento de erro é uma missão nobre em aplicativos.</p>
<p align="justify">Aplicativos onde o programador prevê erros em todas as situações onde ele imagina que pode haver erro são aplicativos mais robustos. Os softwares de teste como o PHPUnit tem a missão de ajudar com isso.</p>
<p align="left"> </p>
<p align="left"><strong>Detalhes</strong></p>
<p align="left"><a href="https://book.cakephp.org/3.0/en/development/debugging.html">https://book.cakephp.org/3.0/en/development/debugging.html</a></p>
<p align="left"> </p>
<h1 class="western"> </h1>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 21:59:32 -0300</pubDate>
		</item>
		<item>
			<title>6 - Segurança</title>
			<link>http://backup/portal/curriculo/livros/cakephp/6-seguranca.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/6-seguranca.html</guid>
			<description><![CDATA[<h3>6 – Segurança</h3>
<p align="left"> </p>
<p align="right"><em><strong>Eu não falhei. Apenas descobri mil maneiras que não funcionam.</strong></em></p>
<p align="right">Thomas Edison</p>
<p><strong>Usando o Componente Security</strong></p>
<p align="justify">O uso do componente Security geralmente é feito no método beforeFilter() dos Controllers.</p>
<p> </p>
<p>Apenas descomente no initialize() do AppController.php, veja.</p>
<p> </p>
<pre class="language-php"><code>public function initialize()
{
parent::initialize();

$this-&gt;loadComponent('RequestHandler', [
'enableBeforeRedirect' =&gt; false,
]);
$this-&gt;loadComponent('Flash');

/*
* Enable the following component for recommended CakePHP security settings.
* see https://book.cakephp.org/3.0/en/controllers/components/security.html
*/
$this-&gt;loadComponent('Security'); // DESCOMENTAR ESTA LINHA
}</code></pre>
<p align="justify"> </p>
<p><strong>Validações</strong></p>
<p>Para que as validações do Cake surtam efeito precisamos criar nossos forms usando o formHelper.</p>
<p> </p>
<p><strong>Salt</strong></p>
<p>Há alguns outros itens que podem ser configurados. Muitos desenvolvedores completam esta lista de itens, mas os mesmos não são obrigatórios para este tutorial. Um deles é definir uma sequência personalizada (ou “salt”) para uso em hashes de segurança.</p>
<p>A sequência personalizada (ou salt) é utilizada para gerar hashes de segurança. Se você utilizou o Composer, ele cuidou disso para você durante a instalação. Apesar disso, você precisa alterar a sequência personalizada padrão editando o arquivo config/app.php. Não importa qual será o novo valor, somente deverá ser algo difícil de descobrir:</p>
<pre>'Security' =&gt; [
    'salt' =&gt; 'valor longo contendo mistura aleatória de valores.',
],
Quando instalamos o Cake usando o composer, o composer já cuida disso e de outras tarefas para nós.</pre>
<p> </p>
<p><strong>Componente CSRF</strong></p>
<p>Cross Site Request Forgery</p>
<p>Ao habilitar o componente CSRF você obtém proteção contra ataques. <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF</a> ou Cross Site Request Forgery (Falsificação de solicitação entre sites) é uma vulnerabilidade comum nas aplicações web. Esta brecha permite que o atacante capture e responda uma requisição, e as vezes envie dados através de uma requisição usando tags de imagem ou recursos em outros domínios.</p>
<p>O CsrfComponent trabalha setando um cookie no navegador do usuário. Quando os formulários são criados com o <a href="https://book.cakephp.org/3.0/pt/views/helpers/form.html#Cake%5CView%5CHelper%5CFormHelper">Cake\View\Helper\FormHelper</a>, um input hidden é adicionado contendo o token CSRF. Durante o evento Controller.startup, se a requisição for POST, PUT, DELETE ou PATCH o componente irá comparar os dados da requisição e o valor do cookie. Se um deles estiver faltando ou os dois valores forem imcompatíveis o componente lançará um Cake\Network\Exception\InvalidCsrfTokenException.</p>
<p>Por default o componente CSRF vem habilitado no routes.php.</p>
<p> </p>
<p><strong>Mais detalhes</strong></p>
<p><a href="http://book.cakephp.org/3.0/en/controllers/components/security.html">http://book.cakephp.org/3.0/en/controllers/components/security.html</a></p>
<p><a href="http://book.cakephp.org/3.0/en/core-libraries/security.html">http://book.cakephp.org/3.0/en/core-libraries/security.html</a></p>
<p><a href="http://book.cakephp.org/3.0/en/controllers/components/csrf.html">http://book.cakephp.org/3.0/en/controllers/components/csrf.html</a></p>
<p align="left"> </p>
<p align="left"> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 21:56:38 -0300</pubDate>
		</item>
		<item>
			<title>5.1 - Uso dos templates do bake no CakePHP 3</title>
			<link>http://backup/portal/curriculo/livros/cakephp/5-1-uso-dos-templates-do-bake-no-cakephp-3.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/5-1-uso-dos-templates-do-bake-no-cakephp-3.html</guid>
			<description><![CDATA[<h3>5.1 - Uso dos templates do bake no CakePHP 3</h3>
<p style="margin-bottom: 0cm; line-height: 100%;" align="right"> </p>
<p style="margin-bottom: 0cm; line-height: 100%;" align="right"><i><b>A causa da derrota, não está nos obstáculos, ou no rigor das circunstâncias, está na falta de determinação e desistência da própria pessoa. </b></i><span style="font-style: normal;"><span style="font-weight: normal;">(Buda)</span></span></p>
<p> </p>
<p><strong>Na pasta dos fontes do CakePHP 3 temos:</strong></p>
<p>vendor/cakephp/bake/src/Template/Bake</p>
<p>vendor/cakephp/bake/src/Template/Bake/Element</p>
<p>vendor/cakephp/bake/src/Template/Bake/Form</p>
<p>vendor/cakephp/bake/src/Template/Bake/Controller</p>
<p>vendor/cakephp/bake/src/Template/Bake/Model</p>
<p>Entre outras pastas.</p>
<p> </p>
<p>Desde a versão 0.1.0 usa-se as tags do ASP no template do bake do CakePHP, que ainda são aceitas na versão 3, mas com previsão de serem removidas na versão 4:</p>
<p>• &lt;% A Bake template php open tag</p>
<p>• %&gt; A Bake template php close tag</p>
<p>• &lt;%= A Bake template php short-echo tag</p>
<p>• &lt;%- A Bake template php open tag, stripping any leading whitespace before the tag</p>
<p>• -%&gt; A Bake template php close tag, stripping trailing whitespace after the tag</p>
<p> </p>
<p><strong>Adiconar também login e logout na geração de código com o Bake.</strong></p>
<p>Para isso mude o arquivo config/bootstrap_cli.php</p>
<p>E deixe assim:</p>
<pre class="language-php"><code>&lt;?php

use Cake\Core\Configure;
use Cake\Core\Exception\MissingPluginException;
use Cake\Event\Event;
use Cake\Event\EventManager;

Configure::write('Log.debug.file', 'cli-debug');
Configure::write('Log.error.file', 'cli-error');

try {
    $this-&gt;addPlugin('Bake');
} catch (MissingPluginException $e) {
// Do not halt if the plugin is missing
}

EventManager::instance()-&gt;on(
    'Bake.beforeRender.Controller.controller',
    function (Event $event) {
        $view = $event-&gt;subject();
        if ($view-&gt;viewVars['name'] == 'Users') {
// add the login and logout actions to the Users controller
            $view-&gt;viewVars['actions'] = [
                'login',
                'logout',
                'index',
                'view',
                'add',
                'edit',
                'delete',
            ];
        }
    }
);
$this-&gt;addPlugin('Migrations');
</code></pre>
<p> </p>
<p>Agora, ao gerar código com o bake assim:</p>
<p>bin/cake bake all users</p>
<p>Ele gerará também os actions login() e logout() e também o template login.ctp</p>
<p> </p>
<p>O Bake usa em seus templates atualmente, na versão 3.7.8, a sintaxe do twig, inclusive seus arquivos tem extensão twig.</p>
<p>Veja por exemplo, parte do código do arquivo vendor/cakephp/bake/src/Template/Bake/Element/form.twig abaixo:</p>
<p> </p>
<pre class="language-php"><code>{% set fields = Bake.filterFields(fields, schema, modelObject) %}
&lt;nav class="large-3 medium-4 columns" id="actions-sidebar"&gt;
&lt;ul class="side-nav"&gt;
&lt;li class="heading"&gt;&lt;?= __('Actions') ?&gt;&lt;/li&gt;
{% if strpos(action, 'add') is same as(false) %}
&lt;li&gt;&lt;?= $this-&gt;Form-&gt;postLink(
__('Delete'),
['action' =&gt; 'delete', ${{ singularVar }}-&gt;{{ primaryKey[0] }}],
['confirm' =&gt; __('Are you sure you want to delete # {0}?', ${{ singularVar }}-&gt;{{ primaryKey[0] }})]
)
?&gt;&lt;/li&gt;
{% endif %}
&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('List {{ pluralHumanName }}'), ['action' =&gt; 'index']) ?&gt;&lt;/li&gt;
{{- "\n" }}</code></pre>
<p> </p>
<p><strong>A versão atual (3.7.8) ainda aceita a sintaxe abaixo:</strong></p>
<p>• &lt;% A Bake template php open tag</p>
<p>• %&gt; A Bake template php close tag</p>
<p>• &lt;%= A Bake template php short-echo tag</p>
<p>• &lt;%- A Bake template php open tag, stripping any leading whitespace before the tag</p>
<p>• -%&gt; A Bake template php close tag, stripping trailing whitespace after the tag</p>
<p><strong>Com estes a extensão deve ser .ctp</strong></p>
<p> </p>
<p><strong>A partir da versão 2.0.0 do Cake a sintaxe passou a usar Twig, inclusive na extensão dos arquivos:</strong></p>
<p>• {% A Bake template php open tag</p>
<p>• %} A Bake template php close tag</p>
<p>• {%= A Bake template php short-echo tag</p>
<p>• {%- A Bake template php open tag, stripping any leading whitespace before the tag</p>
<p>• -%} A Bake template php close tag, stripping trailing whitespace after the tag</p>
<p> </p>
<p><strong>Usa também para as seções de comentários:</strong></p>
<p>{#</p>
<p>e</p>
<p>#}</p>
<p> </p>
<p><strong>Agora veja o arquivo form.ctp usado no plugin ribafs/admin-br em sua versão 1.8</strong>, onde adicionei suporte para o Bootstrap 3:</p>
<pre class="language-php"><code>&lt;%
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* Slightly modified by Òscar Casajuana for the twbs-cake-plugin
* also under the MIT license.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 0.1.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use Cake\Utility\Inflector;

$fields = collection($fields)-&gt;filter(function($field) use ($schema) {
return $schema-&gt;columnType($field) !== 'binary';
});

$pk = "\${$singularVar}-&gt;{$primaryKey[0]}";
%&gt;

&lt;div class="container"&gt;
&lt;div class="actions columns col-lg-2 col-md-3"&gt;
&lt;h3&gt;&lt;?= __('Ações') ?&gt;&lt;/h3&gt;
&lt;ul class="nav nav-stacked nav-pills"&gt;
&lt;% if (strpos($action, 'add') === false): %&gt;
&lt;li class="active disabled"&gt;&lt;?= $this-&gt;Html-&gt;link(__('Editar &lt;%= $singularHumanName %&gt;'), ['action' =&gt; 'edit', &lt;%= $pk %&gt;]) ?&gt; &lt;/li&gt;
&lt;li&gt;&lt;?= $this-&gt;Form-&gt;postLink(__('Excluir'),['action' =&gt; 'delete', &lt;%= $pk %&gt;],['confirm' =&gt; __('Deseja realmente excluir # {0}?', $&lt;%= $singularVar %&gt;-&gt;&lt;%= $primaryKey[0] %&gt;), 'class' =&gt; 'btn-danger'])
?&gt;&lt;/li&gt;
&lt;li&gt;&lt;?= $this-&gt;Html-&gt;link(__('Novo(a) &lt;%= $singularHumanName %&gt;'), ['action' =&gt; 'add']) ?&gt;&lt;/li&gt;</code></pre>
<p> </p>
<p>Dica - Quando eu estava alterando uma view gerada pelo bake original para uso com Bootstrap, troquei uma tag inicial &lt;nav&gt; por &lt;div&gt; mas esqueci de trocar a tag &lt;/nav&gt; final então ao visualizar pelo navegador a view apareceu em apenas uma coluna. Então devemos ficar bem atentos quando alterarmos o código de um template do bake. Um detalhe importante é que a sintaxe do twig pode ser detectada pelo VSCode ao instalar a extensão abaixo:</p>
<p>vscode-twig</p>
<p> </p>
<p>Isso já ajuda, pois o VSCode já mostra o código colorido, separado em seções e até autocompleta o código e não mais todo em cinza.</p>
<p>Veja o início do form.ctp do tempalte do bake no plugin:</p>
<p><a href="https://github.com/elboletaire/twbs-cake-plugin">https://github.com/elboletaire/twbs-cake-plugin</a></p>
<p> </p>
<p><strong>Agora vejamos como vem o template do bake na versão atual (3.7.8) do Cake:</strong></p>
<p>vendor/cake/php/bake/src/Template/Bake/Element/form.twig</p>
<pre class="language-php"><code>{#
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 2.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#}
{% set fields = Bake.filterFields(fields, schema, modelObject) %}
&lt;nav class="large-3 medium-4 columns" id="actions-sidebar"&gt;
&lt;ul class="side-nav"&gt;
&lt;li class="heading"&gt;&lt;?= __('Actions') ?&gt;&lt;/li&gt;
{% if strpos(action, 'add') is same as(false) %}</code></pre>
<p> </p>
<p>Veja que a extensão é twig e a sintaxe não mais usa as tags ASP, mas a sintaxe do twig.</p>
<p>Então, se queremos criar um template para o bake que será suportado pela versão 4 do Cake, não devemos usar as tags do ASP mas as do twig.</p>
<p> </p>
<p><strong>Customizar o template do bake do CakePHP 3 para usar o Twitter BootStrap.</strong></p>
<p>Idealmente não devemos alterar o core do Cake. Para isso é importante criar plugins, helpers, componentes, behaviors, etc. Mas para facilitar e apenas exemplificar iremos alterar o core e ao final indicarei um plugin que foi criado para esta finalidade.</p>
<p> </p>
<p>Minha fonte de consulta para a documentação do BootStrap 4 é o:</p>
<p><a href="https://www.w3schools.com/bootstrap4/default.asp">https://www.w3schools.com/bootstrap4/default.asp</a></p>
<p> </p>
<p><strong>Vou criar o aplicativo financas</strong></p>
<p>Com o banco financas e duas tabelas despesas e receitas</p>
<p>Configurar a rota default para Despesas/index para facilitar o acesso</p>
<p>Após configurar o banco gerar o código com o template default do bake:</p>
<p>bin/cake bake all despesas</p>
<p>bin/cake bake all receitas</p>
<p> </p>
<p>Visualizar pelo navegador</p>
<p><a href="http://localhost/financas">http://localhost/financas</a></p>
<p>Deixe esta aba do navegador aberta e vamos customizar o template default.</p>
<p>Para facilitar, primeiro vamoms customizar o template das views geradas e depois customizaremos o templae do bake.</p>
<p> </p>
<p><strong>Comecemos por baixar o BootStrap 4:</strong></p>
<p><a href="https://getbootstrap.com/docs/4.3/getting-started/download/">https://getbootstrap.com/docs/4.3/getting-started/download/</a></p>
<p>Após descompactar copiamos os arquivos:</p>
<p>bootstrap-reboot.min.css</p>
<p>bootstrap.min.css</p>
<p>bootstrap-grid.min.css</p>
<p> </p>
<p><strong>Para webroot/css</strong></p>
<p>Manterei o CSS default e adicionarei o do BootStrap abaixo para que tenha prioridade.</p>
<p>E alteramos o <strong>src/Template/Layout/default.ctp</strong> para que fique assim:</p>
<pre class="language-php"><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;?=$this-&gt;Html-&gt;charset()?&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;CakePHP 3 com BootStrap 4&lt;/title&gt;
&lt;?=$this-&gt;Html-&gt;meta('icon')?&gt;

&lt;?=$this-&gt;Html-&gt;css('base.css')?&gt;
&lt;?=$this-&gt;Html-&gt;css('style.css')?&gt;
&lt;?=$this-&gt;Html-&gt;css('bootstrap-reboot.css')?&gt;
&lt;?=$this-&gt;Html-&gt;css('bootstrap.min.css')?&gt;
&lt;?=$this-&gt;Html-&gt;css('bootstrap-grid.min.css')?&gt;

&lt;?=$this-&gt;fetch('meta')?&gt;
&lt;?=$this-&gt;fetch('css')?&gt;
&lt;?=$this-&gt;fetch('script')?&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;nav class="top-bar expanded" data-topbar role="navigation"&gt;
    &lt;ul class="title-area col-md-d columns"&gt;
        &lt;li class="name"&gt;
        &lt;h1&gt;&lt;a href="http://backup/portal/"&gt;CakePHP 3 com BootStrap 4&lt;/a&gt;&lt;/h1&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
&lt;/nav&gt;
&lt;?=$this-&gt;Flash-&gt;render()?&gt;
&lt;div class="container clearfix"&gt;
&lt;?=$this-&gt;fetch('content')?&gt;
&lt;/div&gt;
&lt;footer&gt;
&lt;/footer&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p> </p>
<p><strong>Alterar src/Template/Despesas/index.ctp</strong></p>
<p>Vamos por partes. Primeiro o sidebar:</p>
<p>&lt;nav class="large-3 medium-4 columns" id="actions-sidebar"&gt;</p>
<p>&lt;ul class="side-nav"&gt;</p>
<p>&lt;li class="heading"&gt;&lt;?= __('Actions') ?&gt;&lt;/li&gt;</p>
<p> </p>
<p><strong>Troquemos por:</strong></p>
<p>&lt;div class="actions columns col-lg-2 col-md-3"&gt;</p>
<p>&lt;h3&gt;&lt;?= __('Actions') ?&gt;&lt;/h3&gt;</p>
<p>&lt;ul class="nav nav-stacked nav-pills"&gt;</p>
<p> </p>
<p><strong>Ao final o index.ctp de Despesas usando o Botstrap ficará assim:</strong></p>
<p> </p>
<pre class="language-php"><code>&lt;div class="actions columns col-lg-2 col-md-3"&gt;
&lt;h3&gt;&lt;?=__('Actions')?&gt;&lt;/h3&gt;
&lt;ul class="nav nav-stacked nav-pills"&gt;
&lt;li&gt;&lt;?=$this-&gt;Html-&gt;link(__('New Despesa'), ['action' =&gt; 'add'])?&gt;&lt;/li&gt;
&lt;li&gt;&lt;?=$this-&gt;Html-&gt;link(__('List Receitas'), ['controller' =&gt; 'Receitas', 'action' =&gt; 'index'])?&gt;&lt;/li&gt;
&lt;li&gt;&lt;?=$this-&gt;Html-&gt;link(__('New Receita'), ['controller' =&gt; 'Receitas', 'action' =&gt; 'add'])?&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="despesas index col-lg-10 col-md-9 columns"&gt;
&lt;h3&gt;&lt;?=__('Despesas')?&gt;&lt;/h3&gt;
&lt;table class="table table-hover table-stripped"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope="col"&gt;&lt;?=$this-&gt;Paginator-&gt;sort('id')?&gt;&lt;/th&gt;
&lt;th scope="col"&gt;&lt;?=$this-&gt;Paginator-&gt;sort('descricao')?&gt;&lt;/th&gt;
&lt;th scope="col"&gt;&lt;?=$this-&gt;Paginator-&gt;sort('valor')?&gt;&lt;/th&gt;
&lt;th scope="col"&gt;&lt;?=$this-&gt;Paginator-&gt;sort('mes')?&gt;&lt;/th&gt;
&lt;th scope="col"&gt;&lt;?=$this-&gt;Paginator-&gt;sort('created')?&gt;&lt;/th&gt;
&lt;th scope="col"&gt;&lt;?=$this-&gt;Paginator-&gt;sort('modified')?&gt;&lt;/th&gt;
&lt;th scope="col"&gt;&lt;?=$this-&gt;Paginator-&gt;sort('receita_id')?&gt;&lt;/th&gt;
&lt;th scope="col" class="actions"&gt;&lt;?=__('Actions')?&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;?php foreach ($despesas as $despesa): ?&gt;
&lt;tr&gt;
&lt;td&gt;&lt;?=$this-&gt;Number-&gt;format($despesa-&gt;id)?&gt;&lt;/td&gt;
&lt;td&gt;&lt;?=h($despesa-&gt;descricao)?&gt;&lt;/td&gt;
&lt;td&gt;&lt;?=$this-&gt;Number-&gt;format($despesa-&gt;valor)?&gt;&lt;/td&gt;
&lt;td&gt;&lt;?=h($despesa-&gt;mes)?&gt;&lt;/td&gt;
&lt;td&gt;&lt;?=h($despesa-&gt;created)?&gt;&lt;/td&gt;
&lt;td&gt;&lt;?=h($despesa-&gt;modified)?&gt;&lt;/td&gt;
&lt;td&gt;&lt;?=$despesa-&gt;has('receita') ? $this-&gt;Html-&gt;link($despesa-&gt;receita-&gt;id, ['controller' =&gt; 'Receitas', 'action' =&gt; 'view', $despesa-&gt;receita-&gt;id]) : ''?&gt;&lt;/td&gt;
&lt;td class="actions"&gt;
&lt;?=$this-&gt;Html-&gt;link(__('View'), ['action' =&gt; 'view', $despesa-&gt;id])?&gt;
&lt;?=$this-&gt;Html-&gt;link(__('Edit'), ['action' =&gt; 'edit', $despesa-&gt;id])?&gt;
&lt;?=$this-&gt;Form-&gt;postLink(__('Del'), ['action' =&gt; 'delete', $despesa-&gt;id], ['confirm' =&gt; __('Are you sure you want to delete # {0}?', $despesa-&gt;id)])?&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;?php endforeach;?&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="paginator"&gt;
&lt;ul class="pagination"&gt;
&lt;?=$this-&gt;Paginator-&gt;first('&lt;&lt; ' . __('first'))?&gt;
&lt;?=$this-&gt;Paginator-&gt;prev('&lt; ' . __('previous'))?&gt;
&lt;?=$this-&gt;Paginator-&gt;numbers()?&gt;
&lt;?=$this-&gt;Paginator-&gt;next(__('next') . ' &gt;')?&gt;
&lt;?=$this-&gt;Paginator-&gt;last(__('last') . ' &gt;&gt;')?&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;?=$this-&gt;Paginator-&gt;counter(['format' =&gt; __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')])?&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</code></pre>
<p> </p>
<p>E assim procedi com as outras 3 views restantes até concluir.</p>
<p><strong>Crédito:</strong></p>
<p>As classes que estou usando do Bootstrap 4, as encontrei no plugin twbs-cake</p>
<p><a href="https://github.com/elboletaire/twbs-cake-plugin">https://github.com/elboletaire/twbs-cake-plugin</a>. Como este plugin é para o Bootstrap 3 eu converti algumas classes que mudaram para o Bootstrap 4 com ajuda do</p>
<p><a href="https://www.w3schools.com/bootstrap4/default.asp">https://www.w3schools.com/bootstrap4/default.asp</a></p>
<p> </p>
<p align="left"><strong>Detalhes</strong></p>
<p align="left">Plugin que usa o BootStrap 3 com CakePHP 3 e já com Twig:</p>
<p align="left"><a href="https://github.com/ribafs/admin-br">https://github.com/ribafs/admin-br</a></p>
<p align="left"> </p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 21:52:44 -0300</pubDate>
		</item>
		<item>
			<title>5 - Gerando Código com Bake</title>
			<link>http://backup/portal/curriculo/livros/cakephp/5-gerando-codigo-com-bake.html</link>
			<guid isPermaLink="true">http://backup/portal/curriculo/livros/cakephp/5-gerando-codigo-com-bake.html</guid>
			<description><![CDATA[<h3>5 - Gerando CRUD com Bake e muito mais</h3>
<p> </p>
<p align="right"><em><strong>Algumas pessoas querem que algo aconteça, outras desejam que aconteça, outras fazem acontecer.</strong></em></p>
<p align="right">Michael Jordan</p>
<p><a href="http://book.cakephp.org/3.0/en/bake.html">http://book.cakephp.org/3.0/en/bake.html</a></p>
<p align="justify">A console bake do CakePHP é um outro esforço para que você esteja rodando o CakePHP rapidamente. A console do bake pode criar qualquer um dos códigos básicos do CakePHP: models, behaviors, views, helpers, controllers, components, test cases, fixtures e plugins. E não estamos falando apenas de esqueletos de classes, o bake pode criar uma aplicação inteiramente funcional em poucos minutos.</p>
<p> </p>
<p><strong>Pré-requisitos</strong></p>
<p>A console do bake requer:</p>
<p>- PHP CLI</p>
<p>- extensão intl</p>
<p>- Pelo menos um SGBD instalado e configurado na aplicação atual</p>
<p align="left"> </p>
<p align="left"><strong>Executando o bake</strong></p>
<p align="left">cd /var/www/html/cliente</p>
<p align="left">bin/cake bake</p>
<p align="left"><strong>Mostrará:</strong></p>
<p align="left">The following commands can be used to generate skeleton code for your application.</p>
<p align="left">Available bake commands:</p>
<p align="left">- all</p>
<p align="left">- behavior</p>
<p align="left">- cell</p>
<p align="left">- command</p>
<p align="left">- component</p>
<p align="left">- controller</p>
<p align="left">- fixture</p>
<p align="left">- form</p>
<p align="left">- helper</p>
<p align="left">- mailer</p>
<p align="left">- middleware</p>
<p align="left">- migration</p>
<p align="left">- migration_diff</p>
<p align="left">- migration_snapshot</p>
<p align="left">- model</p>
<p align="left">- plugin</p>
<p align="left">- seed</p>
<p align="left">- shell</p>
<p align="left">- shell_helper</p>
<p align="left">- task</p>
<p align="left">- template</p>
<p align="left">- test</p>
<p align="left">- twig_template</p>
<p align="left">By using `cake bake [name]` you can invoke a specific bake task.</p>
<p align="left"> </p>
<p align="left"><strong>Obtendo ajuda para controllers com o bake</strong></p>
<p align="left">bin/cake bake controller --help</p>
<p align="left">Veja:</p>
<p align="left">bin/cake bake controller --help</p>
<p align="left">Bake a controller skeleton.</p>
<p align="left">Usage:</p>
<p align="left">cake bake controller [subcommand] [options] [&lt;name&gt;]</p>
<p align="left">Subcommands:</p>
<p align="left">all Bake all controllers with CRUD methods.</p>
<p align="left">To see help on a subcommand use `cake bake controller [subcommand] --help`</p>
<p align="left">Options:</p>
<p align="left">--actions The comma separated list of actions to generate. You</p>
<p align="left">can include custom methods provided by your template</p>
<p align="left">set here.</p>
<p align="left">--components The comma separated list of components to use.</p>
<p align="left">--connection, -c The datasource connection to get data from.</p>
<p align="left">(default: default)</p>
<p align="left">--force, -f Force overwriting existing files without prompting.</p>
<p align="left">--help, -h Display this help.</p>
<p align="left">--helpers The comma separated list of helpers to use.</p>
<p align="left">--no-actions Do not generate basic CRUD action methods.</p>
<p align="left">--no-test Do not generate a test skeleton.</p>
<p align="left">--plugin, -p Plugin to bake into.</p>
<p align="left">--prefix The namespace/routing prefix to use.</p>
<p align="left">--quiet, -q Enable quiet output.</p>
<p align="left">--theme, -t The theme to use when baking code. (choices:</p>
<p align="left">Bake|Migrations|WyriHaximus/TwigView)</p>
<p align="left">--verbose, -v Enable verbose output.</p>
<p align="left">Arguments:</p>
<p align="left">name Name of the controller to bake (without the `Controller` suffix).</p>
<p align="left">You can use Plugin.name to bake controllers into plugins.</p>
<p align="left"> </p>
<p align="left"><strong>Versatilidade do bake</strong></p>
<p align="left">Ajuda para plugins</p>
<p align="left">bin/cake bake plugin --help</p>
<p align="left"><strong>Gerar tudo para Clientes</strong> (controller, model, templates, etc)</p>
<p align="left">bin/cake bake all Clientes</p>
<p align="left"> </p>
<p align="left"><strong>Gerar novamente forçando</strong></p>
<p align="left">Caso já tenha gerado um código e queira gerar novamente evitando as perguntas para sobrescrever os arquivos gerados, use --force ou -f, assim:</p>
<p align="left">bin/cake bake all Clientes -f</p>
<p align="left"> </p>
<p><strong>Gerar um controller:</strong></p>
<p>bin/cake bake controller Clientes</p>
<p> </p>
<p><strong>Gerar controller sem actions:</strong></p>
<p>bin\cake bake controller --no-actions Clientes</p>
<p> </p>
<p><strong>Gerar Componente</strong></p>
<p>bin/cake bake component Calculo</p>
<p> </p>
<p><strong>Gerar um Template</strong></p>
<p>bin/cake bake template Clientes</p>
<p> </p>
<p><strong>Gerar Helper</strong></p>
<p>bin/cake bake helper MeuForm</p>
<p> </p>
<p><strong>Gerar Cell</strong></p>
<p>bin/cake bake cell MinhaCelula</p>
<p> </p>
<p><strong>Gerar Form</strong></p>
<p>bin/cake bake form MeuForm</p>
<p> </p>
<p><strong>Gerar um Model</strong></p>
<p>bin/cake bake model Clientes</p>
<p> </p>
<p><strong>Gerar Behavior</strong></p>
<p align="left">bin/cake bake behavior MeuBehavior</p>
<p align="left"> </p>
<p><strong>Gerar apenas controller, model e template</strong></p>
<p>bin/cake bake controller clientes</p>
<p>bin/cake bake model clientes</p>
<p>bin/cake bake template clientes index (somente a index)</p>
<p align="left"> </p>
<p><strong>Gerando plugin</strong></p>
<p>bin/cake bake all --plugin CakePtbr articles</p>
<p> </p>
<p><strong>Agora gerar o código completo para o plugin</strong></p>
<p>bin/cake bake all -p CakeAdmin groups</p>
<p>bin/cake bake all -p CakeAdmin users</p>
<p>bin/cake bake all -p CakeAdmin permissions</p>
<p>bin/cake bake all -p CakeAdmin customers</p>
<p> </p>
<p><strong>Criar plugin ContactManager com tabela contacts para o aplicativo cliente</strong></p>
<p>cd /var/www/html/cliente</p>
<p>bin/cake bake plugin ContactManager</p>
<p>bin/cake bake controller --plugin ContactManager Contacts</p>
<p>bin/cake bake migration CreateContacts title:string body:text created modified</p>
<p>bin/cake bake migration CreateGroups name:string created modified</p>
<p>bin/cake bake migration CreateUsers username:string password:string created modified</p>
<p>bin/cake migrations migrate</p>
<p>bin/cake bake model --plugin ContactManager Contacts</p>
<p>bin/cake bake template --plugin ContactManager Contacts</p>
<p> </p>
<p><strong>Estrutura de Arquivos do Plugin</strong></p>
<pre>/src
/plugins
    /ContactManager
        /config
        /src
            /Plugin.php
            /Controller
                /Component
            /Model
                /Table
                /Entity
                /Behavior
            /View
                /Helper
            /Template
                /Layout
        /tests
            /TestCase
            /Fixture
        /webroot</pre>
<p><strong>Regerando o autoloader</strong></p>
<p align="left">composer dump-autoload</p>
<p align="left"> </p>
<p align="left"><strong>Limpando o cache</strong></p>
<p align="left">composer clear-cache</p>
<p align="left"> </p>
<p align="left"><strong>Observação</strong></p>
<p>Existem alguns recursos que não são gerados ou auxiliados pelo bake, como o element.</p>
<p> </p>
<p><strong>Outros comandos</strong></p>
<p>bin/cake bake fixture groups</p>
<p>bin/cake bake test users</p>
<p> </p>
<p><strong>Garantir que não use cache:</strong></p>
<p>bin/cake bake model comments –force<br /> bin/cake bake model issues –force<br /> bin/cake orm_cache clear</p>
<p>Cache do ORM</p>
<p>Reconstruir o cache dos metadados de todas as tabelas da conexão default</p>
<p>bin/cake orm_cache build --connection default</p>
<p> </p>
<p><strong>Para reconstruir o cache dos metadados apenas da tabela artigos</strong></p>
<p>bin/cake orm_cache build --connection default artigos</p>
<p> </p>
<p><strong>Remover o cache de todos os metadados:</strong></p>
<p>bin/cake orm_cache clear</p>
<p> </p>
<p><strong>Remover o cache de todos os metadados da tabela aratigos</strong></p>
<p>bin/cake orm_cache clear artigos</p>
<p align="left"> </p>
<p><strong>Criando Model para o Plugin</strong></p>
<p>bin/cake bake model --plugin Admin Groups</p>
<p>bin/cake bake model --plugin Admin Users</p>
<p> </p>
<p><strong>Criando Templates para o Plugin</strong></p>
<p>bin/cake bake template --plugin Admin Groups</p>
<p>bin/cake bake template --plugin Admin Users</p>
<p> </p>
<p><strong>Criar somente a view login.ctp para o Plugin</strong></p>
<p>bin/cake bake template --plugin Admin Users login</p>
<p align="left"> </p>
<p><strong>Observação importante:</strong></p>
<p align="justify">Atualmente na versão 3, idealmente devemos criar plugins para a pasta vendor, que são hospedados num repositório público, como o GitHub e publicados num repositório do composer, como o Packagist. Assim podemos instalar e publicar o plugin pela linha de comando com o composer.</p>
<p align="left"> </p>
<p align="left"><strong>A oitava maravilha do mundo</strong></p>
<p align="left">Gosto de dizer que o bake é a oitava maravilha do mundo da programação web. Realmente me maravilho com seus resultados mágicos e ele me prende ao Cake.</p>
<p align="left"><strong>Mas gostaria de deixar aqui um alerta</strong>, especialmente para o programador iniciante: evite ficar preso somente ao bake e se satisfazer com o resultado dele. Ao contrário estude o código gerado por ele, que por sinal é muito bom, para então conseguir adaptar seus aplicativos para as tuas necessidades e dos teus clientes.</p>
<p align="left">Comodismo é algo que acaba com o programador e me parece que com qualquer área da vida do ser humano. A curiosidade, a motivação, o interesse em estudar, aprender, mexer, customizar, isso sim, devem estar presentes na vida do programador e do ser humano, me parece.</p>
<p align="left">Detalhes - <a href="https://book.cakephp.org/bake/1.x/en/index.html">https://book.cakephp.org/bake/1.x/en/index.html</a></p>]]></description>
			<category>CakePHP</category>
			<pubDate>Tue, 02 Jul 2019 21:33:08 -0300</pubDate>
		</item>
	</channel>
</rss>
