Search Results for "zend"

Dezembro 2nd 2008

I Fórum de Tecnologia em Software Livre - Serpro - Regional Porto Alegre

Na próxima semana nos dias 10 e 11 de dezembro, estará acontecendo o I Fórum de Tecnologia em Software Livre - Regional Porto Alegre, o fórum tem como objetivo a disseminação de novas tecnologias baseadas em software livre, bem como, a troca de experiências com as comunidades e empresas parceiras, por meio de palestras e mini-cursos.

Estarei lá, dando uma palestra para sobre o framework da Zend (Zend Framework) no dia 11 ás 13:45, ouve um pequeno problema no título da que está no site oficial do evento, mas será: Zend Framework - Aprenda a preocupar-se com seu negócio utilizando-o.

Fica ai o convite a todos. Mais infomações do evento:
I Fórum de Tecnologia em Software Livre - Regional Porto Alegre

[]s

No Comments yet »

Novembro 29th 2008

Injeção de dependência com Zend Framework

É comum ver por ai, as pessoas fazendo o setup da aplicação sempre no arquivo de bootstrap do Zend, algo do tipo:

arquivo: index.php

PHP:
  1. require_once 'Initializer.php';
  2. require_once 'Zend/Loader.php';
  3.  
  4. Zend_Loader::registerAutoload();
  5.  
  6. $frontController = Zend_Controller_Front::getInstance();
  7.  
  8. //inicializando configuração do banco de dados
  9. $db = new Zend_Db_Adapter_Oracle(array(
  10.     'username' => 'xxxxxx',
  11.     'password' => 'xxxxxx',
  12.     'dbname'   => 'xe'
  13. ));
  14.  
  15. Zend_Db_Table_Abstract::setDefaultAdapter($db);
  16.  
  17. //inicializando configuração de routes
  18. //...
  19.  
  20. // inicializando layout
  21. Zend_Layout::startMvc();
  22.  
  23. // inicializando componente tal ....
  24.  
  25. $frontController->addControllerDirectory(dirname(__FILE__) . '/application/default/controllers', 'default');
  26. $frontController->dispatch();

Porém, existem maneiras mais fáceis (e mais elegantes) de fazer isso. Injeção de Dependência é uma delas. Com o Zend Framework existem alguns pontos onde podemos aplicar este tipo de abordagem, utilizando Action Helpers, View Helpers e Plugins. Já expliquei aqui no blog como utilizar plugins, no post Não estenda. Plugue!.

O exemplo abaixo é uma alternativa para setup utilizando plugins, para os usuários do Zend Studio for Eclipse isso é talvez seja familiar, já que a IDE gera o projeto mais ou menos desta mesma forma.

Primeiro nosso plugin:

