Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend Tool and Doctrine 1 Integration Component Proposal

Proposed Component Name Zend Tool and Doctrine 1 Integration
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Zend Tool and Doctrine 1 Integration
Proposers Benjamin Eberlei
Zend Liaison TBD
Revision 1.0 - 9th November 2009 (wiki revision: 7)

Table of Contents

1. Overview

This Proposal aims to integrate Zend Framework and Doctrine 1 via Zend Tool.
All Doctrine 1 CLI commands will be integrated into the Zend_Tool project context
and additional context resources are provided to support Doctrine metadata,
migrations, fixture etc. Both non-modular and modular applications should
be supported for the task of generating models and tables. This proposal
sets on top of Doctrine 1 resource proposal by Matthew Lurz.

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

  • This component MUST use Doctrine 1 Resource for Zend_Application
    • This resource SHOULD be usable with both Modular and non-modular MVC application.
  • This component MUST integrate all Doctrine 1 CLI Tasks
  • This component SHOULD offer additional Zend Project Context Resources that are required for Doctrine.
  • This component SHOULD offer further providers that help the integration of ZF and Doctrine
    • This component SHOULD make use of other Zend components for this goal.
    • This component SHOULD support prototyping of forms
    • This component MAY support Zend_Test and Doctrine integration.

4. Dependencies on Other Framework Components

  • Zend_Application
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Form
  • Zend_CodeGenerator
  • Doctrine 1.2

5. Theory of Operation

The Zend Tool integration will use the configured Zend Application resource
to configure Doctrine 1 for the use with Schema Tool or other CLI tasks.

With a configured Doctrine resource you will be able to issue the following commands:

Commands will all make heavy use of --verbose and --pretend flags.

You should be able to configure via the doctrine resource if you want to use code-generation
to generate abstract classes for forms or tables of Doctrine_Record's.

Usage would look like:

Zend Tool would keep track of the Doctrine context directories and will make sure that the generation
is taking place as configured. If you want to generate different records/tables into different modules
you have to configure the modules accordingly, this will take place in a new config file being called
"doctrine-modules.ini" which has the Doctrine Model <-> ZF Module relationsships and can either be
edited by hand or be configured with the help of "zf configure doctrine.module" and "zf assign-model doctrine.module".

It will now generate the classes in ZF-Style (Supported by Resource Loader):

Or in Pear Style:

With the help of Doctrine Model and Table context files it is possible to find orphaned files at this
point and delete them.

All this is up for discussion and changes, its just an outline over what I think is possible and could be done to integrate Zend Tool and Doctrine 1. What do you think?

6. Milestones / Tasks

  • Milestone 1: Community Review
  • Milestone 2: Prototype
  • Milestone 3: Zend Acceptance
  • Milestone 4: Completion & Documentation

7. Class Index

  • Zend_Doctrine_Tool_Provider_Doctrine
  • Zend_Doctrine_Tool_DoctrineTasks
  • Zend_Doctrine_Tool_Context_DataFixturesDirectory
  • Zend_Doctrine_Tool_Context_MigrationsDirectory
  • Zend_Doctrine_Tool_Context_SqlDirectory
  • Zend_Doctrine_Tool_Context_ModelsDirectory
  • Zend_Doctrine_Tool_Context_YamlSchemaDirectory
  • Zend_Doctrine_Tool_Context_ModelFile
  • Zend_Doctrine_Tool_Context_TableFile
  • Zend_Doctrine_Tool_Context_ModelsAbstractDirectory
  • Zend_Doctrine_Tool_Context_ModelAbstractFile
  • Zend_Doctrine_Tool_Context_TableAbstractFile
  • Zend_Doctrine_Tool_Context_DoctrineModuleConfigFile
  • Zend_Doctrine_Tool_Context_FormDirectory
  • Zend_Doctrine_Tool_Context_FormFile
  • Zend_Doctrine_Tool_Context_FormAbstractFile
  • Zend_Doctrine_Form
  • Zend_Doctrine_CodeGenerator_Form
  • Zend_Doctrine_Import
  • Zend_Doctrine_Import_Builder

8. Use Cases

