39

Better Doctrine 2 Module for Kohana 3

Posted December 27th, 2010 (Updated 22 Feb 2012) in Database, PHP

Update Feb 22 2012: 1.0.8 is out. Now works with and requires Doctrine 2.2. Thanks to Markus for his patch.
Update Nov 05 2011: Updated to version 1.0.7. Now works with Kohana 3.2 and supports schema files located in modules.
Update Jun 22 2011: Updated to version 1.0.6. Now works with Kohana 3 and 3.1 and any Kohana directory structure. The repo has also been moved to GitHub.
Update Feb 21 2011: Updated to version 1.0.5. Fixed some errors with the SQL logger when passing objects to DQL – see changelog for more details.

Since releasing my original Doctrine 2 module for Kohana 3, I’ve done a bit of reshuffling of folders and added some additional features from my Doctrine 1.2 module. Due to the extent of modifications, I decided to put up a new post with some added information on how to use the new module.

Features:

  • Doctrine 2 integration (obviously)
  • Auth and Session drivers
  • /doctrine controller to load your schema files and generate the DB tables
  • Works in Kohana 3.0 and 3.1

For the impatient ones out there, here’s the download link:
Doctrine 2 Module for Kohana 3

 

As always, install the module (remembering to add it to your bootstrap file) and download the latest copy of Doctrine 2 from here, placing into the /modules/doctrine2/classes/vendor/doctrine folder. It should be noted that my module is tailored to the tarball download and not the SVN or Github ones which have a slightly different folder structure.

The Structure

All entities/fixtures/proxies are located in:

application/models
application/models/fixtures/schema
application/models/proxies
application/models/repositories

The /doctrine Controller

This module includes a /doctrine controller which accesses the Doctrine 2 CLI tool. Due to the dodginess of the CLI tool included in the tarball version (at least back when I was first writing my module), I wrote my own and included it in the module.

Please make sure the doctrine file in this folder is executable

chmod +x /modules/doctrine2/bin/doctrine

As noted above, I’ve included a /doctrine controller. This controller allows you to perform many of the CLI’s functions including validating the schema, generating your entitiy files (models) and creating/updating your database tables to match your schema files. As a security precaution, by default this controller is only accessible from localhost – add any IPs you need into the controller file.

Unlike the D1.2 module’s controller, this one will not delete your data. It will update entity files adding any missing fields or functions and it will update the database fields instead of needing to delete/recreate. For the DB table section, I’ve also added a button to show the SQL statements the tool will attempt to perform on the database. You should always use this before clicking the Create Tables button!

The Schema

I prefer using YAML files to generate my entities. They’re placed in /models/fixtures/schema and must be named in a specific way. Each entity requires it’s own YAML file. For your convenience, here are 2 example YAML files and their respective names.

/models/fixtures/schema/models.Product.yml

modelsProduct:
  type: entity
  table: products
  repositoryClass: modelsrepositoriesProductRepository
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    name:
      type: string
      length: 255
  oneToMany:
    serial:
      targetEntity: Serial
      mappedBy: product

/models/fixtures/schema/models.Serial.yml

modelsSerial:
  type: entity
  table: serials
  repositoryClass: modelsrepositoriesSerialRepository
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    serial:
      type: string
      length: 255
  manyToOne:
    product:
      targetEntity: Product
      inversedBy: serial
      joinColumn:
        name: product_id
        referencedColumnName: id

D2 currently doesn’t have great documentation on YAML files so you may wish to switch to one of the other annotation methods such as XML. To do so you’ll need to update the following 2 files:

/modules/doctrine2/init.php
/modules/doctrine2/bin/cli-config.php

As of version 1.0.7 of my module (released Nov 05 2011) you can now also place schema files in the /models/fixtures/schema directory of individual modules. Entities/Proxies/Repos from these schema files will still be generated into application/models.

Example Usage:

I was asked for some example usage. So here it is:

<?php defined('SYSPATH') or die('No direct script access.');
 
class Controller_Welcome extends Controller {
 
	public function action_index()
	{
		$this->response->body('hello, world!');
	}
 