PHP:
  1. <?php
  2.  
  3. require_once 'Zend/Controller/Plugin/Abstract.php';
  4. require_once 'Zend/Controller/Front.php';
  5. require_once 'Zend/Controller/Request/Abstract.php';
  6. require_once 'Zend/Controller/Action/HelperBroker.php';
  7.  
  8. /**
  9.  * plugin de inicialização da aplicação
  10.  *
  11.  */
  12. class Initializer extends Zend_Controller_Plugin_Abstract
  13. {
  14.    
  15.     protected static $_config;
  16.  
  17.     protected $_env;
  18.  
  19.     protected $_front;
  20.  
  21.     protected $_root;
  22.  
  23.     /**
  24.      * Constructor
  25.      *
  26.      * inicializa configurações
  27.      *
  28.      * @param  string $env (development, test, production)
  29.      * @param  string|null $root
  30.      * @return void
  31.      */
  32.     public function __construct($env, $root = null)
  33.     {
  34.         $this->_setEnv($env);
  35.         if (null === $root) {
  36.             $root = realpath(dirname(__FILE__) . '/../');
  37.         }
  38.         $this->_root = $root;
  39.  
  40.         $this->_front = Zend_Controller_Front::getInstance();
  41.        
  42.         $this->initPhpConfig();
  43.     }
  44.  
  45.     /**
  46.      * seta ambiente
  47.      *
  48.      * @param  string $env
  49.      * @return void
  50.      */
  51.     protected function _setEnv($env)
  52.     {
  53.         $this->_env = $env;     
  54.     }
  55.    
  56.  
  57.     /**
  58.      * inicializa configurações do php
  59.      *
  60.      * @return void
  61.      */
  62.     public function initPhpConfig()
  63.     {
  64.         // seta parametros para ambiente de teste
  65.         if ($this->_env == 'test') {
  66.             // habilita todos os erros do php 
  67.             error_reporting(E_ALL | E_STRICT); 
  68.             ini_set('display_startup_errors', 1); 
  69.             ini_set('display_errors', 1);
  70.  
  71.             $this->_front->throwExceptions(true); 
  72.         }
  73.     }
  74.    
  75.     /**
  76.      * faz todas as inicializações antes do inicio do roteamento para os controllers
  77.      *
  78.      * @return void
  79.      */
  80.     public function routeStartup(Zend_Controller_Request_Abstract $request)
  81.     {
  82.         $this->initDb();
  83.         $this->initHelpers();
  84.         $this->initView();
  85.         $this->initPlugins();
  86.         $this->initRoutes();
  87.         $this->initControllers();
  88.     }
  89.    
  90.     /**
  91.      * inicializa banco de dados
  92.      *
  93.      * @return void
  94.      */
  95.     public function initDb()
  96.     {
  97.         $db = new Zend_Db_Adapter_Oracle(array(
  98.             'username' => 'xxxxx',
  99.             'password' => 'xxxxx',
  100.             'dbname'   => 'xe'
  101.         ));
  102.        
  103.         Zend_Db_Table_Abstract::setDefaultAdapter($db);
  104.     }
  105.  
  106.     /**
  107.      * inicializa os action helpers
  108.      *
  109.      * @return void
  110.      */
  111.     public function initHelpers()
  112.     {
  113.         Zend_Controller_Action_HelperBroker::addPath('../application/default/helpers', 'Zend_Controller_Action_Helper');
  114.     }
  115.    
  116.     /**
  117.      * inicializa o view
  118.      *
  119.      * @return void
  120.      */
  121.     public function initView()
  122.     {
  123.         Zend_Layout::startMvc(array(
  124.             'layoutPath' => $this->_root .  '/application/default/layouts',
  125.             'layout' => 'main'
  126.         ));
  127.        
  128.     }
  129.    
  130.     /**
  131.      * inicializa plugins
  132.      *
  133.      * @return void
  134.      */
  135.     public function initPlugins()
  136.     {
  137.     }
  138.    
  139.     /**
  140.      * inicializa routes
  141.      *
  142.      * @return void
  143.      */
  144.     public function initRoutes()
  145.     {
  146.     }
  147.  
  148.     /**
  149.      * inicializa os controllers
  150.      *
  151.      * @return void
  152.      */
  153.     public function initControllers()
  154.     {
  155.         $this->_front->addControllerDirectory($this->_root . '/application/default/controllers', 'default');
  156.     }
  157. }

Após isso, nosso arquivo de bootstrap:

PHP:
  1. require_once 'Initializer.php';
  2. require_once 'Zend/Loader.php';
  3.  
  4. Zend_Loader::registerAutoload();
  5.  
  6. $frontController = Zend_Controller_Front::getInstance();
  7. $frontController->registerPlugin(new Initializer('development'));
  8. $frontController->dispatch();

Dessa forma criamos as rotinas de setup e deixamos que o próprio Zend inicialize as coisas para nós.

[]s

2 Comments »

Novembro 27th 2008

Validação de CNPJ utilizando Zend_Validate

Simplesmente adaptei a validação de CPF e alterei algumas coisas, é muito parecido.

Segue o código:

