У меня есть модель заказов с моделью hasMany OrderProducts. ниже мой код. Я добавил функцию поиска, используя плагин jQuery DataTable. Каждый OrderProducts содержит ref_code.
Я хочу добавить поиск, например, выбор всех ордеров, у которых есть OrderProducts, который содержит ref_code GWG-SC-001 (B) или любого другого пользователя, который вводится в поле поиска.
OrderTable.php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\Validation\Validator;
use Cake\ORM\TableRegistry;
use Cake\I18n\Time;
class OrdersTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public $actsAs = array('Containable');
public function initialize(array $config)
{
parent::initialize($config);
$this->table('orders');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'propertyName' => 'Users',
'foreignKey' => 'user_id',
'className' => 'Users'
]);
$this->belongsTo('OrderStatus', [
'propertyName' => 'OrderStatus',
'foreignKey' => 'order_status_id',
'className' => 'OrderStatus'
]);
$this->hasMany('OrderProducts', [
'className' => 'OrderProducts',
'foreignKey' => 'order_id',
'className' => 'OrderProducts'
]);
$this->hasMany('OrderPayments', [
'propertyName' => 'OrderPayments',
'foreignKey' => 'order_id',
'className' => 'OrderPayments'
]);
}
}
/**
* [getOrdersList description]
* @param [type] $data [description]
* @return [type] [description]
*/
public function getOrdersList($data, $user_id = null)
{
$orderelem = $data['columns'][$data['order'][0]['column']]['name'];
$ordertype = $data['order'][0]['dir'];
$offset = $data['start'];
$limit = $data['length'];
$conditions = array("Orders.payment_status <>" => 0);
if (!empty($data['search']['value'])) {
$like = '%' . trim($data['search']['value']) . '%';
$like2 = $data['search']['value'];
$orValues = array("Order Received");
if (strpos($data['search']['value'], 'Status:') !== false) {
$data['search']['value'] = str_replace('Status: ', '', $data['search']['value']);
$orValues = explode("|", $data['search']['value']);
}
$conditions[] = array(
"Orders.payment_status <>" => 0,
'OR' => [
'Users.first_name LIKE' => $like,
'Users.last_name LIKE' => $like,
'Users.title LIKE' => $like,
'Orders.order_number LIKE' => $like2,
//'Orders.quantity_count LIKE' => $like2,
//'Orders.all_total LIKE' => $like2,
'Orders.tracking_number LIKE' => $like,
'OrderStatus.title' => $like,
'OrderProducts.ref_code' => $like, // this is not working
]
);
if (!empty($orValues)) {
$conditions[0]['OR']['OrderStatus.title IN'] = $orValues;
}
}
$data2 = $this->find('all')
->select([
'id', 'order_number', 'order_type', 'created', 'tracking_number',
'delivery_methods_id', 'order_status_id', 'quantity_count',
'all_total', 'payment_status', 'is_allow_final_payment'
])
->contain([
'Users' => function ($u) {
return $u->select(['title', 'first_name', 'last_name']);
},
'OrderStatus' => function ($os) {
return $os->select(['status' => 'OrderStatus.title']);
},
'OrderProducts'
]);
if ($user_id) {
$data2 = $data2->where(['user_id' => $user_id])->andWhere($conditions);
} else {
$data2 = $data2->where($conditions);
}
$data2 = $data2->limit($limit)
->order([$orderelem => $ordertype])
->offset($offset)
->toArray();
return $data2;
}
Когда я пробую это, это дает ниже ошибку:
"message": "[PDOException] SQLSTATE [42S22]: Столбец не найден: 1054 Неизвестный столбец OrderProducts.ref_code в where where
Пожалуйста, помогите мне в этом вопросе.
ниже запрос генерирует:
SELECT
Orders.id AS 'Orders__id',
Orders.order_number AS 'Orders__order_number',
Orders.order_type AS 'Orders__order_type',
Orders.created AS 'Orders__created',
Orders.tracking_number AS 'Orders__tracking_number',
Orders.delivery_methods_id AS 'Orders__delivery_methods_id',
Orders.order_status_id AS 'Orders__order_status_id',
Orders.quantity_count AS 'Orders__quantity_count',
Orders.all_total AS 'Orders__all_total',
Orders.payment_status AS 'Orders__payment_status',
Orders.is_allow_final_payment AS 'Orders__is_allow_final_payment',
Users.title AS 'Users__title',
Users.first_name AS 'Users__first_name',
Users.last_name AS 'Users__last_name',
OrderStatus.title AS 'status'
FROM
orders Orders
LEFT JOIN
users Users
ON Users.id =
(
Orders.user_id
)
LEFT JOIN
order_status OrderStatus
ON OrderStatus.id =
(
Orders.order_status_id
)
WHERE
(
Orders.payment_status \u003C\u003E :c0
AND
(
Orders.payment_status \u003C\u003E :c1
AND
(
Users.first_name like :c2
OR Users.last_name like :c3
OR Users.title like :c4
OR Orders.order_number like :c5
OR Orders.tracking_number like :c6
OR OrderStatus.title like :c7
OR OrderProducts.ref_code like :c8
OR OrderStatus.title in
(
:c9
)
)
)
)
ORDER BY
Orders.created desc LIMIT 25 OFFSET 25
Когда вы используете "содержать", он часто фактически генерирует отдельные запросы для содержащихся в них моделей. Как вы можете видеть, ваш "сгенерированный запрос" фактически не включает OrderProducts
, поэтому в этом случае он генерирует отдельный запрос для OrderProducts
, а затем объединяет результаты после. Из-за этого вы не можете установить условие для поля, которое не включено в запрос.
TL;DR: вместо того, чтобы содержать OrderProducts, если вы хотите добавить условия к другой модели, используйте вместо этого соединение.
В зависимости от настроек, вы можете быть в состоянии указать joinType
в INNER
для ассоциации.
Если нет, вы всегда можете просто ввести внутреннее соединение, как указано в книге: https://book.cakephp.org/3.0/ru/orm/query-builder.html#using-innerjoinwith
like
.OrderStatus.title LIKE ' => $like, 'OrderProducts.ref_code LIKE ' => $like,