10

私は次のモデルを持っています:

User列{id、user_name、password、user_type}

Admin列{id、user_id、full_name、..... etc}

Editor列{id、user_id、full_name、... etc}

との関係は User'admin' => array(self::HAS_ONE, 'Admin', 'user_id'),'editor' => array(self::HAS_ONE, 'Editor', 'user_id'),

Admin'user' => array(self::BELONGS_TO, 'User', 'user_id'),

Editor'user' => array(self::BELONGS_TO, 'User', 'user_id'),

fullNameこれで、Userモデルに仮想属性を次のように設定しました

public function getFullName()

{

    if($this->user_type=='admin')

        return $this->admin->full_name;

    else if($this->user_type=='editor')

        return $this->editor->full_name;


}

グリッドビューで仮想属性を表示できますがfullName、属性にフィルターを追加してグリッドビューで並べ替え可能にするにはどうすればよいですか?

UPADTE 1:

以下に示すように、@ Jonの回答に従って、モデルのsearch()関数を更新しました。

    public function search()
        {


            $criteria=new CDbCriteria;
            $criteria->select=array('*','COALESCE( editor.full_name,admin.first_name, \'\') AS calculatedName');
            $criteria->with=array('editor','admin');
            $criteria->compare('calculatedName',$this->calculatedName,true);
            $criteria->compare('email',$this->email,true);
            $criteria->compare('user_type',$this->user_type);

            return new CActiveDataProvider($this, array(
                'criteria'=>$criteria,


));
    }

管理者と編集者の両方の名前がグリッドビューに正しく表示されます。しかし、フィルターを検索すると、次の例外が発生します。

CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'calculatedName' in 'where clause'. The SQL statement executed was: SELECT COUNT(DISTINCT `t`.`id`) FROM `user` `t`  LEFT OUTER JOIN `editor` `editor` ON (`editor`.`user_id`=`t`.`id`)  LEFT OUTER JOIN `admin` `admin` ON (`admin`.`user_id`=`t`.`id`)  WHERE (calculatedName LIKE :ycp0) (C:\xampplite\htdocs\yii\framework\db\CDbCommand.php:528)</p><pre>#0 C:\xampplite\htdocs\yii\framework\db\CDbCommand.php(425):

どうすればこれを取り除くことができますか?

更新2:私の間違い。行を変更すると正常に動作します

$criteria->compare('calculatedName',$this->calculatedName,true);

$criteria->compare('COALESCE( editor.full_name,admin.first_name, \'\')',$this->calculatedName,true);

そしてところで@Jonに感謝します。

4

1 に答える 1

8

ここで実行しようとしているのは、計算列を結果セットに効果的に追加することです。結果をフェッチするために使用されるSQLクエリで、AdminEditorテーブルの両方を結合することを想像してください。したがってAdmin.full_nameEditor.full_name目的の値の計算に関係する2つの列です。

少なくとも1つは常にであるAdmin.full_nameため、最終的な値を計算する式は次のようになります。Editor.full_nameNULL

COALESCE(Admin.full_name, Editor.full_name, '')

計算式ができたので、次の手順を実行する必要があります。

  1. モデルに読み取り/書き込み列を追加して、計算列を受け取ります
  2. CDbCriteria2つのテーブルを結合し、計算列を含むを作成します
  3. CSort計算列がレコードの順序にどのように影響するかを説明するを作成します
  4. CActiveDataProviderこれらの基準と並べ替えオプションを使用するを作成します
  5. データプロバイダーをCGridView

したがって、最初にパブリックプロパティをモデルに追加します。

public $calculatedName;

その後:

$criteria = new CDbCriteria(array(
    'select' => array(
        '*',
        'COALESCE(Admin.full_name, Editor.full_name, \'\') AS calculatedName',
    ),
    'with'   => array('Admin', 'Editor'),
    // other options here
));

$sort = new CSort;
$sort->attributes = array(
    'calculatedName' => array(
        'asc'  => 'COALESCE(Admin.full_name, Editor.full_name, \'\')',
        'desc' => 'COALESCE(Admin.full_name, Editor.full_name, \'\') DESC',
    ),
    // other sort order definitions here
);

$dataProvider = new CActiveDataProvider('User', array(
    'criteria' => $criteria,
    'sort'     => $sort,
));

そして最後に、を使用$dataProviderしてグリッドにデータを入力します。calculatedName列名として使用します。

私は実際にこれを実行しなかったので、私がいくつかの詳細を間違えた場合はお詫びします。

更新:CDbCriteria.select文字列として指定し、その文字列に列を区切るために使用されないコンマ(引数を区切るために使用されるコンマなど)が含まれている場合、Yiiはそれを気に入らないことがわかりましたCOALESCE。ありがたいことCDbCriteriaに、列を配列として渡すこともできます。これにより、この問題を回避できます。上記のコードを一致するように更新しました。

好奇心旺盛な人にとって、問題のあるコードはこれです。

于 2012-05-06T22:47:58.327 に答える