Setting Up Doctrine for Zend Framework 1.9.x

After some fiddling and googling and Zendcast watching 🙂 I figured out how to get the models to generate the way I needed them to.
And figuring out why generate-sql and build-all-reload did not create sql schema nor create any tables in the mysql database.

Directory Structure

Standard ZF directory structure with a few addition (Can’t wait for ZFTool to do all this for us)

├───application
│   ├───configs
│   │   ├───data          < --
│   │   │   ├───fixtures <--
│   │   │   └───sql        <--
│   │   └───migrations  <--
│   ├───controllers
│   ├───models
│   ├───scripts            <-- doctrine.php & bat here
│   └───views
├───library
│   ├───Doctrine        <-- Please use the latest 1.2.x
│   ├───vendor         <-- Do not forget this one or things will be bad.
├───public

 

application.ini

Only applicable parts added.
[production]
phpSettings.date.timezone = "Europe/Stockholm"
autoloaderNamespaces[] = "Doctrine"
doctrine.dsn = "mysql://[email protected]/testbench"
doctrine.data_fixtures_path = APPLICATION_PATH "/configs/data/fixtures"
doctrine.sql_path = APPLICATION_PATH "/configs/data/sql"
doctrine.migrations_path = APPLICATION_PATH "/configs/migrations"
doctrine.yaml_schema_path = APPLICATION_PATH "/configs/schema.yml"
doctrine.models_path = APPLICATION_PATH "/models"

Bootstrap.php

Please note the inline comment about model loading attributes, this is what broke it for me, for some reason using conservative will prevent generation and creation of database tables and schemas, although model generation works fine, very puzzling!.

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {

protected function _initDoctrine() {
$this->getApplication()
->getAutoloader()
->pushAutoloader ( array ('Doctrine', 'autoload' ) );
//spl_autoload_register ( array ('Doctrine', 'modelsAutoload' ) );
$manager = Doctrine_Manager::getInstance ();
$manager->setAttribute ( Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true );
// The Model Loading acts a tad weird - Use Default for now.
//$manager->setAttribute ( Doctrine::ATTR_MODEL_LOADING, Doctrine::MODEL_LOADING_AGGRESIVE); // MODEL_LOADING_CONSERVATIVE
$manager->setAttribute ( Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES, false );

$doctrineConfig = $this->getOption('doctrine');
$conn = Doctrine_Manager::connection($doctrineConfig['dsn'],'doctrine');
$conn->setAttribute(Doctrine::ATTR_USE_NATIVE_ENUM,true);

}
}

doctrine.bat

Since this dev machine is on Windows XP:
@echo off
echo Running Doctrine CLI.
"C:\Zend\ZendServer\bin\php.exe" -f C:\Zend\Apache2\htdocs\testbench\application\scripts\doctrine.php %1 %2 %3 %4 %5 %6 %7 %8 %9

doctrine

If you are linux/mac based: (Dont forget to chmod +x it)

#!/usr/bin/env php
< ?php chdir(dirname(__FILE__)); include('doctrine.php');

doctrine.php

Please note the inline comments in this one and customize it to your own liking.

< ?php /** * Doctrine CLI */ error_reporting(E_ALL); define('ROOT_PATH', realpath(dirname(__FILE__))); define('APPLICATION_PATH', realpath(dirname(__FILE__) . "/../")); define('APPLICATION_ENV', 'development'); //Ensure library/ is on include_path set_include_path(implode(PATH_SEPARATOR, array( '../library',get_include_path() ))); /** Zend_Application */ require_once 'Zend/Application.php'; // Create application, bootstrap, and run $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); // Read in the application.ini bootstrap for Doctrine $application->getBootstrap()->bootstrap('doctrine');

// Create the configuration array
$config = $application->getOption('doctrine');
// (Note you can have all of these in application.ini aswell)
$config['generate_models_options'] = array(
// Define the PHPDoc Block in the generated classes
'phpDocPackage' =>'TestBench',
'phpDocSubpackage' =>'Models',
'phpDocName' =>'Danny Froberg',
'phpDocEmail' =>'[email protected]',
'phpDocVersion' =>'1.0',
// Define whats what and named how, where.
'suffix' => '.php',
'pearStyle' => true,
'baseClassPrefix' => 'Base_',
// Unless you have created a custom class or want Default_Model_Base_Abstract
'baseClassName' => 'Doctrine_Record',
// Leave this empty as specifying 'Base' will create Base/Base
'baseClassesDirectory' => NULL,
// Should make it Zend Framework friendly AFAIK
'classPrefix' => 'Default_Model_',
'classPrefixFiles' => false,
'generateBaseClasses' => true,
'generateTableClasses' => false,
'packagesPath' => APPLICATION_PATH . '/models',
'packagesFolderName' => 'packages',

);

