📜 ⬆️ ⬇️

Exact Model Property Names in Doctrine

This article is devoted to the exact (case sensitive) mapping of the names of the columns of the database table to the model properties. This problem is relevant for the 1st branch of ORM, since in the second branch, it seems to have already been solved. But since Since stable release is currently version 1.2.1 and version 2 is in ALPHA4 stage, I think that this problem is relevant for many ORM users.

If camelCase column names / aliases are not used in your project, then this decision will be irrelevant for you.

Problem


While working with Doctrine, I had a problem. Many DB columns had names like camelCase. And when receiving records turned into lowercase. At first I sinned on Mysql.
Column, index, and stored routine, nor are column aliases . Trigger names are case sensitive, which differs from standard SQL.
see Identifier-case-sensitivity

From this it became clear that the column aliases are still case-sensitive, and the problem is that Doctrine itself incorrectly (case-insensitively) substitutes column aliases, making it strtolower (). Googling, came across this page . The bug is closed for the second branch. And for the first, strtolower () is automatically generated for column names. It remains to find where ...
')

Decision


Lots of code found quite quickly. This is Doctrine_Table -> setColumn (). There we see:
$ name = strtolower ($ parts [0]);
and
$ name = strtolower ($ name);

They are responsible for bringing the names of the columns to lower case. Now our task, without changing the ORM classes, is to make the register of column names not change.
First, we create our own class MyDoctrine_Table, in which we overlap the setColumn () function and replace these parts of the code.
class MyDoctrine_Table extends Doctrine_Table
{

public function setColumn($name, $type, $length = null , $options = array(), $prepend = false )
{
if (is_string($options)) {
$options = explode( '|' , $options);
}

foreach ($options as $k => $option) {
if (is_numeric($k)) {
if ( ! empty($option)) {
$options[$option] = true ;
}
unset($options[$k]);
}
}

// extract column name & field name
if (stripos($name, ' as ' ))
{
if (strpos($name, ' as ' )) {
$parts = explode( ' as ' , $name);
} else {
$parts = explode( ' AS ' , $name);
}

if (count($parts) > 1) {
$fieldName = $parts[1];
} else {
$fieldName = $parts[0];
}

//$name = strtolower($parts[0]);
$name = $parts[0];
} else {
$fieldName = $name;
//$name = strtolower($name);
}

$name = trim($name);
$fieldName = trim($fieldName);

if ($prepend) {
$ this ->_columnNames = array_merge(array($fieldName => $name), $ this ->_columnNames);
$ this ->_fieldNames = array_merge(array($name => $fieldName), $ this ->_fieldNames);
} else {
$ this ->_columnNames[$fieldName] = $name;
$ this ->_fieldNames[$name] = $fieldName;
}

if ($length == null ) {
switch ($type) {
case 'integer' :
$length = 8;
break ;
case 'decimal' :
$length = 18;
break ;
case 'string' :
case 'clob' :
case 'float' :
case 'integer' :
case 'array' :
case 'object' :
case 'blob' :
case 'gzip' :
//$length = 2147483647;

//All the DataDict driver classes have work-arounds to deal
//with unset lengths.
$length = null ;
break ;
case 'boolean' :
$length = 1;
case 'date' :
// YYYY-MM-DD ISO 8601
$length = 10;
case 'time' :
// HH:NN:SS+00:00 ISO 8601
$length = 14;
case 'timestamp' :
// YYYY-MM-DDTHH:MM:SS+00:00 ISO 8601
$length = 25;
break ;
}
}

$options[ 'type' ] = $type;
$options[ 'length' ] = $length;

if ($prepend) {
$ this ->_columns = array_merge(array($name => $options), $ this ->_columns);
} else {
$ this ->_columns[$name] = $options;
}

if (isset($options[ 'primary' ]) && $options[ 'primary' ]) {
if (isset($ this ->_identifier)) {
$ this ->_identifier = (array) $ this ->_identifier;
}
if ( ! in_array($fieldName, $ this ->_identifier)) {
$ this ->_identifier[] = $fieldName;
}
}
if (isset($options[ 'default' ])) {
$ this ->hasDefaultValues = true ;
}
}

}


* This source code was highlighted with Source Code Highlighter .

Then in bootstrap.php we include it, and register it as a class of the Doctrine table.

// lowercase
require_once(dirname(__FILE__) . '/lib/doctrine_extra/MyDoctrine/Table.php' );
$conn->setAttribute(Doctrine::ATTR_TABLE_CLASS, 'MyDoctrine_Table' );


* This source code was highlighted with Source Code Highlighter .

Everything, now the name of properties of models completely coincides with names of columns of the table.

Please do not judge strictly, if you have other solutions for this task, I will be glad to hear them in the comments.

Source: https://habr.com/ru/post/81891/


All Articles