Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 1.11.5

Request #3256 Allow custom file and class naming conventions
Submitted: 2005-01-20 23:46 UTC
From: db_dataobjects-bugs-2005 at ryandesign dot com Assigned:
Status: Suspended Package: DB_DataObject
PHP Version: Irrelevant OS: Irrelevant
Roadmaps: (Not assigned)    
Subscription  


 [2005-01-20 23:46 UTC] db_dataobjects-bugs-2005 at ryandesign dot com
Description: ------------ There is code in DB_DataObjects which computes the name to be used for each data object class and its PHP file. In Generator.php it looks like this: $this->classname = $class_prefix.preg_replace('/[^A-Z0-9]/ i','_',ucfirst($this->table)); $i = ''; $outfilename = "{$base}/".preg_replace('/[^A-Z0-9]/ i','_',ucfirst($this->table)).".php"; Code like this is also duplicated in other places in DB_DataObjects. I would like to see these preg_replace()s moved out into new methods, like computeClassName($table) and computeFileName($table), so that I could override these in a child class to implement different behavior. The reason for this is that I do not subscribe to the PEAR notion that the first character of a class name should be uppercase, and do not want this naming convention for files in my project. Furthermore all my table names begin with a version of my project's name, followed by two underscores. This practice is recommended by phpMyAdmin and has several advantages. But I would like to dispense with these prefixes when dealing with the data objects within my project. The numerous places within the DB_DataObjects code where changes would need to be made currently make it impractical for me to implement differing behavior without having to copy large sections of the DB_DataObjects code, which is undesirable from a maintenance standpoint as new versions of DB_DataObjects are released. By abstracting these tasks into separate methods you would enable me to achieve my desired result in the most effective way. See also bugs 3013 and 2740 for similar requests. Implementing the above suggestion may take care of those users' needs as well. I am using DB_DataObjects 1.7.2 with PHP 5.0.3, Apache 1.3.33 and Mac OS X 10.3.7.

Comments

 [2005-01-20 23:56 UTC] alan_k
messing with the table/class case was an early design decision, that looks less clever in hindsight (DBDO wont be doing it..) $string = $do->className($tablename); $string = $do->fileName($tablename); looks like a good addition. (patches welcome), otherwise you may have to wait a while.
 [2005-05-14 03:07 UTC] jrhernandez05 at gmail dot com
I'm currently facing the same issue as the original poster, in which all the tables in my database have a prefix (e.g. T5010_ARTICLES) which I do not want in my class name (I just want an "Articles" class). The problem with having an overridable method such as "className" is that it won't be used in most cases. The reason is that the DataObjects are created through the "factory" method, which is static. Other packages such as DB_DataObject_FormBuilder (which I also use) instantiate objects through this method. Hence, an overridable method is not the solution. What I propose is having another config option, such as "xml_config_file", that when specified would instruct the DB_DataObject to get the settings from this XML file. This XML file would contain the following: - Table to class name and file name mappings - Column name mappings (would map a column name to a property name) - Link information (no separate db.links.ini file) I will be more than glad to provide this patch, but having just seen the DBDO PECL package (which looks very good, BTW), it would not seem reasonable to provide this functionality if DBDO, which will replace DB_DataObject, won't have something similar. I think DBDO should also have this feature, since all references to a table/column name will be in just one file, and abstracted elsewhere. If it could/will be included in DBDO, then I will start working on it...
 [2005-05-14 03:36 UTC] alan_k
[copy of email on the subject] If I understand correctly, the idea is that you have a map, used by the code generator that creates a Class name which may be different to the table name: eg. class MyClass extends DB_DataObject { var $_table = "someothername"; } and you would need the generator to use some kind of map: ClassName TableName _________ _________ MyClass someothername XXXXXXX YYYYYYYYYYYYY ..... - From DataObjects perspective, the best way to handle this would be to do something like: generator_classtable_map = ........ where the value of generator_classtable_map could be a) A string - probably a filename of a wddx formated file b) An array - which could be loaded from an xml file or whatever using a modified createTables.php script.. DBDO doesnt have a generator yet.. ;) - It's not actually 'as' esential, although it would probably be a usefull tool.. Let me know you thoughts.. Regards Alan
 [2005-05-14 21:35 UTC] jrhernandez05 at gmail dot com