$cli = new Doctrine_Cli($config);
$cli->run($_SERVER['argv']);
?>

In the next article we'll take it for a test spin and generate a few models and such 😉

Enjoy.

Continuous Integration for PHP – phpUnderControl & CruiseControl

Did you know that you can automate unit tests (which is the PHP worlds equalient of compilation checks 🙂 ).

Set up your development team using local checkouts of the project and have them do local PHPUnit tests, check their changes in and then get Continuous Integration checks done on a central server using phpUnderControl that emails the team with success/fail reports, it’s a good way to work.

phpUnderControl is an addon application for the continuous integration tool CruiseControl, which integrates some of the best PHP development tools. This project aims to make your first steps with CruiseControl and PHP as easy as possible. Therefore phpUnderControl comes with a command line tool that performs all modifications to an existing CruiseControl installation.

Integrated tools

  • Testing and software metrics – PHPUnit is the most popular xUnit implementation for PHP that provides a framework for automated software tests. Except the pure test automation PHPUnit contains a rich set of features like Code Coverage, Project Mess Detection and Software Metrics. To visualize the generated XML reports phpUnderControl comes with a set of XSL stylesheets that prepare the output for CruiseControl.
  • Documentation – phpUnderControl uses the most common documentation tool for PHP projects, PhpDocumentor, to generate an up to date documentation of the software on every build cycle. Therefore the developers will always get the latest API documentation of their project. Additionally phpUnderControl extracts the documentation violations found by the PhpDocumentor and visualizes these as an additional quality report in the user interface and the project time line of documentation violations.
  • Coding Standards – With the package PHP_CodeSniffer the PEAR project gave PHP developers a very useful tool to detect coding standard violations in a project. Since version 1.0.0RC3 it has native support for the Checkstyle XML format that can be visualized by CruiseControl. PHP_CodeSniffer comes with a variety of pre defined coding standards like PEAR and ZEND but due to its modular structure you can easily implement a custom rule set or extend one of the pre defined sets. This development tool assures that the whole project code will remain clean and consistent.

Go and check it out today 🙂

Bootstrap Zend_Translate

This entry is part 2 of 4 in the series Working with Zend_Translate and Poedit

A recurring problem for site developers is implementing a solid way to create and maintain multilingual sites, this article series is my feeble attempt to guide you through how to quickly implement the Zend_Translate in an Zend Framework 1.9.x site.

The procedures and best practices for this is unfortunately like training a dog, everyone has a different way of doing it and an opinion, so the methods and code I show here are taken out of applications that are running in production so if you have a better way of doing it please feel free to comment!.

I usually use poedit a gettext editor which is available for most platforms to create my translation files, and after some initial configuration of the catalog paths so it can see your source files please see Part 1 of this article series.

The bootstrap below looks for the language specific gettext .mo files in /application/languages/ for example /application/languages/sv_SE.mo

Bootstrap.php

protected function _initTranslate() {
// We use the Swedish locale as an example
$locale = new Zend_Locale('sv_SE');
Zend_Registry::set('Zend_Locale', $locale);

// Create Session block and save the locale
$session = new Zend_Session_Namespace('session');
$langLocale = isset($session->lang) ? $session->lang : $locale;

// Set up and load the translations (all of them!)
$translate = new Zend_Translate('gettext', APPLICATION_PATH . DIRECTORY_SEPARATOR .'languages', $langLocale,
array('disableNotices' => true));

//$translate->setLocale($langLocale); // Use this if you only want to load the translation matching current locale, experiment.

// Save it for later
$registry = Zend_Registry::getInstance();
$registry->set('Zend_Translate', $translate);
}

Now when you use statements like

translate('Contact Admin'); ?>
in your layout.phtml or view.phtml files it will be picked up by poedit and you will be presented with a string “Contact Admin” to translate, in my case i’ll just enter “Kontakta Administratören”.

There is some debate on what to put in the translate strings as identifiers, I personaly prefer the actual term to translate in a base language, in this case English instead of some convoluted “IDS0001” type strings.

Poedit will keep track of changes, i.e if I would change the “Contact Admin” to “Contact us” it will tell you on synchronization that “Contact Admin” disappeared and a new translation is required for “Contact us”. It’s quite easy to send those strings to your translators.

Thats it for today.

Generate Doctrine models/classes that extend a custom record class

When using using Doctrine 1.2.1 and Zend Framework 1.9.x to generate classes from Yaml/db each Base class (which includes the table definition) extends the Doctrine_Record class.

I need to find a way of telling Doctrine to extend my own Base class, or find a different solution to a master/slave db setup using Doctrine.

Example generated model:

abstract class My_Base_User extends Doctrine_Record
{

However I need it to be automatically generated as:

abstract class My_Base_User extends My_Record
{

And the answer is (drumroll)

Typical, as soon as I ask the question I manage to find the answer. I’m recording it here in case anyone else has the same issue.

You can pass in the parameter ‘baseClassName’ into the generateModels* methods and Doctrine will use that as the Base record class.

Examples:

Doctrine_Core::generateModelsFromDb('models', array('master'), array('generateTableClasses' => true, 'baseClassName' => 'My_Record'));

or using Cli:

$options['generate_models_options'] = array(
'pearStyle'             => true,
'baseClassPrefix'       => 'My_',
'baseClassName'         => 'My_Record',
'classPrefix'           => '',
'classPrefixFiles'      => false,
'generateTableClasses'  => true,
);
$cli = new Doctrine_Cli($options);

Object-relational mapping with Doctrine, Flash Builder, and PHP

Richard Bates @ Zend Developer Zone wrote a good article on my favorite ORM Doctrine integration in Zend;

Rich Internet applications built with Adobe Flex and Flash Builder have been steadily gaining a foothold in enterprise development for quite some time. As the platform has grown and evolved, PHP has also made amazing progress toward becoming a mature, powerful object-oriented language with rapid adoption and dozens of frameworks and design pattern implementations. As PHP continues to prosper, developers are able to borrow more and more of the things Java has got right, taking one check after another from the “Java-only” column. One outstanding example of this is object-relational mapping (ORM). A few different PHP ORM implementations are available, and all of them have positive attributes. However, after some experimentation, I’ve found that Doctrine is my favorite.

Read the complete story;

Object-relational mapping with Doctrine, Flash Builder, and PHP.

Automate Db Model Creation with Zend_CodeGenerator_Php_Class

Joey Rivera wrote a very interesting and time saving article about the Zend_CodeGenerator complete with a easy to use code snippet that will create the model and DbTable files and classes for you, as it picks the information directly from your database, it’s no way those pesky typos and cut and paste mistakes creep in when you have to do 10 (or 300) almost identical files.

Worth checking out; Joey’s Blog

Console ProgressBar and Text

The query was; How to set the Text Label on the progressbar in console mode.
The answer by Michael “Ray” Rehbein: You want to set the ‘elements’ option of the adapter.

http://framework.zend.com/manual/en/zend.progressbar.html#zend.progressbar.adapter.console


$pbAdapter = new Zend_ProgressBar_Adapter_Console(
array('elements'=>
array(Zend_ProgressBar_Adapter_Console::ELEMENT_PERCENT,
Zend_ProgressBar_Adapter_Console::ELEMENT_BAR,
Zend_ProgressBar_Adapter_Console::ELEMENT_ETA,
Zend_ProgressBar_Adapter_Console::ELEMENT_TEXT)
)
);

$progressBar = new Zend_ProgressBar($pbAdapter, 0, 10);

for ($i = 0; $i < 10; $i++) {
sleep(1);
$progressBar->update($i, "Iteration: {$i}"); } $progressBar->finish();
}

Quite nifty.

ZamfBrowser 1.0

When doing AMF projects especially in AIR it’s good to see what gets returned from your Zend_AMF services, here is the solution; ZamfBrowser allows developers to unit test ZendAMF Service classes via an Adobe AIR application. Implementation requires a simple edit to the ZendAMF gateway file that allows ZamfBrowser to introspect your server set up and provide access for all classes and methods registered with the Zend_Amf_Server object. For version 1.0 the ZamfBrowser AIR source code is still closed, but it is intended to go Open Source as soon as the source code documentation is complete and a couple of features are implemented that are still in the pipeline.

Go and get it: http://www.zamfbrowser.org/

SVN Externals

The official SVN online manual has an article on this, please read it. I won’t let myself off the hook that easy and will give you a brief example on how to use them. Let’s say you have your own MVC project based on Zend Framework. You should off course store your app in SVN, but using the following command you can dynamically link the framework to you library folder. Please consider the following command knowing that our present working directory is ‘library’:

svn propset 'svn:externals' 'Zend http://framework.zend.com/svn/framework/standard/tags/release-1.7.6/library/Zend' .

This command wil link the Zend library and after performing an svn up your working copy will also include version 1.7.6 of Zend Framework. Please also consider commiting, because other checkouts need to sync the framework too. Maybe I should explain the different fragments of the command too:

  • svn propset: this part will set a property
  • svn:externals: the property we’re gonna set is called ’svn:externals’
  • Zend: we will create a folder called ‘Zend’ which is a checkout of a specific version
  • The URL. Quite self-explanatory
  • The dot (.): the dot specifies that the checkout will happen in the current folder. You can also put a directory name in there

Happy versioning!