zf create project
-- copia delle lib
cp -R /usr/local/lib/php/Zend library/

project init

usa il tool cli per inizializzare app e oggetti.

zf create project
# copia delle lib
cp -/usr/local/lib/php/Zend library/

basic virtual host

NameVirtualHost *:80
<VirtualHost *:80>
DocumentRoot "/usr/local/apache/htdocs/square/public"
ServerName square.localhost
</VirtualHost>

Modules, are plugin: può contenere controller routers e models

Config

# php flags
phpSettings.display_errors = 0
 
# app data
webservice.amazon.affiliates.key = KEY_GOES_HERE
webservice.amazon.ec2.key = KEY_GOES_HERE
webservice.google.maps.key = KEY_GOES_HERE

da un controller, ottenere le configurazioni

// method 1
$options $this->getInvokeArg('bootstrap')->getOptions();
echo 
$options['webservices']['google']['maps']['api'];
// method 2
$this->options = new Zend_Config($this->getInvokeArg('bootstrap')->getOptions());
$this->view->email $this->options->company->email->support;

// method 3: bootstrap
protected function _initConfig() {
    
$config = new Zend_Config($this->getOptions());
    
Zend_Registry::set('config'$config);
    return 
$config;
}
$this->view->supportEmail Zend_Registry::get('config')->company->email->support;

DB setup

zf configure db-adapter "adapter=PDO_MYSQL&dbname=mydb&host=localhost&username=root&password" production
resources.db.adapter "PDO_MYSQL"
resources.db.params.host "your.database.host"
resources.db.params.dbname "database_name"
resources.db.params.username "username"
resources.db.params.password "password"
resources.db.isDefaultTableAdapter true
resources
.db.params.charset "utf8"

If your database settings are preceded by resources.db you won't even need to do anything in your Bootstrap.php file because it will do it for you. Also, by setting the isDefaultTableAdapter setting to true, you can get an instance of your database adapter anywhere in your application.

bootstrapping sequence

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
    
// vengono automaticamente chiamati i metodi che iniziano con _init
    public function _initDBLog() {
        
// echo 'setup my logger';
        // Logger
        $db Zend_Db_Table::getDefaultAdapter();
        
$columnMapping = array('lvl' => 'priority''msg' => 'message');
        
$writer = new Zend_Log_Writer_Db($db'log'$columnMapping);
        
$logger = new Zend_Log($writer);
        
Zend_Registry::set('logger'$logger);

       
// attach more than 1 writer to logging engine
       //$writer = new Zend_Log_Writer_Mail($mail);
       //$logger->addWriter($writer);

       // add client IP and request URL to log message
       $logger->setEventItem('request'$this->getRequest()->getRequestUri());
       
$logger->setEventItem('host'$this->getRequest()->getClientIp());
    }
    public function 
_initLib(){
        
$autoloader Zend_Loader_Autoloader::getInstance();
        
$autoloader->registerNamespace('My_');
        
// es. \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
    }
    public function 
_initPaginator(){
        
Zend_Paginator::setDefaultScrollingStyle('Sliding');
        
Zend_View_Helper_PaginationControl::setDefaultViewPartial(
            
'my_pagination_control.phtml'
        
);
        
// nel controller chiamare $paginator->setView($view);, nel template $this->paginator
    }

}

query dirette

getting the $db object

self::$application = new Zend_Application(...);// get reference to the application object
$db $application->getBootstrap()->getResource('db');
// static access if .ini has a db resource defined
$db Zend_Db_Table::getDefaultAdapter();
// get all
$records $db->fetchAll('SELECT * FROM bugs WHERE bug_id = :bug_id', array('bug_id'=>2) );

// get one
$sql "select count(*) as count from catalog_item where item_id=:item_id";
$count = (int)$db->fetchOne($sql, array(
    
'item_id' => $data['item_id']
));

// update one
$n $db->update('bugs'$data'bug_id = 2');
// udate generico
$n $db->query("UPDATE games SET price = :price WHERE id = :id", array(
    
'price' => '$0.00',
    
'id' => $game['id'])
);

// delete one
$n $db->delete('bugs''bug_id = 3');

// insert
$sql "INSERT INTO catalog_item SET item_id = :item_id";
$db->query($sql$data);

// query generica
$stm $db->query("truncate table catalog_item");
$success $stm->execute();
// placeholder 2
$sql 'SELECT * FROM bugs WHERE ' .
       
'reported_by = :reporter AND bug_status = :status';
$stmt $db->query($sql);
$success $stmt->execute(array(':reporter' => 'goofy'':status' => 'FIXED'));

// fatch
while ($row $stmt->fetch()) {
    echo 
$row['bug_description'];
}
// fetch 2
$rows $stmt->fetchAll();