PHP:
  1. <?php
  2.  
  3. require_once 'Zend/Validate/Abstract.php';
  4.  
  5. /**
  6.  * Validador para fazer a validação de CNPJ (Cadastro Nacional da Pessoa Jurídica)
  7.  *
  8.  * @author Diego Tremper <diegotremper@gmail.com>
  9.  */
  10. class Validate_Cnpj extends Zend_Validate_Abstract
  11. {
  12.     const INVALID_DIGITS = 'i_number';
  13.    
  14.     const INVALID_FORMAT = 'i_format';
  15.    
  16.     protected $_messageTemplates = array (
  17.                     self::INVALID_DIGITS => "O CNPJ '%value%' não é válido",
  18.                     self::INVALID_FORMAT => "O formato do CNPJ '%value%' não é válido"
  19.               );
  20.               
  21.     private $_pattern = '/(\d{2})\.(\d{3})\.(\d{3})\/(\d{4})-(\d{2})/i';
  22.    
  23.     private $_skipFormat = false;
  24.    
  25.     /**
  26.      * Inicializa a instância do validador
  27.      *
  28.      * @param bool $skipFormat ignorar validação no formato?
  29.      */
  30.     public function __construct($skipFormat = false) {
  31.         $this->_skipFormat = $skipFormat;
  32.     }
  33.    
  34.     /**
  35.      * verifica se o cnpj é válido
  36.      *
  37.      * @param string $value cnpj a ser validado
  38.      * @return bool
  39.      */
  40.     public function isValid($value)
  41.     {
  42.         $this->_setValue ( $value );
  43.        
  44.         if (!$this->_skipFormat && preg_match($this->_pattern, $value) == false) {
  45.             $this->_error(self::INVALID_FORMAT);
  46.             return false;
  47.         }
  48.        
  49.         $digits = preg_replace('/[^\d]+/i', '', $value);
  50.         $firstSum = 0;
  51.         $secondSum = 0;
  52.        
  53.         $firstSum += (5*$digits{0}) + (4*$digits{1}) + (3*$digits{2}) + (2*$digits{3});
  54.         $firstSum += (9*$digits{4}) + (8*$digits{5}) + (7*$digits{6}) + (6*$digits{7});
  55.         $firstSum += (5*$digits{8}) + (4*$digits{9}) + (3*$digits{10}) + (2*$digits{11});
  56.        
  57.         $firstDigit = 11 - fmod($firstSum, 11);
  58.        
  59.         if ($firstDigit>= 10) {
  60.             $firstDigit = 0;
  61.         }
  62.        
  63.         $secondSum += (6*$digits{0}) + (5*$digits{1}) + (4*$digits{2}) + (3*$digits{3});
  64.         $secondSum += (2*$digits{4}) + (9*$digits{5}) + (8*$digits{6}) + (7*$digits{7});
  65.         $secondSum += (6*$digits{8}) + (5*$digits{9}) + (4*$digits{10}) + (3*$digits{11});
  66.         $secondSum += ($firstDigit*2);
  67.        
  68.         $secondDigit = 11 - fmod($secondSum, 11);
  69.        
  70.         if ($secondDigit>= 10) {
  71.             $secondDigit = 0;
  72.         }
  73.        
  74.         if (substr($digits, -2) != ($firstDigit . $secondDigit)) {
  75.             $this->_error(self::INVALID_DIGITS);
  76.             return false;
  77.         }
  78.        
  79.         return true;
  80.     }
  81. }

Para testar:

PHP:
  1. <?php
  2.  
  3. require_once 'Validate/Cnpj.php';
  4.  
  5. /**
  6.  * testar cnpj com validação no formato e digito verificador
  7.  */
  8. $v = new Validate_Cnpj ( );
  9. var_dump ( $v->isValid ( "03.847.655/0001-98" ) ); //cnpj válido
  10. print_r ( $v->getMessages () );
  11.  
  12. var_dump ( $v->isValid ( "03.847.655/000198" ) ); //cnpj com formato inválido
  13. print_r ( $v->getMessages () );
  14.  
  15. var_dump ( $v->isValid ( "03.847.655/0001-90" ) ); //cnpj com digito verificador inválido
  16. print_r ( $v->getMessages () );
  17.  
  18. /**
  19.  * testar cnpj com validação de digito verificador e SEM validação de formato
  20.  */
  21. $v = new Validate_Cnpj ( true );
  22. var_dump ( $v->isValid ( "03.847.655/0001-98" ) ); //cnpj válido
  23. var_dump ( $v->isValid ( "03847655000198" ) ); //cnpj válido
  24. print_r ( $v->getMessages () );
  25.  
  26. $v = new Validate_Cnpj ( true );
  27. var_dump ( $v->isValid ( "03847655000190" ) ); //cnpj com digito verificador inválido
  28. print_r ( $v->getMessages () );

Os arquivos estão disponíveis no link a seguir: zend_validate_cnpj

[]s

No Comments yet »

Novembro 26th 2008

Rolling File utilizando Zend_Log

