Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用bindModel和custom finder将CakePHP 2模型关联更改为深度链接?_Php_Mysql_Cakephp_Associations_Cakephp 2.x - Fatal编程技术网

如何使用bindModel和custom finder将CakePHP 2模型关联更改为深度链接?

如何使用bindModel和custom finder将CakePHP 2模型关联更改为深度链接?,php,mysql,cakephp,associations,cakephp-2.x,Php,Mysql,Cakephp,Associations,Cakephp 2.x,我正在尝试复制此SQL查询结果,该结果有效: SELECT r.id, r.day, s.ddbroute_id, s.delivery_id, d.id, d.laststatusid, t.id, t.delivery_id, t.statusstage_id, st.id, st.stage FROM ddbroutes r LEFT JOIN ddbrouteslots s on r.id = s.ddbroute_id LEFT JOIN deliveries d on s.deliv

我正在尝试复制此SQL查询结果,该结果有效:

SELECT r.id, r.day, s.ddbroute_id, s.delivery_id, d.id, d.laststatusid, t.id, t.delivery_id, t.statusstage_id, st.id, st.stage
FROM ddbroutes r
LEFT JOIN ddbrouteslots s on r.id = s.ddbroute_id
LEFT JOIN deliveries d on s.delivery_id = d.id
LEFT JOIN trackingstatuses t on d.laststatusid = t.id 
LEFT JOIN statusstages st on t.statusstage_id = st.id
我使用的是CakePHP2模型

  • bindModel可动态更改模型关联
  • 自定义查找将逻辑放入模型中
  • 在第二级之外,底部表格中没有公共字段。 错误消息是:'Model“Ddbroute”与Model“Delivery”不关联。'。 如果合适的话,我很乐意使用连接。我已经阅读了我能找到的关于StackOverflow的大部分相关文章

    下面是我的代码和更多信息。感谢您的帮助。


    我有五个表(包括以下字段):

    模型中设置了以下关系:

    Ddbroute hasMany Ddbrouteslot (Ddbrouteslot belongsTo Ddbroute)
    Delivery hasOne Ddbrouteslot (Ddbrouteslot belongsTo Delivery)
    Delivery hasMany Trackingstatus (Trackingstatus belongsTo Delivery)
    Statusstage hasMany Trackingstatus (Trackingstatus belongsTo Statusstage)
    
    虽然交付有一个Ddbrouteslot(这将是HASMONY-修订版-现在保留为hasOne),但对于任何单个Ddbroute,每个Ddbrouteslot只关联一个交付。在所有模型中都设置了Containable。我不知道是否需要先使用unbindModel(它没有更改错误消息)

    我在Ddbroute.php模型文件中的代码(仅限于交货表)

    在另一个控制器中,要运行查找操作:

    $this->LoadModel('Ddbroute');
    $ddbstatuses = $this->Ddbroute->find('ddbstatuses');
    $this->set(compact('ddbstatuses')); // to make available in a view
    
    我还进一步尝试使用长连接数组,但该查询没有带来任何传递、跟踪状态或状态阶段信息,尽管该查询似乎已经运行

      public $findMethods = array('ddbstatuses' => true);
    
      protected function _findDdbstatuses($state, $query, $results = array()) {
      if ($state === 'before') {
    
        ClassRegistry::init('Delivery'); // not sure these three lines were needed so I tried with and without them
        ClassRegistry::init('Trackingstatus');
        ClassRegistry::init('Statusstage');
    
    
    
        $query['joins'] = array(
          array(
            'table' => 'ddbrouteslots',
            'alias' => 'Ddbrouteslot',
            'type' => 'LEFT',
            'conditions' => array(
                'Ddbroute.id = Ddbrouteslot.ddbroute_id'
          )),
          array(
            'table' => 'deliveries',
            'alias' => 'Delivery',
            'type' => 'LEFT',
            'conditions' => array(
              'Ddbrouteslot.id = Delivery.id'
          )),
          array(
            'table' => 'trackingstatuses',
            'alias' => 'Trackingstatus',
            'type' => 'LEFT',
            'conditions' => array(
              'Delivery.laststatusid = Trackingstatus.id'
          )),
          array(
            'table' => 'statusstages',
            'alias' => 'Statusstage',
            'type' => 'LEFT',
            'conditions' => array(
              'Trackingstatus.statusstage_id = Statusstage.id'
          ))
      );
    
    
        $query['contain'] = array(
            'Ddbrouteslot',
              'Delivery',  // Not sure I should be adding these other models, so I tried with and without them
              'Trackingstatus',
              'Statusstage'
          );
        return $query;
      }
      return $results;
    }
    

    经过一些帮助,我现在有四个解决方案来获取我的数据,尽管实际上其中三个是第一个的变体。我相对缺乏经验,有些基本的东西我不欣赏

    1。在控制器中

    $this->LoadModel("Ddbrouteslot");
    $res = $this->Ddbrouteslot->find("all", array(
      "conditions" => array(
        "Ddbrouteslot.delivery_id > 0",
        "Ddbrouteslot.ddbroute_id" => 45
    ),
    "contain" => array(
        "Ddbroute",
        "Delivery" => array(
    "Trackingstatus" => array(
       "order" => array(
       "Trackingstatus.id" => "desc"
        ),
        "limit" => 1,
        "Statusstage"
       )
      )
     )
    );
    
    来自DebugKit的计时:主查询为20ms;Trackingstatus和Statusstage是针对四个相关交付的额外查询,每个查询18ms x 4;总时间为164ms。这是相当缓慢,这是不理想的

    这是从第二个模型Ddbrouteslot开始的,因为它与Ddbroute和Delivery都有直接关系。任何关联都没有变化。 从Ddbrouteslot到交货的belongsTo关系运作良好。 在交付和交付id跟踪状态之间已经存在很多关系


    2。使用SQL

    $this->LoadModel("Ddbroute");
    $qres = $this->Ddbroute->query(
        "SELECT *
        FROM 
        ddbroutes AS r
        LEFT JOIN ddbrouteslots s on r.id = s.ddbroute_id
        LEFT JOIN deliveries d on s.delivery_id = d.id
        LEFT JOIN trackingstatuses t on d.laststatusid = t.id 
        LEFT JOIN statusstages st on t.statusstage_id = st.id
        WHERE s.delivery_id > 0 AND s.ddbroute_id = 45
    ;"
    debug($qres);
    
    $rres = $this->Ddbroute->find("all", array(
        "conditions" => array(
        "Ddbroute.id" => 45
    ),
    "recursive" => -1,
    "contain" => array(
    
            "Ddbrouteslot" => array(
                "conditions" => array(
                    "Ddbrouteslot.delivery_id > 0"
                ),
                "Delivery" => array(
                    "Trackingstatus" => array(
                        "order" => array(
                            "Trackingstatus.id" => "desc"
                        ),
                        "limit" => 1,
                        "Statusstage"
                    )
                )
            )
        )
    ));
    debug($rres);
    
    计时:耗时19毫秒。这意味着速度要快得多。Cake文档中不建议这样做,而且很明显,它在数据库之间的可移植性不如纯Cake查找


    3。更改基本型号

    $this->LoadModel("Ddbroute");
    $qres = $this->Ddbroute->query(
        "SELECT *
        FROM 
        ddbroutes AS r
        LEFT JOIN ddbrouteslots s on r.id = s.ddbroute_id
        LEFT JOIN deliveries d on s.delivery_id = d.id
        LEFT JOIN trackingstatuses t on d.laststatusid = t.id 
        LEFT JOIN statusstages st on t.statusstage_id = st.id
        WHERE s.delivery_id > 0 AND s.ddbroute_id = 45
    ;"
    debug($qres);
    
    $rres = $this->Ddbroute->find("all", array(
        "conditions" => array(
        "Ddbroute.id" => 45
    ),
    "recursive" => -1,
    "contain" => array(
    
            "Ddbrouteslot" => array(
                "conditions" => array(
                    "Ddbrouteslot.delivery_id > 0"
                ),
                "Delivery" => array(
                    "Trackingstatus" => array(
                        "order" => array(
                            "Trackingstatus.id" => "desc"
                        ),
                        "limit" => 1,
                        "Statusstage"
                    )
                )
            )
        )
    ));
    debug($rres);
    
    计时:主查询为18ms;对于四次相关交付,交付、跟踪状态和状态阶段各为18ms x 4;总时间为234ms。速度较慢,因为每次发货都需要进行交付,因为它不在Ddbroute的模型内。 改变递归并没有什么不同


    4。使用自定义查找 这是与上面1.)相同的查询,但只是使用了一个自定义的find方法

    public $findMethods = array('ddbstatuses' => true);   
    protected function _findDdbstatuses($state, $query, $results = array()) {
        if ($state === 'before') {       
            $query['conditions'] = array(
              "Ddbrouteslot.delivery_id > 0",
              "Ddbrouteslot.ddbroute_id" => 45
            );
            $query['contain'] = array(
              "Ddbroute",
              "Delivery"=> array(
                 "Trackingstatus" => array(
                    "order" => array(
                    "Trackingstatus.id" => "desc"
                 ),
                 "limit" => 1,
                    "Statusstage"
                  )
               )
              );
             return $query;
          }   
       return $results;
    }  
    

    我现在有了一个解决方案,但是使用CakePHP模型进行查询要比下面的SQL解决方案(2)慢得多。字段“Delivery.laststatusid”可以链接到“Trackingstatus.id”,那么就不需要“order”约束。我用一个unbindModel和bindModel尝试了这一点,试图将hasOne和belongsTo关联起来。由于主键Delivery.id未被使用,我的语法包括
    'foreignKey'=>false,'conditions'=>array('
    Delivery
    laststatusid`=
    Trackingstatus
    id
    ')`)。我收到一条错误消息,laststatusid是未知列。关于如何更快一些有什么想法吗?