SlideShare uma empresa Scribd logo
1 de 34
Baixar para ler offline
Workshop 1:
Desenvolvimento ágil com o CakePHP




               Uma introdução ao
               framework CakePHP e
               suas contribuições para o
               desenvolvimento ágil.
Agenda
     Apresentação
 


     Motivação
 


     Desenvolvimento ágil
 


     Princípios de desenvolvimento ágil
 


     Recursos ágeis do CakePHP
 


     O padrão MVC
 


     O padrão ORM
 


     Validações
 


     Aplicação exemplo (Ajax blog)
 


     Como aproveitar melhor tudo isso?
 


     Agradecimentos
 
Agenda
Apresentação


     A 2km é uma empresa mineira especializada no
 

     desenvolvimento ágil de soluções para web utilizando
     software livre.
     +20 projetos utilizando o CakePHP nos últimos 12
 

     meses.
     Desenvolveu projetos para empresas e organizações como
 

     Record Minas, PMDB-MG, Orca veículos entre outras.
Apresentação


     Carlos Pires (Cadu) é bacharel em ciência da computação.
 

     Desenvolve e é apaixonado pela web e por software livre desde 1999.
     Trabalhou com Java(JEE) por mais de 6 anos em diversas empresas da
     capital mineira. Ultimamente tem se dedicado ao CakePHP e à jQuery.
     Quando não está andando de bike, está estudando línguas (inglês e
     espanhol), curtindo um samba de raíz ou tomando uma cervejinha com
     os amigos.
     Daniel Golgher é tecnólogo em Processamento de Dados, Bacharel em
 

     Sistema de Informação e Especialista em Engenharia de Software.
     Desenvolve em PHP desde 2001. Gosta de software livre, especialmente
     dos projetos: CakePHP, FreeBSD, MySQL, Apache, PHP, Python dentre
     outros.
     Nas horas vagas vai ao cinema com a namorada e passeia com o Baco
     (São Bernardo).
Agenda
Motivação



     Divulgar o framework CakePHP
 


     Divulgar os novos cursos da 2km
 


     Retribuir à comunidade de software livre
 


     Combater o código 'espaguete'
 


     Mostrar que programar pode ser divertido!
 
Agenda
Desenvolvimento ágil



     Estórias de usuário
 


     Programação em Pares
 


     Programação orientada ao teste (TDD)
 


     Refatoração (Refactoring)
 


     Reunião em pé (Stand up meeting)
 


     Sprints
 
Agenda
Princípios do desenvolvimento ágil



     COC – Convention Over Con guration
 


     DRY - Don't Repeat Yourself
 


     KISS - Keep It Short and Simple or Keep It Simple Stupid
 


     SoC - Separation of Concerns
 


     YAGNI - You Ain't Gonna Need It
 
Agenda
Recursos ágeis do CakePHP



     MVC [CoC e SoC]
 


     ORM [CoC]
 


     Validação [DRY e KISS]
 


     Testes unitários (SimpleTest) [TDD]
 


     Helpers, Components e Behaviors [DRY]
 


     Geração de código (Bake) [Productivity]
 
Agenda
Código espaguete?

<div style='display:<?=$valor?$tipo1:$tipo2; ?>'>	
<? if($flag == 0){ ?>	
<script>	
  var a = [<?=implode(',',$lista)?>];	
  <? $SQL = quot;SELECT * FROM clientes WHERE 1 ORDER BY data ASC LIMIT 1 OFFSET 1 quot; ?>	
<? }else{ ?>	
<b> entroh aqui flag= <?=$flag //debugue ?> </b>	
      <? $SQL = quot;SELECT * FROM clientes WHERE quot;.$cond.quot; ORDER BY data ASC LIMIT 1 OFFSET quot;.
$flag ?>	
<script>	
  //	
  var a= [<?=implode(',',$lista_)?>];	
<? } ?>	
  // debugue	
  alert(a);	

<<?php echo '/'.quot;scriptquot;; // kuIDaDeNHo c/AxXx bAhRRaxXXxx ?>>	

</div>	

                                                            Fonte: http://desciclo.pedia.ws/wiki/PHP
Código MVC
<?php	
//Arquivo da Classe de Modelo	
class Usuario extends AppModel {	
        	var $name = 'Usuario';	
        	var $displayField = 'nome';	
}	
?>	

                                                                                           models/usuario.php

<?php	
//Arquivo da Classe de Controle	
class UsuariosController extends AppController {	
        	function teste($grupo_id=null){	
        	       	$usuarios=$this->Usuario->find('list',array('conditions'=>array('grupo_id'=>$grupo_id)));	
        	       	$this->set(compact('usuarios'));	
        	}	
}	
?>	

                                                                           controllers/usuarios_controller.php

