<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PHPGuru.ro</title>
	<atom:link href="http://www.phpguru.ro/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.phpguru.ro</link>
	<description>var_dump and die</description>
	<lastBuildDate>Sun, 20 Jun 2010 12:19:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Zend Framework 1.10.5 and Doctrine 2.0 integration</title>
		<link>http://www.phpguru.ro/articles/zf110_doctrine2/</link>
		<comments>http://www.phpguru.ro/articles/zf110_doctrine2/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 07:43:58 +0000</pubDate>
		<dc:creator>Costin Bereveanu</dc:creator>
				<category><![CDATA[PHP Articles]]></category>
		<category><![CDATA[Doctrine2]]></category>
		<category><![CDATA[PHP5]]></category>
		<category><![CDATA[ZendFramework]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://www.phpguru.ro/?p=8</guid>
		<description><![CDATA[A brief tutorial on integrating ZendFramework 1.10.5 and Doctrine 2.0 in a reusable, non obtrusive way. PHP 5.3 required (due to Doctrine 2).  <a href="http://www.phpguru.ro/articles/zf110_doctrine2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As not all of us are willing to let go <a href="http://framework.zend.com">ZF</a> for <a href="http://www.symfony-project.org">Symfony</a>, the native environment for Doctrine, here is a clean way of integrating Doctrine 2 into your ZF projects.</p>
<p>As the integration method chosen was to create an application resource, you may enable both new projects and existing ones to use Doctrine 2 without changing a single line of bootstrap code.</p>
<p>Added bonus &#8211; memcache integration and a custom Doctrine 2 eAccelerator caching class which I strongly advice against using, at least on Windows <img src='http://www.phpguru.ro/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Requirements:</p>
<ul>
<li>PHP 5.3</li>
<li><a href="http://framework.zend.com/download/latest">ZF 1.10.5 or compatible</a></li>
<li><a href="http://www.doctrine-project.org/projects/orm/download">Doctrine 2.0 beta 2 or compatible</a></li>
<li><a href="http://labs.northscale.com/memcached-packages">Memcache</a> (optional, available on Windows too)</li>
<li>Some of the <a href="http://www.phpguru.ro/download/zf_1.10_doctrine_2.0.rar">attached source code</a></li>
</ul>
<p><span style="font-size: medium;"><span style="line-height: 24px;"><span id="more-8"></span></span></span><br />
Initial setup:<br />
Get ZF and Doctrine 2 and unpack them in the dedicated folders, in the library project folder (make sure you only have library/Zend, not library/Zend/Zend).<br />
Move the folder Symfony from the Doctrine folder onto the one from library, overwriting it (I just thought it would be nice not to have multi layered library folders).<br />
Leave out the tests, bins and other files from both ZF and Doctrine.<br />
Copy the needed files from the attached source folder (library/Keops and the root doctrine files).</p>
<p>You will notice that in the attached project you will have some doctrine related files in the root of your project: these are files created based on the Doctrine 2 sandbox sample. They will allow you to use the very cool Doctrine command line (doctrine.bat) and help you propagate changes from your entities to the db.<br />
The  database connection information is hard coded in doctrine-cli-config.php too, besides application.ini &#8211; when I first integrated ZF and Doctrine 1 I have also updated the CLI tool to read its settings from application.ini; now I guess I was a bit lazy. Anyway, please feel free to do that.</p>
<p>Here is the code of the resource class, located in library/Keops/Application/Resource:</p>
<pre>class Keops_Application_Resource_Doctrine2
      extends Zend_Application_Resource_ResourceAbstract
{
    public function init()
    {
        $bootstrapOptions = $this-&gt;getBootstrap()-&gt;getOptions();

        $options = $this-&gt;getOptions();
        $memcache = null;

        $doctrineConfig = new \Doctrine\ORM\Configuration();
        if (!empty($options['options']['metadataCache'])) {
            $metaCache = new $options['options']['metadataCache']();
            if ($metaCache instanceof
                    \Doctrine\Common\Cache\MemcacheCache) {
                $memcache = new Memcache();
                $memcache-&gt;connect('localhost', 11211);
                $metaCache-&gt;setMemcache($memcache);
            }
            $doctrineConfig-&gt;setMetadataCacheImpl($metaCache);
        }
        if (!empty($options['options']['queryCache'])) {
            $queryCache = new $options['options']['queryCache']();
            if ($queryCache instanceof
                    \Doctrine\Common\Cache\MemcacheCache) {
                if (is_null($memcache)) {
                    $memcache = new Memcache();
                    $memcache-&gt;connect('localhost', 11211);
                }
                $queryCache-&gt;setMemcache($memcache);
            }
            $doctrineConfig-&gt;setQueryCacheImpl($queryCache);
        }

        $driverImpl =
            $doctrineConfig-&gt;newDefaultAnnotationDriver(
                array($options['paths']['entities']));
        $doctrineConfig-&gt;setMetadataDriverImpl($driverImpl);
        //$doctrineConfig-&gt;setEntityNamespaces(
        //    $options['entitiesNamespaces']);

        $doctrineConfig-&gt;setProxyDir($options['paths']['proxies']);
        $doctrineConfig-&gt;setProxyNamespace(
            $options['options']['proxiesNamespace']);

        $this-&gt;getBootstrap()-&gt;em =
            \Doctrine\ORM\EntityManager::create(
                $options['connections']['doctrine'],
                $doctrineConfig);
        return $this-&gt;getBootstrap()-&gt;em;
    }
}</pre>
<p>As you may have probably noticed, the resource is configured to run on a memcache caching system. For testing, you may replace that with the included ArrayCache. For production you should definitely use a caching mechanism though. I don&#8217;t want to turn this into neither a ZF or a Doctrine tutorial, so let&#8217;s leave the subject.</p>
<p>All you need to do to make this work now is to add some settings to application.ini, enabling the new resource; add these to your [production] section:</p>
<pre>pluginPaths.Keops_Application_Resource = APPLICATION_PATH "/../library/Keops/Application/Resource"
autoloaderNamespaces[] = "Doctrine"
autoloaderNamespaces[] = "Keops"
autoloaderNamespaces[] = "Entities"
resources.doctrine2.options.metadataCache = "Doctrine\Common\Cache\MemcacheCache"
resources.doctrine2.options.queryCache = "Doctrine\Common\Cache\MemcacheCache"
resources.doctrine2.options.proxiesNamespace = "Proxies"
resources.doctrine2.paths.entities = APPLICATION_PATH "/doctrine/entities"
resources.doctrine2.paths.proxies = APPLICATION_PATH "/doctrine/proxies"
resources.doctrine2.connections.doctrine.driver = "pdo_mysql"
resources.doctrine2.connections.doctrine.dbname = "eplaza"
resources.doctrine2.connections.doctrine.user = "root"
resources.doctrine2.connections.doctrine.password = "root"</pre>
<p>As you can see, you can customize connection details, multiple database connections (just add more entries to resources.doctrine2.connections), separate caching for queries and metadata (the memcache PHP client will actually be shared) and the path to the entities and auto generated proxies. If you intend to change any of the paths, make sure the CLI tool is updated accordingly.</p>
<p>You are set up! All you need to do now is edit your entities from application/doctrine/entities like the one below:</p>
<pre>namespace Entities;

/**
 * @Entity
 */
class Store
{
    /**
     * @Id @Column(type="integer", name="store_id")
     * @GeneratedValue
     */
    protected $id;

    /**
     * @Column(length=32, nullable=TRUE)
     */
    protected $ext_code;

    /**
     * @Column(length=64)
     */
    protected $name;

    /**
     * @Column(length=8)
     */
    protected $status;

    /**
     * @Column(type="datetime")
     */
    protected $create_ts;

    public function getId()
    {
        return $this-&gt;id;
    }

    public function getName()
    {
        return $this-&gt;name;
    }

    public function setName($name)
    {
        $this-&gt;name = $name;
    }

    public function getExtCode() {
        return $this-&gt;ext_code;
    }

    public function setExtCode($ext_code) {
        $this-&gt;ext_code = $ext_code;
    }

    public function getStatus() {
        return $this-&gt;status;
    }

    public function setStatus($status) {
        $this-&gt;status = $status;
    }

    public function getCreateTs() {
        return $this-&gt;create_ts;
    }

    public function setCreateTs($create_ts) {
        $this-&gt;create_ts = $create_ts;
    }

}</pre>
<p>Update the db mappings (this will update the db and create proxies in application/doctrine/proxies; don&#8217;t remember if you need to create the database before the first run):</p>
<pre>doctrine-update.bat</pre>
<p>And use your new Doctrine 2 ORM:</p>
<pre>class IndexController extends Zend_Rest_Controller
{

    public function indexAction()
    {
        $em = $this-&gt;getInvokeArg('bootstrap')-&gt;em;

        $store = new \Entities\Store();
        $store-&gt;setName('Paris');
        $store-&gt;setStatus('A');
        $store-&gt;setCreateTs(
            new DateTime(Zend_Date::now()-&gt;get(Zend_Date::ISO_8601)));
        $em-&gt;persist($store);
        $em-&gt;flush();

        echo $this-&gt;_helper-&gt;json(
            array('success' =&gt; true, 'newRecordId' =&gt; $store-&gt;getId()));
    }
}</pre>
<p>In the root folder you will find also a doctrine-regen.bat file &#8211; this one will drop the schema and recreate all tables, so make sure you don&#8217;t have any data in the database that you will cry after. Usually you will use doctrine-update.bat, which shouldn&#8217;t delete anything.</p>
<p>I&#8217;ve had some issues putting it all together, especially with the whole Zend autoloader &#8211; Doctrine namespaces thing but it just seemed like a good direction to point my next projects to. Hope some of you will find this useful.</p>
<p>Peace!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpguru.ro/articles/zf110_doctrine2/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
	</channel>
</rss>

