Jump to content

Adding a custom field during the Checkout process


Liyali

Recommended Posts

Hi everybody,

 

I need to add a custom field (checkbox) during the Checkout process and then register the data in database. Later I would like to have this data appearing on the PDF invoice in the back-office.

 

What I have done so far:

- Create the field in the template /themes/themeName/order-carrier.tpl (I want my field to appear right after the TOS section)

- Add a new field in database in the ps_orders table (TINYINT)

- Add this function in /override/classes/Order.php :

 

<?php

class Order extends OrderCore
{
public         $myFieldName;

   public function getFields()
   {
       $fields = parent::getFields();

       $fields['myFieldName'] = pSQL($this->myFieldName);
       return $fields;
   }
}

 

When I die(); inside my getFields() function (var_dump($myFieldName);die;), it appears that my field is always empty. In fact it seems obvious since I never filled $myFieldName before. There is probably a function to override where I should have something like:

 

$myFieldName = $_POST['myFieldName'];

 

but I have no idea where to do that though. Does anyone can help me? Any PS [spam-filter] around here?

Also, any idea how to deal with the invoice later on?

 

Thanks :)

  • Like 1
Link to comment
Share on other sites

Thank you Elpatron for your prompt answer.

 

However, my custom field has no relationship with any product of my catalog. Imagine for example a "Receipt" field, which means that when it is checked, a receipt will be sent with this purchase.

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Unfortunately for you it isn't quite as simple as that since during the order process it isn't actually an Order object that's being manipulated but rather it is a Cart object.

 

If you look at the function _processCarrier() in the ParentOrderController class you'll see that there's a hook function available which you could use to insert your own code into the process. In a module this would be implemented as:

 

public function hookActionCarrierProcess(Array $params)
{
$cart = $params['cart'];
 if (!($cart instanceof Cart))
		return;

$cart->myField = Tools::getValue('myFieldName');
}

 

You could override the Cart class and add your field to that. When it finally becomes an order (e.g. by the time you want to generate the invoice) the order object has a data member $id_cart which you can use to get the Cart object and thus your saved data. To display the data on the invoice you can use the hook function hookDisplayPDFInvoice().

 

public function hookDisplayPDFInvoice(Array $params)
{
	$order_invoice = $params['object'];
	if (!($order_invoice instanceof OrderInvoice))
		return;

	$order = new Order((int)$order_invoice->id_order);
	$cart = new Cart($order->id_cart);

	return 'My field data was :'.$cart->myField;
}

Edited by Paul C (see edit history)
  • Like 3
Link to comment
Share on other sites

Unfortunately for you it isn't quite as simple as that since during the order process it isn't actually an Order object that's being manipulated but rather it is a Cart object. [...]

 

Thank you for your explanation, I managed to do it using with a very similar way too.

Hope this can help someone else in the future.

Edited by Liyali (see edit history)
  • Like 1
Link to comment
Share on other sites

  • 4 months later...
  • 3 months later...
  • 2 months later...
  • 2 weeks later...
  • 3 years later...

In complement of Paul C answer, for PS 1.7.1 :

 

- In a module class, add colums to database in the ps_orders and ps_cart tables : 

private function installSQL()
    {
        $sql = array();

        $sql[] = "ALTER TABLE `"._DB_PREFIX_."cart` ADD client_message TEXT";
        $sql[] = "ALTER TABLE `"._DB_PREFIX_."orders` ADD client_message TEXT";

        $this->executeSQL($sql);

        return true;
    }

    private function uninstallSQL(){
        $sql = array();
        $sql[] = "ALTER TABLE `"._DB_PREFIX_."cart` DROP client_message";
        $sql[] = "ALTER TABLE `"._DB_PREFIX_."orders` DROP client_message";

        $this->executeSQL($sql);
    }

    private function executeSQL($requests){

        foreach ($requests as $q) {
            if (!DB::getInstance()->execute($q)) {
                return false;
            }
        }

    }

Declare your field in Cart.php and Order.php classes :

// at the top
public $client_message;

// in $definition
'fields' => array(
...,
'client_message' => array('type' => self::TYPE_STRING, 'validate' => 'isMessage'),
),

In classes/checkout/CheckoutDeliveryStep.php at the end of the handleRequest function, get the correct params for our module hook function :

$checkoutCart = $this->getCheckoutSession()->getCart();

        if( isset($requestParams['client_message'])){
            $checkoutCart->client_message = $requestParams['client_message'];
        }

