duanpai6581 2009-10-30 06:23
浏览 12
已采纳

使用CakePHP中没有单个外键的模型

I'm working on an application which has data imported from a foreign (and wholly unchangeable) source. I'll simplify some of the tables to explain the problem. Below are the tables with their primary keys.

invoices     (doc_number, date_printed, batch_number)
headers      (doc_number, date_printed, batch_number)
deliveries   (doc_number, date_printed, batch_number)
transactions (doc_number, date_printed, batch_number, line_number)
messages     (doc_number, date_printed, batch_number, line_number)

So you can see that Invoices, Headers and Deliveries have One-to-One relationships. Invoices-to-Transactions and Invoices-to-Messages are One-to-Many.

In importing these tables to my own database, I've changed the existing primary key to be a unique key and added an auto_incrementing field (id) on each table.

Now the problem is setting up the relationships in Cake, since it doesn't really handle composite keys at all. I've been able to get the One-to-One relationships working like this:

class Invoice extends AppModel {
    public $name = "Invoice"
         , $hasOne = array(
            "Header" => array(
                'foreignKey' => false,
                'conditions' => array(
                    "Invoice.doc_number = Header.doc_number",
                    "Invoice.date_printed = Header.date_printed",
                    "Invoice.batch_number = Header.batch_number"
                )
            )
         )
    ;
}

And this works, because the one-to-one relationships are queried in one go with a big LEFT JOIN. Trying the same method with a one-to-many relationship (eg, with Invoices and Transactions) dies, because Cake does two queries: the first to find all the matching Invoices, and then the second to find all the Transactions with a corresponding foreign key which matches the results from the first query: (here's the simplified query it's trying to run)

SELECT `Transaction`.* FROM `transactions` AS `Transaction`
WHERE `Invoice`.`doc_number` = `Transaction`.`doc_number`
AND `Invoice`.`date_printed` = `Transaction`.`date_printed`
AND `Invoice`.`batch_number` = `Transaction`.`batch_number`

You can see, it's not joining onto invoices so the query dies.

Any ideas about how I can make this work?

  • 写回答

2条回答 默认 最新

  • donmqryh49993 2009-10-30 06:32
    关注

    Worst case scenario, you can use the finderQuery parameter of the hasMany relationship. It allows you to completely override the queries.

    You might also be able to add a unique id field that combines the relevant data fields into one. An UPDATE statement could fix existing data and a TRIGGER could be set up to update new records as they are added or changed, assuming that your database supports triggers.

    Edit: With all of the other complexities, you might be better off skipping the hasMany relationship altogether and fetching the Transaction records in a separate find(). If you have to do it very many places you could always wrap it in a function in the Invoice model like this one:

    <?php
    class Invoice extends AppModel() {
        ...
    
        function getInvoice($conditions) {
            $invoice = $this->find('first', compact('conditions'));
    
            $conditions = array(
                 'Transaction.doc_number' => $invoice['Invoice']['doc_number'],
                 'Transaction.date_printed' => $invoice['Invoice']['date_printed'],
                 'Transaction.batch_number' => $invoice['Invoice']['batch_number']);
            $invoice['transactions'] = $this->Transaction->find('all', compact('conditions'));
    
            return $invoice;
        }
    }
    ?>
    

    If you use a function like that in the model, don't forget that Invoice would need a defined relationship to Transaction, even if you don't use it directly, so that $this->Transaction is defined.

    Also, if you prefer the data to be returned the way a hasMany relationship would be, you could always add a foreach loop to recombine them that way.

    Update There's also a SimpleResults behavior in the Cake Bakery that would allow easily returning those results from the other table in the format of a regular hasMany association.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 comsol稳态求解器 找不到解,奇异矩阵有1个空方程返回的解不收敛。没有返回所有参数步长;pid控制
  • ¥15 怎么让wx群机器人发送音乐
  • ¥15 fesafe材料库问题
  • ¥35 beats蓝牙耳机怎么查看日志
  • ¥15 Fluent齿轮搅油
  • ¥15 八爪鱼爬数据为什么自己停了
  • ¥15 交替优化波束形成和ris反射角使保密速率最大化
  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功