OOP select

// base
$select $db->select()->from('products');
$stmt $select->query();
$result $stmt->fetchAll();


// avanzata con condizioni
$select $db->select()
             ->
from('products',
                    array(
'product_id''product_name''price'))
             ->
where('price > ?'$minimumPrice)
             ->
orWhere('price < ?'$maximumPrice);
             ->
order('line_items_per_product DESC')

             ->
limitPage(210//  limit(20, 10)
;
$stmt $select->query();
$result $stmt->fetchAll();
var_dump$select->__toString() );

common operations on Tables:

zf create db-table Guestbook guestbook
class Bugs extends Zend_Db_Table_Abstract {
    protected 
$_name 'bugs';
    protected 
$_rowClass 'BugsRow';
    protected 
$_rowsetClass 'My_Rowset';

    
// finders
    public static function findByStatus($status) {
        
$dbAdapter self::getDefaultAdapter();
        
$where $dbAdapter->quoteInto('bug_status = ?'$status);
        return 
$this->fetchAll($where'bug_id');
    }

    
/* triggers
    public function insert(array $data){
        if (empty($data['created_on'])) {
            $data['created_on'] = time();// add a timestamp
        }
        return parent::insert($data);
    }
    public function update(array $data, $where){
        if (empty($data['updated_on'])) {
            $data['updated_on'] = time();// add a timestamp
        }
        return parent::update($data, $where);
    }
    // public function delete($where) { return parent::delete($data, $where); }
    */
}

// contains an individual row of a Zend_Db_Table object
class BugsRow extends Zend_Db_Table_Row_Abstract {
    public function 
init(){}
}
class 
BugsRowset extends Zend_Db_Table_Rowset_Abstract{

}

// uso:
$bugs = new Bugs();
$row $bugs->fetchRow($bugs->select()->where('bug_id = ?'1));

// Returns an object of type My_Rowset, containing an array of objects of type My_Row.
$rows $table->fetchAll($where);

operazioni su Table

// find
$table = new Bugs();
$rows $table->find(1234);// by ID
// Also returns a Rowset
$rows $table->find(array(12345678));
$o $rows->getRow();

// find filtered
$table = new Bugs();
$select  $table->select()->where('bug_status = ?''NEW')
                           ->
order('bug_id');
$row $table->fetchRow($select);

// insert
$table = new Bugs();
$data = array(
    
'created_on'      => '2007-03-22',
    
'bug_description' => 'Something wrong',
    
'bug_status'      => 'NEW'
);
$table->insert($data);

// insert OO
$bugs = new Bugs();
$newRow $bugs->createRow();
$newRow->bug_description '...description...';
$newRow->bug_status 'NEW';
$newRow->save();

// update
$bugs = new Bugs();
$row $bugs->fetchRow($bugs->select()->where('bug_id = ?'1));
$row->bug_status 'FIXED';
$row->save();

paginate result sets

<?php
// model code
//  incorpora la logica di validazione(solo attivi) e paginazione
public function findAllPaginated($where$order$page=1){
    
$sql '';
    
$sql .= " I.flag_attivo = 1 ";
    
$sql .= $where;

    
$query $this->select();
    
$query->from(array('I' => 'catalog_item'));
    
$query->joinLeft(
        array(
'I2C'=>'catalog_item_has_category'),
        
'I2C.item_id = I.item_id',
        array()
    );
    
$query->joinLeft(
        array(
'C'=>'category'),
        
'I2C.category_id = C.category_id',
        array()
    );
    
$query->where($sql);
    
$query->order($order);

    echo 
'<pre>',var_dump($query->__toString()); // dbg
    die(__FUNCTION__.__FILE__);


    
$data_adapter = new Zend_Paginator_Adapter_DbTableSelect($query);
    
$paginator = new Zend_Paginator$data_adapter );
    
$paginator->setItemCountPerPageZend_Registry::get('config')->pagination->num_per_page );
    
$paginator->setCurrentPageNumber$page );

    return 
$paginator;
}

// controller code
$game = new Default_Game_Model();
$this->view->platformGames $game->getGamesByPlatform($platform$page);
?>

// view code
<?= $this->paginationControl($this->platformGames'Sliding''my_pagination.phtml'); ?>