Hook::exec('actionCarrierProcess', array( 'cart' => $checkoutCart));

In the module hook :

public function hookActionCarrierProcess(Array $params)
    {

        $cart = $params['cart'];
        if (!($cart instanceof Cart))
            return;


        if( isset($params['cart']->client_message) ){

            $cart->client_message = $params['cart']->client_message;

        }
        $cart->save();
        
    }

And in classes/PaymentModule.php in the validateOrder function : 

$order->client_message = $this->context->cart->client_message;
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

And you also need to add in AdminCartsController in ajaxProcessUpdateDeliveryOption function : 

if (Validate::isMessage(($client_message = pSQL(Tools::getValue('client_message'))))) {
                $this->context->cart->client_message = $client_message;
            }

What's the purpose of trying to do something modular if for only one field you need to modify 5 files...

 

Or is there a way to implement these overrides from the module directly ??

  • Thanks 1
Link to comment
Share on other sites

  • 1 month later...
  • 3 months later...

@r4yn0r

I did that trick to send the client_message it in the order confirmation email, i don't use the value in templates.

You can access the variable in templates with {$cart.client_message}, or ($order.client_message}, obviously if $cart and $order are set and not empty, as well as the client_message value.

You can try {debug} in your template to output the accessible smarty variables and look into $cart and $order.

Link to comment
Share on other sites

  • 1 year later...

@Anthony IVOL thank you very much for your post.

I have Prestashop 1.7. I did earlier in my module what you described:
a) At module install step - additional cols in database were added in two tables.
b) New field was declared in this two classes - Cart and Order by extending it from module files.
c) I changed /classes/checkout/CheckoutD eliveryStep.php as you described.
d) I created assigning value from params - from cart to order object and save it in actionCar rierProc ess hook in module.
e) Also change in va lidate Order functi o n.

@Anthony IVOL@r4yn0r mentioned about showing this field on fronted. I also mean that you wrote about processing this new value - but of course, on some step, user should have possibility to type this message. How? Where? How to get this value from frontend in PS 1.7?
I understand that you later don't show this value. But you need to source this value in some way ;)

Please see how I added this new field (a little success) on front in shipping method step:

checkout-newField.png.8a418f6f6a2ea6eaeb549c6ad8945964.png

I achieved this by hook DisplayAfterCarrier (with html code from module's tpl file) and hook Header (added by module JS file by addJS controller). And JS code moves this code "higher" on frontend by this code: $('#myID').prependTo('#delivery');

I can't get this value from this field. I can't do it in any way. I tried to use action hooks (ActionCarrierProcess, ActionCartSave, ActionValidateOrder), I tested this attempts by saving data to txt file - just for debug.

You skip this part how to present this new field for user and how to get this value :) Please help, please give some advice :)

Link to comment
Share on other sites

  • 4 months later...
Am 7/27/2019 um 10:58 AM schrieb Rynraf:

@Anthony IVOL thank you very much for your post.

I have Prestashop 1.7. I did earlier in my module what you described:
a) At module install step - additional cols in database were added in two tables.
b) New field was declared in this two classes - Cart and Order by extending it from module files.
c) I changed /classes/checkout/CheckoutD eliveryStep.php as you described.
d) I created assigning value from params - from cart to order object and save it in actionCar rierProc ess hook in module.
e) Also change in va lidate Order functi o n.

@Anthony IVOL@r4yn0r mentioned about showing this field on fronted. I also mean that you wrote about processing this new value - but of course, on some step, user should have possibility to type this message. How? Where? How to get this value from frontend in PS 1.7?
I understand that you later don't show this value. But you need to source this value in some way ;)

Please see how I added this new field (a little success) on front in shipping method step:

checkout-newField.png.8a418f6f6a2ea6eaeb549c6ad8945964.png

I achieved this by hook DisplayAfterCarrier (with html code from module's tpl file) and hook Header (added by module JS file by addJS controller). And JS code moves this code "higher" on frontend by this code: $('#myID').prependTo('#delivery');

I can't get this value from this field. I can't do it in any way. I tried to use action hooks (ActionCarrierProcess, ActionCartSave, ActionValidateOrder), I tested this attempts by saving data to txt file - just for debug.

You skip this part how to present this new field for user and how to get this value :) Please help, please give some advice :)

Any solution here? I have exact the same problem.

Link to comment
Share on other sites

  • 2 years later...

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...