Alguém já se perguntou porque diabos o Zend_Log não divide os arquivos de logs em vários arquivos? Para quem utiliza ou já utilizou o Log4PHP sabe do que estou falando. Aquela história, o arquivo de log ultrapassou 1MB por ex., é gerado um novo arquivo com o mesmo nome com um sufixo .1 (ex.: aplicacao.log.1) com os logs antigos, e os novos logs são inseridor no arquivo aplicacao.log.

Pois é, dei uma pesquisada sobre isso, alguns dizem que essa funcionalidade não é função do log... que existem outras aplicações que fazem isso... etc,etc. A questão é que isto não foi inserido no framework.

Discução: http://framework.zend.com/issues/browse/ZF-263

Então resolvi fazer uma classe para tratar isso, andei olhando como o Log4PHP faz, e adaptei para o Zend_Log.

PHP:
  1. <?php
  2.  
  3. require_once 'Zend/Log/Writer/Abstract.php';
  4. require_once 'Zend/Log/Formatter/Simple.php';
  5.  
  6. /**
  7.  * @package    Log
  8.  * @author     Diego Tremper <diegotremper@gmail.com>
  9.  */
  10. class Log_Writer_Rolling_File extends Zend_Log_Writer_Abstract {
  11.    
  12.     /**
  13.      * Holds the PHP stream to log to.
  14.      * @var null|stream
  15.      */
  16.     protected $_stream = null;
  17.    
  18.     /**
  19.      * default 1MB
  20.      */
  21.     protected $fileMaxSize = 1048576;
  22.    
  23.     protected $maxFiles = 10;
  24.    
  25.     protected $_filename = null;
  26.    
  27.     /**
  28.      * Class Constructor
  29.      *
  30.      * @param  streamOrUrl     Stream or URL to open as a stream
  31.      * @param  mode            Mode, only applicable if a URL is given
  32.      */
  33.     public function __construct($streamOrUrl, $mode = 'a') {
  34.         if (is_resource ( $streamOrUrl )) {
  35.             $stream_data = stream_get_meta_data ( $streamOrUrl );
  36.            
  37.             if (get_resource_type ( $streamOrUrl ) != 'plainfile') {
  38.                 require_once 'Zend/Log/Exception.php';
  39.                 throw new Zend_Log_Exception ( 'Resource is not a plainfile' );
  40.             }
  41.            
  42.             if ($mode != 'a') {
  43.                 require_once 'Zend/Log/Exception.php';
  44.                 throw new Zend_Log_Exception ( 'Mode cannot be changed on existing streams' );
  45.             }
  46.            
  47.             $filename = $stream_data ['uri'];
  48.             $this->_stream = $streamOrUrl;
  49.         } else {
  50.             if (! $this->_stream = @fopen ( $streamOrUrl, $mode, false )) {
  51.                 $msg = "\"$streamOrUrl\" cannot be opened with mode \"$mode\"";
  52.                 require_once 'Zend/Log/Exception.php';
  53.                 throw new Zend_Log_Exception ( $msg );
  54.             }
  55.            
  56.             $filename = $streamOrUrl;
  57.         }
  58.        
  59.         $this->_fileName = $filename;
  60.        
  61.         fseek ( $this->_stream, filesize ( $this->_fileName ) - 1 );
  62.        
  63.         $this->_formatter = new Zend_Log_Formatter_Simple ( );
  64.     }
  65.    
  66.     /**
  67.      * @return int
  68.      */
  69.     public function getFileMaxSize() {
  70.         return $this->fileMaxSize;
  71.     }
  72.    
  73.     /**
  74.      * Set the maximum size that the output file is allowed to reach
  75.      * before being rolled over to backup files.
  76.      *
  77.      * The maxFileSize option takes an long integer in the range 0 - 2^63.
  78.      * You can specify the value with the suffixes "KB", "MB" or "GB"
  79.      * so that the integer is interpreted being expressed respectively
  80.      * in kilobytes, megabytes or gigabytes. For example, the value "10KB"
  81.      * will be interpreted as 10240.
  82.      *
  83.      * @param int|string $fileMaxSize
  84.      */
  85.     public function setFileMaxSize($fileMaxSize) {
  86.         if (is_string($fileMaxSize)) {
  87.             $this->fileMaxSize = $this->_convertMaxFileSize($fileMaxSize);
  88.         } else {
  89.             $this->fileMaxSize = $fileMaxSize;
  90.         }
  91.     }
  92.    
  93.     /**
  94.      * @return int
  95.      */
  96.     public function getMaxFiles() {
  97.         return $this->maxFiles;
  98.     }
  99.    
  100.     /**
  101.      * @param int $maxFiles
  102.      */
  103.     public function setMaxFiles($maxFiles) {
  104.         $this->maxFiles = $maxFiles;
  105.     }
  106.    
  107.     /**
  108.      * Close the stream resource.
  109.      *
  110.      * @return void
  111.      */
  112.     public function shutdown() {
  113.         if (is_resource ( $this->_stream )) {
  114.             fclose ( $this->_stream );
  115.         }
  116.     }
  117.    
  118.     /**
  119.      * Write a message to the log.
  120.      *
  121.      * @param  array  $event  event data
  122.      * @return void
  123.      */
  124.     protected function _write($event) {
  125.         $line = $this->_formatter->format ( $event );
  126.        
  127.         if (false === @fwrite ( $this->_stream, $line )) {
  128.             require_once 'Zend/Log/Exception.php';
  129.             throw new Zend_Log_Exception ( "Unable to write to stream" );
  130.         }
  131.        
  132.         if (ftell ( $this->_stream )> $this->fileMaxSize)
  133.             $this->_rollOver ();
  134.     }
  135.    
  136.     protected function _rollOver() {
  137.         if ($this->maxFiles> 0) {
  138.             $file = $this->_fileName . '.' . $this->maxFiles;
  139.            
  140.             if (is_writable ( $file ))
  141.                 unlink ( $file );
  142.            
  143.             for($i = $this->maxFiles - 1; $i>= 1; $i --) {
  144.                 $file = $this->_fileName . '.' . $i;
  145.                 if (is_readable ( $file )) {
  146.                     $target = $this->_fileName . '.' . ($i + 1);
  147.                     rename ( $file, $target );
  148.                 }
  149.             }
  150.            
  151.             $target = $this->_fileName . '.1';
  152.            
  153.             $this->shutdown ();
  154.            
  155.             rename ( $this->_fileName, $target );
  156.         }
  157.        
  158.         $this->__construct ( $this->_fileName, 'w' );
  159.     }
  160.    
  161.     /**
  162.      * Convert maxFileSize value
  163.      *
  164.      * @param mixed $value
  165.      */
  166.     private function _convertMaxFileSize($value) {
  167.         $maxFileSize = null;
  168.         $numpart = substr ( $value, 0, strlen ( $value ) - 2 );
  169.         $suffix = strtoupper ( substr ( $value, - 2 ) );
  170.        
  171.         switch ($suffix) {
  172.             case 'KB' :
  173.                 $maxFileSize = ( int ) (( int ) $numpart * 1024);
  174.                 break;
  175.             case 'MB' :
  176.                 $maxFileSize = ( int ) (( int ) $numpart * 1024 * 1024);
  177.                 break;
  178.             case 'GB' :
  179.                 $maxFileSize = ( int ) (( int ) $numpart * 1024 * 1024 * 1024);
  180.                 break;
  181.             default :
  182.                 require_once 'Zend/Log/Exception.php';
  183.                 throw new Zend_Log_Exception ( 'Invalid size' );
  184.         }
  185.        
  186.         return $maxFileSize;
  187.     }
  188.  
  189. }

Para testar:

PHP:
  1. <?php
  2.  
  3. require 'Zend/Log.php';
  4. require 'Log/Writer/Rolling/File.php';
  5.  
  6. $writer = new Log_Writer_Rolling_File('aplicacao.log');
  7. $writer->setFileMaxSize("10KB");
  8. $writer->setMaxFiles(10);
  9. $logger = new Zend_Log($writer);
  10.  
  11. for ($i=0; $i<1000; $i++) {
  12.     $logger->debug('Este é um debug para teste de rolling file utilizando zend_log : ' . $i);
  13. }

Para quem quiser os arquivos, segue o link: rolling_file_zend_log.

[]s

No Comments yet »

Novembro 25th 2008

Validação de CPF utilizando Zend_Validate

Há algum tempo eu estava devendo algum post técnico, então resolvi dar uma brincada com o Zend_Validate, posto aqui um validator que fiz para CPF (Cadastro de Pessoas Físicas). A quem possa servir segue o código:

PHP:
  1. <?php
  2.