<?php if (count($this->platformGames) > 0) { ?>
<?php 
foreach ($this->platformGames AS $game) { ?>
echo "{$game->name} <br />";
<?php ?>
<?php 
?>

model e modelMapper

meglio evitare model e mappers, non sono ben supportati dal framework

controllers

http://framework.zend.com/manual/en/zend.controller.action.html

class FooController extends Zend_Controller_Action {
    
// init code!
    public function init() {

        
// many different layouts
        $layout $this->_helper->layout();
        
$layout->setLayout('three-column');

        
// rendering a template which is not the default (named after the controller's name)
        $this->_helper->viewRenderer('new');
        
// rendering a template and use the html produced
        $html $this->view->render('alternate.phtml');


        
//controller front
        Zend_Controller_Front::getInstance()->setParam('noViewRenderer'true);

        
$response $this->getResponse();
        
$request  $this->getRequest();
        
// $request = Zend_Controller_Front::getInstance()->getRequest();

        // get params
        $request->getParam(); //_GET
        $request->getPost('user'); //_POST
        $request->isGet();
        
$request->isPost();
        
$request->isXmlHttpRequest()

        
$request->getCurrentRouteName() // route name
        $request->getCurrentRoute()     // route object

        // alias a request
        $id $this->_getParam('id'1);

        
// flash messages
        $F $this->_helper->getHelper('FlashMessenger');
        
$flashList Zend_Controller_Action_HelperBroker::getStaticHelper('flashMessenger');
        
$F->addMessage('emissione ordine','error'|'success');
        
$F->getMessages('default'|'error'|'success');

        
// title
        $this->headTitle('Zend Framework');

        
// Redirect
        $this->_redirector $this->_helper->getHelper('Redirector');
        
$this->_redirector->setCode(303)
            ->
setExit(false)
            ->
setGotoSimple("this-action""some-controller"null$parms=array('id'=>1) );
        
$this->_redirector->gotoUrl('/my-controller/my-action/param1/test/param2/test2');
        
// Zend_Controller_Router_Route name
        $this->_redirector->gotoRoute(
            array(
'year' => 2006,
                
'month' => 4,
                
'day' => 24,
                
'id' => 42),
            
'blogArchive'
        
);

        
// create url in controller
        $url $this->view->url(array('order_id'=>5142'order_date'=>20121228),'order_detail');
        
$this->_redirect($url);
        
$this->_forward($action$controller null$module null, array $params null);

        
// perform another action. If called in preDispatch(), the currently requested action will be skipped in favor of the new one.
        // Otherwise, after the current action is processed, the action requested in _forward() will be executed.
        $this->_redirect($url, array $options = array())
    }

    
// JSON AJAX
    public function searchAction(){
        
$data=array('ok'$this->getRequest()->getQuery('term'''));
        
$this->_helper->layout()->disableLayout();
        
$this->_helper->viewRenderer->setNoRender(true);
        echo 
json_encode($data);
        
// OPPURE
        die(json_encode($data));
    }
}

action helpers:

riusare logica trai controller, azioni e modules. utile a inizializzare variabili da usare nel layout. Action helpers have pre and post hooks too. Plugin is that plugin can deal with the behave of the request.

Zend_Controller_Action_HelperBroker::addPath(
    
APPLICATION_PATH .'/controller_helpers');
// or simpler
Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_Multiples());


class 
Zend_Controller_Action_Helper_Multiples extends
Zend_Controller_Action_Helper_Abstract {
    
// reusable logic
    function direct($a) { return $a 2; }
    function 
thrice($a) { return $a 3; }
}

// calling action helper
class IndexController extends Zend_Controller_Action {
    public function 
indexAction(){
        
$twice $this->_helper->multiples($number);
        
$thrice $this->_helper->multiples->thrice($number);
    }
}

static access to res

$R Zend_Controller_Front::getInstance()->getRequest();
$V null;
$U Zend_Auth::getInstance()->getIdentity();

Routing

protected function _initRoutes() {
    
$frontController Zend_Controller_Front::getInstance();
    
$router $frontController->getRouter();// a rewrite router, by default
    $router->setGlobalParam('lang''it');

    
$router->addRoute'catalog_by_id',
        new 
Zend_Controller_Router_Route('catalog/category/:category_id',
            array(
                
'controller' => 'catalog',
                
'action'     => 'category'
                
)
            )
        );

    
$route = new Zend_Controller_Router_Route(
        
'archive/:year',
        array(
            
'controller' => 'archive',
            
'action'     => 'show'
            'year'       
=> 2006//default param
            ),
            array(
'year' => '\d+'// validation param
    );
    
$router->addRoute('archive'$route);
}

Forms

zf create form Guestbook
class Application_Form_Login extends Zend_Form {
    public function 
init() {
        
$this->setAction('/login/signup/')
            ->
setMethod('post')
            ->
setName('create_account');

        
$els=array();
        
$name = new Zend_Form_Element_Text('name');
        
$name->setLabel('Nome:')
            ->
setRequired(true)
            ->
addValidator('Alnum')
            ->
addErrorMessage('Please provide an name value');
        
$els[] = $name;

           
$hitem_id = new Zend_Form_Element_Hidden('item_id');
           
$hitem_id->setValue($item_id);
           
$hitem_id->setDecorators(array('ViewHelper'));// toglie dl/dd
           $els[] = $hitem_id;

        
$submit = new Zend_Form_Element_Submit('submit', array('class'=>'btn btn-primary'));
        
$submit->setLabel('Login');
        
$els[] = $submit;

        
// many more widget ...

        for( $i=0$i count($els); $i++){
            
$this->addElement($els[$i]);
        }
    }

    
/* custom validation logic
    public function isValid($data) {
        if (!parent::isValid($data)) {
            return false;
        } else {
            return true;
        }
    } */
}
// popolare select da DB
$status = new Zend_Form_Element_Select('status');
$status->AddMultiOptions(array(
    
=> "On the Shelf",
    
=> "Currently Playing",
    
=> "For Sale",
    
=> "On Loan"
));

$db Zend_Db_Table_Abstract::getDefaultAdapter();
$options $db->fetchPairs($db->select()->from('status', array('id''name'))->order('name ASC'), 'id');
$status = new Zend_Form_Element_Select('status');
$status->AddMultiOptions($options);

database validation:

$val_opt = array(
            
'adapter'=>Zend_Db_Table::getDefaultAdapter(),
            
'field'=>'email',
            
'table'=>'login' );
$email = new Zend_Form_Element_Text('email');
$email->setLabel('Email:')
        ->
setRequired(true)
        ->
addValidator('EmailAddress')
        ->
addValidator(new Zend_Validate_Db_NoRecordExists$val_opt ) )
        ->
