¿Cómo puedo resolver la restricción de la clave del extranjero 'sqlstate [23000]: violación de la restricción de integridad:
-
16-10-2019 - |
Pregunta
He estado tratando de crear un módulo simple para habilitar los comentarios de pedido al finalizar la compra. Sé que hay una serie de extensiones gratuitas que hacen esto, pero necesito agregar funcionalidad adicional, así que decidí escribirla desde cero.
En el momento en que guardo el comentario usando un observador, obtengo una alerta de JavaScript y busco en el archivo de excepción.
exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`musicstore`.`checkout_comments`, CONSTRAINT `FK_CHECKOUT_COMMENTS_ORDER_ID_SALES_FLAT_ORDER_ENTITY_ID` FOREIGN KEY (`order_id`) REFERENCES `sales_flat_order` (`entity_id`) ON DELETE CASCADE O)'
Aquí está mi script install-0.0.1
<?php
/* @var $installer Mage_Core_Model_Resource_Setup */
$installer = $this;
$installer->startSetup();
$table = $installer->getConnection()
->newTable($installer->getTable('checkoutcomments/comments_table'))
->addColumn('comment_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'identity' => true,
'unsigned' => true,
'nullable' => false,
'primary' => true,
), 'Comment ID')
->addColumn('order_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'unsigned' => true,
'nullable' => false,
), 'Real Order ID')
->addColumn('comment', Varien_Db_Ddl_Table::TYPE_TEXT, '64k', array(
), 'Comment')
->addForeignKey(
$installer->getFkName(
'checkoutcomments/comments_table',
'order_id',
'sales/order',
'entity_id'
),
'order_id', $installer->getTable('sales/order'), 'entity_id',
Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
->setComment('Checkout Comments');
$installer->getConnection()->createTable($table);
$installer->endSetup();
Tabla de comprobación_comments:
mysql> describe checkout_comments;
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| comment_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| order_id | int(10) unsigned | NO | MUL | NULL | |
| comment | text | YES | | NULL | |
+------------+------------------+------+-----+---------+----------------+
3 rows in set (0.07 sec)
config.xml
<events>
<controller_action_predispatch_checkout_onepage_saveOrder>
<observers>
<save_checkout_comments>
<class>checkoutcomments/observer</class>
<method>prepareCheckoutComment</method>
</save_checkout_comments>
</observers>
</controller_action_predispatch_checkout_onepage_saveOrder>
<sales_order_place_after>
<observers>
<save_checkout_comments>
<class>checkoutcomments/observer</class>
<method>saveCheckoutComment</method>
</save_checkout_comments>
</observers>
</sales_order_place_after>
</events>
Observador.php
public function prepareCheckoutComment($observer){
$message = $observer->getControllerAction()
->getRequest()
->getPost('checkoutcomments');
Mage::getSingleton('core/session')->setCheckoutComment($message);
}
public function saveCheckoutComment($observer){
$order = $observer->getOrder();
$message = Mage::getSingleton('core/session')->getCheckoutComment(true);
if (!$order || empty ($message)) {
return;
}
$commentModel = Mage::getModel('checkoutcomments/comment');
$commentModel->setOdrderId($order->getId())
->setComment($message)
->save();
}
He probado con diferentes eventos
<sales_model_service_quote_submit_after>
<observers>
<save_checkout_comments>
<class>checkoutcomments/observer</class>
<method>saveCheckoutComment</method>
</save_checkout_comments>
</observers>
</sales_model_service_quote_submit_after>
<sales_model_service_quote_submit_success>
<observers>
<save_checkout_comments>
<class>checkoutcomments/observer</class>
<method>saveCheckoutComment</method>
</save_checkout_comments>
</observers>
</sales_model_service_quote_submit_success>
<checkout_submit_all_after>
<observers>
<save_checkout_comments>
<class>checkoutcomments/observer</class>
<method>saveCheckoutComment</method>
</save_checkout_comments>
</observers>
</checkout_submit_all_after>
Matriz de depuración
2013-11-20T19:28:08+00:00 DEBUG (7): Array
(
[increment_id] => 100000043
[store_id] => 1
[quote_id] => 55
[quote (Mage_Sales_Model_Quote)] => Array
(
[entity_id] => 55
[store_id] => 1
[created_at] => 2013-11-20 19:21:20
[updated_at] => 2013-11-20 19:28:08
[is_active] => 1
[is_virtual] => 0
[is_multi_shipping] => 0
[items_count] => 1
[items_qty] => 1
[orig_order_id] => 0
[store_to_base_rate] => 1
[store_to_quote_rate] => 1
[base_to_global_rate] => 1
[base_to_quote_rate] => 1
[global_currency_code] => GBP
[base_currency_code] => GBP
[store_currency_code] => GBP
[quote_currency_code] => GBP
[grand_total] => 20
[base_grand_total] => 20
[customer_id] => 2
[customer_tax_class_id] => 3
[customer_group_id] => 1
[customer_email] => *************
[customer_firstname] => *************
[customer_lastname] => ************
[customer_note_notify] => 1
[customer_is_guest] => 0
[remote_ip] => ::1
[applied_rule_ids] =>
[reserved_order_id] => 100000043
[subtotal] => 15
[base_subtotal] => 15
[subtotal_with_discount] => 15
[base_subtotal_with_discount] => 15
[is_changed] => 1
[trigger_recollect] => 0
[is_persistent] => 0
[virtual_items_qty] => 0
[taxes_for_items] => Array
(
)
[can_apply_msrp] =>
[totals_collected_flag] => 1
[inventory_processed] => 1
)
[customer (Mage_Customer_Model_Customer)] => Array
(
[website_id] => 1
[entity_id] => 2
[entity_type_id] => 1
[attribute_set_id] => 0
[email] => ***************
[group_id] => 1
[store_id] => 1
[created_at] => 2013-11-17 10:40:11
[updated_at] => 2013-11-20 19:28:08
[is_active] => 1
[disable_auto_group_change] => 0
[firstname] => ******
[lastname] => *******
[password_hash] => 456731650daade64aa54e0d4ea97c69a:OrJLah1fNeeX0lNEUmyoU9n1DAQ8sGyC
[created_in] => English
[mcd_meeting12_avatar] => logo.png
[default_billing] => 1
[default_shipping] => 1
[tax_class_id] => 3
[parent_id] => 0
[_profile_picture_dir_cache] => /Applications/MAMP/htdocs/Developer/media/mcd/images/customer/2
)
[remote_ip] => ::1
[customer_id] => 2
[customer_email] => *********
[customer_firstname] => **********
[customer_lastname] => *************
[customer_group_id] => 1
[customer_tax_class_id] => 3
[customer_note_notify] => 1
[customer_is_guest] => 0
[quote_base_grand_total] => 20
[global_currency_code] => GBP
[base_currency_code] => GBP
[store_currency_code] => GBP
[order_currency_code] => GBP
[store_to_base_rate] => 1.0000
[store_to_order_rate] => 1.0000
[base_to_global_rate] => 1.0000
[base_to_order_rate] => 1.0000
[is_virtual] => 0
[applied_rule_ids] =>
[total_qty_ordered] => 1
[weight] => 0.5
[shipping_method] => flatrate_flatrate
[shipping_description] => Flat Rate - Fixed
[subtotal] => 15
[tax_amount] => 0
[discount_amount] => 0
[shipping_amount] => 5
[shipping_incl_tax] => 5
[shipping_tax_amount] => 0
[grand_total] => 20
[base_subtotal] => 15
[base_tax_amount] => 0
[base_discount_amount] => 0
[base_shipping_amount] => 5
[base_shipping_incl_tax] => 5
[base_shipping_tax_amount] => 0
[base_grand_total] => 20
[hidden_tax_amount] => 0
[base_hidden_tax_amount] => 0
[shipping_hidden_tax_amount] => 0
[base_shipping_hidden_tax_amount] => 0
[base_shipping_hidden_tax_amnt] => 0
[discount_description] =>
[shipping_discount_amount] => 0
[base_shipping_discount_amount] => 0
[subtotal_incl_tax] => 15
[base_subtotal_incl_tax] => 15
[payment_surcharge_amount] => 0
[base_payment_surcharge_amount] => 0
[applied_taxes] => Array
(
)
[converting_from_quote] => 1
[store_name] => Main Website
Main Store
English
[total_item_count] => 1
[protect_code] => b599b9
[created_at] => 2013-11-20 19:28:08
[updated_at] => 2013-11-20 19:28:08
[entity_id] => 80
[billing_address_id] => 71
[shipping_address_id] => 72
[applied_tax_is_saved] => 1
[state] => pending
[status] =>
)
No tengo idea de cómo resolver esto o por qué está sucediendo y me gustaría pedirle a Mo alguna orientación, por favor.
Solución
Primero retire el error tipográfico:
$commentModel->setOrderId($order->getId())
->setComment($message)
->save();
Además, sugeriría usar
$commentModel = Mage::getModel('checkoutcomments/comment')->load($order->getId(), 'order_id');
Lo que se aseguraría de que esté actualizando el mismo comentario en caso de que su código se ejecute dos veces.
Otros consejos
El problema (como se sospecha en los comentarios) es el evento que está utilizando. sales_order_place_after
. Ese evento se envía después del pago es colocado. El pedido aún no se guarda en ese punto.
Puedes probar con sales_model_service_quote_submit_success
o sales_model_service_quote_submit_after
. Recomiendo el primero.