CakePHP saveField перед сохранением не действует? (2.4.3)

Я на 99% уверен, что это должна быть ошибка пользователя (потому что в противном случае я уверен, что тысячи пользователей написали бы, что они испытывают эту проблему), но я не могу понять, что ее вызывает!

У меня есть следующий код в модели:

public function setProductPackagingId($id, $product_packaging_id)
{
    $this->id = $id;
    return $this->saveField('product_packaging_id', $product_packaging_id);
}

public function beforeSave()
{       
    $this->data[$this->alias]['version'] = 2;
    debug($this->data);
    return true;
}

public function afterSave($created, $options)
{
    debug($options);
}

Когда я выполняю функцию setProductPackagingId(), срабатывает функция beforeSave и возвращается отладка ($this->data):

array(
'PurchaseOrderProduct' => array(
    'id' => (int) 1,
    'product_packaging_id' => (int) 54,
    'version' => (int) 1000
  )
)

Однако SQL, сгенерированный CakePHP, всего лишь:

UPDATE `roving_tms`.`purchase_order_products` SET `product_packaging_id` = 54  WHERE `roving_tms`.`purchase_order_products`.`id` = 1

Итак, мое поле версии, добавленное в beforeSave, каким-то образом пропущено в сгенерированном SQL?

Кроме того, debug($options) в afterSave возвращает:

array(
'validate' => false,
'fieldList' => array(
    (int) 0 => 'product_packaging_id'
),
'callbacks' => true,
'counterCache' => true
)

Однако, если я изменю setProductPackagingId на следующее:

public function setProductPackagingId($id, $product_packaging_id)
{   
    $purchase_order_product = array(
            'PurchaseOrderProduct' => array(
                    'id' => $id,
                    'product_packaging_id' => $product_packaging_id
                    ));

    return $this->save($purchase_order_product);
}

отладка ($ это-> данные); в beforeSave() выдает тот же результат, что и раньше.

Однако полученный SQL:

UPDATE `roving_tms`.`purchase_order_products` SET `id` = 1, `product_packaging_id` = 54, `version` = 1000  WHERE `roving_tms`.`purchase_order_products`.`id` = 1

(версия включена, что я и хотел)

И отладка($options) в afterSave() производит:

array(
'validate' => true,
'fieldList' => array(),
'callbacks' => true,
'counterCache' => true

)

Единственные отличия, которые я здесь вижу, заключаются в том, что в случае, когда использовалось saveField(), afterSave $options['fieldlist'] содержал параметр product_packaging_id. Однако при вызове из save() параметр $options['fieldlist'] был пустым.

Есть ли что-то действительно очевидное и глупое, что я здесь делаю, что мешает правильной работе beforeSave с saveField? Или это желаемый результат в CakePHP? Если мне нужно использовать beforeSave с saveField, должен ли я выполнить другое обновление базы данных непосредственно из beforeSave (это звучит как глупая идея по причинам ввода-вывода базы данных). Или мне как-то нужно вручную отредактировать параметр fieldList, чтобы другие поля, которые я хочу отредактировать, действительно были отредактированы?


person user984976    schedule 15.12.2013    source источник


Ответы (1)


CakePHP saveField() используется для сохранения одного поля.

При этом, зачем Cake генерирует запрос и включает другое поле, которое не имеет ничего общего с единственным полем, которое вы специально сказали ему сохранить?

Ответ таков: он строит запрос для обновления единственного поля, которое вы ему указали. Если вы передадите 20 полей с вашими данными, а затем вызовете saveField(), он все равно сгенерирует запрос только для обновления указанного вами поля и полностью проигнорирует остальные данные, независимо от того, находятся ли они в исходных данных или добавлены во время beforeSave().

"Used to save a single field value."

http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-savefield-string-fieldname-string-fieldvalue-validate-false

person Dave    schedule 15.12.2013
comment
Я понимаю, что он используется для обновления одного поля, однако явно не указано, что вы не можете манипулировать другими полями через beforeSave. У меня (ошибочно) сложилось впечатление, что это просто сокращение для выполнения обычной операции save() над одним полем. Возможно, эта информация должна быть предоставлена ​​в API beforeSave(), потому что я ожидаю, что если функция beforeSave будет выполняться, она должна работать как обычно. - person user984976; 15.12.2013
comment
Нет, он есть, прочитайте всю документацию по методу: callbacks Установите значение false, чтобы отключить callbacks. Использование «до» или «после» активирует только эти обратные вызовы. - person floriank; 15.12.2013
comment
@burzum, что ты имеешь в виду? Обратный вызов выполняется, просто код, который вы пишете внутри обратного вызова, имеет разный эффект в зависимости от того, был ли он вызван из save() или saveField(). - person user984976; 15.12.2013
comment
Cakephp генерирует SQL, чтобы попытаться обновить другие поля. В моем случае. Даже если я пытаюсь обновить один, он возвращается с ошибкой не нулевого значения в совершенно другом поле. Пора переходить на хороший фреймворк. - person ronaldosantana; 10.04.2015
comment
@RonaldoSantana - как и любой фреймворк, если вы его не понимаете и делаете что-то неправильно, вы получите неправильные результаты. К счастью, у CakePHP есть ТОННА бесплатной онлайн-информации, учебных пособий, документации и т. д. - person Dave; 10.04.2015