addErrorMessage('Please provide an email value');
// NotEmpty     Returns false if argument is empty
// StringLength Returns false if argument does not conform to specified minimum/maximum length
// InArray      Returns false if argument is not in specified array
// Identical    Returns false if argument does not match specified value
// Alnum        Returns false if argument does not contain only alphanumeric characters
// Alpha        Returns false if argument does not contain only alphabetic characters
// Int          Returns false if argument is not an integer
// Float        Returns false if argument is not a floating-point number
// Hex          Returns false if argument is not a hexadecimal value
// Digits       Returns false if argument does not contain only numbers
// Between      Returns false if argument is not in a specified numeric range
// GreaterThan         Returns false if argument is not greater than a specified value
// LessThan            Returns false if argument is not less than a specified value
// Date                Returns false if argument is not a valid date
// EmailAddress        Returns false if argument does not conform to standard email address conventions
// Hostname            Returns false if argument does not conform to standard host name conventions
// Ip                  Returns false if argument does not conform to standard IP address conventions
// Regex               Returns false if argument does not conform to specified regular expression pattern
// Barcode             Returns false if argument is not a valid bar code
// Ccnum               Returns false if argument does not conform to the Luhn algorithm for standard credit card number onventions
// Iban                Returns false if argument is not a valid IBAN number
// Exists              Returns false if argument is not a valid file
// Count               Returns false if number of uploaded files is outside the range specified in argument
// Size                Returns false if uploaded file size is outside the range specified in argument
// FilesSize           Returns false if uploaded file size total is outside the range specified in argument
// Extension           Returns false if uploaded file extension does not match those specified in argument
// MimeType            Returns false if uploaded file MIME type does not match those specified in argument
// IsCompressed        Returns false if uploaded file is not a compressed archive file
// IsImage             Returns false if uploaded file is not an image file
// ImageSize           Returns false if uploaded image dimensions are outside the range specified in argument
// Crc32, Md5, Sha1,   Returns false if uploaded file content does not match the hash value specified in
// Hash argument (supports crc32, md5, and sha1 hash algorithms)
// ExcludeExtension    Returns false if uploaded file extension matches those specified in argument
// ExcludeMimeType     Returns false if uploaded file MIME type matches those specified in argument
// WordCount           Returns false if number of words in uploaded file is outside the range specified in argument
// Db_RecordExists     Returns false if a particular record does not exist in the database and table specified in argument
// Db_NoRecordExists   Returns false if a particular record exists in the database and table specified in argument

->addValidator(new Zend_Validate_Int())
->
addValidator(new Zend_Validate_Between(1,100));
->
addValidator(new Zend_Validate_Alpha(true));
->
addValidator(new Zend_Validate_EmailAddress());

file upload form

