<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NemoPS &#187; Development</title>
	<atom:link href="http://nemops.com/category/tutorials/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://nemops.com</link>
	<description>Prestashop Tutorials, Modules and More!</description>
	<lastBuildDate>Wed, 05 Dec 2018 13:25:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.35</generator>
	<item>
		<title>Private Orders Shop in PrestaShop and thirty bees part 1: manual customer verification</title>
		<link>http://nemops.com/private-orders-shop-in-prestashop-and-thirty-bees-part-1-manual-customer-verification/</link>
		<comments>http://nemops.com/private-orders-shop-in-prestashop-and-thirty-bees-part-1-manual-customer-verification/#comments</comments>
		<pubDate>Wed, 30 May 2018 12:39:37 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[customers]]></category>
		<category><![CDATA[orders]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[private]]></category>
		<category><![CDATA[thirtybees]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=3133</guid>
		<description><![CDATA[<p>In this 2-part tutorial series, we will see how to create a private orders shop in PrestaShop and thirty bees. In this first part we will see how to add a manual approval for new customers while in the second on we will learn how to prevent orders from people who are not registered and [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/private-orders-shop-in-prestashop-and-thirty-bees-part-1-manual-customer-verification/">Private Orders Shop in PrestaShop and thirty bees part 1: manual customer verification</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In this 2-part tutorial series, we will see how to create a private orders shop in PrestaShop and thirty bees.<br />
In this first part we will see how to add a manual approval for new customers while in the second on  we will learn how to prevent orders from people who are not registered and approved by us.<br />
<span id="more-3133"></span></p>
<h2>Watch the screencast</h2>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/CkNh1VEdpbw" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<h2>Text Version</h2>
<p>I will use PrestaShop 1.6 for the demo but the modification works in thirty bees as well. Bear in mind it DOES NOT work in PrestaShop 1.7.</p>
<p>Open up controllers/front/AuthController.php</p>
<p>Look for the following code, around line 455. If it’s not in those whereabouts, just make sure you change every instance</p>
<pre class="brush: php; title: ; notranslate">
$customer-&gt;active = 1;
</pre>
<p>set to 0, so that the user cannot perform any action right away.</p>
<p>Now we also want to give the user some feedback, so let&#8217;s redirect him to a custom page. Scroll down a few lines, and where you see all these redirects:</p>
<pre class="brush: php; title: ; notranslate">
if (($back = Tools::getValue('back')) &amp;&amp; $back == Tools::secureReferrer($back)) {
                            Tools::redirect(html_entity_decode($back));
                        }
</pre>
<p>And add a new one before</p>
<pre class="brush: php; title: ; notranslate">
  Tools::redirect($this-&gt;context-&gt;link-&gt;getPageLink('welcome'));
</pre>
<p>Of course this page does not exist yet but we will create it in a moment.</p>
<p>Before that though, we have to take care of a little issue. Since the user has been created but set to inactive, the system treats it as banned by default. Even if we are to redirect to a page, we would instantly be kicked out of the session and redirected to the login. We want to create an exception so that the welcome page can be displayed. </p>
<p>Let&#8217;s go ahead and open up the customer class, so classes/customer.php<br />
Look for the following method:</p>
<pre class="brush: php; title: ; notranslate">
public static function isBanned($id_customer)
</pre>
<p>And at the very beginning, add:</p>
<pre class="brush: php; title: ; notranslate">
        if(Context::getContext()-&gt;controller-&gt;php_self == 'welcome')
            return false;
</pre>
<p>That’s settled! Now for our welcome page, I will create a new controller and a template file in the theme folder</p>
<p>Let’s head to controllers/front, and create a new PHP file first, named WelcomeController.php:</p>
<pre class="brush: php; title: ; notranslate">
class WelcomeControllerCore extends FrontController
{
    public $php_self = 'welcome';


    public function initContent()
    {
        parent::initContent();
        $this-&gt;setTemplate(_PS_THEME_DIR_.'welcome.tpl');
    }
}
</pre>
<p>Then in the theme folder, create a new file named welcome.tpl, adding the following code inside</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
{capture name=&quot;path&quot;} {l s='Welcome'}{/capture}
&lt;h1&gt;{l s='Welcome to'} {$shop_name}! &lt;/h1&gt;
&lt;hr&gt;
&lt;p&gt;
	{l s='Your account is currently under review, you will receive an email as soon as it is validated'}
&lt;/p&gt;
</pre>
<p>So let&#8217;s go ahead and try it out now&#8230; but before let&#8217;s clear cache by erasing cache/class_index.php, since we added a new controller and the system wouldn’t read it otherwise.</p>
<p>The next step is to send out and email when a status is changed to active for the customer, in the back office.<br />
Open controllers/admin/admincustomerscontroller.php</p>
<p>We will add a new method, which is inherited from the admincontroller class:</p>
<pre class="brush: php; title: ; notranslate">

    public function processStatus()
    {
        if($object = parent::processStatus()) {
            if(get_class($object) == 'Customer' &amp;&amp; $object-&gt;active) // the customer has been activated, send out an email
            {
                Mail::Send($object-&gt;id_lang, 'account_activated', $this-&gt;l('Your account has been activated'),
                    ['name' =&gt; $object-&gt;firstname .' '. $object-&gt;lastname],
                $object-&gt;email,
                $object-&gt;firstname .' '. $object-&gt;lastname,
                Configuration::get('PS_SHOP_EMAIL'),
                Configuration::get('PS_SHOP_NAME'));
            }
        }

       return $object;
    }

</pre>
<p>Of course, there is no such email template so we have to create it. I suggest copying an existing one, like the order confirmation, and adding new text, just to be quicker. The code is different for every template, just bear in mind to add the {name} variable inside it, so that the customer name is displayed!</p>
<p>This is it for part 1, make sure you test the email as well since sometimes they do fail for odd reasons, if you don&#8217;t see it coming, triple check the template names and make sure they are located in the proper path for each language you use.</p>
<p>In part two we will see how to prevent orders in case a customer is not registered, which is fundamental not to break the system if you have a one page checkout, as right now it would display an error.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/private-orders-shop-in-prestashop-and-thirty-bees-part-1-manual-customer-verification/">Private Orders Shop in PrestaShop and thirty bees part 1: manual customer verification</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/private-orders-shop-in-prestashop-and-thirty-bees-part-1-manual-customer-verification/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make product fields multi-language in PrestaShop and ThirtyBees</title>
		<link>http://nemops.com/prestashop-thirtybees-multi-language-product-fields/</link>
		<comments>http://nemops.com/prestashop-thirtybees-multi-language-product-fields/#comments</comments>
		<pubDate>Mon, 18 Sep 2017 02:56:55 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[language]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[products]]></category>
		<category><![CDATA[thirtybees]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=3067</guid>
		<description><![CDATA[<p>In this tutorial we will learn how to make product fields translatable in PrestaShop 1.6, and see how to apply the method to the &#8220;price per&#8230;&#8221; field. Introduction You might have come across the need to translate the price per unit field in your PrestaShop or Thirtybees, but crashed against the software&#8217;s limitation, as that&#8217;s [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-thirtybees-multi-language-product-fields/">Make product fields multi-language in PrestaShop and ThirtyBees</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In this tutorial we will learn how to make product fields translatable in PrestaShop 1.6, and see how to apply the method to the &#8220;price per&#8230;&#8221; field.<br />
<span id="more-3067"></span></p>
<h2>Introduction</h2>
<p>You might have come across the need to translate the price per unit field in your PrestaShop or Thirtybees, but crashed against the software&#8217;s limitation, as that&#8217;s a single language property. Any product field can be made multi-language with a simple modification, so let&#8217;s see how to do it using the Unity one as example in this tutorial!</p>
<div class="separator"></div>
<h2>Step 1 &#8211; Adding the new database column</h2>
<p>In order to make the field translatable, we have to add it to the <strong>product_lang </strong>table in the database. Not only, but  we also have to erase the same column in both the product and product_shop tables, to avoid conflicts when retrieving values from the database. Let&#8217;s add it first!</p>
<p>Using phpMyAdmin or Adminer, locate the <strong>*prefix*product_lang</strong> table in your database, and add a new column as <strong>VARCHAR</strong>, 24 characters long. Once done, it will look like this:</p>
<p><img src="http://nemops.com/wp-content/uploads/2017/09/multilang_field_db.png" alt="multilang_field_db" width="606" height="97" class="aligncenter size-full wp-image-3069" /></p>
<p>Next, let&#8217;s get rid of the leftovers: open the *prefix*product table and drop the <strong>unity</strong> column first, and then on the <strong>product_shop</strong> table.<br />
We are done! We just broke the Product class though, and have to compensate by letting it know where to grab the new values from.</p>
<div class="separator"></div>
<h2>Step 2 &#8211; Editing the product class</h2>
<p>We have a new column in the database, but at this point the Product class would still just ignore it. To have it lookup, and save into the correct table, we must tell it that the property we are wanting to translate is a multilanguage field. To do so, we must change its definition.</p>
<p>Open up <strong>Product.php</strong>, located in the <em>classes/</em> folder.</p>
<p>Scroll down until you find the following line, part of the <strong>$definition</strong> property:</p>
<pre class="brush: php; title: ; notranslate">
'unity'                     =&gt; ['type' =&gt; self::TYPE_STRING, 'shop' =&gt; true, 'validate' =&gt; 'isString'],
</pre>
<p>To make any field translatable, we can simply add &#8216;lang&#8217; => true as follows</p>
<pre class="brush: php; title: ; notranslate">
'unity'                     =&gt; ['type' =&gt; self::TYPE_STRING, 'shop' =&gt; true, 'validate' =&gt; 'isString', 'lang' =&gt; true],
</pre>
<p><strong>Please notice that, as always, using an override is strongly recommended, instead of editing core files.</strong></p>
<div class="separator"></div>
<h2>Step 3 &#8211; Editing the back office</h2>
<h3>The controller</h3>
<p>This is the most complicated part, as we will have to edit both the admin controller for products, and the correct template. For our example, the template is <strong>prices.tpl</strong>, but it will be different if the field you want to translate is in another tab.</p>
<p>Let&#8217;s start with the controller. The prices template does not offer us any option for translating fields, and therefore misses the indispensable $languages variable.<br />
Open up <strong>AdminProductsController</strong>, located in <em>controllers/admin</em></p>
<p>We are interested in the method called <strong>initFormPrices</strong>, so once you find it you can simply clone that to an override, or continue editing the core.</p>
<p>Right after $data is assigned, at the very beginning of the function, but <strong>before $product = $obj</strong>, add the following</p>
<pre class="brush: php; title: ; notranslate">
if (!$this-&gt;default_form_language) {
    $this-&gt;getLanguages();
}
$data-&gt;assign(array(
    'languages'=&gt; $this-&gt;_languages,
    'id_lang' =&gt; $this-&gt;context-&gt;language-&gt;id,
    'default_form_language' =&gt; $this-&gt;default_form_language,
));
</pre>
<p><strong>Explanation</strong>: Nothing too complex here, we are first checking if languages are loaded, and if not, assigning them to the controller. Then, we simply assign that class property to the template, along with a few other required ones. Please notice we do not use a common smarty assign, but the $data variable instead.</p>
<h3>The template</h3>
<p>Time to make our changes visible in the back office! For the unity field, let&#8217;s open up <em>*admin folder*/themes/default/template/controllers/products/prices.tpl</em></p>
<p>Locate the input with id unity, which will look more or less like the following:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;input id=&quot;unity&quot; name=&quot;unity&quot; type=&quot;text&quot; value=&quot;{$product-&gt;unity|htmlentitiesUTF8}&quot;  maxlength=&quot;255&quot; onkeyup=&quot;if (isArrowKey(event)) return ;unitySecond();&quot; onchange=&quot;unitySecond();&quot;/&gt;
</pre>
<p>Instead of this input, we will use a handy template PrestaShop makes available to us. Replace the above with the following code:</p>
<pre class="brush: php; title: ; notranslate">
{include file=&quot;controllers/products/input_text_lang.tpl&quot;
languages=$languages
input_class=&quot;{$class_input_ajax}{if !$product-&gt;id || Configuration::get('PS_FORCE_FRIENDLY_PRODUCT')}copy2friendlyUrl{/if} updateCurrentText&quot;
input_value=$product-&gt;unity
input_name=&quot;unity&quot;}
</pre>
<p>Save and refresh, and you will see the new field, translatable, appearing in the prices table of the back office. Time to test it, and see if it&#8217;s saving properly.<br />
We can take an extra step and translate the preview below as well:</p>
<pre class="brush: php; title: ; notranslate">
&lt;span id=&quot;unity_second&quot;&gt;{$product-&gt;unity}&lt;/span&gt;
</pre>
<p>to</p>
<pre class="brush: php; title: ; notranslate">
&lt;span id=&quot;unity_second&quot;&gt;{$product-&gt;unity.{$id_lang}}&lt;/span&gt;
</pre>
<p>At this point we can go ahead and test the Front Office. If everything has been done correctly, as soon as you change language, the class should automatically pick the correct translation for the field. Neat!</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-thirtybees-multi-language-product-fields/">Make product fields multi-language in PrestaShop and ThirtyBees</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-thirtybees-multi-language-product-fields/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Restrict Cart Rules to specific categories in PrestaShop</title>
		<link>http://nemops.com/prestashop-cart-rules-specific-category/</link>
		<comments>http://nemops.com/prestashop-cart-rules-specific-category/#comments</comments>
		<pubDate>Wed, 22 Jun 2016 09:53:21 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[cart rules]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[vouchers]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2796</guid>
		<description><![CDATA[<p>You might want to use discount vouchers on your site, but restrict the usage for certain categories or products. Let&#8217;s see how to do it in PrestaShop. Two cases In this tutorial, we will see how we can restrict the usage of vouchers for different categories in PrestaShop. There are two ways we can do [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-cart-rules-specific-category/">Restrict Cart Rules to specific categories in PrestaShop</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>You might want to use discount vouchers on your site, but restrict the usage for certain categories or products. Let&#8217;s see how to do it in PrestaShop.</p>
<p><span id="more-2796"></span></p>
<h2>Two cases</h2>
<p>In this tutorial, we will see how we can restrict the usage of vouchers for different categories in PrestaShop. There are two ways we can do this, depending on our needs. The first consist of simply restricting the rule to some categories, and apply discounts in the cart to products belonging to them, only.<br />
However, if you really want to exclude the usage of specific vouchers on certain products, there is a more complex procedure to use, which involves coding.</p>
<div class="separator"></div>
<h2>The easy way</h2>
<p>If you are happy with having the rule be available on all products, but only affect the ones you want, from a specific category, then the easy way will be enough.<br />
We are assuming you already know <a href="http://nemops.com/prestashop-discounts-cart-rules/#.V2VRvPn5jmg" title="How to use Discounts in PrestaShop">How to use Discounts in PrestaShop</a>, so let&#8217;s proceed from the Cart Rule configuration page:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/06/voucher_restrictions.png"><img src="http://nemops.com/wp-content/uploads/2016/06/voucher_restrictions-680x391.png" alt="PrestaShop Cart Rule configuration" width="680" height="391" class="aligncenter size-large wp-image-2799" /></a></p>
<p>Give the rule some generic conditions and a code (so we can test it); then, under <strong>restrictions</strong>, tick <strong>Product selection</strong>.<br />
In the &#8220;Add a rule concerning&#8221; select box, choose categories, then hit add. A new box will appear below, where you can choose the category you want to restrict this voucher to</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/06/voucher_restrictions_2.png"><img src="http://nemops.com/wp-content/uploads/2016/06/voucher_restrictions_2-680x273.png" alt="PrestaShop cart rules category restriction configuration" width="680" height="273" class="aligncenter size-large wp-image-2798" /></a></p>
<p>Then, in the action tab, if you select a discount percentage, <strong>you must make sure to check the &#8220;selected Products&#8221; box, under &#8220;Apply a discount to&#8221;.</strong> This will make sure other products are not affected by the price reduction.<br />
This, however, limits us in the case we want to use another rule (cheapest product?) or free shipping on specific categories only. Therefore, if you have more specific needs, read on.</p>
<div class="separator"></div>
<h2>The advanced way</h2>
<p>If you are not happy with the above solution, then you might want to code some extra checks in the <strong>CartRule</strong> class, to make the rule invalid if your cart contains extra products.<br />
Open up <strong>CartRule.php</strong>, located in the <em>classes</em> folder, or create an override for it.<br />
Locate the <strong>checkValidity</strong> method, then the following snippet:</p>
<pre class="brush: php; title: ; notranslate">
...
  // gonna slow the thing down a bit

        /* This loop checks:
            - if the voucher is already in the cart
            - if a non compatible voucher is in the cart
            - if there are products in the cart (gifts excluded)
            Important note: this MUST be the last check, because if the tested cart rule has priority over a non combinable one in the cart, we will switch them
        */
        $nb_products = Cart::getNbProducts($context-&gt;cart-&gt;id);
        $otherCartRules = array();
        if ($check_carrier) {
            $otherCartRules = $context-&gt;cart-&gt;getCartRules();
        }

        ...
</pre>
<p>Right before it, we need to get products, in case the variable is not set yet, and check for our conditions</p>
<pre class="brush: php; title: ; notranslate">
        if(!isset($products))
            $products = $context-&gt;cart-&gt;getProducts();

        if($products)
        {
            // first, let's get our current cart rule ID
            if($this-&gt;id == 1) // not thought for extensive usage
            {
                // having them hardcoded here, can be expanded
                $valid_categories = array(7); // Blouses category
            }
            
        }
</pre>
<p>This part is not thought for an extensive usage, so if you want to use more than a couple of special price rules, you might need to find another way. We are hardcoding the cart rule id, so that this condition is only applied when we are adding it. This will also make sure this rule is removed from the cart, in case other invalid products are added afterwards.<br />
Let&#8217;s now check if all products are at least belonging to the Blouses category</p>
<pre class="brush: php; title: ; notranslate">
        if(!isset($products))
            $products = $context-&gt;cart-&gt;getProducts();

        if($products)
        {
            // first, let's get our current cart rule ID
            if($this-&gt;id == 1) // not thought for extensive usage
            {
                // having them hardcoded here, can be expanded
                $valid_categories = array(7); // Blouses category
                foreach ($products as $prod) {
                    $prod_categories = Product::getProductCategories($prod['id_product']);
                    foreach ($valid_categories as $val_cat) {
                        if(!in_array($val_cat, $prod_categories)) // if the blouse category is not among product categories
                           return (!$display_error) ? false : Tools::displayError('One or more products in your cart are not compatible with this discount'); // we deny the voucher's usage
                    }
                }    
            }
            
        }
</pre>
<p>If the product is not in any of the valid categories (in this case, just Blouses), then we cannot add the rule. Save and refresh, then clear cache if you used an override.<br />
You can now try adding the rule to the cart. First, with a valid product only. Then remove the rule, add an invalid product, and add the rule back again. You should see a message popping up:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/06/vouchers_restrictions_3.png"><img src="http://nemops.com/wp-content/uploads/2016/06/vouchers_restrictions_3-680x305.png" alt="PrestaShop Cart Rule restricted by category" width="680" height="305" class="aligncenter size-large wp-image-2800" /></a></p>
<p>If not, the condition is not triggering, and you have to go back and print a debug of the rule/categories.<br />
If you see the error, you can erase the invalid product, add the voucher again (it should be valid this time), then add the product once more. The rule should be automatically removed from your cart, since it becomes invalid. Unfortunately, there is no way to trigger an error message when this happens.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-cart-rules-specific-category/">Restrict Cart Rules to specific categories in PrestaShop</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-cart-rules-specific-category/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hooking modules to the Category Back Office in Prestashop</title>
		<link>http://nemops.com/hook-modules-prestashop-category-back-office/</link>
		<comments>http://nemops.com/hook-modules-prestashop-category-back-office/#comments</comments>
		<pubDate>Tue, 17 May 2016 09:42:05 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[category]]></category>
		<category><![CDATA[hooks]]></category>
		<category><![CDATA[prestashop]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2772</guid>
		<description><![CDATA[<p>If you want to add extra fields to the category configuration page, there is no better way than using a module hooked to DisplayBackOfficeCategory. Let&#8217;s see how to implement it! Starting with a simple module First, download the project file, and place the module you will find inside the &#8220;start&#8221; folder in the modules/ folder [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/hook-modules-prestashop-category-back-office/">Hooking modules to the Category Back Office in Prestashop</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>If you want to add extra fields to the category configuration page, there is no better way than using a module hooked to DisplayBackOfficeCategory. Let&#8217;s see how to implement it!</p>
<p><span id="more-2772"></span></p>
<a class="download-files button style1" href="http://nemops.com/wp-content/uploads/2016/05/project.zip" title="Download Project Files">Download Project Files</a>
<h2>Starting with a simple module</h2>
<p>First, download the project file, and place the module you will find inside the &#8220;start&#8221; folder in the modules/ folder of your prestashop installation.</p>
<p>Open up displaybocategorytut.php, it&#8217;s just a very basic module structure.</p>
<pre class="brush: php; title: ; notranslate">
if (!defined('_PS_VERSION_'))
	exit;

class displayBoCategoryTut extends Module
{

	protected $_errors = array();
	protected $_html = '';


	public function __construct()
	{
		$this-&gt;name = 'displaybocategorytut';
		$this-&gt;tab = 'front_office_features';
		$this-&gt;version = '1.0';
		$this-&gt;author = 'Nemo';
		$this-&gt;need_instance = 0;
		
		$this-&gt;bootstrap = true;

	 	parent::__construct();

		$this-&gt;displayName = $this-&gt;l('Display BO Category Tutorial');
		$this-&gt;description = $this-&gt;l('Displays an additional field in the category back office');
	}
	
	public function install()
	{
		if (!parent::install())
			return false;
		return true;
	}

	public function uninstall()
	{
		if (!parent::uninstall())
			return false;
		return true;
	}

}

</pre>
<p>The first thing we need is of course some additional data we want to save and retrieve. For this reason, we need an extra method to modify the database, and add a further column to the category table:</p>
<pre class="brush: php; title: ; notranslate">
	public function alterTable($method = 'add')
	{
		if($method == 'add')
			$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'category ADD `myowninput` VARCHAR (255) NOT NULL';
		else 
			$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'category DROP COLUMN `myowninput`';

		if(!Db::getInstance()-&gt;Execute($sql))
			return false;
		return true;
	}
</pre>
<p><strong>Explanation</strong>: since we need the extra column, we are using a single method to add and remove it. We are passing in a &#8220;method&#8221; parameter, so that we can switch between actions depending on our needs.</p>
<p>As mentioned, we need this column to be added when installing, and removed when uninstalling, so let&#8217;s amend the install and uninstall methods as well:</p>
<pre class="brush: php; title: ; notranslate">


	public function install()
	{
		if (!parent::install() OR
			!$this-&gt;alterTable() OR
			!$this-&gt;registerHook('displayBackOfficeCategory') OR
			!$this-&gt;registerHook('categoryAddition') OR
			!$this-&gt;registerHook('categoryUpdate')
			)
			return false;
		return true;
	}

	public function uninstall()
	{
		if (!parent::uninstall() OR
			!$this-&gt;alterTable('remove'))
			return false;
		return true;
	}

</pre>
<p>Additionally, I am registering two hooks to update the field&#8217;s value. This would not be necessary if we had a Category class override to take care of the extra field (see more on <a href="http://nemops.com/extending-prestashop-objects/" title="Extending PrestaShop Objects">Extending PrestaShop Objects</a>).</p>
<p>Next, we will need some way to retrieve our custom field from the database</p>
<pre class="brush: php; title: ; notranslate">
	public function getMyOwnInput($id_category)
	{
		return Db::getInstance()-&gt;getValue('SELECT myowninput FROM '._DB_PREFIX_.'category WHERE id_category = '. (int)$id_category);
	}
</pre>
<p>Then, it&#8217;s time to display something in the category back office. Let&#8217;s create the hooking method:</p>
<pre class="brush: php; title: ; notranslate">
	public function hookDisplayBackOfficeCategory($params)
	{

		// we need an actual id, otherwise if we are just adding the category this field can be left empty
		if(Tools::getValue('id_category'))
			$myowninput = $this-&gt;getMyOwnInput(Tools::getValue('id_category'));
		else $myowninput = '';

		$this-&gt;context-&gt;smarty-&gt;assign(array(
			'myowninput'=&gt; $myowninput
		));


		return $this-&gt;display(__FILE__, 'backoffice.tpl');
	}

</pre>
<p><strong>Explanation:</strong> First off, we make sure we have a category ID that we can use to retrieve the value from the database. We use a switch to prevent the script from causing trouble in case there is none (that is, we are just creating a new category). Then, we assign the input value to the template, and return it. We don&#8217;t have it yet, so let&#8217;s create a new file inside <em>views\templates\hook</em>, naming it <strong>backoffice.tpl</strong></p>
<p>Let&#8217;s add some simple markup:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
&lt;div class=&quot;form-group&quot;&gt;
	&lt;label class=&quot;control-label col-lg-3&quot;&gt;
		&lt;span class=&quot;label-tooltip&quot;&gt;
			{l s='Custom Input' mod='displaybocategorytut'}
		&lt;/span&gt;
	&lt;/label&gt;
	&lt;div class=&quot;col-lg-4&quot;&gt;
		&lt;input type=&quot;text&quot; name=&quot;myowninput&quot; value=&quot;{$myowninput}&quot;&gt;
	&lt;/div&gt;
	&lt;div class=&quot;col-lg-6 col-lg-offset-3&quot;&gt;
	&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>We are ready to install the module! Go ahead and do it from the modules page. If everything goes smoothly as it should, reach a category and click edit (or add one). It should display our new field:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/05/displaybocategory.png"><img src="http://nemops.com/wp-content/uploads/2016/05/displaybocategory-680x247.png" alt="New input in the PrestaShop Category Back Office " width="680" height="247" class="aligncenter size-large wp-image-2776" /></a></p>
<p>It won&#8217;t do much at the time being, since we are not saving the value on submit. For this, we need another couple of methods that will take advantage of the hooks we registered upon install:</p>
<pre class="brush: php; title: ; notranslate">
	public function hookCategoryAddition($params)
	{
		Db::getInstance()-&gt;update('category', array('myowninput' =&gt; pSQL(Tools::getValue('myowninput'))), 'id_category = ' . $params['category']-&gt;id);
	}

	public function hookCategoryUpdate($params)
	{
		$this-&gt;hookCategoryAddition($params);
	}
</pre>
<p><strong>Explanation:</strong> here we are using some standard code to update the database: the myowninput value is sent over via POST when submitting the page, and the $params variable passed to the method contains a useful Category object, from which we are taking the ID.</p>
<p>Now write something in the field and save, it should be stored in the database! To make sure everything runs smoothly, create a new category as well, adding content to our field before submitting the page.</p>
<p>Once everything works, you can try to expand the module with hooks, in the front office as well, and take full advantage of the new value.</p>
<h3>Additional Resources </h3>
<ul>
<li>
Learn how to develop PrestaShop Modules with my <a href="http://nemops.com/prestashop-modules-course/" title="PrestaShop Modules Course">PrestaShop Modules Course</a>
</li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/hook-modules-prestashop-category-back-office/">Hooking modules to the Category Back Office in Prestashop</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/hook-modules-prestashop-category-back-office/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding new fields to the PrestaShop CSV Importer</title>
		<link>http://nemops.com/new-fields-prestashop-csv-importer/</link>
		<comments>http://nemops.com/new-fields-prestashop-csv-importer/#comments</comments>
		<pubDate>Mon, 04 Apr 2016 09:40:19 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[back office]]></category>
		<category><![CDATA[csv]]></category>
		<category><![CDATA[import]]></category>
		<category><![CDATA[spreadsheet]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2750</guid>
		<description><![CDATA[<p>The CSV import PrestaShop natively comes with becomes useless if we have added custom fields to our objects. Let&#8217;s see how to overcome the limit, and enable extra fields in the CSV Importer as well. Adding an extra field to PrestaShop objects Before doing anything with CSVs or the importer, we need a field to [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/new-fields-prestashop-csv-importer/">Adding new fields to the PrestaShop CSV Importer</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>The CSV import PrestaShop natively comes with becomes useless if we have added custom fields to our objects. Let&#8217;s see how to overcome the limit, and enable extra fields in the CSV Importer as well.</p>
<p><span id="more-2750"></span></p>
<h2>Adding an extra field to PrestaShop objects</h2>
<p>Before doing anything with CSVs or the importer, we need a field to fill with your data. If you don&#8217;t know how to add one, here is a tutorial on <a href="http://nemops.com/extending-prestashop-objects/#.Vv5Nkfn5jmg" title="How to extend PrestaShop Objects">How to extend PrestaShop Objects</a>, and add new fields to them.<br />
In this example, we will use that extrafield one added in the tutorial.<br />
As a side note, it&#8217;s not strictly necessary to add the extra field to the product object, as we will see, but it&#8217;s essential to have a database column we can use.</p>
<div class="separator"></div>
<h2>Two approaches</h2>
<p>Given that the Product class override is not strictly necessary, we can proceed in two ways, depending on our needs: the first, is to complete the previous tutorial, and add the field to the Product Object; the second is to stop after adding the database column, and override an extra method of the AdminImportController, to manually update the new field. We will cover both to see how they work.</p>
<div class="separator"></div>
<h2>The AdminImportController override</h2>
<p>Let&#8217;s start playing with the real file. First of all, create a new file in <em>override/controllers/admin</em>, and name it <strong>AdminImportController.php</strong></p>
<p>Open it up, and add some standard override code within PHP tags</p>
<pre class="brush: php; title: ; notranslate">
class AdminImportController extends AdminImportControllerCore
{

}
</pre>
<p>Next, we want to tell the Importer we have an extra field for products. To do this, we have to override the whole construct method, since it&#8217;s the one defining available fields for all entities. It&#8217;s too long to copy it here, to make sure you grab yours from the original Controller, and drop it into the override.</p>
<pre class="brush: php; title: ; notranslate">
class AdminImportController extends AdminImportControllerCore
{
        $this-&gt;bootstrap = true;
        $this-&gt;entities = array(
            $this-&gt;l('Categories'),
            $this-&gt;l('Products'),
            $this-&gt;l('Combinations'),
            $this-&gt;l('Customers'),
            $this-&gt;l('Addresses'),
            $this-&gt;l('Manufacturers'),
            $this-&gt;l('Suppliers'),
            $this-&gt;l('Alias'),
        );
        // more code here

        $this-&gt;separator = ($separator = Tools::substr(strval(trim(Tools::getValue('separator'))), 0, 1)) ? $separator :  ';';
        $this-&gt;multiple_value_separator = ($separator = Tools::substr(strval(trim(Tools::getValue('multiple_value_separator'))), 0, 1)) ? $separator :  ',';
        AdminController::__construct();
}
</pre>
<p><strong>Make absolutely sure you change the very last call to AdminController::__construct(); to avoid losing any modification to the product properties.</strong></p>
<p>Now that the override is in place, we must let it know about our field. Locate the following snippet:</p>
<pre class="brush: php; title: ; notranslate">
            case $this-&gt;entities[$this-&gt;l('Products')]:
                self::$validators['image'] = array(
                    'AdminImportController',
                    'split'
                );
</pre>
<p>You will notice it&#8217;s followed by an array defining available fields:</p>
<pre class="brush: php; title: ; notranslate">
               $this-&gt;available_fields = array(
                    'no' =&gt; array('label' =&gt; $this-&gt;l('Ignore this column')),
                    'id' =&gt; array('label' =&gt; $this-&gt;l('ID')),
                    'active' =&gt; array('label' =&gt; $this-&gt;l('Active (0/1)')),
                    'name' =&gt; array('label' =&gt; $this-&gt;l('Name')),
                    'category' =&gt; array('label' =&gt; $this-&gt;l('Categories (x,y,z...)')),
                    'price_tex' =&gt; array('label' =&gt; $this-&gt;l('Price tax excluded')),
                    'price_tin' =&gt; array('label' =&gt; $this-&gt;l('Price tax included')),
                    'id_tax_rules_group' =&gt; array('label' =&gt; $this-&gt;l('Tax rules ID')),
                    'wholesale_price' =&gt; array('label' =&gt; $this-&gt;l('Wholesale price')),
                    'on_sale' =&gt; array('label' =&gt; $this-&gt;l('On sale (0/1)')),
                    'reduction_price' =&gt; array('label' =&gt; $this-&gt;l('Discount amount')),
                    'reduction_percent' =&gt; array('label' =&gt; $this-&gt;l('Discount percent')),
                    'reduction_from' =&gt; array('label' =&gt; $this-&gt;l('Discount from (yyyy-mm-dd)')),
                    'reduction_to' =&gt; array('label' =&gt; $this-&gt;l('Discount to (yyyy-mm-dd)')),
                    'reference' =&gt; array('label' =&gt; $this-&gt;l('Reference #')),
                    'supplier_reference' =&gt; array('label' =&gt; $this-&gt;l('Supplier reference #')),
                    'supplier' =&gt; array('label' =&gt; $this-&gt;l('Supplier')),
                    'manufacturer' =&gt; array('label' =&gt; $this-&gt;l('Manufacturer')),
                    'ean13' =&gt; array('label' =&gt; $this-&gt;l('EAN13')),
                    'upc' =&gt; array('label' =&gt; $this-&gt;l('UPC')),
                    'ecotax' =&gt; array('label' =&gt; $this-&gt;l('Ecotax')),
                    'width' =&gt; array('label' =&gt; $this-&gt;l('Width')),
                    'height' =&gt; array('label' =&gt; $this-&gt;l('Height')),
                    'depth' =&gt; array('label' =&gt; $this-&gt;l('Depth')),
                    'weight' =&gt; array('label' =&gt; $this-&gt;l('Weight')),
                    'quantity' =&gt; array('label' =&gt; $this-&gt;l('Quantity')),
                    'minimal_quantity' =&gt; array('label' =&gt; $this-&gt;l('Minimal quantity')),
                    'visibility' =&gt; array('label' =&gt; $this-&gt;l('Visibility')),
                    'additional_shipping_cost' =&gt; array('label' =&gt; $this-&gt;l('Additional shipping cost')),
                    'unity' =&gt; array('label' =&gt; $this-&gt;l('Unit for the unit price')),
                    'unit_price' =&gt; array('label' =&gt; $this-&gt;l('Unit price')),
                    'description_short' =&gt; array('label' =&gt; $this-&gt;l('Short description')),
                    'description' =&gt; array('label' =&gt; $this-&gt;l('Description')),
                    'tags' =&gt; array('label' =&gt; $this-&gt;l('Tags (x,y,z...)')),
                    'meta_title' =&gt; array('label' =&gt; $this-&gt;l('Meta title')),
                    'meta_keywords' =&gt; array('label' =&gt; $this-&gt;l('Meta keywords')),
                    'meta_description' =&gt; array('label' =&gt; $this-&gt;l('Meta description')),
                    'link_rewrite' =&gt; array('label' =&gt; $this-&gt;l('URL rewritten')),
                    'available_now' =&gt; array('label' =&gt; $this-&gt;l('Text when in stock')),
                    'available_later' =&gt; array('label' =&gt; $this-&gt;l('Text when backorder allowed')),
                    'available_for_order' =&gt; array('label' =&gt; $this-&gt;l('Available for order (0 = No, 1 = Yes)')),
                    'available_date' =&gt; array('label' =&gt; $this-&gt;l('Product availability date')),
                    'date_add' =&gt; array('label' =&gt; $this-&gt;l('Product creation date')),
                    'show_price' =&gt; array('label' =&gt; $this-&gt;l('Show price (0 = No, 1 = Yes)')),
                    'image' =&gt; array('label' =&gt; $this-&gt;l('Image URLs (x,y,z...)')),
                    'delete_existing_images' =&gt; array(
                        'label' =&gt; $this-&gt;l('Delete existing images (0 = No, 1 = Yes)')
                    ),
                    'features' =&gt; array('label' =&gt; $this-&gt;l('Feature (Name:Value:Position:Customized)')),
                    'online_only' =&gt; array('label' =&gt; $this-&gt;l('Available online only (0 = No, 1 = Yes)')),
                    'condition' =&gt; array('label' =&gt; $this-&gt;l('Condition')),
                    'customizable' =&gt; array('label' =&gt; $this-&gt;l('Customizable (0 = No, 1 = Yes)')),
                    'uploadable_files' =&gt; array('label' =&gt; $this-&gt;l('Uploadable files (0 = No, 1 = Yes)')),
                    'text_fields' =&gt; array('label' =&gt; $this-&gt;l('Text fields (0 = No, 1 = Yes)')),
                    'out_of_stock' =&gt; array('label' =&gt; $this-&gt;l('Action when out of stock')),
                    'shop' =&gt; array(
                        'label' =&gt; $this-&gt;l('ID / Name of shop'),
                        'help' =&gt; $this-&gt;l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
                    ),
                    'advanced_stock_management' =&gt; array(
                        'label' =&gt; $this-&gt;l('Advanced Stock Management'),
                        'help' =&gt; $this-&gt;l('Enable Advanced Stock Management on product (0 = No, 1 = Yes).')
                    ),
                    'depends_on_stock' =&gt; array(
                        'label' =&gt; $this-&gt;l('Depends on stock'),
                        'help' =&gt; $this-&gt;l('0 = Use quantity set in product, 1 = Use quantity from warehouse.')
                    ),
                    'warehouse' =&gt; array(
                        'label' =&gt; $this-&gt;l('Warehouse'),
                        'help' =&gt; $this-&gt;l('ID of the warehouse to set as storage.')
                    )
                );
</pre>
<p>This represents all of the fields, or columns, that you can map to every column of your csv file. At this point, it&#8217;s enough to append our element to the array:</p>
<pre class="brush: php; title: ; notranslate">
                    'depends_on_stock' =&gt; array(
                        'label' =&gt; $this-&gt;l('Depends on stock'),
                        'help' =&gt; $this-&gt;l('0 = Use quantity set in product, 1 = Use quantity from warehouse.')
                    ),
                    'warehouse' =&gt; array(
                        'label' =&gt; $this-&gt;l('Warehouse'),
                        'help' =&gt; $this-&gt;l('ID of the warehouse to set as storage.')
                    ),
                    'extrafield' =&gt; array(
                        'label' =&gt; $this-&gt;l('Extrafield'),
                        'help' =&gt; $this-&gt;l('Something')
                    )
                );
</pre>
<p>Save, then reach the <em>cache</em> folder and delete <strong>class_index.php</strong>, so that the override file is loaded.</p>
<p><strong>If you added the Product class override, you can skip to Testing The Import</strong></p>
<p>Otherwise, there is a little snippet you need to add. Unfortunately, in order to do it we have to <strong>override the whole ProductImport()</strong> method. Therefore, copy and paste yours into the override file we created; then, reach the very end of it, where it reads:</p>
<pre class="brush: php; title: ; notranslate">
        $this-&gt;closeCsvFile($handle);
        Module::processDeferedFuncCall();
        Module::processDeferedClearCache();
        Tag::updateTagCount();
</pre>
<p>Right before, add the following statement</p>
<pre class="brush: php; title: ; notranslate">
Db::getInstance()-&gt;update('product', array('extrafield' =&gt; $info['extrafield']), 'id_product = ' . (int)$product-&gt;id);
</pre>
<p>This will manually update the field, in case it was not part of the product object.</p>
<div class="separator"></div>
<h2>Testing The Import</h2>
<p><strong>Before proceeding: Make sure you do not have a product with the same ID of the sample one, or it will be overridden.</strong></p>
<p>We are ready for a test run. Download the product csv sample from <strong>Advanced Parameters > CSV Import</strong></p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/download_sample.png"><img src="http://nemops.com/wp-content/uploads/2016/04/download_sample-680x332.png" alt="PrestaShop Sample CSV File Download" width="680" height="332" class="aligncenter size-large wp-image-2752" /></a></p>
<p>Open up the file in any text editor, get rid of all lines apart from the heading and first product. Then, add a new heading after &#8220;Warehouse&#8221;, and a value for it on the next line:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/extrafield_product.png"><img src="http://nemops.com/wp-content/uploads/2016/04/extrafield_product.png" alt="Adding an extra field value to the csv for PrestaShop" width="349" height="104" class="aligncenter size-full wp-image-2754" /></a></p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/extrafield_heading.png"><img src="http://nemops.com/wp-content/uploads/2016/04/extrafield_heading.png" alt="Adding an extra field to the csv for PrestaShop" width="381" height="140" class="aligncenter size-full wp-image-2753" /></a></p>
<p>Save the file. Now load it up in the importer. Make sure you select Products as entity, and leave all other settings as default. Hit Next.</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/importer_settings.png"><img src="http://nemops.com/wp-content/uploads/2016/04/importer_settings-680x752.png" alt="PrestaShop CSV Import Settings" width="680" height="752" class="aligncenter size-large wp-image-2755" /></a></p>
<p>On the next screen, hit the next arrow until you reach the end of the file. You should see the new column popping up:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/importer_columns.png"><img src="http://nemops.com/wp-content/uploads/2016/04/importer_columns-680x172.png" alt="PrestaShop CSV Import Settings for Columns" width="680" height="172" class="aligncenter size-large wp-image-2756" /></a></p>
<p>Now proceed and simply hit import to complete the process. You will probably get an error because of the broken image url, but the new field should be added to the database:</p>
<p><a href="http://nemops.com/wp-content/uploads/2016/04/database_updated.png"><img src="http://nemops.com/wp-content/uploads/2016/04/database_updated.png" alt="PrestaShop Database Updated PrestaShop Database via CSV via CSV" width="537" height="219" class="aligncenter size-full wp-image-2757" /></a></p>
<p>We are done! Now you can display the extra field the way you like, whether it is with a module or following the previously linked tutorial.</p>
<h3>Additional Resources on CSV Import in PrestaShop</h3>
<ul>
<li><a href="http://nemops.com/extending-prestashop-objects/#.Vv5Nkfn5jmg" title="How to extend PrestaShop Objects">How to extend PrestaShop Objects</a></li>
<li><a href="http://nemops.com/prestashop-import-csv-data-in-1-6/#.VwIzWvn5jmg" title="Prestashop: Import CSV data in 1.6">Prestashop: Import CSV data in 1.6</a></li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/new-fields-prestashop-csv-importer/">Adding new fields to the PrestaShop CSV Importer</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/new-fields-prestashop-csv-importer/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Overriding Modules Controllers in PrestaShop 1.6</title>
		<link>http://nemops.com/overriding-modules-controllers-in-prestashop-1-6/</link>
		<comments>http://nemops.com/overriding-modules-controllers-in-prestashop-1-6/#comments</comments>
		<pubDate>Wed, 02 Mar 2016 11:39:49 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[modules]]></category>
		<category><![CDATA[overrides]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[prestashop 1.6]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2723</guid>
		<description><![CDATA[<p>Thanks to a PrestaShop forums&#8217; user, we can now easily extend modules&#8217; controllers without any hardcoded modification. Let&#8217;s see how do do it! Last Week, forum user alexdee2007 posted an interesting override: it allows us to extend PrestaShop Modules&#8217; controllers. Previously, we would have had to hardcode any modification within the originals, because the core [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/overriding-modules-controllers-in-prestashop-1-6/">Overriding Modules Controllers in PrestaShop 1.6</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Thanks to a PrestaShop forums&#8217; user, we can now easily extend modules&#8217; controllers without any hardcoded modification. Let&#8217;s see how do do it!</p>
<p><span id="more-2723"></span></p>
<a class="download-files button style1" href="http://nemops.com/wp-content/uploads/2016/03/Dispatcher.zip" title="Download Project Files">Download Project Files</a>
<p>Last Week, forum user <strong>alexdee2007</strong> posted an interesting override: it allows us to extend PrestaShop Modules&#8217; controllers. Previously, we would have had to hardcode any modification within the originals, because the core system didn&#8217;t allow for such overrides. You can find a link to the original thread at the end of the tutorial.</p>
<div class="separator"></div>
<h2>What does the override do?</h2>
<p>Its concept is very simple, yet smart. It extends the <strong>Dispatcher</strong> class&#8217; <strong>Dispatch()</strong> method, modifying what the system looks for, once loading modules front controllers. Here is the core part:</p>
<pre class="brush: php; title: ; notranslate">
if (file_exists(_PS_OVERRIDE_DIR_ . 'modules/' . $module_name . '/controllers/front/' . $this-&gt;controller . '.php')) {
    include_once(_PS_OVERRIDE_DIR_ . 'modules/' . $module_name . '/controllers/front/' . $this-&gt;controller . '.php');
    $controller_class = $module_name . $this-&gt;controller . 'ModuleFrontControllerOverride';
} else {

    $controller_class = $module_name . $this-&gt;controller . 'ModuleFrontController';
}
</pre>
<p>Basically, it looks for the existence of any file, in the override directory, with the same path and name of the original controller. If it exists, it assigns the name plus &#8220;Override&#8221; to the current class name (which is what PrestaShop does already, for modules).<br />
This way, to extend any Module&#8217;s controller, we can simply create a file inside <em>override/modules/*modulename*/controllers/front</em>, named the same as the original, and then append Override to its Class name.</p>
<div class="separator"></div>
<h2>Video &#8211; A practical example</h2>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/nvVgbQZS-Eg" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<div class="separator"></div>
<h3>Additional Recources</h3>
<ul>
<li><a href="http://nemops.com/prestashop-modules-course" title="PrestaShop Modules Course">PrestaShop Modules Course</a></li>
<li><a href="https://www.prestashop.com/forums/topic/480523-override-front-controller-of-modules/?p=2262437" title="The original Forum Thread">The original Forum Thread</a></li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/overriding-modules-controllers-in-prestashop-1-6/">Overriding Modules Controllers in PrestaShop 1.6</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/overriding-modules-controllers-in-prestashop-1-6/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Essential Prestashop Functions – Day 5</title>
		<link>http://nemops.com/prestashop-functions-5/</link>
		<comments>http://nemops.com/prestashop-functions-5/#comments</comments>
		<pubDate>Tue, 08 Sep 2015 08:40:16 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[functions]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[smarty]]></category>
		<category><![CDATA[template]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2522</guid>
		<description><![CDATA[<p>Prestashop has lots of time-saving functions that we can use when developing modules or extensions. In today&#8217;s batch, we will examine template level functions. Assigning variables to smarty from PHP Creating translatable strings These are to be used whenever you want to create a translatable string in a template. After adding them, you can reach [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-functions-5/">Essential Prestashop Functions – Day 5</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Prestashop has lots of time-saving functions that we can use when developing modules or extensions. In today&#8217;s batch, we will examine template level functions.</p>
<p><span id="more-2522"></span></p>
<h2>Assigning variables to smarty from PHP</h2>
<pre class="brush: php; title: ; notranslate">

$this-&gt;context-&gt;smarty-&gt;assign('variablenameinsmarty', $myvalue); // you will be able to access this as {$variablenameinsmarty} in the template

// same as above, but in batch
$this-&gt;context-&gt;smarty-&gt;assign(array(
	'variablenameinsmarty' =&gt; $myvalue,
	'anothervariablenameinsmarty' =&gt; $myothervalue,
));

</pre>
<div class="separator"></div>
<h2>Creating translatable strings</h2>
<pre class="brush: php; html-script: true; title: ; notranslate">

{l s='This is my string'} // theme template
{l s='This is my string' mod='modulename'}// module template
{l s='There are %s errors' sprintf=[$account_error|@count]} // theme template with variable replacement
{l s='No file selected' js=1} // supposed to be used in a javascript script, only within addJsDef (see below)
{l s='Billing Address' pdf='true'} // only used within PDF templates
</pre>
<p>These are to be used whenever you want to create a translatable string in a template. After adding them, you can reach out the translations page in the back office and add them into other languages. &#8220;mod&#8221; ones will be found under &#8220;Installed Modules Translations&#8221;; &#8220;pdf&#8221; ones under PDF Translations; theme ones under Front Office Translations, choosing the specific template.</p>
<div class="separator"></div>
<h2>Adding javascript variable definitions</h2>
<pre class="brush: php; html-script: true; title: ; notranslate">

{addJsDef wishlistProductsIds=$wishlist_products}

{addJsDef mySliderCount=7}

{addJsDefL name='youhavelides'}{l s='You save Slides!' js=1}{/addJsDefL}

</pre>
<p>These are needed when you want to pass data from the template to any attached .js file. You will have to make sure to write any script inside a jquery ready statement if you load them in the header, or variables won&#8217;t be readily available. Notice how the first one uses the javascript variable name, while the language one sets it using name=&#8221;.</p>
<h3>Example Usage</h3>
<pre class="brush: jscript; title: ; notranslate">
// will alert &quot;You have slides!&quot; in the current language
if(mySliderCount &gt; 0)
	alert(youhavelides);

</pre>
<div class="separator"></div>
<h2>Displaying a formatted price</h2>
<pre class="brush: php; html-script: true; title: ; notranslate">

{convertPrice price=$price} // display Price in the current currency
{displayPrice price=$price currency=$id_currency} // specify the currency
</pre>
<p>These are used to format the price only. They will not take care of any conversion rate, even if the first one is named that way.</p>
<h3>Example Usage</h3>
<pre class="brush: php; html-script: true; title: ; notranslate">

// default currency is $, id 2 is Euros
{convertPrice price=1} // $1.00
{displayPrice price=1 currency=2} // 1,00 €

</pre>
<div class="separator"></div>
<h2>Displaying a formatted date</h2>
<pre class="brush: php; html-script: true; title: ; notranslate">

{dateFormat date=$date full =1} // display a date formatted like specified in the back office

</pre>
<h3>Example Usage</h3>
<pre class="brush: php; html-script: true; title: ; notranslate">

// chosen date format is dd/mm/yyyy H:i
{dateFormat date=&quot;2015-01-07 22:45:01&quot; } // 07/01/2015
{dateFormat date=&quot;2015-01-07 22:45:01&quot; full=1} // 07/01/2015 22:45

</pre>
<div class="separator"></div>
<h2>Getting a page Link</h2>
<pre class="brush: php; html-script: true; title: ; notranslate">

{$link-&gt;getPageLink('pagename', ssl, id_lang, &quot;GET string or Array&quot;)}

</pre>
<h3>Example Usage</h3>
<pre class="brush: php; html-script: true; title: ; notranslate">

// Gets a link for step 3 of the order process, with ssl
{$link-&gt;getPageLink('order', true, NULL, &quot;step=3&quot;)}

// link to the contact us page
&lt;a href=&quot;{$link-&gt;getPageLink('contact'}&quot; title=&quot;{l s='Contact us'}&quot;&gt;{l s='Contact us'}&lt;/a&gt;

</pre>
<div class="separator"></div>
<h2>Getting a Product Image</h2>
<pre class="brush: php; html-script: true; title: ; notranslate">

{$link-&gt;getImageLink(link_rewrite, id_image, 'image_type')}

</pre>
<h3>Example Usage</h3>
<pre class="brush: php; html-script: true; title: ; notranslate">

// gets the home_default image type, having a product as array
&lt;img src=&quot;{$link-&gt;getImageLink($product.link_rewrite, $product.id_image, 'home_default')}&quot;/&gt;

</pre>
<div class="separator"></div>
<h2>Adding a new hook</h2>
<pre class="brush: php; html-script: true; title: ; notranslate">

{hook h='displaySomething'} // will process any hookDisplaySomething method
{hook h='displaySomething' parameter='my string'} // will pass a variable named &quot;parameter&quot; with value &quot;my string&quot; later available using &quot;params['mystring']&quot; in the hook method

</pre>
<div class="separator"></div>
<h2>Conclusion</h2>
<p>This batch concludes our series on Useful Prestashop Functions. Bear in mind logic should be kept off the templates as much as possible, to preserve the MVC pattern (Prestashop is heading towards it with Prestashop 1.7 removing plenty of modifiers next year). Therefore, whenever possible, try using the PHP counterpart of these functions, preprocessing the output and only using template for displaying data.</p>
<h3>Additional Resources</h3>
<ul>
<li><a href="http://nemops.com/prestashop-functions-1/#.Vb8upPnzrmg" title="Essential Prestashop Functions – Day 1">Essential Prestashop Functions – Day 1</a></li>
<li><a href="http://nemops.com/prestashop-functions-2/#.Vb9Bxvnzrmg" title="Essential Prestashop Functions – Day 2">Essential Prestashop Functions – Day 2</a></li>
<li><a href="http://nemops.com/prestashop-functions-3/#.Vb9EAPnzrmg" title="Essential Prestashop Functions – Day 3">Essential Prestashop Functions – Day 3</a></li>
<li><a href="http://nemops.com/prestashop-functions-4/#.Ve6ZPhHzrmg" title="Essential Prestashop Functions – Day 4">Essential Prestashop Functions – Day 4</a></li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-functions-5/">Essential Prestashop Functions – Day 5</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-functions-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Essential Prestashop Functions &#8211; Day 4</title>
		<link>http://nemops.com/prestashop-functions-4/</link>
		<comments>http://nemops.com/prestashop-functions-4/#comments</comments>
		<pubDate>Wed, 12 Aug 2015 09:39:09 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[category]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[products list]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2504</guid>
		<description><![CDATA[<p>Prestashop has lots of time-saving functions that we can use when developing modules or extensions. Let&#8217;s see how to get various products list and deal with cookies, in this fourth batch. NOTICE: Values with &#8220;=&#8221; in the declaration are optional. Getting products of a Category This is the preferred method to get products from any [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-functions-4/">Essential Prestashop Functions &#8211; Day 4</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Prestashop has lots of time-saving functions that we can use when developing modules or extensions. Let&#8217;s see how to get various products list and deal with cookies, in this fourth batch.</p>
<p><span id="more-2504"></span></p>
<p><strong>NOTICE: Values with &#8220;=&#8221; in the declaration are optional. </strong></p>
<h2>Getting products of a Category</h2>
<pre class="brush: php; title: ; notranslate">

Category::getProducts($id_lang, $p, $n, $order_by = null, $order_way = null, $get_total = false, $active = true, $random = false, $random_number_products = 1, $check_access = true, Context $context = null);

</pre>
<p>This is the preferred method to get products from any category in Prestashop. It&#8217;s used not only in categories pages, but by the homefeatured module, as well as others.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

$category = new Category(5);

// Retrieves the first 15 products of a category
$products = $category-&gt;getProducts($this-&gt;context-&gt;language-&gt;id, 1, 15);

// Retrieves the first 15 products of a category, returning the number of total products for that category as well. Ordered by price, lowest to highest
$products = $category-&gt;getProducts($this-&gt;context-&gt;language-&gt;id, 1, 15, 'price', 'asc', true);


// Gets a random number of products, in random order (yes, even if we specified it)
$products = $category-&gt;getProducts($this-&gt;context-&gt;language-&gt;id, 1, 15, 'price', 'asc', false, true);


</pre>
<div class="separator"></div>
<h2>Getting new products</h2>
<pre class="brush: php; title: ; notranslate">

Product::getNewProducts($id_lang, $page_number = 0, $nb_products = 10, $count = false, $order_by = null, $order_way = null, Context $context = null);

</pre>
<p>This method can be used statically, without having to instantiate the product class.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

$newProducts = Product::getNewProducts((int) $this-&gt;context-&gt;language-&gt;id, 0, 10);

</pre>
<div class="separator"></div>
<h2>Getting discounted products</h2>
<pre class="brush: php; title: ; notranslate">

Product::getPricesDrop($id_lang, $page_number = 0, $nb_products = 10, $count = false,
		$order_by = null, $order_way = null, $beginning = false, $ending = false, Context $context = null);

</pre>
<p>This method can also be used statically, without having to instantiate the product class.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">


// get the last 10 prices drop, ordered by position
$price_drops = Product::getPricesDrop((int) $this-&gt;context-&gt;language-&gt;id, 0, 10);

// get the last 10 prices drops, ordered by price, but only where the offer's start date is after july 23, 2015
$price_drops =  Product::getPricesDrop((int) $this-&gt;context-&gt;language-&gt;id, 0, 10, false,
		'price', 'asc', '2015-7-23 10:45:32');

</pre>
<div class="separator"></div>
<h2>Getting Best Sales</h2>
<pre class="brush: php; title: ; notranslate">

ProductSale::getBestSales($id_lang, $page_number = 0, $nb_products = 10, $order_by = null, $order_way = null)

</pre>
<p>This method can also be used statically, without having to instantiate the product class.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// get 10 best selling products, ordered by best selling
$products = ProductSale::getBestSales($this-&gt;context-&gt;language-&gt;id, 0, 10);

</pre>
<div class="separator"></div>
<h2>Getting Best Sales (Light)</h2>
<pre class="brush: php; title: ; notranslate">

ProductSale::getBestSalesLight($id_lang, $page_number = 0, $nb_products = 10, Context $context = null)

</pre>
<p>Lighter and quicker version of the above method, which only retrieves strictly necessary information (not recommended to display products in the product-list template)</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// get 5 best selling products, ordered by best selling, called from a hook method
$products = ProductSale::getBestSalesLight((int)$params['cookie']-&gt;id_lang, 0, 5))

</pre>
<div class="separator"></div>
<h2>Adding variables to the cookie object</h2>
<pre class="brush: php; title: ; notranslate">

Cookie::__set($key, $value);

</pre>
<p>Useful to store dynamic information through pages (like user preferences for the current login session)</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// you might want to trigger this when a user clicks on the cookie loaw banner (where any), so that you are not prompting him to accept it on every page
$this-&gt;context-&gt;cookie-&gt;__set('cookielawaccepted', 1);

// The value can hold strings as well (arrays can be saved by serializing them)
$this-&gt;context-&gt;cookie-&gt;__set('mycustomoptionmode', 'test');


</pre>
<div class="separator"></div>
<h2>Checking cookie variables</h2>
<pre class="brush: php; title: ; notranslate">

Cookie::__get($key);

</pre>
<p>Gets the given key&#8217;s value from the cookie object.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// Following up the previous example, you can use this to avoid prompting the user again
if(!$this-&gt;context-&gt;cookie-&gt;__get('cookielawaccepted'))
{
	// display the message 
}

</pre>
<div class="separator"></div>
<h2>Clearing a cookie variable</h2>
<pre class="brush: php; title: ; notranslate">

Cookie::__unset($key);

</pre>
<p>Removes the given key from the cookie object.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// removes the cookie law entry,
$this-&gt;context-&gt;cookie-&gt;__unset('cookielawaccepted')

</pre>
<div class="separator"></div>
<h2>Logging a user out</h2>
<pre class="brush: php; title: ; notranslate">

Customer::logout();

</pre>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// Clears all of the current session data for this customer
$this-&gt;context-&gt;customer-&gt;logout();

</pre>
<div class="separator"></div>
<h3>Additional Resources</h3>
<ul>
<li><a href="http://nemops.com/prestashop-functions-1/#.Vb8upPnzrmg" title="Essential Prestashop Functions – Day 1">Essential Prestashop Functions – Day 1</a></li>
<li><a href="http://nemops.com/prestashop-functions-2/#.Vb9Bxvnzrmg" title="Essential Prestashop Functions – Day 2">Essential Prestashop Functions – Day 2</a></li>
<li><a href="http://nemops.com/prestashop-functions-3/#.Vb9EAPnzrmg" title="Essential Prestashop Functions – Day 3">Essential Prestashop Functions – Day 3</a></li>
<li><a href="http://nemops.com/prestashop-functions-5/#.Ve6fNxHzrmg" title="Essential Prestashop Functions – Day 5">Essential Prestashop Functions – Day 5</a></li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-functions-4/">Essential Prestashop Functions &#8211; Day 4</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-functions-4/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Essential Prestashop Functions – Day 3</title>
		<link>http://nemops.com/prestashop-functions-3/</link>
		<comments>http://nemops.com/prestashop-functions-3/#comments</comments>
		<pubDate>Mon, 03 Aug 2015 10:34:07 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[functions]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[products]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2495</guid>
		<description><![CDATA[<p>Prestashop has lots of time-saving functions that we can use when developing modules or extensions. The third batch will be focused on product-related methods. NOTICE: Values with &#8220;=&#8221; in the declaration are optional. Getting a Product&#8217;s Price Both methods can be equally used to get a product&#8217;s price. While the first needs to be ran [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-functions-3/">Essential Prestashop Functions – Day 3</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Prestashop has lots of time-saving functions that we can use when developing modules or extensions. The third batch will be focused on product-related methods.</p>
<p><span id="more-2495"></span></p>
<p><strong>NOTICE: Values with &#8220;=&#8221; in the declaration are optional.</strong></p>
<h2>Getting a Product&#8217;s Price</h2>
<pre class="brush: php; title: ; notranslate">

// It needs an instance
Product::getPrice($tax = true, $id_product_attribute = null, $decimals = 6,
		$divisor = null, $only_reduc = false, $usereduc = true, $quantity = 1)

// Static way
Product::getPriceStatic($id_product, $usetax = true, $id_product_attribute = null, $decimals = 6, $divisor = null,
		$only_reduc = false, $usereduc = true, $quantity = 1, $force_associated_tax = false, $id_customer = null, $id_cart = null,
		$id_address = null, &amp;$specific_price_output = null, $with_ecotax = true, $use_group_reduction = true, Context $context = null,
		$use_customer_price = true);

</pre>
<p>Both methods can be equally used to get a product&#8217;s price. While the first needs to be ran by a product instance, the second is static and can be ran from every context, as long as you provide the product id.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// get the product price, after instanciating a new object

$product = new Produc(4); // instanciate a product with id = 4
// get the price, but dynamically check if it needs to apply taxes or not
$product_price = $product-&gt;getPrice(Product::$_taxCalculationMethod == PS_TAX_INC);
// get the price of a specific combination, always with taxes
$product_attribute_price = $product-&gt;getPrice(true, 77);


// get price without instanciating an object
$products = array(
	0 =&gt; array('id_product' =&gt; 2),
	1 =&gt; array('id_product' =&gt; 86),
	2 =&gt; array('id_product' =&gt; 12),
);

foreach($products as $key =&gt; $product)
	$products[$key]['price'] = Product::getPriceStatic($product['id_product']);

</pre>
<div class="separator"></div>
<h2>Getting a Product&#8217;s Name</h2>
<pre class="brush: php; title: ; notranslate">

Product::getProductName($id_product, $id_product_attribute = null, $id_lang = null);

</pre>
<p>Retrieves the given product name in a single language (if not specified, the current one)</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// Gets the name in the current language
$name = Product::getProductName(34);

// Gets the combination name in a chosen language
$name = Product::getProductName(34, 6, 2);

</pre>
<div class="separator"></div>
<h2>Getting a Product&#8217;s Quantity</h2>
<pre class="brush: php; title: ; notranslate">


Product::getQuantity($id_product, $id_product_attribute = null, $cache_is_pack = null);

// This will consider a specific warehouse
Product::getRealQuantity($id_product, $id_product_attribute = 0, $id_warehouse = 0, $id_shop = null)

</pre>
<p>They both return the product&#8217;s quantity, but the latter is to be preferred with advanced stock management in mind.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// gets the quantity of all products in the array
$products = array(
	0 =&gt; array('id_product' =&gt; 2),
	1 =&gt; array('id_product' =&gt; 86),
	2 =&gt; array('id_product' =&gt; 12),
);

foreach($products as $key =&gt; $product)
	$products[$key]['qty'] = Product::getQuantity($product['id_product']);


// Gets quantity for a specific combination of a product (product id = 6, combination id = 99)
$quantity = Product::getQuantity(6, 99);


// Gets the quantity in stock for the specific warehouse ID
$quantity = Product::getRealQuantity(6, 0, 1);

</pre>
<div class="separator"></div>
<h2>Getting and displaying Products Cover Image</h2>
<pre class="brush: php; title: ; notranslate">

// Returns an image ID
Product::getCover($id_product, Context $context = null);

// Uses the product rewrite and image id to get the actual image link
Link::getImageLink($name, $ids, $type = null);

</pre>
<p>These can be used in conjunction to display the product&#8217;s cover.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// returns an array like array('id_image' =&gt; 66)
$cover = Product::getCover(5);

if($cover) // if there is an image
{
	// notice 'ipod-nano' is the product link_rewrite field here;
	$img_link = $this-&gt;context-&gt;link-&gt;getImageLink('ipod-nano', $cover['id_image']); // remember the previous is an array
}

</pre>
<div class="separator"></div>
<h2>Getting Product Features for the front office</h2>
<pre class="brush: php; title: ; notranslate">

// Gets features so they can be properly displayed
Product::getFrontFeatures($id_lang);

// The same, but static
Product::getFrontFeaturesStatic($id_lang, $id_product);

</pre>
<p>These methods come in handy when you want to display product features with their names and values.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

$product = new Product(10);
$features = $product-&gt;getFrontFeatures($this-&gt;context-&gt;language-&gt;id);


// static way
$features = Product::getFrontFeaturesStatic($this-&gt;context-&gt;language-&gt;id, 10);

</pre>
<div class="separator"></div>
<h2>Getting Product Categories</h2>
<pre class="brush: php; title: ; notranslate">



// Get ids of the categories this product belongs to
Product::getCategories();

// The same, Static
Product::getProductCategories($id_product);

// Get more data about categories, including name and link_rewrite
Product::getProductCategoriesFull($id_product, $id_lang = null);

// Get all parent categories, up to the root, in a single language. It will only consider the default one as starting point
Product::getParentCategories($id_lang = null);

</pre>
<p>They are all used to retrieve data about the product&#8217;s category association.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

$product = new Product(10);
// $categories will be ids only
$categories = $product-&gt;getCategories();

// Using the same Object, get all parents
$parent_categories = $product-&gt;getParentCategories();

// Static way, getting more data in the current language
$categories = Product::getProductCategoriesFull(10, $this-&gt;context-&gt;language-&gt;id);


</pre>
<div class="separator"></div>
<h3>Additional Resources</h3>
<ul>
<li><a href="http://nemops.com/prestashop-functions-1/#.Vb8upPnzrmg" title="Essential Prestashop Functions – Day 1">Essential Prestashop Functions – Day 1</a></li>
<li><a href="http://nemops.com/prestashop-functions-2/#.Vb9Bxvnzrmg" title="Essential Prestashop Functions – Day 2">Essential Prestashop Functions – Day 2</a></li>
<li><a href="http://nemops.com/prestashop-functions-4/#.Vc2cffnzrmg" title="Essential Prestashop Functions – Day 4">Essential Prestashop Functions – Day 4</a></li>
<li><a href="http://nemops.com/prestashop-functions-5/#.Ve6fNxHzrmg" title="Essential Prestashop Functions – Day 5">Essential Prestashop Functions – Day 5</a></li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-functions-3/">Essential Prestashop Functions – Day 3</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-functions-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Essential Prestashop Functions – Day 2</title>
		<link>http://nemops.com/prestashop-functions-2/</link>
		<comments>http://nemops.com/prestashop-functions-2/#comments</comments>
		<pubDate>Tue, 28 Jul 2015 12:19:28 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[functions]]></category>
		<category><![CDATA[prestashop]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2492</guid>
		<description><![CDATA[<p>Prestashop has lots of time-saving functions that we can use when developing modules or extensions. In this second batch we will examine database-related methods. NOTICE: Values with &#8220;=&#8221; in the declaration are optionals. Database-related Functions These methods serve as helpers so that we don&#8217;t have to create a new mysql connection every time we want [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-functions-2/">Essential Prestashop Functions – Day 2</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Prestashop has lots of time-saving functions that we can use when developing modules or extensions. In this second batch we will examine database-related methods.</p>
<p><span id="more-2492"></span></p>
<p><strong>NOTICE: Values with &#8220;=&#8221; in the declaration are optionals.</strong></p>
<h2>Database-related Functions</h2>
<pre class="brush: php; title: ; notranslate">

// Retrieving an array of values from the given table
Db::getInstance()-&gt;executeS($sql, $array = true, $use_cache = true);

// Retrieving a single value
Db::getInstance()-&gt;getValue($sql, $use_cache = true);

// Retrieving a whole row
Db::getInstance()-&gt;getRow($sql, $use_cache = true);

// Executing a generic query, returns true if succeeded, false if failed
Db::getInstance()-&gt;execute($sql, $use_cache = true)

// Inserting a row
Db::getInstance()-&gt;insert($table, $data, $null_values = false, $use_cache = true, $type = Db::INSERT, $add_prefix = true)

// Updating values
Db::getInstance()-&gt;update($table, $data, $where = '', $limit = 0, $null_values = false, $use_cache = true, $add_prefix = true)

// Erase the given entry
Db::getInstance()-&gt;delete($table, $where = '', $limit = 0, $use_cache = true, $add_prefix = true)

// Escape data
Db::getInstance()-&gt;escape($string, $html_ok = false, $bq_sql = false)

// Get the primary key of the last item you added
Db::getInstance()-&gt;Insert_ID()

</pre>
<p>These methods serve as helpers so that we don&#8217;t have to create a new mysql connection every time we want to run a query</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

// Returns an array with each item correspinding to a single database row
// It should only be used to retrieve values, use execute or the other helpers to insert/update them
$customers = Db::getInstance()-&gt;executeS('SELECT * FROM '._DB_PREFIX_.'customers');

// Returns product data of the ones that belong to the given category only (id = 4)
$products = Db::getInstance()-&gt;executeS('
	SELECT * FROM '._DB_PREFIX_.'product p
	LEFT JOIN '._DB_PREFIX_.'category_product cp ON (cp.id_product = p.id_product)
	WHERE cp.id_category = 4
');


// Retrieving the specific product name for our current language
$product_name = Db::getInstance()-&gt;getValue('SELECT name FROM '._DB_PREFIX_.'product_lang WHERE id_product = 1 AND id_lang = ' . $this-&gt;context-&gt;language-&gt;id);

// Get the whole row for customer id = 1
$customer = Db::getInstance()-&gt;getRow('SELECT * FROM '._DB_PREFIX_.'customer WHERE id_customer = 1');


// Insert some data manually (not recommended, unless you have some really specific SQL to use)
Db::getInstance()-&gt;execute('INSERT INTO '._DB_PREFIX_.'customer (id_customer, email, firstname, lastname) VALUES (9, &quot;nemo@nemops.com&quot;, &quot;Fabio&quot;, &quot;Porta&quot;)');

// Inserting a row
// The $data array must be configured like 
// 		column =&gt; value

$data = array(
	'id_customer' =&gt; 1,
	'email' =&gt; &quot;nemo@nemops.com&quot;,
	'firstname' =&gt; &quot;Fabio&quot;,
	'lastname' =&gt; &quot;Porta&quot;,
);
Db::getInstance()-&gt;insert('customer', $data);

// Updating values, array configured as above
$data = array(
	'id_customer' =&gt; 1,
	'email' =&gt; &quot;nemo@nemops.com&quot;,
	'firstname' =&gt; &quot;Fabio&quot;,
	'lastname' =&gt; &quot;Porta&quot;,
);
Db::getInstance()-&gt;update('customer', $data, 'id_customer = 1');

// Erase customer with id = 1
Db::getInstance()-&gt;delete('customer', 'id_customer = 1');

// Escape data
$sanitized = Db::getInstance()-&gt;escape('&lt;div class=&quot;test&quot;&gt;&lt;div&gt;', true);
// will return &lt;div class=\&quot;test\&quot;&gt;&lt;div&gt;

// Get the primary key of the last item you added

$data = array(
	'email' =&gt; &quot;nemo@nemops.com&quot;,
	'firstname' =&gt; &quot;Fabio&quot;,
	'lastname' =&gt; &quot;Porta&quot;,
);
Db::getInstance()-&gt;insert('customer', $data);
$last_id = Db::getInstance()-&gt;Insert_ID()
// $last_id will be the id_customer of the entry we just added


</pre>
<div class="separator"></div>
<h2>The Query object in Prestashop</h2>
<pre class="brush: php; title: ; notranslate">

DbQuery::select($fields)
DbQuery::from($table, $alias = null)
DbQuery::join($fields)
DbQuery::leftJoin($table, $alias = null, $on = null)
DbQuery::where($restriction)
DbQuery::having($restriction)
DbQUery::orderBy($fields)
DbQUery::groupBy($fields)
DbQuery::limit($limit, $offset = 0)

</pre>
<p>All these functions are used to streamline a query creation. Inspect the <strong>DbQuery</strong> class to have a complete list.</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

	// get all products with id &gt; 3, with relative language data

	$query = new DbQuery();
	$query-&gt;select('p.*, pl.*')
		-&gt;from('product', 'p')
		-&gt;leftJoin('product_lang', 'pl', 'p.id_product = pl.id_product')
		-&gt;where('p.id_product &gt; 34')
		-&gt;where('pl.id_lang = ' . $this-&gt;context-&gt;language-&gt;id)
		-&gt;groupBy('p.id_product')
		-&gt;limit(5)

	$result = Db::getInstance()-&gt;getValue($query);

</pre>
<div class="separator"></div>
<h2>Quick escape in a SQL query</h2>
<pre class="brush: php; title: ; notranslate">

pSQL($string, $htmlOK = false)

</pre>
<p>Sanitize data which will be injected into SQL query</p>
<h3>Example Usage</h3>
<pre class="brush: php; title: ; notranslate">

	$search = '2&quot; clamps';
	// get aliases for the given search word, as you can see the above requires douple quotes to be escaped
	$aliases = Db::getInstance()-&gt;executeS('
	SELECT a.alias
	FROM `'._DB_PREFIX_.'alias` a
	WHERE `search` = \''.pSQL($search).'\'');

</pre>
<h2>Wrapping it up</h2>
<p>All of the methods we examined today are a huge time saver when dealing with the Database in Prestashop. I rarely use the query object, I admit, as I prefer relying on the other methods. However, since it&#8217;s getting more and more built into the standard workflow of core modules and methods, it&#8217;s good practice to start using that as well, and integrate it into your own Prestashop Module/Extension.</p>
<div class="separator"></div>
<h3>Additional Resources</h3>
<ul>
<li><a href="http://nemops.com/prestashop-functions-1/#.Vb8upPnzrmg" title="Essential Prestashop Functions – Day 1">Essential Prestashop Functions – Day 1</a></li>
<li><a href="http://nemops.com/prestashop-functions-3/#.Vb9EAPnzrmg" title="Essential Prestashop Functions – Day 3">Essential Prestashop Functions – Day 3</a></li>
<li><a href="http://nemops.com/prestashop-functions-4/#.Vc2cffnzrmg" title="Essential Prestashop Functions – Day 4">Essential Prestashop Functions – Day 4</a></li>
<li><a href="http://nemops.com/prestashop-functions-5/#.Ve6fNxHzrmg" title="Essential Prestashop Functions – Day 5">Essential Prestashop Functions – Day 5</a></li>
</ul>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-functions-2/">Essential Prestashop Functions – Day 2</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-functions-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
