Florian644 Posted September 21, 2022 Share Posted September 21, 2022 (edited) Hello, I made a module where the customer is able to customize a product. On the front page of the module, the product is displayed as an SVG element, the customer can customize this SVG element with Javascript, the SVG element code is change in real time at every actions from the customers. When the customer add the product to shopping cart, this function is called in the module's front controller : // Add the product in shopping cart public function addToShoppingCart(){ if ($this->context->cookie->id_cart){ $cart = $this->context->cart; } if ($cart->id == null){ $cart = new Cart(); $cart->id_customer = (int)($this->context->cookie->id_customer); $cart->id_address_delivery = (int) (Address::getFirstCustomerAddressId($cart->id_customer)); $cart->id_address_invoice = $cart->id_address_delivery; $cart->id_lang = (int)($this->context->cookie->id_lang); $cart->id_currency = (int)($this->context->cookie->id_currency); $cart->id_carrier = 1; $cart->recyclable = 0; $cart->gift = 0; $cart->add(); $this->context->cookie->id_cart = (int)($cart->id); } $cart->gift_message = Tools::getValue('svgTemplateResult'); $cart->update(); // Update the shopping cart $cart->updateQty(1, $this->getProductId(), $id_product_attribute = null, $id_customization = false, $operator = 'up', $id_address_delivery = 0, $shop = null, $auto_add_cart_rule = true); } As you can see, I get the cart if it's already created or create it if not. I add Tools::getValue('svgTemplateResult') which is the SVG element code as a string, to a place in the Cart object and try to get it back in my main php file of the module with the actionValidateOrder hook like this : public function hookActionValidateOrder($params) { echo "<pre>"; print_r($params['cart']); echo "<pre>"; die(); } But the value is not in gift_message anymore and by having a look in the database, I found when it's deleted. In the checkout page, just when i chose a Carrier, BOUM, the value is deleted from the Cart object and cannot be find once the actionValidateOrder is triggered. Please, how can I do pass this value from the Cart object to the Order object. Is there an actionHook when the Carrier is chosen ? I found some but haven't tried yet. I will now. Also, I made an override to add a field to OrderDetail object, the field just wait to be filled with this value and finally get the SVG element displayed in the order details summary in Back Office. Edited September 21, 2022 by Florian644 (see edit history) Link to comment Share on other sites More sharing options...
ps8modules Posted September 21, 2022 Share Posted September 21, 2022 Hi, public function addToShoppingCart() { if ($this->context->cart->id){ $id_cart = $this->context->cart->id; } if (!$id_cart){ $cart = new Cart(); $cart->id_customer = (int)($this->context->cookie->id_customer); $cart->id_address_delivery = (int) (Address::getFirstCustomerAddressId($cart->id_customer)); $cart->id_address_invoice = $cart->id_address_delivery; $cart->id_lang = (int)($this->context->cookie->id_lang); $cart->id_currency = (int)($this->context->cookie->id_currency); $cart->id_carrier = 1; $cart->recyclable = 0; $cart->gift = 0; $cart->gift_message = Tools::getValue('svgTemplateResult'); $cart->add(); $this->context->cookie->__set('id_cart', $cart->id); } else { $cart = new Cart ((int) $id_cart); $cart->gift_message = Tools::getValue('svgTemplateResult'); $cart->updateQty(1, $this->getProductId(), $id_product_attribute = null, $id_customization = false, $operator = 'up', $id_address_delivery = 0, $shop = null, $auto_add_cart_rule = true); } } Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 13 hours ago, 4you.software said: Hi, public function addToShoppingCart() { if ($this->context->cart->id){ $id_cart = $this->context->cart->id; } if (!$id_cart){ $cart = new Cart(); $cart->id_customer = (int)($this->context->cookie->id_customer); $cart->id_address_delivery = (int) (Address::getFirstCustomerAddressId($cart->id_customer)); $cart->id_address_invoice = $cart->id_address_delivery; $cart->id_lang = (int)($this->context->cookie->id_lang); $cart->id_currency = (int)($this->context->cookie->id_currency); $cart->id_carrier = 1; $cart->recyclable = 0; $cart->gift = 0; $cart->gift_message = Tools::getValue('svgTemplateResult'); $cart->add(); $this->context->cookie->__set('id_cart', $cart->id); } else { $cart = new Cart ((int) $id_cart); $cart->gift_message = Tools::getValue('svgTemplateResult'); $cart->updateQty(1, $this->getProductId(), $id_product_attribute = null, $id_customization = false, $operator = 'up', $id_address_delivery = 0, $shop = null, $auto_add_cart_rule = true); } } Thanks for the answer. The $cart->updateQty() is not firing in the first case, if there is no $id_cart. It needs to be added in that if too no ? Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 (edited) And where do you see that $id_cart is not passed? $cart = new Cart() => return $cart->id !! You can also directly call Hook::exec $cart = new Cart(); /* or $cart = new Cart(int) $id_cart); */ $data = [ 'cart' => $cart, 'product' => $product, 'id_product_attribute' => $id_product_attribute, 'id_customization' => $id_customization, 'quantity' => $quantity, 'operator' => $operator, 'id_address_delivery' => $id_address_delivery, 'shop' => $shop, 'auto_add_cart_rule' => $auto_add_cart_rule, ]; Hook::exec('actionCartUpdateQuantityBefore', $data); Edited September 22, 2022 by 4you.software (see edit history) Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 4 minutes ago, 4you.software said: And where do you see that $id_cart is not passed? $cart = new Cart() => return $cart->id !! In the case where there is no shopping cart created, we go in the if (!$id_cart) and not in the 'else', so the cart is not updated Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 (edited) And what is your problem? public function addToShoppingCart() { if ($this->context->cart->id){ $id_cart = $this->context->cart->id; } if (!$id_cart){ // not exists, create $cart = new Cart(); $cart->id_customer = (int)($this->context->cookie->id_customer); $cart->id_lang = (int)($this->context->cookie->id_lang); $cart->id_currency = (int)($this->context->cookie->id_currency); $cart->id_carrier = 1; $cart->recyclable = 0; $cart->gift = 0; $cart->gift_message = Tools::getValue('svgTemplateResult'); $cart->add(); $this->context->cookie->__set('id_cart', $cart->id); $data = [ 'cart' => $cart, 'product' => $product, 'id_product_attribute' => $id_product_attribute, 'id_customization' => $id_customization, 'quantity' => '1', 'operator' => 'up', 'id_address_delivery' => (int)(Address::getFirstCustomerAddressId($cart->id_customer)), 'id_address_invoice' => (int)(Address::getFirstCustomerAddressId($cart->id_customer)), 'shop' => $this->context->shop->id, 'auto_add_cart_rule' => true, ]; Hook::exec('actionCartUpdateQuantityBefore', $data); } else { // exists, update $cart = new Cart ((int) $id_cart); $cart->gift_message = Tools::getValue('svgTemplateResult'); $cart->update(); } } Edited September 22, 2022 by 4you.software (see edit history) Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 (edited) 20 minutes ago, 4you.software said: And where do you see that $id_cart is not passed? $cart = new Cart() => return $cart->id !! You can also directly call Hook::exec $cart = new Cart(); /* or $cart = new Cart(int) $id_cart); */ $data = [ 'cart' => $cart, 'product' => $product, 'id_product_attribute' => $id_product_attribute, 'id_customization' => $id_customization, 'quantity' => $quantity, 'operator' => $operator, 'id_address_delivery' => $id_address_delivery, 'shop' => $shop, 'auto_add_cart_rule' => $auto_add_cart_rule, ]; Hook::exec('actionCartUpdateQuantityBefore', $data); Ok this is interesting. The problem in your proposition before is that if there is no cart already created the we go in "if(!$id_cart)" and not in the "else" where the updadeQty() is firing. I tried, I need to click 2 times on "Add to shopping cart" to get 1 time the product. The first time we go in "if(!$id_cart)" and create the object, second time we go in "else" as the object is already created and we updateQty(). My problem is not about putting the string in the Cart object, my 1st code does that well. The problem is that when I chose the Carrier in Checkout, the Cart->gift_message data is deleted. And so the hookActionValidateOrder's $params['cart']->gift_message is empty. I verified in real time in database, the gift_message has my string until the very moment I chose a Carrier. Edited September 22, 2022 by Florian644 (see edit history) Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 Add your own field to the cart and override Cart.php. Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 (edited) 6 minutes ago, 4you.software said: Add your own field to the cart and override Cart.php. Ok I thought about that and now I hear that from you, I don't know why I didn't end up trying this sooner aha. Big thanks for helping me, I'll let you know. Edited September 22, 2022 by Florian644 (see edit history) 1 Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 ./override/classes/Cart.php class Cart extends CartCore { public $my_custom_field; public function __construct($id_product = null){ self::$definition['fields']['my_custom_field'] = array('type' => self::TYPE_STRING); parent::__construct(); } } your module: $cart->my_custom_field = ''; Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 Just now, 4you.software said: ./override/classes/Cart.php class Cart extends CartCore { public $my_custom_field; public function __construct($id_product = null){ self::$definition['fields']['my_custom_field'] = array('type' => self::TYPE_STRING); parent::__construct(); } } your module: $cart->my_custom_field = ''; And also in the database directly I presume or no need ? I did that for the OrderDetail object (override + manually new field in database) PS: I need a TYPE_HTML because it's slicing my content if not. Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 Yes, it must exist in the database, yes, you can change the type to HTML. self::$definition['fields']['my_custom_field'] = array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'); Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 (edited) 40 minutes ago, 4you.software said: Yes, it must exist in the database, yes, you can change the type to HTML. self::$definition['fields']['my_custom_field'] = array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'); It doesn't work. Here's my override in ../override/classes : <?php class Cart extends CartCore { public $my_custom_field; public function __construct($id_product = null){ self::$definition['fields']['my_custom_field'] = array('type' => self::TYPE_STRING); parent::__construct(); } } (I put back TYPE_STRING to first test with a simple word) When I var_dump($cart->my_custom_field) after adding to cart, it works, I have the word in the my_custom_field. I show you a screenshot of my database new field. It stays NULL even when my var_dump() show me the field. Is the override not working ? EDIT: OK I just forgot to empty the cache.. Edited September 22, 2022 by Florian644 (see edit history) 1 Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 (edited) 1 hour ago, 4you.software said: Yes, it must exist in the database, yes, you can change the type to HTML. self::$definition['fields']['my_custom_field'] = array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'); Sorry but I have a new issue. I'm now in the hookActionValidateOrder with the value I needed in Cart so that's reaally nice ! I need now to pass this value in $params['order']->getOrderDetailList()[0]['svgTemplate'] svgTemplate being an added field with override. Here's my code and it doesn't work.. public function hookActionValidateOrder($params) { $params['order']->getOrderDetailList()[0]['svgTemplate'] = $params['cart']->my_custom_field; $params['order']->update(); // or $params['order']->save(); echo "<pre>"; print_r($params['cart']->my_custom_field); echo "<pre>"; die(); } Edited September 22, 2022 by Florian644 (see edit history) Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 (edited) Order::getOrderDetailList = OrderDetail::getList($id_order) so the data from the order_detail table is returned. But you have your value stored in the cart table. Edited September 22, 2022 by 4you.software (see edit history) Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 (edited) 9 minutes ago, 4you.software said: Order::getOrderDetailList = OrderDetail::getList($id_order) so the data from the order_detail table is returned. But you have your value stored in the cart table. I don't understand this line. My point is to display the "my_custom_field" value into the order's summary in Back Office. So I guess OrderDetail object. Edited September 22, 2022 by Florian644 (see edit history) Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 public function hookActionValidateOrder($params) { $getDataInCart = Db::getInstance()->getValue('SELECT my_custom_field FROM '._DB_PREFIX_.'cart WHERE id_cart = '.$this->context->cart->id); if ($getDataInCart){ /* add value to smarty variable */ } } Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 3 minutes ago, 4you.software said: public function hookActionValidateOrder($params) { $getDataInCart = Db::getInstance()->getValue('SELECT my_custom_field FROM '._DB_PREFIX_.'cart WHERE id_cart = '.$this->context->cart->id); if ($getDataInCart){ /* add value to smarty variable */ } } $params['cart']->my_custom_field gives me the right value, why is it needed to do that ? Adding the value in the OrderDetail is what's tricking me. $params['order']->getOrderDetailList() gives me access to the OrderDetails fields but I can't reach to update the svgTemplate field. Sorry if I don't make myself understandable. Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 So try what returns. print_r($params['order']->getOrderDetailList()[0]); Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 (edited) 6 minutes ago, 4you.software said: So try what returns. print_r($params['order']->getOrderDetailList()[0]); Yeah I tried this. It returns this : Do I need to do something like this ? $query = "UPDATE `"._DB_PREFIX_."order_detail` SET svgTemplate=". $params['cart']->my_custom_field; Db::getInstance()->Execute($query); Edited September 22, 2022 by Florian644 (see edit history) Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 If you use my proposal, you will load your own variables in the TPL template. public function hookActionValidateOrder($params) { $this->context->smarty->assign('my_variable_smarty', $params['cart']->my_custom_field); } and tpl order-confirmation.tpl add {$my_variable_smarty} The simplest solution. 1 Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 4 minutes ago, Florian644 said: Do I need to do something like this ? $query = "UPDATE `"._DB_PREFIX_."order_detail` SET svgTemplate=". $params['cart']->my_custom_field; Db::getInstance()->Execute($query); You should have already treated that, then it will work. Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 7 minutes ago, 4you.software said: If you use my proposal, you will load your own variables in the TPL template. public function hookActionValidateOrder($params) { $this->context->smarty->assign('my_variable_smarty', $params['cart']->my_custom_field); } and tpl order-confirmation.tpl add {$my_variable_smarty} The simplest solution. I need it in the Back Office orders. So in src/PrestaShopBundle/Resources/views/Admin/Sell/Order/Order/Blocks/View/products.html.twig Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 And where do you have the code to create the field in the backoffice? Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 (edited) To get the data from the order detail table you need to override the same as you did with Cart.php and add a field. Edited September 22, 2022 by 4you.software (see edit history) Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 (edited) class OrderDetail extends OrderDetailCore { public $svgTemplate; public function __construct($id = null){ self::$definition['fields']['svgTemplate'] = array('type' => self::TYPE_HTML); parent::__construct(); } } Edited September 22, 2022 by 4you.software (see edit history) Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 (edited) Yes that's what I did but for OrderDetail, somebody helped me and told me that I should create a new field in OrderDetail to get the value in the Back Office orders. class OrderDetail extends OrderDetailCore { public $svgTemplate; public function __construct($id = null) { self::$definition['fields']['svgTemplate'] = [ 'type' => self::TYPE_HTML, 'required' => false ]; parent::__construct($id); } } Edited September 22, 2022 by Florian644 (see edit history) Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 We keep going round and round. If you save the svgtemplate in the cart, it applies to all products. If you save the svgtemplate for each product separately, it must be saved in cart_product. Once the cart is saved and the order continues, it must be entered in order_detail and indexed by product id and variant id. Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 This is a real mess. Programming part of the module for saving to the database and reading from the database is a maximum of half an hour's work. It is only important to have all the documents at once, not in parts. This is how we go back to square one and I'm running out of time and patience 🤥 Link to comment Share on other sites More sharing options...
Florian644 Posted September 22, 2022 Author Share Posted September 22, 2022 23 minutes ago, 4you.software said: We keep going round and round. If you save the svgtemplate in the cart, it applies to all products. If you save the svgtemplate for each product separately, it must be saved in cart_product. Once the cart is saved and the order continues, it must be entered in order_detail and indexed by product id and variant id. This is my first module and seeing that the Prestashop documentation is useless I do what I can... My thoughts was to save an array in the my_custom_field. Keys would be the product id and values the svgTemplate. It's kind of difficult to have a fluent talk on forums.. Link to comment Share on other sites More sharing options...
ps8modules Posted September 22, 2022 Share Posted September 22, 2022 So the last hint. your module install function add: Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'cart_product` ADD `svgTemplate` TEXT NULL DEFAULT NULL AFTER `id_product`'); Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'order_detail` ADD `svgTemplate` TEXT NULL DEFAULT NULL AFTER `product_id`'); your module uninstall function add: Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'cart_product` DROP `svgTemplate`'); Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'order_detail` DROP `svgTemplate`'); your module hook function: public function hookActionValidateOrder($params) { $getData = Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'cart_product WHERE id_cart = '.$this->context->cart->id); $idOrder = $params['order']->id; foreach ($getData as $data){ Db::getInstance()->execute( "UPDATE ".DB_PREFIX_."order_detail SET svgTemplate = '".htmlspecialchars($data['svgTemplateResult'])."' WHERE id_order = ".$idOrder." AND product_id = ".$data['id_product']." AND product_attribute_id = ".$data['id_product_attribute']." AND id_shop = ".$this->context->shop->id); } /* your code to display */ } your front controller: public function addToShoppingCart() { /* your code */ Db::getInstance()->execute( "UPDATE ".DB_PREFIX_."cart_product SET svgTemplate = '".htmlspecialchars(Tools::getValue('svgTemplateResult'))."' WHERE id_cart = ".$cart->id." AND id_product = ".Tools::getValue('id_product')." AND id_product_attribute = ".Tools::getValue('id_product_attribute')." AND id_shop = ".$this->context->shop->id); } override OrderDetail.php class OrderDetail extends OrderDetailCore { public $svgTemplate; public function __construct($id = null) { self::$definition['fields']['svgTemplate'] = [ 'type' => self::TYPE_HTML, 'required' => false]; parent::__construct($id); } } 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now