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
更有用。
明确说明,我的问题是:
$primary
标志实际上有用的是什么?$results
数组的结构有用,或者我错过了什么?答案 0 :(得分:12)
确实,$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(或其他一些父类)期望{可能导致的问题{ {1}}传入的方式。另外,这种方式没有复制$results
数组的开销。
答案 1 :(得分:1)
如果您不能总是依赖于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;
}
答案 2 :(得分:0)
我遇到了这个问题。接受的答案很有效。但是,我不得不做一个小调整。如果您正在寻找修改字段,例如从徽标构建一个完全限定的文件名,那么最好创建一个新字段,因为"返回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'];
}
}
答案 3 :(得分:-2)
书中的答案......
$ primary参数指示当前模型是否为 查询所源自的模型或此模型是否存在 被问到是一个协会。如果模型被查询为关联 $ results的格式可能不同;
期望$ primary为true的代码可能会得到“无法使用 字符串偏移量作为数组“如果递归查找,则来自PHP的致命错误 使用
因此,它可能在某些情况下用于逻辑处理,并且可能会被用来对你的$ results产生影响