Skip to content

Commit

Permalink
[1.5] Changing runtime autoload strategy (closes #974):
Browse files Browse the repository at this point in the history
 * Using absolute path in core autoloading
 * introducing PropelAutoloader for models
 * removing the need for include path change in installation docs
  • Loading branch information
fzaninotto committed May 25, 2010
1 parent 79e401a commit 61f51c5
Show file tree
Hide file tree
Showing 19 changed files with 163 additions and 68 deletions.
37 changes: 2 additions & 35 deletions docs/guide/01-Installation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,9 @@ Download a tarball of each of the Propel components from the Propel website, and

Once this is done, you'll need to setup your PHP environment to use this library.

== Setting Up PHP for Propel ==
== Setting Up PHP for the Propel Generator ==

The following instructions are only required if you installed Propel from a tarball, or from Subversion.

=== Generator Setup ===

The Propel generator component bundles a `propel-gen` sh script (and a `propel-gen.bat` script for Windows). This script simplifies the commandline invocation of the Propel generator by hiding any references to Phing.

Expand All @@ -119,36 +117,6 @@ In order to allow an easier execution the script, you can also:
> ln -s /usr/local/propel/generator/bin/propel-gen propel-gen
}}}

=== Runtime Setup ===

Propel requires that the runtime classes are in PHP `include_path`.

The easiest and most permanent way to set your `include_path` is to simply edit your `php.ini` file and add the `propel/runtime/lib/` directory to the `include_path` variable:

{{{
; Unix
include_path="/usr/local/lib/php:/usr/local/propel/runtime/lib"
}}}

or, if you're using Windows,

{{{
; Windows
include_path="C:\PHP\PEAR;C:\PHP\apps\propel\runtime\lib"
}}}

If you do not have access to the `php.ini` file and cannot specify the `include_path` value in your `.htaccess` file, you can always do this at runtime within your PHP scripts:

{{{
#!php
<?php
set_include_path("/usr/local/propel/runtime/lib" . PATH_SEPARATOR . get_include_path());
}}}

Now the Propel runtime environment is ready to be used by your object model. As you will learn later, you will also need to modify the `include_path` to account for your object model PHP classes (i.e. the classes that the Propel generator builds for you).

Note: Only the the runtime classes need to be in the `include_path`; the build process calculates the `include_path` for the generator classes automatically. In other words, this step is not required to build your object model, but it is required to actually use your generated code from a PHP script.

== Testing Propel Installation ==

You can test that the '''Propel generator''' component is properly installed by calling the `propel-gen` script from the CLI:
Expand All @@ -169,8 +137,7 @@ You can test that the '''Propel runtime''' component is properly installed by re
require_once 'propel/Propel.php';

// manual installation
set_include_path("/usr/local/propel/runtime/lib" . PATH_SEPARATOR . get_include_path());
require_once 'Propel.php';
require_once '/usr/local/propel/runtime/lib/Propel.php';

// Propel setup code ... (to be discussed later)
}}}
Expand Down
26 changes: 22 additions & 4 deletions runtime/lib/Propel.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,15 @@ class Propel
*/
private static $forceMasterConnection = false;

/**
* @var string Base directory to use for autoloading. Initialized in self::initBaseDir()
*/
protected static $baseDir;