Actually, I wasn't considering the generator portion, although the generator can also use this XML approach. I am primarily concerned on how the DataObject itself gets its database structure info. There could be an additional setting named "xml_config_file", or something to that effect, and that file would have the database structure information (it would consolidate the information for the "table()", "keys()", "sequenceKey()", and "links()" methods. Below is an example of how the XML file could look like. Before viewing it, keep in mind that where I work we have a naming convention of TXXXX_NAME for tables and CXXXX_NAME for columns. <database-structure> <table name="t1001_customers" id-column-names="c1001_customer_id" sequence-key="c1001_customer_id,false,s1001_customer_id" class-name="Customer"> <column name="c1001_customer_id" data-type="integer" nullable="false" property-name="ID" /> <column name="c1001_name" data-type="string" nullable="false" property-name="name" /> <column name="c1001_phone" data-type="string" nullable="true" property-name="phone" /> <column name="c1002_state_id" data-type="integer" nullable="true" property-name="stateID" /> <link property-name="state" column-name="c1002_state_id" table-name="t1002_states" table-column-name="c1002_state_id" /> </table> <table name="t1002_states" id-column-names="c1002_state_id" sequence-key="c1002_state_id,false,c1002_state_id" class-name="State"> <column name="c1002_state_id" data-type="integer" nullable="false" property-name="ID" /> <column name="c1002_name" data-type="string" nullable="false" property-name="name" /> <column name="c1002_abbreviation" data-type="string" nullable="false" property-name="abbreviation" /> </table> </database-structure> Some notes on the above: 1) id-column-names maps is used by "keys()". 2) sequence-key is used by "sequenceKey()". 3) The class-name attribute contains the name of the class to use. If not specified, then the table name will be used. 4) The data-type attribute contains a primitive PHP type. It might be useful if it could also contain the name of a class (if it's not a primitive type, then it would be assumed that it's a class and the property would be initialized as $this->$p = new $dataType($columnValue)). 5) Each "link" tag under a table would specify the links under each table. In the example above, there would be an additional property for the Customer class named "state", which would be an instance of the State class, which has three other properties: "ID", "name", and "abbreviation". Let me know what you think and if you have any suggestions.
 [2005-05-14 21:41 UTC] jrhernandez05 at gmail dot com
The XML code above looks cluttered due to wrapping. Hope the following is a bit clearer to read: <database-structure> <table name="t1001_customers" id-column-names="c1001_customer_id" sequence-key="c1001_customer_id,false,s1001_customer_id" class-name="Customer"> <column name="c1001_customer_id" data-type="integer" nullable="false" property-name="ID" /> <column name="c1001_name" data-type="string" nullable="false" property-name="name" /> <column name="c1001_phone" data-type="string" nullable="true" property-name="phone" /> <column name="c1002_state_id" data-type="integer" nullable="true" property-name="stateID" /> <link property-name="state" column-name="c1002_state_id" table-name="t1002_states" table-column-name="c1002_state_id" /> </table> <table name="t1002_states" id-column-names="c1002_state_id" sequence-key="c1002_state_id,false,c1002_state_id" class-name="State"> <column name="c1002_state_id" data-type="integer" nullable="false" property-name="ID" /> <column name="c1002_name" data-type="string" nullable="false" property-name="name" /> <column name="c1002_abbreviation" data-type="string" nullable="false" property-name="abbreviation" /> </table> </database-structure>
 [2005-05-17 23:16 UTC] db_dataobjects-bugs-2005 at ryandesign dot com