public function init() {
    
$this->setAction('/sandbox/example/form')
      ->
setEnctype('multipart/form-data')
      ->
setMethod('post');
      
// create file input for photo upload
      $photo = new Zend_Form_Element_File('photo');
      
$photo->setDestination('/tmp/upload');// NOTA: FONDAMENTALE!
      // ->setMultiFile() per caricare array di file

    // create file input for item images
    $images = new Zend_Form_Element_File('images');
    
$images->setMultiFile(3)
    ->
addValidator('IsImage')
    ->
addValidator('Size'false'204800')
    ->
addValidator('Extension'false'jpg,png,gif')
    ->
addValidator('ImageSize'false, array(
        
'minwidth' => 150,
        
'minheight' => 150,
        
'maxwidth' => 150,
        
'maxheight' => 150
    
))->setValueDisabled(true);
}

function 
action() {
    
$save_path APPLICATION_PATH ."/../tmp/item_file";
    
$input_name 'item_file';

    
$form->getElement($input_name)->setDestination($save_path);
    
$upload $form->getElement($input_name)->getTransferAdapter();
    
$ext pathinfo($upload->getFileName($input_name), PATHINFO_EXTENSION);
    
$upload->clearFilters();
    
$upload->addFilter('Rename', array(
        
'target' => sprintf('%d_%d.%s'$id='test'rand(0,9), $ext),
        
'overwrite' => true
    
));
    
$upload->receive($input_name);
    
// you MUST use following functions for knowing about uploaded file
    // Returns the file name for 'file_path' named file element
    $name $upload->getFileName($input_name);
    
$size $upload->getFileSize($input_name);
    
$mimeType $upload->getMimeType($input_name);

    
Zend_Debug::dump(array(
        
'name' => $name ,
        
'size' => $size ,
    ), 
'upl data:');

    
//  gestione dati
    $uploaded_data $form->getValues();
    
Zend_Debug::dump($uploaded_data'form data:');
}
$f->addFilter(new Zend_Filter_HtmlEntities());
$f->addFilter('Alpha', array('allowWhiteSpace' => true))
$f->addFilter('HtmlEntities');
$f->addFilter('StripTags')
$f->addFilter('HTMLEntities')
$f->addFilter('StringTrim')
$f->addFilter('StringToLower');

setta un rendering template

// form code
$this->setDecorators( array( array('ViewScript', array('viewScript' => '_form_login.phtml'))));
// per ogni campo, rimuovi i decorators di default
$email = new Zend_Form_Element_Text('email');
$email->setAttrib('size'35)
  ->
removeDecorator('label')
  ->
removeDecorator('htmlTag');

Finally, create the file named _form_login.phtml (placing it within application/views/scripts) which was referenced within the FormLogin model. This file is responsible for rendering the form exactly as you'd like it to appear within the browser.

<form id="login" action="<?= $this->element->getAction(); ?>"
method="<?= $this->element->getMethod(); ?>">
<
p>
E-mail Address<br />
<?= 
$this->element->email?>
</p>
<p>
Password<br />
<?= $this->element->pswd?>
</p>
<p>
<?= $this->element->submit?>

rendering personalizzato delle labels

// @see decorator Label
class myform extend Zend_Form {
    
// sovrascrittura rendering delle label per mostrare "*" colorati
    function addElement($element$name NULL$options NULL) {
        
$label $element->getLabel();
        
$label str_replace('*','<span style="color:#c00;">*</span>',$label);
        
$element->setLabel($label);
        
$decorator $element->getDecorator('Label');
        if( !empty(
$decorator) ) {
            
$decorator->setOption('escape'false);
        }
        return 
parent::addElement($element$name$options);
    }
}
// sostituisce decorator Error con rendering personalizzato
$username->addDecorator('Callback', [
    
'callback'  => function($content$element$options) {
        
$view    $element->getView();
        
$errors $element->getMessages();
        if (empty(
$errors)) {
            return 
$content;
        }
        
$s_error implode(' 'array_values($errors) );
        return 
'@@'.$s_error;
    },
    
// 'href'  => 'http://example.com',// passed to callback as option
    'placement' => Zend_Form_Decorator_Abstract::APPEND
]);

action handling form