	public function action_test()
	{
		$Product = new modelsProduct();
		$Product->setName('New Product');
		Doctrine::em()->persist($Product);
		Doctrine::em()->flush();
 
		$response = "Created Product with ID " . $Product->getId();
 
		if ( Kohana::VERSION >= 3.1 )
			$this->response->body($response);
		else
			$this->request->response = $response;
	}
 
} // End Welcome

Much Wootage!

Your module is now set up. Congratulations :)

For those who missed it, here’s the complete module download link again – be sure to read the installation instructions included in the download:
Doctrine 2 Module for Kohana 3

  • Paul

    Hi,

    This looks really good but doesnt seem to work for me.

    I have attempted to follow the instructions but when I now run a page I get the error:
    ErrorException [ Parse Error ]: syntax error, unexpected T_STRING, expecting T_CONSTANT_ENCAPSED_STRING or ‘(‘
    This is on line MODPATH/doctrine2/init.php [ 2 ]

    Any idea why this might be?

    Thanks

  • Dave Lewicki

    This was helpful! Super thanks!

    Now: Any ideas on how to approach making entities work w/ the Kohana file system? For example if I want to have entity files live in different modules and include various modules at run time, where do the non-autogenerated (i.e. production) proxies live?

    Maybe they’re sorted out w/ namespaces? I’m going to tackle this but just wondering if you had any thoughts…

    great posts! THanks!

    -Dave

    • Flynsarmy

      Hey Dave,

      I’ve actually never written a project in D2 and as such have never really experienced this issue. You could probably fix it by modifying the auto_load function in /modules/doctrine2/init.php to include models folders from loaded modules if they exist.

      If you do end up writing a patch, please send it my way – I’d be happy to include it and get this obviously useful functionality added!

      EDIT: Upon looking at the code – it’s currently using Kohana::find_file() – would this not already include models folders in modules?

  • jdewit

    How are you accessing the entity manager in your controller?

    • Flynsarmy

      jdewit: Doctrine::em() but if you have multiple databases set up you can also use Doctrine::em(‘connection_name’)

      • jdewit

        Thanks, got the entitiy manager working. Created my database via the console, and I’m pretty sure the init.php file is configured properly.

        In my controller I try,

        $account = new \entities\Account();

        I get the following error, Class ‘entities\Account’ not found. I dont think I am using namespaces properly.

        my account entity is in a folder called entities in the models folder and starts off like this

        <?php

        namespace entities;

        /**
        * @Entity(repositoryClass="repositories\AccountRepository")
        */
        class Account
        {
        ….

        Can you show me a sample of how you access your entities in the controller and how you have your entities named.

        Thanks you!

        • jdewit

          Nevermind! I figured it out. Proper namespace was model\entities\Account.

  • Slackz

    Thank you. To be honest, I don’t use a vanilla Kohana install, but I was just having some trouble following where you were supposed to put things as I’ve yet to use a plugin for Kohana. This should allow me to find out where to plug the files into what I do use — which is system/module folders shared amongst all of my apps, and each app with a dedicated application folder, all sitting outside of the webroot.

    • Flynsarmy

      Watch that when you upgrade your system folder there are no regressions – especially as 3.10 has a substancially different API to 9. You dont want to go destroying 10 sites at once :)

      • slackz

        True. I tend not to update frameworks on apps that ‘work’. This can be bad, but truth be told, the lifespan of an app isn’t that long these days anyway.

  • Slackz

    Flyns. I#ve been having some trouble figuring out how to use Doctrine 2.0 with Kohana 3.1. Any chance you can do a short tutorial on this?

    • Flynsarmy

      Sure – I’ll get one going. You might want to read the cookbook or reference manual though. Plenty of information there http://www.doctrine-project.org/projects/orm/2.0/docs/en

      Also visit the #doctrine channel on freenode (IRC). Thats where I get alot of my help when I’m stuck.

      • Slackz

        To be honest, I really just need a sample model to see how to actually build one with Kohana.

        • Flynsarmy

          Slackz,

          Here are the following D2 models (to be placed in /models folder):
          User.php,
          Role.php, Token.php (for auth module),
          Session.php (session module)

          Link:
          http://pastebin.com/XCiufG41

          These were all automatically generated from the following YAML files (placed in /models/fixtures/schema):
          models.User.yml
          models.Role.yml, models.UserToken.yml,
          models.Session.yml

          Link:
          http://pastebin.com/w9dMMwdh

          I generated the models from the YAML files by going to /doctrine and hitting the ‘load schema’ button. /doctrine is only available via localhost.

          Disclaimer: The YAML files might not match the models exactly – I pastebin’d old backup files. This is just an example of how they should be written.

  • Karl Shea

    If Cookie::$salt isn’t set, an exception is thrown, but it never gets logged since it’s swallowed somewhere along the way, and seems to fail silently. So all that’s written to the log is a Doctrine failure about the entity not having an id.

  • David

    Do you have an Amazon wishlist by any chance? You saved me at least a day of time of hacking to shoe horn Doctrine into Kohana

    • Flynsarmy

      Happy to help :)

  • Jack9

    This guide is no longer valid. The latest Kohana is incompatible with this package in a number of ways.

    • Flynsarmy

      I’ve updated the module. Should be working now.

  • Wmartin

    I’m new to this framework, and integrate Doctrine, gender and institutions now need to generate tables from entities

    I am using the following command:

    modules/doctrine2/bin/doctrine php orm: schema-tool: create

    but I get the following error.

    [ErrorException]
    class_parents (): Class does not exist and Product not could be loaded

    I understand and I hope I can help

    thanks

    • Flynsarmy

      Try using the buttons on http://yoursite.com/doctrine – they should automate the process of generating your entities for you.

      • Paweł P.

        Hello good job, good module but
        I have a little problem – I guess

        When I using cli command, it’s returns
        a error – please look:

        Fatal error: Uncaught exception ‘Doctrine\DBAL\DBALException’ with message ‘The given ‘driver’ pdo_ is unknown, Doctrine currently supports only the following drivers: pdo_mysql, …

        Config is ok, I using pdo_mysql driver. Server configuration seems also look right.

        PHP Version 5.3.6 + MYSQL 5.5.9
        PDO drivers enabled: mysql, sqlite, sqlite2, pgsql.

        In my case, using http://mysite.com/doctrinecannot generate anything.

        Hmmm… What next? Can u help me? Please.

        Best regards!

        Paweł P.

        • Flynsarmy

          The CLI tool is set up to require the following command syntax:

          /path/to/modules/doctrine2/bin/doctrine default <DOCROOT> <APPPATH> orm:validate-schema

          If typing that stuff into the terminal doesn’t work for you, open
          /modules/doctrine2/bin/cli-config.php and check that the DB_CONN, DOCROOT, APPPATH constants are being defined correctly, and get_db_info() functino is returning what you expect it to return.

          • Paweł P.
            modules/doctrine2/bin/doctrine default /Applications/MAMP/htdocs/kohana_project/kohana-3.2-doctrine-2.2/ /Applications/MAMP/htdocs/kohana_project/kohana-3.2-doctrine-2.2/application/ orm:validate-schema

            Ok, terminal output is:

            "Warning: require(/Applications/MAMP/htdocs/kohana_project/kohana-3.2-doctrine-2.2/application/models/Product.php): failed to open stream: No such file or directory in /Applications/MAMP/htdocs/kohana_project/kohana-3.2-doctrine-2.2/modules/doctrine2/classes/vendor/doctrine/Doctrine/Common/ClassLoader.php on line 163

            Fatal error: require(): Failed opening required ‘/Applications/MAMP/htdocs/kohana_project/kohana-3.2-doctrine-2.2/application/models/Product.php’ (include_path=’.:’) in /Applications/MAMP/htdocs/kohana_project/kohana-3.2-doctrine-2.2/modules/doctrine2/classes/vendor/doctrine/Doctrine/Common/ClassLoader.php on line 163
            Pawel:kohana-3.2-doctrine-2.2 pawepaczynski$”

            Is the same like http://mysite.com/index.php/welcome/test

            Fatal error: DoctrineCommonClassLoader::loadClass() [function.require]: Failed opening required '/Applications/MAMP/htdocs/kohana_project/kohana-3.2-doctrine-2.2/application/models/Product.php' (include_path='.:/Applications/MAMP/bin/php/php5.3.6/lib/php') in /Applications/MAMP/htdocs/kohana_project/kohana-3.2-doctrine-2.2/modules/doctrine2/classes/vendor/doctrine/Doctrine/Common/ClassLoader.php on line 163

            Just because Product.php isn’t generate yet.

            Ok, now I looking to cli-config.php

            • Flynsarmy

              If you’ve gone to the URL /doctrine and can’t generate anything, have you checked that the folders

              /application/models
              /application/models/fixtures/schema
              /application/models/repositories
              /application/models/proxies

              exist and are writable?

              • Paweł P.

                Yes – Writable and exist.

                • Flynsarmy

                  It definately sounds like your /application/config/database.php file isn’t set correctly. The error you specified above about driver ‘pdo_’ would indicate that the driver line in cli-config.php isn’t receiving your config variable.

                  /application/config/database.php should look like so:

                  <?php defined('SYSPATH') or die('No direct access allowed.');
                   
                  return array
                  (
                  	'default' => array
                  	(
                  		'type'       => 'mysql',
                  		'connection' => array(
                  			/**
                  			 * The following options are available for MySQL:
                  			 *
                  			 * string   hostname     server hostname, or socket
                  			 * string   database     database name
                  			 * string   username     database username
                  			 * string   password     database password
                  			 * boolean  persistent   use persistent connections?
                  			 * array    variables    system variables as "key => value" pairs
                  			 *
                  			 * Ports and sockets may be appended to the hostname.
                  			 */
                  			'hostname'   => 'your host',
                  			'database'   => 'your database',
                  			'username'   => 'your username',
                  			'password'   => 'your pw',
                  			'persistent' => FALSE,
                  		),
                  		'table_prefix' => '',
                  		'charset'      => 'utf8',
                  		'caching'      => FALSE,
                  		'profiling'    => TRUE,
                  	),
                  );
                  • Paweł P.

                    /config/database.php is set.

                    But I checked define vars in cli-config.php
                    and $_SERVER['argv'] is empty.

                    Hmmm…

                    • Flynsarmy

                      Do you have safe_mode or similar turned on in PHP? The /doctrine controller calls passthru to run the cli tool when you click the buttons.

                      Perhaps your PHP install isn’t doing that correctly?

                    • Paweł P.

                      From php.ini

                      safe_mode = Off;
                      register_argc_argv = On;

          • Paweł P.

            Shit, how to debug /modules/doctrine2/bin/cli-config.php ?

            • Flynsarmy
              $fp = fopen(APPPATH.'/application/logs/log.log', 'a');
              fprintf($fp, "Your log messages");
              fclose($fp);
  • Markus

    All in kohana/doctrine works fine, the db tables are generated etc. but the example (Controller_Welcome) throws following error:

    Doctrine\ORM\Mapping\MappingException [ 0 ]: Class models\Product is not a valid entity or mapped super class.

    I tryd different Kohana and Doctrine Versions. Can anybody help?

    • Markus

      I guess, I got it.

      For doctrine 2.2 there needs a change in the inti.php in the module-folder in the __construct method:
      from:

      $driver = $config-&gt;newDefaultAnnotationDriver( APPPATH.'doctrine/Entities' );

      to:

      DoctrineCommonAnnotationsAnnotationRegistry::registerFile(MODPATH.'doctrine2/classes/vendor/doctrine/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
      $reader = new DoctrineCommonAnnotationsAnnotationReader();
      $reader = new DoctrineCommonAnnotationsCachedReader($reader, $cache);
      $driver = new DoctrineORMMappingDriverAnnotationDriver($reader, (array) APPPATH.'doctrine/Entities');

      So I can use generated models from doctrine 2.2.

  • mikspark

    Please some examples how to use auth and session driver

  • Dr.Insano

    Hi! Thank you very much for this module. Do you know if it works with Doctrine 2.3 ?