4

CakePHP2.2.3についてサポートが必要です。

私が持っているもの

現在、次の設定があります。

Post 多くを持っています Attachment

それは正常に動作し、ページは2つのクエリで生成されます。

SELECT *, `Post`.`id` 
FROM `posts` AS `Post` 
WHERE 1 = 1 
ORDER BY `Post`.`created` DESC

SELECT 
    `Attachment`.`id`, 
    `Attachment`.`post_id`, 
    `Attachment`.`created` 
FROM 
    `attachments` AS `Attachment` 
WHERE 
    `Attachment`.`post_id` IN (1, 2, 3, ..., n) 

欲しいもの

関係を次のように拡張したいと思います。

Post hasMany Attachment ; すべてのAttachment belongsTo Type

そして、CakePHPをそれに従わせるのが辛いのかわかりません。
基本的に、私が必要とするのは次のとおりです。

SELECT *, `Post`.`id` 
FROM `posts` AS `Post` 
WHERE 1 = 1 
ORDER BY `Post`.`created` DESC

SELECT 
    `Attachment`.`id`, 
    `Attachment`.`post_id`, 
    `Attachment`.`created`, 
    `Type`.`title`, `Type`.`icon` 
FROM 
    `attachments` AS `Attachment` 
LEFT JOIN 
    `types` AS `Type` 
    ON (`Attachment`.`type_id`=`Type`.`id`) 
WHERE 
    `Attachment`.`post_id` IN (1, 2, 3, ..., n) 

LEFT JOIN types追加されたことに注意してください。

したがって、2番目のクエリで対応する型データを取得します。ループ内または->query()呼び出しを使用してデータを取得できることはわかっていますが、これを可能な限り効果的かつ柔軟にしたいと考えています。

問題

ContainableModel Unbindingトリックおよびこれ)を試しましたが、成功しませんでした。オプションのさまざまな組み合わせを試しましたが、結合も削除したと思います。これが私のPostsController今の姿です。

class PostsController extends AppController {
    public function index() {

        $this->Post->unbindModel(array('hasMany' => array('Attachment')));
        $this->Post->Attachment->unbindModel(array('belongsTo' => array('Type')));

        $this->Post->bindModel(array(
            'hasMany' => array(
                'Attachment' => array(
                    'className'  => 'Attachment',
                // when uncommented, throws the "Unknown column Post.id" SQLSTATE error
                //  'conditions' => array('Post.id' => 'Attachment.post_id'),
                    'foreignKey' => false,
                ),
            ),
        ));
        $this->Post->Attachment->bindModel(array(
            'belongsTo' => array(
                'Filetype' => array(
                    'className'  => 'Filetype',
                //  'conditions' => array('Type.id' => 'Attachment.type_id'),
                    'foreignKey' => false,
                ),
            ),
        ));
        $all = $this->Post->find('all', array(
            'joins' => array(
                array(
                    'table' => 'users',
                    'prefix' => '',
                    'alias' => 'User',
                    'type' => 'INNER',
                    'conditions' => array(
                        'User.id = Post.user_id',
                    )
                ),
            ),
            'contain' => array('Attachment', 'Type'),
            'conditions' => array(),
            'fields' => array('*'),
            'order' => 'Post.created ASC'
        ));
        var_dump($all);exit;
    }
}

ただし、ループ内の反復ごとに追加のクエリを実行し、すべての添付ファイルを取得します。

SELECT `Attachment`.`id`, ... 
FROM `attachments` AS `Attachment` 
WHERE 1 = 1 

この関連付けの条件のコメントを解除すると、SQLSTATE「ColumnPost.idnotfounderror」がスローされます。ここに結合されたPostテーブルがないためだと思います。

これを設定するには手が必要です。

助けてください!ありがとう

アップデート

コントローラーを次のように変更しました。bindModel/コードがないことに注意してくださいunbindModel。関係はモデルクラスで設定されます(この場合は正しいですか?)。