<?php	
//Arquivo da Classe de Visão	
$form->create('Usuario',array('action'=>'teste'));	
$form->input('usuario');	
$form->end('Enviar');	
?>	

                                                                                     views/usuarios/teste.ctp
Código em uma camada?

<?php	
$conn = mysql_connect('localhost','root','senha');	
mysql_select_db('meu_banco',$conn);	
$query = 'SELECT id,nome FROM usuarios WHERE grupo=quot;'.$_POST['grupo_id'].'quot;';	
$result = mysql_query($query);	
?>	
<html>	
        	<head>...</head>	
        	<body>	
        	       	<form action=quot;teste.phpquot;>	
        	       	        	Selecione o usuário:	
        	       	        	<select name='usuario'>	
        	       	        	<?php 	
        	       	        	while($row = mysql_fetch_row($result)){	
        	       	        	        	echoquot;<option id=quot;.$row[0].quot;>quot;.$row[1].quot;</option>quot;;	
        	       	        	}       		
        	       	        	?>	
        	       	        	</select>	
        	       	        	<input type='submit'>	
        	       	</form>	
        	</body>	
</html> 	

                                                      Exemplo de código em uma camada
Agenda
O padrão ORM
                                  1
   2


                                           4




                  3




               Tabelas e relacionamentos
O padrão ORM
<?php 	
          	class Produto extends AppModel {	

                                                1
          	      	var   $name=quot;Produtoquot;;	
          	      		
                                                                 2
          	      	var   $hasOne = array('Descricao');	
          	      		
          	      	var   $hasAndBelongsToMany = array('Usuario');	
                                                                      3
          	      		
          	      	var   $belongsTo = array('Categoria' => array(	
          	      	          	'className' => 'Categoria',	
          	      	          	'foreignKey' => 'categoria_id')	
                                                                 4
          	      	);	
          	      		
          	      	var   $hasMany = array('Comentario' => array(	
          	      	          	'className' => 'Comentario',	
          	      	          	'foreignKey' => 'comentario_id',	
          	      	          	'dependent' => false,	
          	      	          	'conditions' => '',	
          	      	          	'fields' => '',	
          	      	          	'order' => '',	
          	      	          	'limit' => ’’	
          	      	          	)	
          	      	);	
          	}	
?>	

                                                         Classe do modelo Produto com os relacionamentos
Agenda
Validações
var $validate = array(	
        	'login' => array('isUnique' => array(	
        	       	        	       	        	        	'rule'=>'isUnique',	
        	       	        	       	        	        	'message'=>'Este e-mail já existe na base de dados.'),	
        	       	        	       	'email' => array(	
        	       	        	       	        	        	'rule' => 'email',	
        	       	        	       	        	        	'message' => 'O campo E-mail deve ser um email válido')	
        	),	
        	'senha' => array(	
        	       	'rule' => array(	
        	       	        	       	'confirmaSenha', 'senha'),	
        	       	        	       	'message' => 'O campo senha e a confirmação da senha não conferem'	
        	),	
        	'confirma_senha' => array(	
        	       	'rule' => 'alphanumeric',	
        	       	'required' => true,	
        	       	'message'=>'O campo confirmação da senha é obrigatório',	
        	       	'on'=>'create'	
        	),	
        	'nome' => array(	
        	       	'rule' => array('between', 2, 64),	
        	       	'message' => 'O campo nome deve possuir de 2 a 64 caracteres')       		
        	);	

       	function confirmaSenha($data) {	
       	       	return $data ['senha'] == $this->data ['Usuario'] ['confirma_senha']; 	
       	}	

                                                                                          models/usuario.php
Agenda
Aplicação Exemplo: Ajax blog


CREATE TABLE `posts` (

   `id` int(10) unsigned NOT NULL auto_increment,

  	`title` varchar(50) default NULL,

  	`body` text,

  	`created` datetime default NULL,

  	`updated` datetime default NULL,

  	PRIMARY KEY (`id`),

  	KEY `title` (`title`)

) ENGINE=MyISAM DEFAULT CHARSET=latin1	


                                                     Estrutura da tabela posts da aplicação exemplo
Ajax blog: Con guração do banco


<?php	
class DATABASE_CONFIG {	

       	var $default = array(	
       	       	'driver' => 'mysql',	
       	       	'connect' => 'mysql_connect',	
       	       	'host' => 'localhost',	
       	       	'login' => 'root',	
       	       	'password' => 'passwd',	
       	       	'database' => 'test', 	
       	       	'prefix' => '' 	
       	);	
}	
?>	


                           Arquivo de con guração do banco: con g/database.php
Ajax blog: Camada de modelo


<?php	

class Post extends AppModel {	

