实体虚拟字段在不同视图中的工作方式不同 - CakePHP 4
Entity Virtual Fields works differently in different views - CakePHP 4
我在数据库中有 3 个表:
- 产品:编号 |标题
- 食谱:编号 |标题 | input_price
- 菜肴:id | product_id | recipe_id |数量
一种产品包含许多配方,其数量相应,例如:
- 产品:炒饭
- 菜肴:米饭 |每公斤 10 美元 | 0.1公斤
+ 鸡蛋 |每件 1 美元 | 1 件
// in src/Model/Table/ProductsTable.php
public function initialize(array $config): void
{
$this->belongsToMany('Recipes', [
'foreignKey' => 'product_id',
'targetForeignKey' => 'recipe_id',
'joinTable' => 'Dishes',
]);
$this->hasMany('Dishes');
}
// in src/Model/Table/RecipesTable.php
public function initialize(array $config): void
{
$this->belongsToMany('Products', [
'foreignKey' => 'recipe_id',
'targetForeignKey' => 'product_id',
'through' => 'Dishes',
]);
$this->hasMany('Dishes');
}
// in src/Model/Table/DishsTable.php
public function initialize(array $config): void
{
$this->belongsTo('Products', [
'foreignKey' => 'product_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Recipes', [
'foreignKey' => 'recipe_id',
'joinType' => 'INNER',
]);
}
我创建了一个虚拟字段来计算单个产品所有配方的总成本:
// in src/Model/Entity/Product.php
class Product extends Entity
{
protected $_accessible = [
'title' => true,
'unit' => true,
'price' => true,
'dishes' => true,
'created' => true,
'modified' => true,
];
protected function _getTotalCost()
{
$dishes = $this->dishes;
$total_cost = 0;
foreach ($dishes as $dish) { // <--- this is line 44
$input_price = $dish->recipe->input_price;
$quantity = $dish->quantity;
$amount = $input_price * $quantity;
$total_cost += $amount;
}
return $total_cost;
}
}
它在 templates/Products/view 中完美运行。php:
echo $product->total_cost;
// result ;
但是在templates/Products/index.php中显示错误:
Warning (2): Invalid argument supplied for foreach() [APP/Model\Entity\Product.php, line 44]
Code Context
App\Model\Entity\Product::_getTotalCost() - APP/Model\Entity\Product.php, line 44
Cake\ORM\Entity::get() - CORE\src\Datasource\EntityTrait.php, line 289
Cake\ORM\Entity::__get() - CORE\src\Datasource\EntityTrait.php, line 129
include - ROOT\templates\Products\index.php, line 30
Cake\View\View::_evaluate() - CORE\src\View\View.php, line 1176
Cake\View\View::_render() - CORE\src\View\View.php, line 1134
Cake\View\View::render() - CORE\src\View\View.php, line 764
Cake\Controller\Controller::render() - CORE\src\Controller\Controller.php, line 696
Cake\Controller\Controller::invokeAction() - CORE\src\Controller\Controller.php, line 538
Cake\Controller\ControllerFactory::invoke() - CORE\src\Controller\ControllerFactory.php, line 79
Cake\Http\BaseApplication::handle() - CORE\src\Http\BaseApplication.php, line 251
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 77
Authentication\Middleware\AuthenticationMiddleware::process() - ROOT\vendor\cakephp\authentication\src\Middleware\AuthenticationMiddleware.php, line 124
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 73
Cake\Http\Middleware\CsrfProtectionMiddleware::process() - CORE\src\Http\Middleware\CsrfProtectionMiddleware.php, line 156
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 73
请告诉我如何解决这个问题。非常感谢您的帮助!
您的 view
操作的控制器可能使用 contain
来包含产品的菜肴和食谱,而 index
操作则不是。您应该能够简单地更新 index
中查询的 contain
部分,或者如果它完全缺失则添加它。
我在数据库中有 3 个表:
- 产品:编号 |标题
- 食谱:编号 |标题 | input_price
- 菜肴:id | product_id | recipe_id |数量
一种产品包含许多配方,其数量相应,例如:
- 产品:炒饭
- 菜肴:米饭 |每公斤 10 美元 | 0.1公斤 + 鸡蛋 |每件 1 美元 | 1 件
// in src/Model/Table/ProductsTable.php
public function initialize(array $config): void
{
$this->belongsToMany('Recipes', [
'foreignKey' => 'product_id',
'targetForeignKey' => 'recipe_id',
'joinTable' => 'Dishes',
]);
$this->hasMany('Dishes');
}
// in src/Model/Table/RecipesTable.php
public function initialize(array $config): void
{
$this->belongsToMany('Products', [
'foreignKey' => 'recipe_id',
'targetForeignKey' => 'product_id',
'through' => 'Dishes',
]);
$this->hasMany('Dishes');
}
// in src/Model/Table/DishsTable.php
public function initialize(array $config): void
{
$this->belongsTo('Products', [
'foreignKey' => 'product_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Recipes', [
'foreignKey' => 'recipe_id',
'joinType' => 'INNER',
]);
}
我创建了一个虚拟字段来计算单个产品所有配方的总成本:
// in src/Model/Entity/Product.php
class Product extends Entity
{
protected $_accessible = [
'title' => true,
'unit' => true,
'price' => true,
'dishes' => true,
'created' => true,
'modified' => true,
];
protected function _getTotalCost()
{
$dishes = $this->dishes;
$total_cost = 0;
foreach ($dishes as $dish) { // <--- this is line 44
$input_price = $dish->recipe->input_price;
$quantity = $dish->quantity;
$amount = $input_price * $quantity;
$total_cost += $amount;
}
return $total_cost;
}
}
它在 templates/Products/view 中完美运行。php:
echo $product->total_cost;
// result ;
但是在templates/Products/index.php中显示错误:
Warning (2): Invalid argument supplied for foreach() [APP/Model\Entity\Product.php, line 44]
Code Context
App\Model\Entity\Product::_getTotalCost() - APP/Model\Entity\Product.php, line 44
Cake\ORM\Entity::get() - CORE\src\Datasource\EntityTrait.php, line 289
Cake\ORM\Entity::__get() - CORE\src\Datasource\EntityTrait.php, line 129
include - ROOT\templates\Products\index.php, line 30
Cake\View\View::_evaluate() - CORE\src\View\View.php, line 1176
Cake\View\View::_render() - CORE\src\View\View.php, line 1134
Cake\View\View::render() - CORE\src\View\View.php, line 764
Cake\Controller\Controller::render() - CORE\src\Controller\Controller.php, line 696
Cake\Controller\Controller::invokeAction() - CORE\src\Controller\Controller.php, line 538
Cake\Controller\ControllerFactory::invoke() - CORE\src\Controller\ControllerFactory.php, line 79
Cake\Http\BaseApplication::handle() - CORE\src\Http\BaseApplication.php, line 251
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 77
Authentication\Middleware\AuthenticationMiddleware::process() - ROOT\vendor\cakephp\authentication\src\Middleware\AuthenticationMiddleware.php, line 124
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 73
Cake\Http\Middleware\CsrfProtectionMiddleware::process() - CORE\src\Http\Middleware\CsrfProtectionMiddleware.php, line 156
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 73
请告诉我如何解决这个问题。非常感谢您的帮助!
您的 view
操作的控制器可能使用 contain
来包含产品的菜肴和食谱,而 index
操作则不是。您应该能够简单地更新 index
中查询的 contain
部分,或者如果它完全缺失则添加它。