class GuestbookController extends Zend_Controller_Action {
    
// basic example
    public function signAction() {
        
$request $this->getRequest();
        
$form    = new Application_Form_Guestbook();
        if (
$this->getRequest()->isPost()) {
            if (
$form->isValid($request->getPost())) {
                
$comment = new Application_Model_Guestbook($form->getValues());
                
$mapper  = new Application_Model_GuestbookMapper();
                
$mapper->save($comment);
                return 
$this->_helper->redirector('index');
            }
        }
        
$this->view->form $form;
    }
    
// interaction with model
    public function loginAction() {
    
$form = new Application_Model_FormLogin();
    if ( 
$this->getRequest()->isPost() ) {
        if ( 
$form->isValid($this->_request->getPost()) ) {
            
$db Zend_Db_Table::getDefaultAdapter();
            
$authAdapter = new Zend_Auth_Adapter_DbTable($db);
            
$authAdapter->setTableName('accounts');
            
$authAdapter->setIdentityColumn('email');
            
$authAdapter->setCredentialColumn('pswd');
            
$authAdapter->setCredentialTreatment('MD5(? ) and confirmed = 1');

            
$email=$form->getValue('email');
            
$passwd=$form->getValue('pswd');
            
$authAdapter->setIdentity($email);
            
$authAdapter->setCredential($passwd);

            
$auth Zend_Auth::getInstance();
            
$result $auth->authenticate($authAdapter);

            
// Did the user successfully login?
            if ( $result->isValid() ) {

                
$account = new Application_Model_Account();
                
$lastLogin $account->findByEmail($form->getValue('email'));
                
$lastLogin->last_login date('Y-m-d H:i:s');
                
$lastLogin->save();

                
$this->_helper->flashMessenger->addMessage('You are logged in');
                
$this->_helper->redirector('index''index' );
            } else {
                
$this->view->errors["form"] = array("Login failed." );
            }
        } else {
            
$this->view->errors $form->getErrors();
        }
    }
    
$this->view->form $form;
}

Email

send e-mail(HTML by default):

$mail = new Zend_Mail();
$mail->setFrom(Zend_Registry::get('config')->email->support);
$mail->addTo($form->getValue('email'));
$mail->setSubject("subject");
// Retrieve the e-mail message text
include "_email_template.phtml";
$mail->setBodyText($email);
$mail->send();

SMTP config:

class Bootstrap {
    protected function 
_initEmailTransport() {
        if( 
APPLICATION_ENV == 'development' ){
           
$mailTransport = new Zend_Mail_Transport_File(array('path'=> dirname(__FILE__) ));
        } else {
            
$emailConfig = array(
                
'auth'=> 'login',
                
'username' => Zend_Registry::get('config')->email->username,
                
'password' => Zend_Registry::get('config')->email->password,
                
'ssl'      => Zend_Registry::get('config')->email->protocol,
                
'port'     => Zend_Registry::get('config')->email->port
            
);
            
$mailTransport = new Zend_Mail_Transport_SmtpZend_Registry::get('config')->email->server$emailConfig);
        }
        
Zend_Mail::setDefaultTransport($mailTransport);
    }
}

application ini

# custom config
email.server   = "smtp.gmail.com"
email.port     = 587
email.username = "test@gmail.com"
email.password = "secret"
email.protocol = "tls"

Auth ACL

script login: http://robertbasic.com/blog/login-example-with-zend_auth/

$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('login')->setCredentialColumn('password')->setCredentialTreatment('MD5(?)');
$authAdapter->setIdentityColumn('email');

// pass to the adapter the submitted email and password
$authAdapter->setIdentity($email)->setCredential($password);

$auth Zend_Auth::getInstance();

$result $auth->authenticate($authAdapter);
// is the user a valid one?
if ($result->isValid()) {
    
$userInfo self::getUserInfo($authAdapter);
    
// the default storage is a session with namespace Zend_Auth
    $authStorage $auth->getStorage();
    
$authStorage->write($userInfo);
    
$this->_redirect($this->view->url(array(), 'homepage'));
} else {
    
$a_m $result->getMessages();
}

Cache

// bootstrap setup
$cacheDir = ROOT_DIR . '/var/cache';
$cacheBackEnd = 'File';
// alternatively $cacheBackEnd = 'Sqlite';
if (!is_writable($cacheDir)) {
    // error
}
$frontendOptions = array(
    'lifetime' => $lifetime,
    'automatic_serialization' => true
);
$backendOptions = array(
    'cache_dir' => $cacheDir, // BE FILE
    'cache_db_complete_path' => $cacheDir . '/cache.db', // BE DB
);
return $cacheEngine = Zend_Cache::factory('Core', $cacheBackEnd, $frontendOptions, $backendOptions);
// apc
Zend_Cache::factory('File', 'APC', $frontOps=array(), $backOps=array());
//
// uso nei controller/models
$cacheEngine = Zend_Registry::get('cache');
$c_key = '';
if( ($c_result = $cacheEngine->load($c_key)) === false ) {
    $c_result = ; // do computation
    $cacheEngine->save($c_result, $c_key);
} else {
    // get from cache
}

View

per condividere tra modules:

//include our custom helpers
$view->addHelperPath(APPLICATION_PATH '/views/helpers''My_View_Helper');

definire helpers personalizzati