         	var $name = 'Post';	

}	

?>	


                                 Classe de modelo da tabela posts: models/post.php
Ajax blog: Camada de controle
<?php	
class PostsController extends AppController {	
        	var $name = 'Posts';	
        	var $layout = 'ajax_blog';	
        	var $helpers = array ('html', 'javascript', 'ajax', 'time' );	

       	function index() {	
       	       	$this->set ( 'data', $this->Post->find ( 'all' ) );	
       	}	
       	function view($id) {	
       	       	$this->layout = 'ajax';	
       	       	$this->set ( 'data', $this->Post->read (null,$id) );	
       	}	
       	function delete($id = null) {	
       	       	if (isset ( $id )) {	
       	       	        	$id = substr ( $id, 5 );	
       	       	}	
       	       	$this->Post->del ( $id );	
       	       	$this->set ( 'data', $this->Post->find ( 'all' ) );	
       	       	$this->render ( 'list', 'ajax' );	
       	}	
       	function add() {	
       	       	if (! empty ( $this->data )) {	
       	       	        	if ($this->Post->save ( $this->data )) {	
       	       	        	        	$this->set ( 'data', $this->Post->find ( 'all' ) );	
       	       	        	        	$this->render ( 'list', 'ajax' );	
       	       	        	}	
       	       	} else {	
       	       	        	$this->render ( 'add', 'ajax' );	
       	       	}	
       	}	
}	
?>	

                               Classe de controle dos posts: controllers/posts_controller.php
Ajax blog: Layout padrão
<!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Transitional//ENquot; quot;http://www.w3.org/TR/xhtml1/DTD/
xhtml1-transitional.dtdquot;>	
<html xmlns=quot;http://www.w3.org/1999/xhtmlquot;>	
<head>	
<title>CakePHP :: Ajax Blog :: <?php echo $title_for_layout?></title>	
<?php echo $html->charset(); ?>	
<?php echo $javascript->link(array('prototype','scriptaculous','zebra_tables')); ?>	
<?php echo $html->css('css'); ?>	
</head>	

<body>	
<div id=quot;containerquot;>	
    <center><h2>Cake Framework AJAX Demo</h2></center>	
        	<div id=quot;contentquot;>	
        	     <?php echo $content_for_layout?>	
        	</div>	
    <div id=quot;pb-cakequot;>	
         <a href=quot;http://www.cakephp.org/quot; class=quot;simplequot;>	
         <?php echo $html->image('cake.power.png',array(	
                  	'width'=>quot;80quot;,	
                  	'height'=>quot;15quot;,	
                  	'alt'=>quot;CakePHP :: A Rapid Development Frameworkquot;,	
                  	 'border'=>quot;0quot;));	
        	?>	
        	</a>	
    </div>	
</div>	
</body>	
</html>	

                                                   Layout padrão dos posts: views/layouts/ajax_blog.ctp
Ajax blog: View da index
<form action=quot;/posts/searchquot;>	
     <p>	
          <?php echo $html->image('magnify.png', array('alt'=>'Magnify Icon')); ?> <b>Live Search:</b>	
          <input type=quot;textquot; name=quot;livesearchquot; id=quot;livesearchquot; size=quot;40quot;>	
          <?php echo $html->image('spinner.gif', array('alt'=>'Spinner', 'id'=>'search_spinner',
'style'=>'display:none;')); ?>	
     </p>	
</form>	
<?php echo $ajax->observeField('livesearch', array(	
         	'update'=>'post_table', 'url'=>quot;/posts/searchquot;, 'frequency'=>1,	
         	'loading'=>quot;Element.show('search_spinner');quot;, 'complete'=>quot;Element.hide('search_spinner');stripe();quot;)	
         	);	
?>	
<div id=quot;wastebinquot; class=quot;wastebinquot;>	
    <center><b>Drag the post's title right here.</b></center>	
    <div>	
        <p id=quot;indicatorquot;>	
             <?php echo $html->image('spinner.gif', array('alt'=>'Indicator')); ?> Deleting ...	
        </p>	
    </div>	
</div>	
<?php echo $ajax->dropRemote('wastebin',	
         	       	        	array('accept'=>'title', 'hoverclass'=>'wastebin-active'),	
         	       	        	array('url'=>'/posts/delete/',	
         	       	        	'with'=>'{id:element.id}',	
         	       	        	'update'=>'post_table', 	
         	       	        	'loading'=>'Element.show('indicator')', 	
         	       	        	'complete'=>'Element.hide('indicator');stripe();'	
         	       	        	)); 	
?>	
...	

                                                                       Layout da view da index: views/posts/index.ctp
