Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow a prefix for model class names #33

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ You may also need to pass a username and password to your database driver, using
ORM::configure('username', 'database_user');
ORM::configure('password', 'top_secret');

You can pass configuration specific to Paris by using the `configure` method of the ORMWrapper class.

ORMWrapper::configure('prefix', 'Prefix');
ORMWrapper::configure('namespace', 'Namespace\To');
ORMWrapper::configure('prefix_tables', true);
ORMWrapper::configure('namespace_tables', true);

Configuration options:

* `prefix`: a prefix to your classes that will be prepended to Model class names. Defaults to empty.
* `namespace`: a namespace to your classes that will be prepended to Model class names. Defaults to empty.
* `prefix_tables`: Whether the prefix will be added to the table name (e.g. PrefixModel -> prefix_model) or not. Defaults to `false`.
* `namespace_tables`: Whether the namespace will be added to the table name (e.g. Namespace\To\Model -> namespace_to_model) or not. Defaults to `false`.

### Model Classes ###

You should create a model class for each entity in your application. For example, if you are building an application that requires users, you should create a `User` class. Your model classes should extend the base `Model` class:
Expand Down
51 changes: 48 additions & 3 deletions paris.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@
*/
class ORMWrapper extends ORM {

// ------------------------ //
// --- CLASS PROPERTIES --- //
// ------------------------ //

// Class configuration
public static $_config = array(
'prefix' => '',
'namespace' => '',
'namespace_tables' => false,
'prefix_tables' => false,
);

// --------------------------- //
// --- INSTANCE PROPERTIES --- //
// --------------------------- //

/**
* The wrapped find_one and find_many classes will
* return an instance or instances of this class.
Expand Down Expand Up @@ -152,7 +168,7 @@ class Model {
const DEFAULT_FOREIGN_KEY_SUFFIX = '_id';

/**
* The ORM instance used by this model
* The ORM instance used by this model
* instance to communicate with the database.
*/
public $orm;
Expand Down Expand Up @@ -187,8 +203,8 @@ protected static function _get_table_name($class_name) {

/**
* Convert a namespace to the standard PEAR underscore format.
*
* Then convert a class name in CapWords to a table name in
*
* Then convert a class name in CapWords to a table name in
* lowercase_with_underscores.
*
* Finally strip doubled up underscores
Expand All @@ -197,13 +213,41 @@ protected static function _get_table_name($class_name) {
* Project\Models\CarTyre would be project_models_car_tyre.
*/
protected static function _class_name_to_table_name($class_name) {
if (!ORMWrapper::$_config['namespace_tables']) {
$parts = explode('\\', $class_name);
$class_name = $parts[count($parts) - 1];
}
if (!ORMWrapper::$_config['prefix_tables']) {
$class_name = preg_replace('/(?<=^|\\\\)' . preg_quote(ORMWrapper::$_config['prefix']) . '(?=[^\\\\]+$)/', '', $class_name, 1);
}
return strtolower(preg_replace(
array('/\\\\/', '/(?<=[a-z])([A-Z])/', '/__/'),
array('_', '_$1', '_'),
$class_name
));
}

/**
* Internal method to normalise the class name with any prefixes or
* namespaces configured on the ORMWrapper
*/
protected static function _normalise_class_name($class_name) {
$config_prefix = ORMWrapper::$_config['prefix'];
$config_namespace = trim(ORMWrapper::$_config['namespace'], '\\');
$class_name = trim($class_name, '\\');
$class_path = explode('\\', $class_name);
$class_name = array_pop($class_path);
$class_prefix = preg_replace('/^([a-zA-Z_\x7f-\xff][a-z0-9_\x7f-\xff]+).*/','$1', $class_name);
$class_namespace = implode('\\', $class_path);
if ($config_prefix && $config_prefix !== $class_prefix) {
$class_name = $config_prefix . $class_name;
}
if ($config_namespace || $class_namespace) {
$class_name = ($class_namespace ? $class_namespace : $config_namespace) . '\\' . $class_name;
}
return $class_name;
}

/**
* Return the ID column name to use for this class. If it is
* not set on the class, returns null.
Expand Down Expand Up @@ -235,6 +279,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) {
$class_name = self::_normalise_class_name($class_name);
$table_name = self::_get_table_name($class_name);
$wrapper = ORMWrapper::for_table($table_name);
$wrapper->set_class_name($class_name);
Expand Down
4 changes: 2 additions & 2 deletions test/idiorm.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,13 @@ class ORM {
* will be the only configuration required to use Idiorm.
*/
public static function configure($key, $value=null) {
// Shortcut: If only one argument is passed,
// Shortcut: If only one argument is passed,
// assume it's a connection string
if (is_null($value)) {
$value = $key;
$key = 'connection_string';
}
self::$_config[$key] = $value;
static::$_config[$key] = $value;
}

/**
Expand Down
212 changes: 189 additions & 23 deletions test/test_php53.php
Original file line number Diff line number Diff line change
@@ -1,33 +1,199 @@
<?php

namespace Tests;
namespace {

use ORM, Model,DummyPDO, Tester;
/*
* Testing for Paris for features specific to php5.3
*
* We deliberately don't test the query API - that's Idiorm's job.
* We just test Paris-specific functionality.
*
* Checks that the generated SQL is correct
*
*/

/*
* Testing for Paris for features specifics to PHP >= 5.3
*
* We deliberately don't test the query API - that's Idiorm's job.
* We just test Paris-specific functionality.
*
* Checks that the generated SQL is correct
*
*/
require_once dirname(__FILE__) . "/idiorm.php";
require_once dirname(__FILE__) . "/../paris.php";
require_once dirname(__FILE__) . "/test_classes.php";

require_once dirname(__FILE__) . "/idiorm.php";
require_once dirname(__FILE__) . "/../paris.php";
require_once dirname(__FILE__) . "/test_classes.php";
// Enable logging
ORM::configure('logging', true);

// Enable logging
ORM::configure('logging', true);
// Set up the dummy database connection
$db = new DummyPDO('sqlite::memory:');
ORM::set_db($db);

// Set up the dummy database connection
$db = new DummyPDO('sqlite::memory:');
ORM::set_db($db);
// Allow these tests to be run independently or as part of the full suite
if (!class_exists('Simple')) {
class Simple extends Model {
}
}

class PrefixSimple extends Model {
}

class PrePrefixSimple extends Model {
}

}

namespace Tests {

use ORM, Model,DummyPDO, Tester;

class Simple extends Model {
}

class PrefixSimple extends Model {
}

class PrePrefixSimple extends Model {
}

}

namespace Tests2 {

use ORM, Model,DummyPDO, Tester;

class Simple extends Model {
}

class PrefixSimple extends Model {
}

class PrePrefixSimple extends Model {
}

class Simple extends Model {
}

Model::factory('Tests\Simple')->find_many();
$expected = 'SELECT * FROM `tests_simple`';
Tester::check_equal("Namespaced auto table name", $expected);
namespace {

/*
* Testing prefixing
*/
// Do not prefix tables
ORMWrapper::configure('prefix_tables', false);
// Configured prefix
ORMWrapper::configure('prefix', 'Prefix');
Model::factory('Simple')->find_many();
$expected = 'SELECT * FROM `simple`';
Tester::check_equal("No prefix on auto table name", $expected);

// Configured prefix is the class prefix so is ignored
Model::factory('PrefixSimple')->find_many();
$expected = 'SELECT * FROM `simple`';
Tester::check_equal("Configured prefix used to remove prefix when already present", $expected);

// Configured prefix is a substring of class prefix so is not ignored
ORMWrapper::configure('prefix', 'Pre');
Model::factory('PrefixSimple')->find_many();
$expected = 'SELECT * FROM `prefix_simple`';
Tester::check_equal("Configured prefix used to remove correct prefix only", $expected);

// Prefix tables
ORMWrapper::configure('prefix_tables', true);

// Configured prefix
ORMWrapper::configure('prefix', 'Prefix');
Model::factory('Simple')->find_many();
$expected = 'SELECT * FROM `prefix_simple`';
Tester::check_equal("Prefixed auto table name", $expected);

// Configured prefix is the class prefix so is ignored
Model::factory('PrefixSimple')->find_many();
$expected = 'SELECT * FROM `prefix_simple`';
Tester::check_equal("Configured prefix ignored when already present", $expected);

// Configured prefix is a substring of class prefix so is not ignored
ORMWrapper::configure('prefix', 'Pre');
Model::factory('PrefixSimple')->find_many();
$expected = 'SELECT * FROM `pre_prefix_simple`';
Tester::check_equal("Configured prefix used when not exactly the class prefix", $expected);

// Set table prefixing back to normal
ORMWrapper::configure('prefix_tables', false);

/*
* Testing namepacing
*/
// Do not namepace tables

// Simple namespace
ORMWrapper::configure('prefix', '');
Model::factory('Tests\\Simple')->find_many();
$expected = 'SELECT * FROM `simple`';
Tester::check_equal("No namespace on auto table name", $expected);

// Normalised simple namespace
Model::factory('\\Tests\\Simple')->find_many();
$expected = 'SELECT * FROM `simple`';
Tester::check_equal("No normalised namespace on auto table name", $expected);

// Configured namespace
ORMWrapper::configure('namespace', 'Tests');
Model::factory('Simple')->find_many();
$expected = 'SELECT * FROM `simple`';
Tester::check_equal("No configured namespaced on auto table name", $expected);

// Normalised configured namespace
ORMWrapper::configure('namespace', '\\Tests\\');
Model::factory('Simple')->find_many();
$expected = 'SELECT * FROM `simple`';
Tester::check_equal("No normalised configured namespaced on auto table name", $expected);

// Supplied namespace overrides configured namespace
ORMWrapper::configure('namespace', 'Tests');
Model::factory('Tests2\\Simple')->find_many();
$expected = 'SELECT * FROM `simple`';
Tester::check_equal("Supplied namespace removed on auto table name", $expected);

// Configured prefix and supplied namespace
ORMWrapper::configure('prefix', 'Prefix');
ORMWrapper::configure('namespace', '');
Model::factory('Tests\\Simple')->find_many();
$expected = 'SELECT * FROM `simple`';
Tester::check_equal("No namespace or configured prefix on auto table name", $expected);

// Namespace tables
ORMWrapper::configure('namespace_tables', true);

// Simple namespace
ORMWrapper::configure('prefix', '');
Model::factory('Tests\\Simple')->find_many();
$expected = 'SELECT * FROM `tests_simple`';
Tester::check_equal("Namespaced auto table name", $expected);

// Normalised simple namespace
Model::factory('\\Tests\\Simple')->find_many();
$expected = 'SELECT * FROM `tests_simple`';
Tester::check_equal("Normalised namespaced auto table name", $expected);

// Configured namespace
ORMWrapper::configure('namespace', 'Tests');
Model::factory('Simple')->find_many();
$expected = 'SELECT * FROM `tests_simple`';
Tester::check_equal("Configured namespaced auto table name", $expected);

// Normalised configured namespace
ORMWrapper::configure('namespace', '\\Tests\\');
Model::factory('Simple')->find_many();
$expected = 'SELECT * FROM `tests_simple`';
Tester::check_equal("Normalised configured namespaced auto table name", $expected);

// Supplied namespace overrides configured namespace
ORMWrapper::configure('namespace', 'Tests');
Model::factory('Tests2\\Simple')->find_many();
$expected = 'SELECT * FROM `tests2_simple`';
Tester::check_equal("Supplied namespace overrides configured namespace", $expected);

// Configured prefix and supplied namespace
ORMWrapper::configure('prefix', 'Prefix');
ORMWrapper::configure('namespace', '');
Model::factory('Tests\\Simple')->find_many();
$expected = 'SELECT * FROM `tests_simple`';
Tester::check_equal("Configured prefix prepended to class base name", $expected);

// Set table namespacing back to normal
ORMWrapper::configure('namespace_tables', true);
}