//  /application/views/helpers/TWBAlert.php
class Zend_View_Helper_TWBAlert extends Zend_View_Helper_Abstract {
    public  function 
TWBAlert($gender) {
        return 
'';
    }
}
// view code
Jason owns 14 games, and <?= $this->Gender("m"); ?> is

Layout

<?php echo $this->doctype() ?>
<html>
<head>
    <?php echo $this->headTitle() ?>
    <?php echo $this->headMeta() ?>
    <?php echo $this->headLink() ?>
    <?php echo $this->headStyle() ?>
    <?php echo $this->headScript() ?>
</head>
<body class="tundra">
    <?php echo $this->layout()->content ?>
    <?php echo $this->inlineScript() ?>
</body>
</html>
// render a file
$view = new Zend_View();
//$view->setScriptPath('/path/to/app/views');
$view->"Hay";
echo 
$view->render('someView.php');


echo 
$this->escape($this->variable);// good view-script practice!
echo $this->url($par=array('username' => 'martel'), $route_name='user');
echo 
$this->translate("Hello from ZF-Boilerplate!");
echo 
$this->partial('pager.phtml''list'$pagerData)


$this->headStyle()->appendStyle($styles, array('conditional' => 'lt IE 7'));
$this->HeadScript()->append();

// breadcrumbs
echo $this->navigation()->breadcrumbs();


echo 
$this->paginationControl($this->paginator'Sliding''my_pagination_control.phtml');
echo 
$this->paginator// se impostate le var globali in bootstrap

$r Zend_Markup::factory('Textile');
$r->render($str);

CLI

<?php
defined
('APPLICATION_PATH') || define('APPLICATION_PATH'realpath(dirname(__FILE__) . '/../application'));

// Define application environment
defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'development'));

// bootstrap app resources
require_once 'Zend/Application.php';
$application = new Zend_ApplicationAPPLICATION_ENVAPPLICATION_PATH '/configs/application.ini' );
$application->bootstrap();

// Setup the CLI Commands
try {
    
$opts = new Zend_Console_Getopt(array(
        
'host|h=s'      => 'Databse Host, required string parameter',
        
'port|p-i'      => 'Database Port, optional integer parameter',
        
'help'          => 'Help'
    
));
    
$opts->parse();
} catch (
Zend_Console_Getopt_Exception $e) {
    exit(
$e->getMessage() ."\n\n"$e->getUsageMessage());
}
// APP MAIN
// access framework and application specific resources
$db $application->getBootstrap()->getResource('db');
$amazonPublicKey Zend_Registry::get('config') ->amazon->product_advertising->public->key;
// Retrieve all of the games stored in the GameNomad database
$data $db->fetchAll('SELECT id, asin, name FROM games ORDER BY id');

I18n

bootsrap {
// traduzione messaggi di errore
$translator = new Zend_Translate(
    
'array',
    
dirname(__FILE__).'/../resources/languages',
    
'it',
    array(
'scan' => Zend_Translate_Adapter::LOCALE_DIRECTORY)
    );
// nome standard del framework, se settato i componenti(es. Zend_Form) tentano di usarlo
// e vanno in errore se non ci sono le traduzioni
// Zend_Registry::set('Zend_Translate', $translator);
// Zend_Form::setDefaultTranslator($translator);
Zend_Validate_Abstract::setDefaultTranslator($translator);


// aggiungere lingue
$translate->addTranslation(APPLICATION_PATH '/../languages/messages.de.php''de_DE');
$translate->addTranslation(APPLICATION_PATH '/../languages/messages.fr_FR.php''fr_FR');



// riconoscimento automatico lingua, dal browser
if ($session->locale) {
    
// define locale, usato da number/date/currency format
    $locale = new Zend_Locale($session->locale);
} else {
    try{
        
$locale = new Zend_Locale(Zend_Locale::BROWSER);
    } catch (
Zend_Locale_Exception $e) {
        
$config $this->getOptions();
        
$locale = new Zend_Locale($config['resources']['locale']['default']);
    }
}
Zend_Registry::set('Zend_Locale'$locale);
Zend_Registry::set('Zend_Translate'$translator);


// Log dei messaggi non trovati
$writer = new Zend_Log_Writer_Stream(APPLICATION_PATH.'/../logs/i18n.log');
$log    = new Zend_Log($writer);

$translate = new Zend_Translate(
    array(
        
'adapter' => 'array',
        
'content' => APPLICATION_PATH.'/i18n/it.php',
        
'locale'  => 'it',
        
//-- log --------------
        'log'             => $log,
        
'logMessage'      => "Missing '%message%' within locale '%locale%'",
        
'logPriority'     => Zend_Log::ALERT,
        
'logUntranslated' => true
    
)
);
}

// uso nelle action:
$this->view->message $translate->_('one'),
// nelle view
echo $this->translate('welcome');