Ajax blog: Elemento da listagem dos posts

    <td>	
        <div class=quot;titlequot; id=quot;post_<?php echo $post['id'];?>quot;>	
	      	     <?php echo $html->image('document.gif', array('alt'=>'MagnifyIcon')); ?>	
	      	     <?php echo $post['title']; ?>	
	      	</div>	
	      	 <?php echo $ajax->drag('post_'.$post['id'], array('revert'=>'true')); ?>	
    </td>	
    <td><?php echo date(quot;d/m/Yquot;, strtotime($post['created'])) ?> </td>     	
    <td>	
    <?php echo $ajax->link('View',quot;/posts/view/{$post['id']}quot;, 	
	        	array('fallback'=>'#view',	
	      	         	 'update'=>quot;post_contentquot;,	
	      	         	 'complete'=>quot;new Effect.Appear('post_content');quot;)) ?>	
    | <?php echo $ajax->link('Edit', quot;/posts/edit/{$post['id']}quot;,	
         	array('fallback'=>'#edit',	
	      	         	 'update'=>quot;add_postquot;,	
	      	         	 'complete'=>quot;new Effect.Appear('add_post');quot;)) ?>	
    | <?php echo $ajax->link('Delete', quot;/posts/delete/{$post['id']}quot;,	
         	array('fallback'=>'#list',	
	      	         	 'update'=>quot;post_tablequot;,	
	      	         	 'complete'=>quot;stripe();quot;)) ?> 	
    </td>	


                                      Elemento da listagem dos posts: views/elements/ajax_posts_lists.ctp
Agenda
Como aproveitar melhor tudo isso?


Fazendo os cursos de desenvolvimento web que a
2km interativa! está lançando:
 Curso de CakePHP (Curso mais completo do

CakePHP no Brasil - 60 horas)
 Curso de jQuery (Abordando as novidades da versão
 

1.3. Em breve)
 Curso de Padrões Web (em breve)
 
Agenda
Agradecimentos

Agradecemos a presença de todos neste sábado e
esperamos vê-los nos próximos workshops!

Dúvidas, críticas, sugestões e doações para:
Carlos Pires (e-mail: carlos.pires@2km.com.br / Twitter: @cadu)
Daniel Golgher (e-mail: daniel@2km.com.br / Twitter: @golgher)


                http://www.2km.com.br

Mais conteúdo relacionado

Mais procurados

Programación Nativa de un CRUD
Programación Nativa de un CRUD Programación Nativa de un CRUD
Programación Nativa de un CRUD FUNDET ECUADOR
 
Zend Framework: abordagem prática
Zend Framework: abordagem práticaZend Framework: abordagem prática
Zend Framework: abordagem práticaMarcelo Andrade
 
Як досвід компанії перетворився на фреймворк
Як досвід компанії перетворився на фреймворкЯк досвід компанії перетворився на фреймворк
Як досвід компанії перетворився на фреймворкShtrih Sruleg
 
Palestra sobre MongoDB com PHP no PHP'n'Rio
Palestra sobre MongoDB com PHP no PHP'n'Rio Palestra sobre MongoDB com PHP no PHP'n'Rio
Palestra sobre MongoDB com PHP no PHP'n'Rio Suissa
 
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説Takashi Uemura
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasJavier Eguiluz
 
Curso Symfony - Clase 1
Curso Symfony - Clase 1Curso Symfony - Clase 1
Curso Symfony - Clase 1Javier Eguiluz
 
Analizador sintáctico de Pascal escrito en Bison
Analizador sintáctico de Pascal escrito en BisonAnalizador sintáctico de Pascal escrito en Bison
Analizador sintáctico de Pascal escrito en BisonEgdares Futch H.
 
New text document (2) 2
New text document (2) 2New text document (2) 2
New text document (2) 2raj lex
 
Javascript and jQuery for Mobile
Javascript and jQuery for MobileJavascript and jQuery for Mobile
Javascript and jQuery for MobileIvano Malavolta
 

Mais procurados (16)

Programación Nativa de un CRUD
Programación Nativa de un CRUD Programación Nativa de un CRUD
Programación Nativa de un CRUD
 
Zend Framework: abordagem prática
Zend Framework: abordagem práticaZend Framework: abordagem prática
Zend Framework: abordagem prática
 
jQuery入門
jQuery入門jQuery入門
jQuery入門
 
Як досвід компанії перетворився на фреймворк
Як досвід компанії перетворився на фреймворкЯк досвід компанії перетворився на фреймворк
Як досвід компанії перетворився на фреймворк
 
DOCUMENTACION PAGINA WEB PHP
DOCUMENTACION PAGINA WEB PHPDOCUMENTACION PAGINA WEB PHP
DOCUMENTACION PAGINA WEB PHP
 
