【问题标题】:CakePHP 2.x: Is the $primary flag on Model::afterFind() actually useful?CakePHP 2.x:Model::afterFind() 上的 $primary 标志真的有用吗?
【发布时间】:2014-02-07 23:50:58
【问题描述】:

CakePHP 的 Model::afterFind() 回调看起来像:

afterFind(array $results, boolean $primary = false)

根据文档:

$primary 参数指示当前模型是否是发起查询的模型,或者此模型是否作为关联进行查询。如果将模型作为关联进行查询,$results 的格式可能会有所不同。

它们可以不同,但实验表明它们总是不同。据我所知,$primary 参数实际上并不是那么有用。如果它设置为false,您可能会或可能不会获得扁平的数据结构,因此您可能会或可能不会收到可怕的“不能将字符串偏移量用作数组”错误消息。

虽然我还没有尝试过,但我根据文档的想法是完全忽略$primary标志,只检查数据:

public function afterFind($results, $primary = false) {
  if (array_key_exists(0, $results) {
    // operate on $results[0]['User']['fieldname']
  } else {
    // operate on $results['fieldname']
  }
  return $results;
}

这是 hackish,我不喜欢它,但它似乎比 $primary 更有用。

明确说明,我的问题是:

  1. $primary 标志实际上有什么用处?
  2. 我是否正确对于确定$results 数组的结构没有用处,还是我遗漏了什么?

【问题讨论】:

    标签: cakephp


    【解决方案1】:

    确实,$primary 参数似乎只在警告您$results 的格式不可预测的情况下有用。它对确定$results 的格式没有用处。

    更多信息在这里:https://groups.google.com/forum/?fromgroups=#!topic/cake-php/Mqufi67UoFo

    那里提供的解决方案是检查!isset($results[$this->primaryKey]) 以查看$results 是什么格式。这也有点小技巧,但可以说比检查密钥“0”更好。

    我最终想出的解决方案是这样做:

    public function afterFind($results, $useless) {
    
        // check for the primaryKey field
        if(!isset($results[$this->primaryKey])) {
            // standard format, use the array directly
            $resultsArray =& $results;
        } else {
            // stupid format, create a dummy array
            $resultsArray = array(array());
            // and push a reference to the single value into our array
            $resultsArray[0][$this->alias] =& $results;
        }
    
        // iterate through $resultsArray
        foreach($resultsArray as &$result) {
            // operate on $result[$this->alias]['fieldname']
            // one piece of code for both cases. yay!
        }
    
        // return $results in whichever format it came in
        // as but with the values modified by reference
        return parent::afterFind($results, $useless);
    }
    

    这减少了代码重复,因为您不必编写两次字段更改逻辑(一次用于数组,一次用于非数组)。

    您可以通过在方法末尾返回 $resultsArray 来完全避免引用的东西,但我不确定如果 CakePHP(或其他一些父类)期望 $results 可能会导致什么问题以传入的方式。另外,这种方式没有复制$results数组的开销。

    【讨论】:

    • 今天遇到了这个问题。有时 $results 集是一个多维数组,有时不是。我觉得这应该是一个很大的问题。
    • 哇,我可以吻你。在撞了我的头 4 小时后,这才救了我。
    【解决方案2】:

    如果您不能总是依赖primaryKey 在字段列表中并且您知道要查找的密钥,那么您可以使用更简单的方法。这是一个例子:

    /**
     * Decrypt password
     *
     * @see Model::afterFind()
     */
    public function afterFind($results, $primary = false) {        
        if (!empty($results['password'])) {
            $results['password'] = Security::rijndael($results['password'], Configure::read('encrypt.key'), 'decrypt');
            return $results;
        }
    
        foreach ($results as &$r) {
            if (!empty($r[$this->alias]['password'])) {
                $r[$this->alias]['password'] = Security::rijndael($r[$this->alias]['password'], Configure::read('encrypt.key'), 'decrypt');
            }
        }
        return $results;
    }
    

    【讨论】:

      【解决方案3】:

      我遇到了这个问题。接受的答案效果很好。然而,我不得不做一个小的调整。如果您要修改一个字段,例如从徽标构造一个完全限定的文件名,最好创建一个新字段,如“return parent::afterFind($results, $useless);”如果模型 find 是从其他模型调用的,则会执行两次。

      foreach($resultsArray as &$result) {
              // operate on $result[$this->alias]['fieldname']
              // one piece of code for both cases. yay!
      
              // Added logoFull instead of modifying logo
              if(isset($result[$this->alias]['logo'])){
                  $result[$this->alias]['logoFull'] = Configure::read('urlImg') . 'logos' . DIRECTORY_SEPARATOR .
                      'carrier' . DIRECTORY_SEPARATOR . $result[$this->alias]['logo'];
              }
          }
      

      【讨论】:

        【解决方案4】:

        书中的答案...

        $primary 参数表示当前模型是否为 查询源自的模型或此模型是否 被查询为关联。如果将模型作为关联进行查询 $results 的格式可以不同;

        期望 $primary 为真的代码可能会得到“无法使用 如果递归查找是,则字符串偏移量作为数组”来自 PHP 的致命错误 用过。

        因此,它在某些情况下可能对逻辑处理很有用,并且可以用来对您的 $results 产生连锁反应

        【讨论】:

        • 您可能会注意到我引用了文档的同一部分。但是,正如我在问题中所说,如果 $primary 设置为 false 并不一定意味着 $results 的格式会有所不同。正如文档所说,“$results 的格式 可以 不同。”但话又说回来,它可能不会。实验支持这一点。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-18
        • 2011-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-21
        相关资源
        最近更新 更多