diff --git a/README.markdown b/README.markdown index 60c24c07..dea897e6 100644 --- a/README.markdown +++ b/README.markdown @@ -64,26 +64,28 @@ Changelog #### 1.3.0 - released XXXX-XX-XX -* Add support for multiple database connections +* Documentation moved to [paris.rtfd.org](http://paris.rtfd.org) and now built using [Sphinx](http://sphinx-doc.org/) +* Add support for multiple database connections - closes [issue #15](https://github.com/j4mie/idiorm/issues/15) [[tag](https://github.com/tag)] +* Allow a prefix for model class names - see Configuration in the documentation - closes [issues #33](https://github.com/j4mie/paris/issues/33) * Exclude tests and git files from git exports (used by composer) -* Update included Idiorm version for tests -* Implement `set_expr` - closes issue #39 -* Add `is_new` - closes issue #40 -* Add support for the new IdiormResultSet object -* Change Composer to use a classmap so that autoloading is better supported [[javierd](https://github.com/javiervd)] - issue #44 +* Implement `set_expr` - closes [issue #39](https://github.com/j4mie/paris/issues/39) +* Add `is_new` - closes [issue #40](https://github.com/j4mie/paris/issues/40) +* Add support for the new IdiormResultSet object in Idiorm - closes [issue #14](https://github.com/j4mie/paris/issues/14) +* Change Composer to use a classmap so that autoloading is better supported [[javierd](https://github.com/javiervd)] - [issue #44](https://github.com/j4mie/paris/issues/44) * Move tests into PHPUnit to match Idiorm +* Update included Idiorm version for tests * Move documentation to use Sphinx #### 1.2.0 - released 2012-11-14 * Setup composer for installation via packagist (j4mie/paris) -* Add in basic namespace support, see issue #20 -* Allow properties to be set as an associative array in `set()`, see issue #13 -* Patch in idiorm now allows empty models to be saved (j4mie/idiorm see issue #58) +* Add in basic namespace support, see [issue #20](https://github.com/j4mie/paris/issues/20) +* Allow properties to be set as an associative array in `set()`, see [issue #13](https://github.com/j4mie/paris/issues/13) +* Patch in idiorm now allows empty models to be saved (j4mie/idiorm see [issue #58](https://github.com/j4mie/paris/issues/58)) #### 1.1.1 - released 2011-01-30 -* Fix incorrect tests, see issue #12 +* Fix incorrect tests, see [issue #12](https://github.com/j4mie/paris/issues/12) #### 1.1.0 - released 2011-01-24 diff --git a/docs/configuration.rst b/docs/configuration.rst index e1152122..47f9c55c 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -32,10 +32,37 @@ For example, if you are using MySQL: ORM::configure('username', 'database_user'); ORM::configure('password', 'top_secret'); -Configuration -~~~~~~~~~~~~~ +Model prefixing +~~~~~~~~~~~~~~~ + +Setting: ``Model::$auto_prefix_models`` + +To save having type out model class name prefixes whenever code utilises ``Model::for_table()`` +it is possible to specify a prefix that will be prepended onto the class name. + +The model prefix is treated the same way as any other class name when Paris +attempts to convert it to a table name. This is documented in the :doc:`Models` +section of the documentation. + +Here is a namespaced example to make it clearer: + +:: + + Model::$auto_prefix_models = '\\Tests\\'; + Model::factory('Simple')->find_many(); // SQL executed: SELECT * FROM `tests_simple` + Model::factory('SimpleUser')->find_many(); // SQL executed: SELECT * FROM `tests_simple_user` + +.. note:: + + It is possible to define the table name by setting ``$_table`` in your + individual model classes. As documented in the :doc:`Models` section of + the documentation. + + +Further Configuration +~~~~~~~~~~~~~~~~~~~~~ -The only configuration options provided by Paris itself are the +The only other configuration options provided by Paris itself are the ``$_table`` and ``$_id_column`` static properties on model classes. To configure the database connection, you should use Idiorm’s configuration system via the ``ORM::configure`` method. diff --git a/docs/models.rst b/docs/models.rst index 9c60602d..97defec8 100644 --- a/docs/models.rst +++ b/docs/models.rst @@ -31,6 +31,11 @@ your table names are in *lowercase\_with\_underscores* style. It will convert between the two automatically. For example, if your class is called ``CarTyre``, Paris will look for a table named ``car_tyre``. +If you are using namespaces then they will be converted to a table name +in a similar way. For example ``\\Models\\CarTyre`` would be converted to +``models_car_tyre``. Note here that backslashes are replaced with underscores +in addition to the *CapWords* replacement discussed in the previous paragraph. + To override this default behaviour, add a **public static** property to your class called ``$_table``: @@ -40,6 +45,14 @@ your class called ``$_table``: public static $_table = 'my_user_table'; } +Auto Prefixing +^^^^^^^^^^^^^^ + +To save having type out model class name prefixes whenever code utilises ``Model::for_table()`` +it is possible to specify a prefix that will be prepended onto the class name. + +See the :doc:`Configuration` documentation for more details. + ID Column ~~~~~~~~~ diff --git a/paris.php b/paris.php index 694b5de9..66df9589 100644 --- a/paris.php +++ b/paris.php @@ -158,6 +158,15 @@ class Model { // Default foreign key suffix used by relationship methods const DEFAULT_FOREIGN_KEY_SUFFIX = '_id'; + /** + * Set a prefix for model names. This can be a namespace or any other + * abitrary prefix such as the PEAR naming convention. + * @example Model::$auto_prefix_models = 'MyProject_MyModels_'; //PEAR + * @example Model::$auto_prefix_models = '\MyProject\MyModels\'; //Namespaces + * @var string + */ + public static $auto_prefix_models = null; + /** * The ORM instance used by this model * instance to communicate with the database. @@ -207,7 +216,7 @@ protected static function _class_name_to_table_name($class_name) { return strtolower(preg_replace( array('/\\\\/', '/(?<=[a-z])([A-Z])/', '/__/'), array('_', '_$1', '_'), - $class_name + ltrim($class_name, '\\') )); } @@ -242,7 +251,7 @@ protected static function _build_foreign_key_name($specified_foreign_key_name, $ * its find_one or find_many methods are called. */ public static function factory($class_name, $connection_name = null) { - + $class_name = self::$auto_prefix_models . $class_name; $table_name = self::_get_table_name($class_name); if ($connection_name == null) { diff --git a/test/ModelPrefixingTest.php b/test/ModelPrefixingTest.php new file mode 100644 index 00000000..d242e32b --- /dev/null +++ b/test/ModelPrefixingTest.php @@ -0,0 +1,58 @@ +assertClassHasStaticAttribute('auto_prefix_models', 'Model'); + $this->assertInternalType('null', Model::$auto_prefix_models); + } + + public function testSettingAndUnsettingStaticPropertyValue() { + $model_prefix = 'My_Model_Prefix_'; + $this->assertInternalType('null', Model::$auto_prefix_models); + Model::$auto_prefix_models = $model_prefix; + $this->assertInternalType('string', Model::$auto_prefix_models); + $this->assertEquals($model_prefix, Model::$auto_prefix_models); + Model::$auto_prefix_models = null; + $this->assertInternalType('null', Model::$auto_prefix_models); + } + + public function testNoPrefixOnAutoTableName() { + Model::$auto_prefix_models = null; + Model::factory('Simple')->find_many(); + $expected = 'SELECT * FROM `simple`'; + $this->assertEquals($expected, ORM::get_last_query()); + } + + public function testPrefixOnAutoTableName() { + Model::$auto_prefix_models = 'MockPrefix_'; + Model::factory('Simple')->find_many(); + $expected = 'SELECT * FROM `mock_prefix_simple`'; + $this->assertEquals($expected, ORM::get_last_query()); + } + + public function testPrefixOnAutoTableNameWithTableSpecified() { + Model::$auto_prefix_models = 'MockPrefix_'; + Model::factory('TableSpecified')->find_many(); + $expected = 'SELECT * FROM `simple`'; + $this->assertEquals($expected, ORM::get_last_query()); + } + +} \ No newline at end of file diff --git a/test/ModelPrefixingTest53.php b/test/ModelPrefixingTest53.php new file mode 100644 index 00000000..1bb1e91f --- /dev/null +++ b/test/ModelPrefixingTest53.php @@ -0,0 +1,73 @@ +find_many(); + $expected = 'SELECT * FROM `tests_simple`'; + $this->assertEquals($expected, ORM::get_last_query()); + } + + public function testPrefixOnAutoTableName() { + Model::$auto_prefix_models = '\\Tests\\'; + Model::factory('Simple')->find_many(); + $expected = 'SELECT * FROM `tests_simple`'; + $this->assertEquals($expected, ORM::get_last_query()); + } + + public function testPrefixOnAutoTableNameWithTableSpecified() { + Model::$auto_prefix_models = '\\Tests\\'; + Model::factory('TableSpecified')->find_many(); + $expected = 'SELECT * FROM `simple`'; + $this->assertEquals($expected, ORM::get_last_query()); + } + + public function testNamespacePrefixSwitching() { + Model::$auto_prefix_models = '\\Tests\\'; + Model::factory('TableSpecified')->find_many(); + $expected = 'SELECT * FROM `simple`'; + $this->assertEquals($expected, ORM::get_last_query()); + + Model::$auto_prefix_models = '\\Tests2\\'; + Model::factory('TableSpecified')->find_many(); + $expected = 'SELECT * FROM `simple`'; + $this->assertEquals($expected, ORM::get_last_query()); + } + } +} + +namespace Tests { + use ORM, Model, MockPDO; + class Simple extends Model { } + class TableSpecified extends Model { + public static $_table = 'simple'; + } +} +namespace Tests2 { + use ORM, Model, MockPDO; + class Simple extends Model { } + class TableSpecified extends Model { + public static $_table = 'simple'; + } +} \ No newline at end of file diff --git a/test/MultipleConnectionsTest.php b/test/MultipleConnectionsTest.php new file mode 100644 index 00000000..e3920366 --- /dev/null +++ b/test/MultipleConnectionsTest.php @@ -0,0 +1,47 @@ +find_one(1); + $statement = ORM::get_last_statement(); + $this->assertInstanceOf('MockPDOStatement', $statement); + + $simple = Model::factory('Simple', self::ALTERNATE); // Change the object's default connection + $simple->find_one(1); + $statement = ORM::get_last_statement(); + $this->assertInstanceOf('MockDifferentPDOStatement', $statement); + + $temp = Model::factory('Simple', self::ALTERNATE)->find_one(1); + $statement = ORM::get_last_statement(); + $this->assertInstanceOf('MockDifferentPDOStatement', $statement); + } + + public function testCustomConnectionName() { + $person3 = Model::factory('ModelWithCustomConnection')->find_one(1); + $statement = ORM::get_last_statement(); + $this->assertInstanceOf('MockDifferentPDOStatement', $statement); + } + +} \ No newline at end of file diff --git a/test/ParisTest.php b/test/ParisTest.php index 6e8cbdf8..afdd4cb3 100644 --- a/test/ParisTest.php +++ b/test/ParisTest.php @@ -5,22 +5,16 @@ class ParisTest extends PHPUnit_Framework_TestCase { const ALTERNATE = 'alternate'; public function setUp() { - // Set up the dummy database connection ORM::set_db(new MockPDO('sqlite::memory:')); - ORM::set_db(new MockDifferentPDO('sqlite::memory:'), self::ALTERNATE); // Enable logging ORM::configure('logging', true); - ORM::configure('logging', true, self::ALTERNATE); } public function tearDown() { ORM::configure('logging', false); - ORM::configure('logging', false, self::ALTERNATE); - ORM::set_db(null); - ORM::set_db(null, self::ALTERNATE); } public function testSimpleAutoTableName() { @@ -153,24 +147,4 @@ public function testHasManyThroughRelationWithCustomIntermediateModelAndKeyNames $this->assertEquals($expected, ORM::get_last_query()); } - public function testMultipleConnections() { - $simple = Model::factory('Simple')->find_one(1); - $statement = ORM::get_last_statement(); - $this->assertInstanceOf('MockPDOStatement', $statement); - - $simple = Model::factory('Simple', self::ALTERNATE); // Change the object's default connection - $simple->find_one(1); - $statement = ORM::get_last_statement(); - $this->assertInstanceOf('MockDifferentPDOStatement', $statement); - - $temp = Model::factory('Simple', self::ALTERNATE)->find_one(1); - $statement = ORM::get_last_statement(); - $this->assertInstanceOf('MockDifferentPDOStatement', $statement); - } - - public function testCustomConnectionName() { - $person3 = Model::factory('ModelWithCustomConnection')->find_one(1); - $statement = ORM::get_last_statement(); - $this->assertInstanceOf('MockDifferentPDOStatement', $statement); - } -} +} \ No newline at end of file diff --git a/test/bootstrap.php b/test/bootstrap.php index 7ea2e3e9..1ac0883c 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -128,4 +128,8 @@ class BookTwo extends Model { public function authors() { return $this->has_many_through('Author', 'AuthorBook', 'custom_book_id', 'custom_author_id'); } -} \ No newline at end of file +} +class MockPrefix_Simple extends Model { } +class MockPrefix_TableSpecified extends Model { + public static $_table = 'simple'; +} \ No newline at end of file