Palestra sobre MongoDB com PHP no PHP'n'Rio
Palestra sobre MongoDB com PHP no PHP'n'Rio Palestra sobre MongoDB com PHP no PHP'n'Rio
Palestra sobre MongoDB com PHP no PHP'n'Rio
 
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
WordPressのテンプレートをカスタマイズするために必要なphpを初歩から解説
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadas
 
Web components v1 intro
Web components v1 introWeb components v1 intro
Web components v1 intro
 
Index1
Index1Index1
Index1
 
Curso Symfony - Clase 1
Curso Symfony - Clase 1Curso Symfony - Clase 1
Curso Symfony - Clase 1
 
Analizador sintáctico de Pascal escrito en Bison
Analizador sintáctico de Pascal escrito en BisonAnalizador sintáctico de Pascal escrito en Bison
Analizador sintáctico de Pascal escrito en Bison
 
New text document (2) 2
New text document (2) 2New text document (2) 2
New text document (2) 2
 
Jquery Framework
Jquery FrameworkJquery Framework
Jquery Framework
 
Javascript and jQuery for Mobile
Javascript and jQuery for MobileJavascript and jQuery for Mobile
Javascript and jQuery for Mobile
 
Alaindavila
AlaindavilaAlaindavila
Alaindavila
 

Destaque

Proyecto de vida
Proyecto de vidaProyecto de vida
Proyecto de vidaevrojas
 
Nd p informe evercom le interesa la información de las gestoras de fondos de ...
Nd p informe evercom le interesa la información de las gestoras de fondos de ...Nd p informe evercom le interesa la información de las gestoras de fondos de ...
Nd p informe evercom le interesa la información de las gestoras de fondos de ...evercom
 
Novos Programas de Português V
Novos Programas de Português VNovos Programas de Português V
Novos Programas de Português VLuís Ferreira
 
Anexo x plano de melhoria
Anexo x   plano de melhoriaAnexo x   plano de melhoria
Anexo x plano de melhoriaAMG Sobrenome
 
Pesquisa Automotivo
Pesquisa AutomotivoPesquisa Automotivo
Pesquisa Automotivogazetaonline
 
Polha Trôpega
Polha TrôpegaPolha Trôpega
Polha Trôpegaevandrof
 
Radio 2.0 Flumotion presentacion Olivier Quero organized by Actuonda
Radio 2.0 Flumotion presentacion Olivier Quero organized by ActuondaRadio 2.0 Flumotion presentacion Olivier Quero organized by Actuonda
Radio 2.0 Flumotion presentacion Olivier Quero organized by ActuondaACTUONDA
 
Np planes semana santa
Np planes semana santaNp planes semana santa
Np planes semana santaevercom
 
Np medio ambiente
Np medio ambienteNp medio ambiente
Np medio ambienteevercom
 
презентация Microsoft office power point
презентация Microsoft office power pointпрезентация Microsoft office power point
презентация Microsoft office power pointlukianov
 
2012 guía de lectura parcial 1
2012 guía de lectura parcial 12012 guía de lectura parcial 1
2012 guía de lectura parcial 1UNSA
 
Metodos de estudio
Metodos de estudioMetodos de estudio
Metodos de estudioAndres Vivas
 
Présentation de notre ville. groupe 2
Présentation de notre ville. groupe 2Présentation de notre ville. groupe 2
Présentation de notre ville. groupe 2School
 

Destaque (20)

Proyecto de vida
Proyecto de vidaProyecto de vida
Proyecto de vida
 
Nd p informe evercom le interesa la información de las gestoras de fondos de ...
Nd p informe evercom le interesa la información de las gestoras de fondos de ...Nd p informe evercom le interesa la información de las gestoras de fondos de ...
Nd p informe evercom le interesa la información de las gestoras de fondos de ...
 
Fluidos0.2 Temario
Fluidos0.2 TemarioFluidos0.2 Temario
Fluidos0.2 Temario
 
Novos Programas de Português V
Novos Programas de Português VNovos Programas de Português V
Novos Programas de Português V
 
Anexo x plano de melhoria
Anexo x   plano de melhoriaAnexo x   plano de melhoria
Anexo x plano de melhoria
 
Sinais3
Sinais3Sinais3
Sinais3
 
Mausam bday
Mausam bdayMausam bday
Mausam bday
 
Pesquisa Automotivo
Pesquisa AutomotivoPesquisa Automotivo
Pesquisa Automotivo
 
MFResume
MFResumeMFResume
MFResume
 
Polha Trôpega
Polha TrôpegaPolha Trôpega
Polha Trôpega
 
Radio 2.0 Flumotion presentacion Olivier Quero organized by Actuonda
Radio 2.0 Flumotion presentacion Olivier Quero organized by ActuondaRadio 2.0 Flumotion presentacion Olivier Quero organized by Actuonda
Radio 2.0 Flumotion presentacion Olivier Quero organized by Actuonda
 