I personally wouldn't want to have to create and maintain such an XML file. My table names follow a convention, always. I'd much rather define a short PHP function to map those table names to the corresponding class and file names than have to maintain an umpteen-line XML file over the lifetime of my application. It seems to me like I should be able to do it like this: require_once 'DB/DataObject.php'; DB_DataObject::setClassNamer(create_function('$x', 'return strtolower(substr($x, strpos($x, "__")+2));' )); DB_DataObject::setFileNamer(create_function('$x', 'return strtolower(substr($x, strpos($x, "__")+2)) ' . '. ".class";')); This would implement the naming strategy I want, which is to say that I have a table called "myDatabase__myTable" and I want the class to be "mytable" and the PHP file to be "mytable.class.php". Then, after that initial setup, any PHP file, any 3rd-party library like DB_DataObjects_FormBuilder, can call the factory method or whatever, and internally, DB_DataObject can call DB_DataObject::getClassName($tableName) to get the class name and DB_DataObject::getFileName($tableName) to get the file name. Here's how these four new functions might be implemented in DB_DataObject: class DB_DataObject { function setClassNamer($function) { global $_DB_DATAOBJECT; $_DB_DATAOBJECT['classNamer'] = $function; } function setFileNamer($function) { global $_DB_DATAOBJECT; $_DB_DATAOBJECT['fileNamer'] = $function; } function getClassName($tableName) { global $_DB_DATAOBJECT; return $_DB_DATAOBJECT['classNamer']($tableName); } function getFileName($tableName) { global $_DB_DATAOBJECT; return $_DB_DATAOBJECT['fileNamer']($tableName) . '.php'; } } Column names could be handled in a similar way. I have no comment on how this could work in DBDO as I've never worked with PECL.
 [2005-05-18 03:21 UTC] jrhernandez05 at gmail dot com
From my experience, the XML approach is not cumbersome to maintain (our production J2EE server uses this same approach, and we've been using it for about 4 years now with no complaints). But I do see that with your approach, there would be less code to write. I would actually go further and have a class which implements the "namer" methods. The DB_DataObject class could use one standard namer class, DB_DataObject_Namer, and implement two static methods, "getNamer" and "setNamer". Users could extend the DB_DataObject_Namer class and override whichever namer methods they need. Here's an example: DB_DATAOBJECT_NAMER ------------------------- class DB_DataObject_Namer { function getClassName($tableName) { return $tableName; } function getFileName($tableName) { return $tableName . '.php'; } function getPropertyName($tableName, $columnName) { return $columnName; } function getLinkPropertyName($table1, $column1, $table2, $column2) { return '_' . str_replace( '.', '_', $column1 ); } }; MY_NAMER -------- class MyNamer extends DB_DataObject_Namer { function getClassName($tableName) { return substr( $tableName, strpos( $tableName, '_' ) + 1 ); } function getFileName($tableName) { // in this case, the class and file names are the same return $this->getClassName( $tableName ) . '.php'; } /* NOTE: By not overriding the other methods, the default behavior will be used. */ }; SAMPLE USAGE ------------ require_once( 'DB/DataObject.php' ); require_once( 'MyCompany/MyNamer.php' ); DB_DataObject::setNamer( new MyNamer() ); // use DB_DataObject as usual...
 [2005-05-18 04:53 UTC] alan_k
This would be the ideal solution eg. implemented by the ini setting: name_provider_class = DB_DataObject_Namer The default class could implement all the current naming rules, and Custom classes could either extend or replace it.
 [2005-10-05 08:53 UTC] pearuser at yahoo dot com
FWIW: simple patch to have control of filename prefix (ini option class_filename_prefix. --- /usr/lib/php/DB/DataObject/Generator.php 2005-10-05 03:48:09.000000000 -0500 +++ Generator.php 2005-10-05 03:46:07.000000000 -0500 @@ -495,6 +495,7 @@ System::mkdir(array('-p',$base)); } $class_prefix = $options['class_prefix']; + $class_filename_prefix = $options['class_filename_prefix']; if ($extends = @$options['extends']) { $this->_extends = $extends; $this->_extendsFile = $options['extends_location']; @@ -506,9 +507,9 @@ $i = ''; if (strpos($options['class_location'],'%s') !== false) { - $outfilename = sprintf($options['class_location'], preg_replace('/[^A-Z0-9]/i','_',ucfirst($this->table))); + $outfilename = sprintf($options['class_location'], preg_replace('/[^A-Z0-9]/i','_',$class_filename_prefix.ucfirst($this->table))); } else { - $outfilename = "{$base}/".preg_replace('/[^A-Z0-9]/i','_',ucfirst($this->table)).".php"; + $outfilename = "{$base}/".preg_replace('/[^A-Z0-9]/i','_',$class_filename_prefix.ucfirst($this->table)).".php"; } $oldcontents = ''; if (file_exists($outfilename)) {
 [2009-10-13 05:46 UTC] alan_k (Alan Knowles)
-Status: Verified +Status: Suspended
Suspending - no patches to implement a 'name provider'