9. Class Skeletons

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Nov 11, 2009

    <p>Hi. I welcome this initiative!<br />
    Why would one need a ini to map modules to models? Matthews resource plugin defines paths in its .ini for each model you wish to create. One is free to point them at a module... I feel I am missing something...<br />
    One of the problems that is consistently emerging is modular support. Could someone be a little verbose on expressing the exact problem of modular support? Also (how) does this tie in with autoloading and or PEAR style model organization (Doctrine 1.2+). Should the model class names reflect the module name? (Model_Base_Entity vs CMS_Model_Base_Entity) Ah, questions, tastes and best practices...</p>

    <p>And some concrete feedback : Proposed is to put doctrine models in the directory 'module/models'. Personally I have other, none-doctrine, model classes at that location (so these can be used from both controllers and amf-services) and therefore place the doctrine models within a directory called doctrine.</p>

    <p>module/models/... (custom model classes)<br />
    module/models/doctrine/...</p>

    1. Nov 11, 2009

      <p>The problem is not ZF not going to find the models, the problem is that Doctrine Schema files don't support the notion of a module. That means you would want to have a means to generate the models into different modules, say you have three modules: Default, Cms and Guestbook.</p>

      <p>Then you have different models, User, Article, Category, Comment, (Guestbook)-Entry.</p>

      <p>You would want to have the following generation of the models:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      User => Model_User
      Article => Cms_Model_Article
      Category => Cms_Model_Category
      Comment => Cms_Model_Comment
      GuestbookEntry => Guestbook_Model_Entry
      ]]></ac:plain-text-body></ac:macro>

      <p>This has to be configured in an additional way for the Doctrine Import scripts (CLI ./doctrine generate-models) to build the files correctly.</p>

      <p>For your example you could define the doctrine paths to be:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      Default Module => Model_Doctrine_
      Cms => Cms_Model_Doctrine_
      Guestbook => Guestbook_Model_Doctrine_
      ]]></ac:plain-text-body></ac:macro>

      <p>with the respective:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      User => Model_Doctrine_User
      Article => Cms_Model_Doctrine_Article
      Category => Cms_Model_Doctrine_Category
      Comment => Cms_Model_Doctrine_Comment
      GuestbookEntry => Guestbook_Model_Doctrine_Entry
      ]]></ac:plain-text-body></ac:macro>

      <p>This way these files for this classes won't be mixed with your other model files.</p>

  2. Nov 11, 2009

    <p>Wouldn't want one to be able to only run commands on a single module? I know I would<br />
    example :</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    zf create doctrine <moduleName> # Generate all Database, Models, Forms for module moduleName
    zf rebuild doctrine.db <moduleName> # Drop and Create database for module moduleName
    zf load doctrine.data <moduleName> # Loads data from fixtures directory for module moduleName
    ... etc ...
    ]]></ac:plain-text-body></ac:macro>

    1. Nov 11, 2009

      <p>great idea, i buy it <ac:emoticon ac:name="smile" /></p>

    2. Nov 11, 2009

      <p>Good catch Bas. I just wanted to point out that care would need to be taken in the case of interdependent modules due to connection binding, see <a class="external-link" href="http://www.doctrine-project.org/documentation/manual/1_1/en/yaml-schema-files#features-examples:connection-binding">http://www.doctrine-project.org/documentation/manual/1_1/en/yaml-schema-files#features-examples:connection-binding</a>. In these cases, models for 2 or more modules could be bound to same connection.</p>

  3. Dec 12, 2009

    <p>I'd suggest grouping all doctrine tasks under one namespace if possible. It's good practise all along ZF.</p>
    <ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
    zf doctrine build-all

    zf doctrine build-all-reload
    ]]></ac:plain-text-body></ac:macro>
    <p>etc. This is (at least for me) expected behaviour. </p>

    1. Dec 12, 2009

      <p>Zend Tool has namespaces at third position, for semantic reasons.</p>

      <p>zf <action> <provider>.</p>

      <p>The Provider will be Doctrine, so its all grouped in one namespace.</p>

  4. Dec 14, 2009

    <p>Is it possible to access the code of this proposal? It's all included in the Zym git repository, but it's not accessible at all. Could you point out where we can download the complete Doctrine namespace for Zend Tool? Copy/paste every file from the webinterface is too much work <ac:emoticon ac:name="wink" /></p>

  5. Dec 15, 2009

    <p>I have another comment, a bit related to the one Bas K posted at first. I think it's a good idea to have the ability configure paths relative to a module's root. In combination with the module specific commands (zf create doctrine <moduleName>) this component will be very flexible in respect of modular loading and generation of models.</p>

    <p>I'd like to have all module specific information inside my module directory. That said, for now I have this set of configuration:</p>
    <ul>
    <li>scheme file: configs/scheme.yml</li>
    <li>fixtures: configs/data/fixtures/</li>
    <li>sql: configs/data/sql/</li>
    <li>migration: configs/migrations/</li>
    <li>models: models/<br />
    This means the scheme file for e.g. a guestbook module is located at application/modules/guestbook/configs/scheme.yml</li>
    </ul>

    <p>I took care of the autoloading with the modules application resource (<a class="external-link" href="http://juriansluiman.nl/en/blog/article/105/doctrine-modular-loading-of-models">http://juriansluiman.nl/en/blog/article/105/doctrine-modular-loading-of-models</a>). I think the module-based configuration (for both config files and the models/forms) is a more flexible approach to keep the loved ZF modular structure including the Doctrine advantages.</p>

    <p>My comment has several implications:</p>
    <ul>
    <li>Mapping (configure doctrine.module & assign-model doctrine.module) isn't required anymore, the module controls itself</li>
    <li>Actions with a module argument are easy and convenient to implement</li>
    <li>Actions without a module argument loops through all modules to perform the selected action (this might be the negative side of my comment)</li>
    </ul>

    <p>I think there are several options to configure Doctrine such it's intelligent with loading the models in Zend's modular structure. A lot of information is spread lately about the integration of Doctrine with ZF, but 99% forgets the modular structure because Doctrine doesn't provide such an organized structure. I hope with the integration of Doctrine 1 and Zend_Tool (this proposal) we look more at this problem and provide a better method to keep things inside the module directory (imho the preferred method).<br />
    I know my comment doens't only apply to this proposal, but is also meant for the Doctrine resource (<a class="external-link" href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Application_Resource_Doctrine+-+Matthew+Lurz">http://framework.zend.com/wiki/display/ZFPROP/Zend_Application_Resource_Doctrine+-+Matthew+Lurz</a>). I thought this was the best place to put my ideas down <ac:emoticon ac:name="smile" /></p>

  6. Mar 08, 2010

    <p>I committed the first working version of my tooling support for ZF + Doctrine prototype to my user branch: </p>

    <p><a class="external-link" href="http://framework.zend.com/svn/framework/standard/branches/user/beberlei/zfdoctrine/">http://framework.zend.com/svn/framework/standard/branches/user/beberlei/zfdoctrine/</a></p>

    <p>Using it boils down to the following commands:</p>

    <p>First you need to modify your .zf.ini to look for the DoctrineProvider in "library/Zend/Doctrine/Tool/DoctrineProvider.php"</p>

    <p>Then:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    zf create project foo
    cd foo
    zf create-project doctrine --dsn="dsnhere" --with-resource-directories
    zf create module addressbook
    ]]></ac:plain-text-body></ac:macro>

    <p>Now you can go to your application/config/schema directory and create a yaml schema, for example:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    Model_User:
    tableName: users
    columns:
    username:
    type: string(255)
    password:
    type: string(255)
    contact_id:
    type: integer
    relations:
    Contact:
    class: Addressbook_Model_Contact
    local: contact_id
    foreign: id
    foreignAlias: User
    foreignType: one
    type: one

    Addressbook_Model_Contact:
    tableName: contacts
    columns:
    first_name:
    type: string(255)
    last_name:
    type: string(255)
    phone:
    type: string(255)
    email:
    type: string(255)
    address:
    type: string(255)
    relations:
    User:
    class: Model_User
    local: id
    foreign: contact_id
    foreignAlias: Contact
    foreignType: one
    type: one
    ]]></ac:plain-text-body></ac:macro>

    <p>Plus add the module resource loaders to your Bootstrap:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    public function _initResourceLoaders()

    Unknown macro: { $resourceLoader = new Zend_Application_Module_Autoloader(array( 'basePath' => APPLICATION_PATH . "/modules/addressbook", 'namespace' => 'Addressbook', )); $resourceLoader = new Zend_Application_Module_Autoloader(array( 'basePath' => APPLICATION_PATH . "/", 'namespace' => '', )); }

    ]]></ac:plain-text-body></ac:macro>

    <p>Here you can see the requirements on the model. ZF and Doctrine Integration only works if you follow it completly:</p>

    <p>Your Models have to be called either Model_Foo or Module_Model_Foo</p>

    <p>Now you can go generate the models from the YAML file:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    zf generate-models-yaml doctrine
    zf build-all-reload doctrine --force
    ]]></ac:plain-text-body></ac:macro>

    <p>The first command generates the Model_User and Addressbook_Model_Contact aswell as their respective Base clases Model_Base_User and Adressbook_Model_Base_Contact. The second command creates the database from the schema and loads a fixture from the "application/configs/fixtures".</p>

    <p>What is missing:</p>

    <ul>
    <li>Documentation</li>
    <li>Tool support to create multiple places where a YAML schema can be generated.</li>
    </ul>

    <p>Be aware:</p>

    <p>This proposal tightly integrates ZF and Doctrine in the default project schema. Any attempt to use it in another way will fail, and you should use the components strengths separately to get where you want to.</p>

    <p>I would appreciate feedback from anyone who wants to give it a try.</p>

  7. Mar 11, 2010

    <p>Hello everyone,</p>

    <p>I can't checkout your repository :</p>

    <p>C:\Users\MightyDucks\Desktop\zend\library\Zend\Doctrine2\Application\Resource\Entitymanager.php<br />
    In directory 'C:\Users\MightyDucks\Desktop\zend\library\Zend\Doctrine2\Application\Resource'<br />
    Can't open file <br />
    'C:\Users\MightyDucks\Desktop\zend\library\Zend\Doctrine2\Application\Resource\.svn\tmp\text-base\Entitymanager.php.svn-base': <br />
    The specified file is not found.</p>

    <p>Can you check your repos ?</p>

    <p>Thank you</p>

  8. Apr 26, 2010

    <p>Hi Julien - I had the same problem today. It is because there are two files in that dir (Entitymanager.php and EntityManager.php) which obviously resolve to the same file in windows due to its lack of case sensitivity. There is no way around this at present other than doing the check-out on a non-windows machine. I've sent Benjamin (beberlei) an email asking him to remove the extra file so check-outs work <ac:emoticon ac:name="smile" /></p>