class PostsController extends AppController {
    public function index() {
        $options = array(
            'contain' => array(
                'Post',
                'Type'
            ),
            'order' => 'Post.created DESC',
            'conditions' => array(
            //  'Post.title LIKE' => 'my post'
            )
        );

    //  The following throws "Fatal error: Call to a member function find() on a non-object"
    //  $posts = $this->Attachment->find('all', $options); 

    //  So I had to use $this->Post->Attachment instead of $this->Attachment
        $posts = $this->Post->Attachment->find('all', $options);
        $this->set(compact('posts'));
    }   
}

これはAttachmentモデルです:

class Attachment extends AppModel {
    public $belongsTo = array(
        'Type' => array(
            'className' => 'Type',
            'foreignKey' => 'type_id',
        ),
        'Post' => array(
            'className' => 'Post',
            'foreignKey' => 'post_id',
        ),
    );
}

上記のコードはこのクエリを実行します:

SELECT 
    `Attachment`.`id`, `Attachment`.`type_id`, `Attachment`.`post_id`, `Attachment`.`created`, 
    `Type`.`id`, `Type`.`title`, 
    `Post`.`id`, `Post`.`text`, `Post`.`created` 
FROM 
    `attachments` AS `Attachment` 
    LEFT JOIN `types` AS `Type` ON (`Attachment`.`type_id` = `Type`.`id`) 
    LEFT JOIN `posts` AS `Post` ON (`Attachment`.`post_id` = `Post`.`id`) 
WHERE 
    1 = 1 
ORDER BY 
    `Post`.`created` ASC

すべてはここの添付ファイルについてです。つまり、投稿は添付ファイルに結合されているため、投稿に添付ファイルがない場合は返されません。これはおそらくAttachment->find()、添付ファイルの観点からの呼び出しであるためです。私はそれがちょうどあるべきだと思います:

// ...
FROM 
    `posts` AS `Post`
    LEFT JOIN `attachments` AS `Attachment`  ON (`Attachment`.`post_id` = `Post`.`id`) 
    LEFT JOIN `types` AS `Type` ON (`Attachment`.`type_id` = `Type`.`id`) 
// ...

しかし、それはうまくいきませんね?、、がありますがposts、それらには異なる関係タイプがあります。もともと、私はCakePHPが実行する2つの別々のクエリを投稿しました-それには理由があるに違いありません。attachmentstypes

UPDATE2

私はまだ、初期設定で2番目のクエリをモデルに変更することがすべてだと信じています( 「欲しいもの」Attachmentセクションを参照してください)。だから私は添付ファイル自体と一緒に添付ファイルの種類を取得します。その場合、テーブルをLEFT JOINすることで、データベース関係ロジックが壊れることはありませんね。1つの複雑な呼び出し でそれを行う方法がないことを確認したいだけです。typesattachments
find()

4

2 に答える 2

3

Cake が hasMany リレーションシップを検出すると、自動的に複数のクエリを作成してデータを取得します。これらのクエリを作成する際に、LEFT 結合できる関係 (hasOne と belongsTo) を探します。

Cake はこれを行うことができないため、それらを自分でマージする必要があります。

public function index() {
  $posts = $this->Post->find('all');
  // get all attachments for all found posts
  $attachments = $this->Post->Attachment->find('all', array(
    'contain' => array('Type'),
    'conditions' => array('Post.id' => Set::extract('/Post/id', $posts)
  ));
  // now join them to the posts array
  foreach ($posts as $key => $data) {
    $postId = $data['Post']['id'];
    // append any data related to this post to the post's array
    $posts[$key] += Set::extract("/Attachment[post_id=$postId]/..", $attachments);
  }
  $this->set(compact('posts'));
}

配列を複数回反復処理するため、これは最も効率的な方法ではありませ$attachmentsんが、アイデアが得られると確信しています。

于 2012-12-17T21:04:37.277 に答える