// set locale to session, from param
class action {
    
// action to manually override locale
    public function indexAction() {
        
// if supported locale, add to session
        $has_transl in_array($this->getRequest()->getParam('locale'),array('en_US''en_GB''de_DE''fr_FR'));
        if ( 
$has_transl ) {
            
$session = new Zend_Session_Namespace('_l10n_');
            
$session->locale $this->getRequest()->getParam('locale');
        }
        
// redirect to requesting URL
        $url $this->getRequest()->getServer('HTTP_REFERER');
        
$this->_redirect($url);
    }
}
// view
echo $this->url(array('module' => 'default',
    
'controller' => 'locale''action' => 'index',
    
'locale' => 'en_GB'));

// controller
$url $this->view->url(array('order_id'=>5142'order_date'=>20121228),'order_detail');
$this->_redirect($url);

Zend_Lucene

indexing:

$index Zend_Search_Lucene::create('/tmp/indexes');
foreach (
glob('*.xml') as $file) {
  
// read source xml
  $xml simplexml_load_file($file);
  
// create new document in index
  $doc = new Zend_Search_Lucene_Document();
  
// index and store fields
  $doc->addField(Zend_Search_Lucene_Field::UnIndexed('id'$xml->id));
  
$doc->addField(Zend_Search_Lucene_Field::Text('from'$xml->from));
  
$doc->addField(Zend_Search_Lucene_Field::Text('to'$xml->to));
  
$doc->addField(Zend_Search_Lucene_Field::Text('date'strtotime($xml->date)));
  
$doc->addField(Zend_Search_Lucene_Field::UnStored('subject'$xml->subject));
  
$doc->addField(Zend_Search_Lucene_Field::UnStored('body'$xml->body));
  
// save result to index
  $index->addDocument($doc);
}
// set number of documents in index
$count $index->count();

search:

$config $this->getInvokeArg('bootstrap')->getOption('indexes');
  
$index Zend_Search_Lucene::open($config['indexPath']);
  
$results $index->findZend_Search_Lucene_Search_QueryParser::parse($q) );
  
$this->view->results $results;

TDD phpunit

cd /tests
# exec all tests
$ phpunit
# exec single test
phpunit application/controllers/AccountControllerTest
// basic action testing
public function testDoesAccountIndexPageExistAndReturn200ResponseCode() {
    
$this->dispatch('/about');
    
$this->assertController('about');
    
$this->assertAction('index');
    
$this->assertResponseCode(200);
}

// testare il rendering di un form
public function testContactActionContainsContactForm() {
    
$this->dispatch('/about/contact');
    
$this->assertQueryCount('form#contact'1);
    
$this->assertQueryCount('input[name~="name"]'1);
    
$this->assertQueryCount('input[name~="email"]'1);
    
$this->assertQueryCount('input[name~="message"]'1);
    
$this->assertQueryCount('input[name~="submit"]'1);
}

// testa i valori sono accettati
public function testIsValidContactInformationEmailedToSupport(){
  
$this->request->setMethod('POST')->setPost(array(
      
'name' => 'test',
      
'email' => 'test@gmail.com',
      
'message' => "This is my test message."
  
));
  
$this->dispatch('/about/contact');
  
$this->assertRedirectTo('/');
}

deinclude

toglie gli include dal sorgente per maggiore performance, conviene tenere un backup prima di eseguire la funzione

<?php
$files 
= new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__ '/../src'));
// $file SplFileInfo
foreach ($files as $file) {
    if (!
$file->isFile() || 'php' != $file->getExtension() ) { continue; }
    echo 
$file->getRealPath() . PHP_EOL;
    
$code file_get_contents($file->getRealPath());
    
$code preg_replace("~require_once '[a-zA-Z0-9\/]+\.php';~"'//\\0'$code);
    
$code preg_replace('~require_once "[a-zA-Z0-9\/]+\.php";~''//\\0'$code);
    
$code preg_replace("~require_once\('[a-zA-Z0-9\/]+\.php'\);~"'//\\0'$code);
    
$code preg_replace('~require_once\("[a-zA-Z0-9\/]+\.php"\);~''//\\0'$code);
    
$code preg_replace("~include_once '[a-zA-Z0-9\/]+\.php';~"'//\\0'$code);
    
$code preg_replace('~include_once "[a-zA-Z0-9\/]+\.php";~''//\\0'$code);
    
$code preg_replace("~include_once\('[a-zA-Z0-9\/]+\.php'\);~"'//\\0'$code);
    
$code preg_replace('~include_once\("[a-zA-Z0-9\/]+\.php"\);~''//\\0'$code);
    
file_put_contents($file->getRealPath(), $code);
}