cakephp 3 中的特征和行为有什么区别?
What is the difference between trait and behavior in cakephp 3?
我发现 cakephp 3 中的软删除是通过 traits 实现的。我尝试通过行为来实现它。但与特征版本不同,SoftDeleteBehavior 不起作用。
我的模型初始化方法中有这一行:
$this->addBehavior('SoftDelete');
这是我的 SoftDeleteBehavior
namespace App\Model\Behavior;
use Cake\ORM\Behavior;
use Cake\ORM\RulesChecker;
use Cake\Datasource\EntityInterface;
use App\Model\Behavior\MyQuery;
class SoftDeleteBehavior extends Behavior {
public $user_id = 1;
public function getDeleteDate() {
return isset($this->deleteDate) ? $this->deleteDate : 'deleted';
}
public function getDeleter() {
return isset($this->deleter) ? $this->deleter : 'deleter_id';
}
public function query() {
return new MyQuery($this->connection(), $this);
}
/**
* Perform the delete operation.
*
* Will soft delete the entity provided. Will remove rows from any
* dependent associations, and clear out join tables for BelongsToMany associations.
*
* @param \Cake\DataSource\EntityInterface $entity The entity to soft delete.
* @param \ArrayObject $options The options for the delete.
* @throws \InvalidArgumentException if there are no primary key values of the
* passed entity
* @return bool success
*/
protected function _processDelete($entity, $options) {
if ($entity->isNew()) {
return false;
}
$primaryKey = (array)$this->primaryKey();
if (!$entity->has($primaryKey)) {
$msg = 'Deleting requires all primary key values.';
throw new \InvalidArgumentException($msg);
}
if (isset($options['checkRules']) && !$this->checkRules($entity, RulesChecker::DELETE, $options)) {
return false;
}
$event = $this->dispatchEvent('Model.beforeDelete', [
'entity' => $entity,
'options' => $options
]);
if ($event->isStopped()) {
return $event->result;
}
$this->_associations->cascadeDelete(
$entity,
['_primary' => false] + $options->getArrayCopy()
);
$query = $this->query();
$conditions = (array)$entity->extract($primaryKey);
$statement = $query->update()
->set([$this->getDeleteDate() => date('Y-m-d H:i:s') , $this->getDeleter() => $this->user_id])
->where($conditions)
->execute();
$success = $statement->rowCount() > 0;
if (!$success) {
return $success;
}
$this->dispatchEvent('Model.afterDelete', [
'entity' => $entity,
'options' => $options
]);
return $success;
}
如果我使用 trait,SoftDeleteTrait 会以真正的方式工作。但是 SoftDeleteBehavior 无法正常工作!
一个是 PHP 语言结构,另一个是编程概念。你可能想要read upon what traits are,这样你就明白这个问题,就目前而言,并没有太大意义。另外像“不工作”之类的东西不能作为正确的问题描述,以后请更具体。
也就是说,CakePHP 行为确实服务于水平代码重用的目的,类似于特征,而不是通过继承进行垂直重用。
然而,即使它们在概念上有相似之处,你也不能像你在代码中那样简单地交换它们,一个特征将被组合到使用它的 class 中,这样它就变成了它的一部分就像直接写在 class 定义中一样,因此具有覆盖继承代码的能力,例如 Table::_processDelete()
方法,另一方面,行为是完全独立的 class,它在运行时作为依赖项被实例化并注入到 table class 中,并且通过 table class 委托对其方法的调用(参见 Table::__call()
),除非 table class 上已经存在同名方法,在您的情况下,这意味着永远不会调用 _processDelete()
。
我建议您多学习一些 PHP/OOP 基础知识,因为这是相当基础的东西,只需查看源代码即可轻松理清。能够理解 CakePHP 代码库和所用概念的工作原理将使您的生活更加轻松。
我发现 cakephp 3 中的软删除是通过 traits 实现的。我尝试通过行为来实现它。但与特征版本不同,SoftDeleteBehavior 不起作用。 我的模型初始化方法中有这一行:
$this->addBehavior('SoftDelete');
这是我的 SoftDeleteBehavior
namespace App\Model\Behavior;
use Cake\ORM\Behavior;
use Cake\ORM\RulesChecker;
use Cake\Datasource\EntityInterface;
use App\Model\Behavior\MyQuery;
class SoftDeleteBehavior extends Behavior {
public $user_id = 1;
public function getDeleteDate() {
return isset($this->deleteDate) ? $this->deleteDate : 'deleted';
}
public function getDeleter() {
return isset($this->deleter) ? $this->deleter : 'deleter_id';
}
public function query() {
return new MyQuery($this->connection(), $this);
}
/**
* Perform the delete operation.
*
* Will soft delete the entity provided. Will remove rows from any
* dependent associations, and clear out join tables for BelongsToMany associations.
*
* @param \Cake\DataSource\EntityInterface $entity The entity to soft delete.
* @param \ArrayObject $options The options for the delete.
* @throws \InvalidArgumentException if there are no primary key values of the
* passed entity
* @return bool success
*/
protected function _processDelete($entity, $options) {
if ($entity->isNew()) {
return false;
}
$primaryKey = (array)$this->primaryKey();
if (!$entity->has($primaryKey)) {
$msg = 'Deleting requires all primary key values.';
throw new \InvalidArgumentException($msg);
}
if (isset($options['checkRules']) && !$this->checkRules($entity, RulesChecker::DELETE, $options)) {
return false;
}
$event = $this->dispatchEvent('Model.beforeDelete', [
'entity' => $entity,
'options' => $options
]);
if ($event->isStopped()) {
return $event->result;
}
$this->_associations->cascadeDelete(
$entity,
['_primary' => false] + $options->getArrayCopy()
);
$query = $this->query();
$conditions = (array)$entity->extract($primaryKey);
$statement = $query->update()
->set([$this->getDeleteDate() => date('Y-m-d H:i:s') , $this->getDeleter() => $this->user_id])
->where($conditions)
->execute();
$success = $statement->rowCount() > 0;
if (!$success) {
return $success;
}
$this->dispatchEvent('Model.afterDelete', [
'entity' => $entity,
'options' => $options
]);
return $success;
}
如果我使用 trait,SoftDeleteTrait 会以真正的方式工作。但是 SoftDeleteBehavior 无法正常工作!
一个是 PHP 语言结构,另一个是编程概念。你可能想要read upon what traits are,这样你就明白这个问题,就目前而言,并没有太大意义。另外像“不工作”之类的东西不能作为正确的问题描述,以后请更具体。
也就是说,CakePHP 行为确实服务于水平代码重用的目的,类似于特征,而不是通过继承进行垂直重用。
然而,即使它们在概念上有相似之处,你也不能像你在代码中那样简单地交换它们,一个特征将被组合到使用它的 class 中,这样它就变成了它的一部分就像直接写在 class 定义中一样,因此具有覆盖继承代码的能力,例如 Table::_processDelete()
方法,另一方面,行为是完全独立的 class,它在运行时作为依赖项被实例化并注入到 table class 中,并且通过 table class 委托对其方法的调用(参见 Table::__call()
),除非 table class 上已经存在同名方法,在您的情况下,这意味着永远不会调用 _processDelete()
。
我建议您多学习一些 PHP/OOP 基础知识,因为这是相当基础的东西,只需查看源代码即可轻松理清。能够理解 CakePHP 代码库和所用概念的工作原理将使您的生活更加轻松。