Np planes semana santa
Np planes semana santaNp planes semana santa
Np planes semana santa
 
Np medio ambiente
Np medio ambienteNp medio ambiente
Np medio ambiente
 
Practica
PracticaPractica
Practica
 
Conto II
Conto IIConto II
Conto II
 
презентация Microsoft office power point
презентация Microsoft office power pointпрезентация Microsoft office power point
презентация Microsoft office power point
 
2012 guía de lectura parcial 1
2012 guía de lectura parcial 12012 guía de lectura parcial 1
2012 guía de lectura parcial 1
 
animalesca humanidad
animalesca humanidadanimalesca humanidad
animalesca humanidad
 
Metodos de estudio
Metodos de estudioMetodos de estudio
Metodos de estudio
 
Présentation de notre ville. groupe 2
Présentation de notre ville. groupe 2Présentation de notre ville. groupe 2
Présentation de notre ville. groupe 2
 

2km Workshop: Desenvolvimento ágil com o CakePHP

  • 1. Workshop 1: Desenvolvimento ágil com o CakePHP Uma introdução ao framework CakePHP e suas contribuições para o desenvolvimento ágil.
  • 2. Agenda Apresentação   Motivação   Desenvolvimento ágil   Princípios de desenvolvimento ágil   Recursos ágeis do CakePHP   O padrão MVC   O padrão ORM   Validações   Aplicação exemplo (Ajax blog)   Como aproveitar melhor tudo isso?   Agradecimentos  
  • 4. Apresentação A 2km é uma empresa mineira especializada no   desenvolvimento ágil de soluções para web utilizando software livre. +20 projetos utilizando o CakePHP nos últimos 12   meses. Desenvolveu projetos para empresas e organizações como   Record Minas, PMDB-MG, Orca veículos entre outras.
  • 5. Apresentação Carlos Pires (Cadu) é bacharel em ciência da computação.   Desenvolve e é apaixonado pela web e por software livre desde 1999. Trabalhou com Java(JEE) por mais de 6 anos em diversas empresas da capital mineira. Ultimamente tem se dedicado ao CakePHP e à jQuery. Quando não está andando de bike, está estudando línguas (inglês e espanhol), curtindo um samba de raíz ou tomando uma cervejinha com os amigos. Daniel Golgher é tecnólogo em Processamento de Dados, Bacharel em   Sistema de Informação e Especialista em Engenharia de Software. Desenvolve em PHP desde 2001. Gosta de software livre, especialmente dos projetos: CakePHP, FreeBSD, MySQL, Apache, PHP, Python dentre outros. Nas horas vagas vai ao cinema com a namorada e passeia com o Baco (São Bernardo).
  • 7. Motivação Divulgar o framework CakePHP   Divulgar os novos cursos da 2km   Retribuir à comunidade de software livre   Combater o código 'espaguete'   Mostrar que programar pode ser divertido!  
  • 9. Desenvolvimento ágil Estórias de usuário   Programação em Pares   Programação orientada ao teste (TDD)   Refatoração (Refactoring)   Reunião em pé (Stand up meeting)   Sprints  
  • 11. Princípios do desenvolvimento ágil COC – Convention Over Con guration   DRY - Don't Repeat Yourself   KISS - Keep It Short and Simple or Keep It Simple Stupid   SoC - Separation of Concerns   YAGNI - You Ain't Gonna Need It  
  • 13. Recursos ágeis do CakePHP MVC [CoC e SoC]   ORM [CoC]   Validação [DRY e KISS]   Testes unitários (SimpleTest) [TDD]   Helpers, Components e Behaviors [DRY]   Geração de código (Bake) [Productivity]  
  • 15. Código espaguete? <div style='display:<?=$valor?$tipo1:$tipo2; ?>'> <? if($flag == 0){ ?> <script> var a = [<?=implode(',',$lista)?>]; <? $SQL = quot;SELECT * FROM clientes WHERE 1 ORDER BY data ASC LIMIT 1 OFFSET 1 quot; ?> <? }else{ ?> <b> entroh aqui flag= <?=$flag //debugue ?> </b> <? $SQL = quot;SELECT * FROM clientes WHERE quot;.$cond.quot; ORDER BY data ASC LIMIT 1 OFFSET quot;. $flag ?> <script> // var a= [<?=implode(',',$lista_)?>]; <? } ?> // debugue alert(a); <<?php echo '/'.quot;scriptquot;; // kuIDaDeNHo c/AxXx bAhRRaxXXxx ?>> </div> Fonte: http://desciclo.pedia.ws/wiki/PHP
  • 16. Código MVC <?php //Arquivo da Classe de Modelo class Usuario extends AppModel { var $name = 'Usuario'; var $displayField = 'nome'; } ?> models/usuario.php <?php //Arquivo da Classe de Controle class UsuariosController extends AppController { function teste($grupo_id=null){ $usuarios=$this->Usuario->find('list',array('conditions'=>array('grupo_id'=>$grupo_id))); $this->set(compact('usuarios')); } } ?> controllers/usuarios_controller.php <?php //Arquivo da Classe de Visão $form->create('Usuario',array('action'=>'teste')); $form->input('usuario'); $form->end('Enviar'); ?> views/usuarios/teste.ctp
  • 17. Código em uma camada? <?php $conn = mysql_connect('localhost','root','senha'); mysql_select_db('meu_banco',$conn); $query = 'SELECT id,nome FROM usuarios WHERE grupo=quot;'.$_POST['grupo_id'].'quot;'; $result = mysql_query($query); ?> <html> <head>...</head> <body> <form action=quot;teste.phpquot;> Selecione o usuário: <select name='usuario'> <?php while($row = mysql_fetch_row($result)){ echoquot;<option id=quot;.$row[0].quot;>quot;.$row[1].quot;</option>quot;; } ?> </select> <input type='submit'> </form> </body> </html> Exemplo de código em uma camada
  • 19. O padrão ORM 1 2 4 3 Tabelas e relacionamentos
  • 20. O padrão ORM <?php class Produto extends AppModel { 1 var $name=quot;Produtoquot;; 2 var $hasOne = array('Descricao'); var $hasAndBelongsToMany = array('Usuario'); 3 var $belongsTo = array('Categoria' => array( 'className' => 'Categoria', 'foreignKey' => 'categoria_id') 4 ); var $hasMany = array('Comentario' => array( 'className' => 'Comentario', 'foreignKey' => 'comentario_id', 'dependent' => false, 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => ’’ ) ); } ?> Classe do modelo Produto com os relacionamentos
  • 22. Validações var $validate = array( 'login' => array('isUnique' => array( 'rule'=>'isUnique', 'message'=>'Este e-mail já existe na base de dados.'), 'email' => array( 'rule' => 'email', 'message' => 'O campo E-mail deve ser um email válido') ), 'senha' => array( 'rule' => array( 'confirmaSenha', 'senha'), 'message' => 'O campo senha e a confirmação da senha não conferem' ), 'confirma_senha' => array( 'rule' => 'alphanumeric', 'required' => true, 'message'=>'O campo confirmação da senha é obrigatório', 'on'=>'create' ), 'nome' => array( 'rule' => array('between', 2, 64), 'message' => 'O campo nome deve possuir de 2 a 64 caracteres') ); function confirmaSenha($data) { return $data ['senha'] == $this->data ['Usuario'] ['confirma_senha']; } models/usuario.php
  • 24. Aplicação Exemplo: Ajax blog CREATE TABLE `posts` (
 `id` int(10) unsigned NOT NULL auto_increment,
 `title` varchar(50) default NULL,
 `body` text,
 `created` datetime default NULL,
 `updated` datetime default NULL,
 PRIMARY KEY (`id`),
 KEY `title` (`title`)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 Estrutura da tabela posts da aplicação exemplo
  • 25. Ajax blog: Con guração do banco <?php class DATABASE_CONFIG { var $default = array( 'driver' => 'mysql', 'connect' => 'mysql_connect', 'host' => 'localhost', 'login' => 'root', 'password' => 'passwd', 'database' => 'test', 'prefix' => '' ); } ?> Arquivo de con guração do banco: con g/database.php
  • 26. Ajax blog: Camada de modelo <?php class Post extends AppModel { var $name = 'Post'; } ?> Classe de modelo da tabela posts: models/post.php
  • 27. Ajax blog: Camada de controle <?php class PostsController extends AppController { var $name = 'Posts'; var $layout = 'ajax_blog'; var $helpers = array ('html', 'javascript', 'ajax', 'time' ); function index() { $this->set ( 'data', $this->Post->find ( 'all' ) ); } function view($id) { $this->layout = 'ajax'; $this->set ( 'data', $this->Post->read (null,$id) ); } function delete($id = null) { if (isset ( $id )) { $id = substr ( $id, 5 ); } $this->Post->del ( $id ); $this->set ( 'data', $this->Post->find ( 'all' ) ); $this->render ( 'list', 'ajax' ); } function add() { if (! empty ( $this->data )) { if ($this->Post->save ( $this->data )) { $this->set ( 'data', $this->Post->find ( 'all' ) ); $this->render ( 'list', 'ajax' ); } } else { $this->render ( 'add', 'ajax' ); } } } ?> Classe de controle dos posts: controllers/posts_controller.php
  • 28. Ajax blog: Layout padrão <!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Transitional//ENquot; quot;http://www.w3.org/TR/xhtml1/DTD/ xhtml1-transitional.dtdquot;> <html xmlns=quot;http://www.w3.org/1999/xhtmlquot;> <head> <title>CakePHP :: Ajax Blog :: <?php echo $title_for_layout?></title> <?php echo $html->charset(); ?> <?php echo $javascript->link(array('prototype','scriptaculous','zebra_tables')); ?> <?php echo $html->css('css'); ?> </head> <body> <div id=quot;containerquot;> <center><h2>Cake Framework AJAX Demo</h2></center> <div id=quot;contentquot;> <?php echo $content_for_layout?> </div> <div id=quot;pb-cakequot;> <a href=quot;http://www.cakephp.org/quot; class=quot;simplequot;> <?php echo $html->image('cake.power.png',array( 'width'=>quot;80quot;, 'height'=>quot;15quot;, 'alt'=>quot;CakePHP :: A Rapid Development Frameworkquot;, 'border'=>quot;0quot;)); ?> </a> </div> </div> </body> </html> Layout padrão dos posts: views/layouts/ajax_blog.ctp
  • 29. Ajax blog: View da index <form action=quot;/posts/searchquot;> <p> <?php echo $html->image('magnify.png', array('alt'=>'Magnify Icon')); ?> <b>Live Search:</b> <input type=quot;textquot; name=quot;livesearchquot; id=quot;livesearchquot; size=quot;40quot;> <?php echo $html->image('spinner.gif', array('alt'=>'Spinner', 'id'=>'search_spinner', 'style'=>'display:none;')); ?> </p> </form> <?php echo $ajax->observeField('livesearch', array( 'update'=>'post_table', 'url'=>quot;/posts/searchquot;, 'frequency'=>1, 'loading'=>quot;Element.show('search_spinner');quot;, 'complete'=>quot;Element.hide('search_spinner');stripe();quot;) ); ?> <div id=quot;wastebinquot; class=quot;wastebinquot;> <center><b>Drag the post's title right here.</b></center> <div> <p id=quot;indicatorquot;> <?php echo $html->image('spinner.gif', array('alt'=>'Indicator')); ?> Deleting ... </p> </div> </div> <?php echo $ajax->dropRemote('wastebin', array('accept'=>'title', 'hoverclass'=>'wastebin-active'), array('url'=>'/posts/delete/', 'with'=>'{id:element.id}', 'update'=>'post_table', 'loading'=>'Element.show('indicator')', 'complete'=>'Element.hide('indicator');stripe();' )); ?> ... Layout da view da index: views/posts/index.ctp
  • 30. Ajax blog: Elemento da listagem dos posts <td> <div class=quot;titlequot; id=quot;post_<?php echo $post['id'];?>quot;> <?php echo $html->image('document.gif', array('alt'=>'MagnifyIcon')); ?> <?php echo $post['title']; ?> </div> <?php echo $ajax->drag('post_'.$post['id'], array('revert'=>'true')); ?> </td> <td><?php echo date(quot;d/m/Yquot;, strtotime($post['created'])) ?> </td> <td> <?php echo $ajax->link('View',quot;/posts/view/{$post['id']}quot;, array('fallback'=>'#view', 'update'=>quot;post_contentquot;, 'complete'=>quot;new Effect.Appear('post_content');quot;)) ?> | <?php echo $ajax->link('Edit', quot;/posts/edit/{$post['id']}quot;, array('fallback'=>'#edit', 'update'=>quot;add_postquot;, 'complete'=>quot;new Effect.Appear('add_post');quot;)) ?> | <?php echo $ajax->link('Delete', quot;/posts/delete/{$post['id']}quot;, array('fallback'=>'#list', 'update'=>quot;post_tablequot;, 'complete'=>quot;stripe();quot;)) ?> </td> Elemento da listagem dos posts: views/elements/ajax_posts_lists.ctp
  • 32. Como aproveitar melhor tudo isso? Fazendo os cursos de desenvolvimento web que a 2km interativa! está lançando:  Curso de CakePHP (Curso mais completo do CakePHP no Brasil - 60 horas) Curso de jQuery (Abordando as novidades da versão   1.3. Em breve) Curso de Padrões Web (em breve)  
  • 34. Agradecimentos Agradecemos a presença de todos neste sábado e esperamos vê-los nos próximos workshops! Dúvidas, críticas, sugestões e doações para: Carlos Pires (e-mail: carlos.pires@2km.com.br / Twitter: @cadu) Daniel Golgher (e-mail: daniel@2km.com.br / Twitter: @golgher) http://www.2km.com.br