/**
* @var array A map of class names and their file paths for autoloading
*/
private static $autoloadMap = array(
'PropelException' => 'PropelException.php',
protected static $autoloadMap = array(

'DBAdapter' => 'adapter/DBAdapter.php',
'DBMSSQL' => 'adapter/DBMSSQL.php',
Expand Down Expand Up @@ -221,6 +225,7 @@ class Propel
'BasePeer' => 'util/BasePeer.php',
'NodePeer' => 'util/NodePeer.php',
'PeerInfo' => 'util/PeerInfo.php',
'PropelAutoloader' => 'util/PropelAutoloader.php',
'PropelColumnTypes' => 'util/PropelColumnTypes.php',
'PropelConditionalProxy' => 'util/PropelConditionalProxy.php',
'PropelModelPager' => 'util/PropelModelPager.php',
Expand Down Expand Up @@ -258,7 +263,8 @@ public static function initialize()
self::$connectionMap = array();

if (isset(self::$configuration['classmap']) && is_array(self::$configuration['classmap'])) {
self::$autoloadMap = array_merge(self::$configuration['classmap'], self::$autoloadMap);
PropelAutoloader::getInstance()->addClassPaths(self::$configuration['classmap']);
PropelAutoloader::getInstance()->register();
}

self::$isInit = true;
Expand Down Expand Up @@ -797,11 +803,21 @@ public static function close()
public static function autoload($className)
{
if (isset(self::$autoloadMap[$className])) {
require(self::$autoloadMap[$className]);
require self::$baseDir . self::$autoloadMap[$className];
return true;
}
return false;
}

/**
* Initialize the base directory for the autoloader.
* Avoids a call to dirname(__FILE__) each time self::autoload() is called.
* FIXME put in the constructor if the Propel class ever becomes a singleton
*/
public static function initBaseDir()
{
self::$baseDir = dirname(__FILE__) . '/';
}

/**
* Include once a file specified in DOT notation and reutrn unqualified clasname.
Expand Down Expand Up @@ -895,4 +911,6 @@ public static function isInstancePoolingEnabled()
}
}

// Since the Propel class is not a true singleton, this code cannot go into the __construct()
Propel::initBaseDir();
spl_autoload_register(array('Propel', 'autoload'));
113 changes: 113 additions & 0 deletions runtime/lib/util/PropelAutoloader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/

/**
* Simple autoloader for Propel generated model classes.
* This class implements the singleton pattern.
*
* @author Prancois Zaninotto
* @author Fabien Potencier
* @version $Revision$
* @package propel.util
*/
class PropelAutoloader
{

static protected $instance = null;

protected $classes = array();

/**
* Retrieves the singleton instance of this class.
*
* @return PropelAutoloader A PropelAutoloader instance.
*/
static public function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new PropelAutoloader();
}

return self::$instance;
}

/**
* Register PropelAutoloader in spl autoloader.
*
* @return void
*/
static public function register()
{
ini_set('unserialize_callback_func', 'spl_autoload_call');

if (false === spl_autoload_register(array(self::getInstance(), 'autoload'))) {
throw new Exception(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance())));
}
}

/**
* Unregister PropelAutoloader from spl autoloader.
*
* @return void
*/
static public function unregister()
{
spl_autoload_unregister(array(self::getInstance(), 'autoload'));
}

/**
* Sets the path for a list of classes.
*
* @param array $classMap An associative array $className => $classPath
*/
public function addClassPaths($classMap)
{
$this->classes = array_merge($this->classes, $classMap);
}

/**
* Sets the path for a particular class.
*
* @param string $class A PHP class name
* @param string $path A path (absolute or relative to the include path)
*/
public function addClassPath($class, $path)
{
$this->classes[$class] = $path;
}

/**
* Returns the path where a particular class can be found.
*
* @param string $class A PHP class name
*
* @return string|null A path (absolute or relative to the include path)
*/
public function getClassPath($class)
{
return isset($this->classes[$class]) ? $this->classes[$class] : null;
}

/**
* Handles autoloading of classes that have been registered in this instance
*
* @param string $class A class name.
*
* @return boolean Returns true if the class has been loaded
*/
public function autoload($class)
{
if (isset($this->classes[$class])) {
require $this->classes[$class];
return true;
}
return false;
}
}
4 changes: 2 additions & 2 deletions test/test.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
<pathelement dir="${tests.dir.resolved}" />
<pathelement dir="${tests.classes.dir.resolved}" />
<pathelement dir="${propel-generator.classes.dir.resolved}" />
<pathelement dir="${propel-runtime.classes.dir.resolved}" />
</path>

<target name="configure">
Expand All @@ -50,7 +49,8 @@
<define name="TESTS_BASE_DIR" value="${tests.dir.resolved}" />
<adhoc>
<![CDATA[
require_once 'Propel.php';
// initializes the Propel runtime autoload
require_once '${propel-runtime.classes.dir.resolved}/Propel.php';
]]>
</adhoc>

