Doctrineの正確なモデルプロパティ名

この記事では、データベーステーブルの列名からモデルプロパティへの正確な(大文字と小文字を区別する)マッピングについて説明します。 この問題は、ORMの最初のブランチに関連しています。 2番目のブランチでは、すでに解決されているようです。 しかし、以来 現時点での安定リリースはバージョン1.2.1で、バージョン2はALPHA4ステージにあります。この問題は多くのORMユーザーに関係があると思います。

camelCaseの列名/エイリアスがプロジェクトで使用されていない場合、この解決策は関係ありません。

問題


Doctrineで作業しているときに問題がありました。 多くのデータベース列の名前はcamelCaseでした。 そして、レコードを受信すると、それらは小文字になりました。 最初はMysqlで罪を犯しました。
列、インデックス、ストアドルーチン名は、どのプラットフォームで大文字と小文字が区別されず、列のエイリアスも区別されませ 。 トリガー名は大文字と小文字が区別され、標準のSQLとは異なります。
Identifier-case-sensitivityを参照してください

このことから、列のエイリアスは依然として大文字と小文字が区別されることが明らかになり、問題の本質はDoctrine自体が列のエイリアスを間違って(大文字と小文字を区別しない)置き換えてstrtolower()にすることです。 グーグル、 このページに出くわしました 。 バグは2番目のブランチで閉じられます。 そして最初に、列名に対してstrtolower()が自動的に生成されます。 どこを見つけるために残っています...

解決策


コードの断片は非常に迅速に発見されました。 これはDoctrine_Table-> setColumn()です。 そこに見る:
$ name = strtolower($パーツ[0]);
そして
$ name = strtolower($ name);

列名を小文字にキャストするのは、それらのユーザーです。 ここで、ORMクラスを変更せずに行う作業は、列名の大文字と小文字を変更しないようにすることです。
まず、独自のMyDoctrine_Tableクラスを作成します。このクラスでは、setColumn()関数をオーバーライドし、これらのコードセクションを置き換えます。
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 .

それからbootstrap.phpにインクルードし、Doctrineテーブルクラスとして登録します。

// 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 .

これで、モデルプロパティの名前がテーブル列の名前と完全に一致するようになりました。

この問題を解決する他の選択肢がある場合、厳しく判断しないようお願いします。コメントでそれらを聞いてうれしいです。

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


All Articles