Expand Down
2 changes: 1 addition & 1 deletion test/testsuite/generator/model/BehaviorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public function testMofifyTable()
public function testModifyDatabase()
{
set_include_path(get_include_path() . PATH_SEPARATOR . "fixtures/bookstore/build/classes");
require_once 'Propel.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/Propel.php';
Propel::init('fixtures/bookstore/build/conf/bookstore-conf.php');
$tmap = Propel::getDatabaseMap(Table3Peer::DATABASE_NAME)->getTable(Table3Peer::TABLE_NAME);
$this->assertTrue(array_key_exists('do_nothing', $tmap->getBehaviors()), 'A database behavior is automatically copied to all its table');
Expand Down
2 changes: 1 addition & 1 deletion test/testsuite/runtime/connection/PropelPDOTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

require_once 'PHPUnit/Framework/TestCase.php';
require_once 'connection/PropelPDO.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/connection/PropelPDO.php';
set_include_path(get_include_path() . PATH_SEPARATOR . "fixtures/bookstore/build/classes");
Propel::init('fixtures/bookstore/build/conf/bookstore-conf.php');

Expand Down
4 changes: 2 additions & 2 deletions test/testsuite/runtime/map/ColumnMapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
*/

require_once 'PHPUnit/Framework/TestCase.php';
require_once 'map/ColumnMap.php';
require_once 'map/TableMap.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/map/ColumnMap.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/map/TableMap.php';

/**
* Test class for TableMap.
Expand Down
6 changes: 3 additions & 3 deletions test/testsuite/runtime/map/DatabaseMapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
*/

require_once 'PHPUnit/Framework/TestCase.php';
require_once 'map/ColumnMap.php';
require_once 'map/TableMap.php';
require_once 'map/DatabaseMap.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/map/ColumnMap.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/map/TableMap.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/map/DatabaseMap.php';

class TestDatabaseBuilder
{
Expand Down
4 changes: 2 additions & 2 deletions test/testsuite/runtime/map/RelationMapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
*/

require_once 'PHPUnit/Framework/TestCase.php';
require_once 'map/RelationMap.php';
require_once 'map/TableMap.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/map/RelationMap.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/map/TableMap.php';

/**
* Test class for RelationMap.
Expand Down
4 changes: 2 additions & 2 deletions test/testsuite/runtime/map/TableMapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
*/

require_once 'PHPUnit/Framework/TestCase.php';
require_once 'map/ColumnMap.php';
require_once 'map/TableMap.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/map/ColumnMap.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/map/TableMap.php';

class TestableTableMap extends TableMap
{
Expand Down
4 changes: 1 addition & 3 deletions test/testsuite/runtime/om/BaseObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
*/

require_once 'PHPUnit/Framework/TestCase.php';
require_once 'om/BaseObject.php';


require_once dirname(__FILE__) . '/../../../../runtime/lib/om/BaseObject.php';

/**
* Test class for BaseObject.
Expand Down
4 changes: 2 additions & 2 deletions test/testsuite/runtime/query/CriteriaCombineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
*/

require_once 'tools/helpers/BaseTestCase.php';
require_once 'query/Criteria.php';
require_once 'util/BasePeer.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/query/Criteria.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/util/BasePeer.php';

set_include_path(get_include_path() . PATH_SEPARATOR . "fixtures/bookstore/build/classes");
Propel::init('fixtures/bookstore/build/conf/bookstore-conf.php');
Expand Down
5 changes: 2 additions & 3 deletions test/testsuite/runtime/query/CriteriaFluidConditionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
*/

require_once 'tools/helpers/BaseTestCase.php';
require_once 'query/Criteria.php';
require_once 'util/PropelConditionalProxy.php';

require_once dirname(__FILE__) . '/../../../../runtime/lib/query/Criteria.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/util/PropelConditionalProxy.php';

/**
* Test class for Criteria fluid conditions.
Expand Down
4 changes: 2 additions & 2 deletions test/testsuite/runtime/query/CriteriaMergeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
*/

require_once 'tools/helpers/BaseTestCase.php';
require_once 'query/Criteria.php';
require_once 'util/BasePeer.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/query/Criteria.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/util/BasePeer.php';

set_include_path(get_include_path() . PATH_SEPARATOR . "fixtures/bookstore/build/classes");
Propel::init('fixtures/bookstore/build/conf/bookstore-conf.php');
Expand Down
4 changes: 2 additions & 2 deletions test/testsuite/runtime/query/CriteriaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
*/

require_once 'tools/helpers/BaseTestCase.php';
require_once 'query/Criteria.php';
require_once 'util/BasePeer.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/query/Criteria.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/util/BasePeer.php';

set_include_path(get_include_path() . PATH_SEPARATOR . "fixtures/bookstore/build/classes");
Propel::init('fixtures/bookstore/build/conf/bookstore-conf.php');
Expand Down
2 changes: 1 addition & 1 deletion test/testsuite/runtime/query/JoinTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

require_once 'tools/helpers/BaseTestCase.php';
require_once 'query/Criteria.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/query/Criteria.php';

set_include_path(get_include_path() . PATH_SEPARATOR . "fixtures/bookstore/build/classes");
Propel::init('fixtures/bookstore/build/conf/bookstore-conf.php');
Expand Down
2 changes: 1 addition & 1 deletion test/testsuite/runtime/util/PropelConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

require_once 'PHPUnit/Framework/TestCase.php';
require_once 'config/PropelConfiguration.php';
require_once dirname(__FILE__) . '/../../../../runtime/lib/config/PropelConfiguration.php';

/**
* Test for PropelConfiguration class
Expand Down
Loading

0 comments on commit 61f51c5

Please sign in to comment.