Tuto : personnaliser la page magasins dans PrestaShop

PrestaShop
  • Accueil
  • Blog
  • Tuto : personnaliser la page magasins dans PrestaShop

PrestaShop propose d’afficher une page avec la liste de tous les points de vente physique dont vous disposez.
Voyons voir comment personnaliser cette page magasins dans PrestaShop.

Constat : une page magasins dans PrestaShop assez limitée

Vous avez une option dans l’administration de PrestaShop qui permet d’affiche au choix :

  • soit une Google map avec les points de vente,
  • soit une liste classique des magasins (affichage simplifié).

page-magasins-prestashop

 

C’est plutôt limité, notamment si on veut avoir les deux affichages.

Tuto : personnaliser la page magasins dans PrestaShop

[edit du 05/10/2017] Voici un tuto vidéo (qualité de son médiocre, veuillez m’en excuser) pour appliquer les modifications :

On va faire en sorte que la page magasins dans PrestaShop affiche désormais la Google map ET la liste des magasins.
On va d’abord créer un override du fichier StoresController.php qu’on va placer dans le dossier www/override/controllers/front avec le contenu suivant :

class StoresController extends StoresControllerCore
{
/**
* Assign template vars for classical stores
*/
protected function assignStores()
{
$magasins = Db::getInstance()->executeS('
SELECT s.*, cl.name country, st.iso_code state
FROM '._DB_PREFIX_.'store s
'.Shop::addSqlAssociation('store', 's').'
LEFT JOIN '._DB_PREFIX_.'country_lang cl ON (cl.id_country = s.id_country)
LEFT JOIN '._DB_PREFIX_.'state st ON (st.id_state = s.id_state)
WHERE s.active = 1 AND cl.id_lang = '.(int)$this->context->language->id);

$addresses_formated = array();

foreach ($magasins as &$magasin) {
$address = new Address();
$address->country = Country::getNameById($this->context->language->id, $magasin['id_country']);
$address->address1 = $magasin['address1'];
$address->address2 = $magasin['address2'];
$address->postcode = $magasin['postcode'];
$address->city = $magasin['city'];

$addresses_formated[$magasin['id_store']] = AddressFormat::getFormattedLayoutData($address);

$magasin['has_picture'] = file_exists(_PS_STORE_IMG_DIR_.(int)$magasin['id_store'].'.jpg');
if ($working_hours = $this->renderStoreWorkingHours($magasin)) {
$magasin['working_hours'] = $working_hours;
}
}

$this->context->smarty->assign('hasStoreIcon', file_exists(_PS_IMG_DIR_.Configuration::get('PS_STORES_ICON')));

$distance_unit = Configuration::get('PS_DISTANCE_UNIT');
if (!in_array($distance_unit, array('km', 'mi'))) {
$distance_unit = 'km';
}

$this->context->smarty->assign(array(
'distance_unit' => $distance_unit,
'simplifiedStoresDiplay' => false,
'stores' => $this->getStores(),
'magasins' => $magasins,
'addresses_formated' => $addresses_formated,
));
}
}

On va modifier le fichier d’apparence stores.tpl du thème :

{capture name=path}{l s='Our stores'}{/capture}

<h1 class="page-heading">
{l s='Our stores'}
</h1>

{if $simplifiedStoresDiplay}
{if $stores|@count}
<p class="store-title">
<strong class="dark">
{l s='Here you can find our store locations. Please feel free to contact us:'}
</strong>
</p>
<table class="table table-bordered">
<thead>
<tr>
<th class="logo">{l s='Logo'}</th>
<th class="name">{l s='Store name'}</th>
<th class="address">{l s='Store address'}</th>
<th class="store-hours">{l s='Working hours'}</th>
</tr>
</thead>
{foreach $stores as $store}
<tr class="store-small">
<td class="logo">
{if $store.has_picture}
<div class="store-image">
<img src="{$img_store_dir}{$store.id_store}-medium_default.jpg" alt="{$store.name|escape:'html':'UTF-8'}" width="{$mediumSize.width}" height="{$mediumSize.height}"/>
</div>
{/if}
</td>
<td class="name">
{$store.name|escape:'html':'UTF-8'}
</td>
<td class="address">
{assign value=$store.id_store var="id_store"}
{foreach from=$addresses_formated.$id_store.ordered name=adr_loop item=pattern}
{assign var=addressKey value=" "|explode:$pattern}
{foreach from=$addressKey item=key name="word_loop"}
<span {if isset($addresses_style[$key])} class="{$addresses_style[$key]}"{/if}>
{$addresses_formated.$id_store.formated[$key|replace:',':'']|escape:'html':'UTF-8'}
</span>
{/foreach}
{/foreach}
<br/>
{if $store.phone}<br/>{l s='Phone:'} {$store.phone|escape:'html':'UTF-8'}{/if}
{if $store.fax}<br/>{l s='Fax:'} {$store.fax|escape:'html':'UTF-8'}{/if}
{if $store.email}<br/>{l s='Email:'} {$store.email|escape:'html':'UTF-8'}{/if}
{if $store.note}<br/><br/>{$store.note|escape:'html':'UTF-8'|nl2br}{/if}
</td>
<td class="store-hours">
{if isset($store.working_hours)}{$store.working_hours}{/if}
</td>
</tr>
{/foreach}
</table>
{/if}
{else}
<div id="map"></div>
<p class="store-title">
<strong class="dark">
{l s='Enter a location (e.g. zip/postal code, address, city or country) in order to find the nearest stores.'}
</strong>
</p>
<div class="store-content">
<div class="address-input">
<label for="addressInput">{l s='Your location:'}</label>
<input class="form-control grey" type="text" name="location" id="addressInput" value="{l s='Address, zip / postal code, city, state or country'}" />
</div>
<div class="radius-input">
<label for="radiusSelect">{l s='Radius:'}</label>
<select name="radius" id="radiusSelect" class="form-control">
<option value="15">15</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
<img src="{$img_ps_dir}loader.gif" class="middle" alt="" id="stores_loader" />
</div>
<div>
<button name="search_locations" class="button btn btn-default button-small">
<span>
{l s='Search'}<i class="icon-chevron-right right"></i>
</span>
</button>
</div>
</div>
<div class="store-content-select selector3">
<select id="locationSelect" class="form-control">
<option>-</option>
</select>
</div>

<table id="stores-table" class="table table-bordered">
<thead>
<tr>
<th class="num">#</th>
<th>{l s='Store'}</th>
<th>{l s='Address'}</th>
<th>{l s='Distance'}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>

<!-- stores -->
{*<pre>{$magasins|print_r}</pre>*}
{if $magasins|@count}
<ul id="list_stores">
{foreach $magasins as $magasin}
<li>
<p class="title">{$magasin.name|escape:'html':'UTF-8'}</p>
{assign value=$magasin.id_store var="id_store"}
{foreach f<br />
rom=$addresses_formated.$id_store.ordered name=adr_loop item=pattern}
{assign var=addressKey value=" "|explode:$pattern}
{foreach from=$addressKey item=key name="word_loop"}
<p {if isset($addresses_style[$key])} class="{$addresses_style[$key]}"{/if}>
{$addresses_formated.$id_store.formated[$key|replace:',':'']|escape:'html':'UTF-8'}
</p>
{/foreach}
{/foreach}
{if $magasin.phone}<p>{l s='Phone:'} {$magasin.phone|escape:'html':'UTF-8'}</p>{/if}
{if $magasin.fax}<p>{l s='Fax:'} {$magasin.fax|escape:'html':'UTF-8'}</p>{/if}
{if $magasin.email}<p>{l s='Email:'} {$magasin.email|escape:'html':'UTF-8'}</p>{/if}
{if $magasin.note}<p>{$magasin.note|escape:'html':'UTF-8'|nl2br}</p>{/if}
{*{if isset($magasin.working_hours)}<p>{$magasin.working_hours}</p>{/if}*}
</li>
{/foreach}
</ul>
{/if}

{strip}
{addJsDef map=''}
{addJsDef markers=array()}
{addJsDef infoWindow=''}
{addJsDef locationSelect=''}
{addJsDef defaultLat=$defaultLat}
{addJsDef defaultLong=$defaultLong}
{addJsDef hasStoreIcon=$hasStoreIcon}
{addJsDef distance_unit=$distance_unit}
{addJsDef img_store_dir=$img_store_dir}
{addJsDef img_ps_dir=$img_ps_dir}
{addJsDef searchUrl=$searchUrl}
{addJsDef logo_store=$logo_store}
{addJsDefL name=translation_1}{l s='No stores were found. Please try selecting a wider radius.' js=1}{/addJsDefL}
{addJsDefL name=translation_2}{l s='store found -- see details:' js=1}{/addJsDefL}
{addJsDefL name=translation_3}{l s='stores found -- view all results:' js=1}{/addJsDefL}
{addJsDefL name=translation_4}{l s='Phone:' js=1}{/addJsDefL}
{addJsDefL name=translation_5}{l s='Get directions' js=1}{/addJsDefL}
{addJsDefL name=translation_6}{l s='Not found' js=1}{/addJsDefL}
{/strip}
{/if}

A cela, on va ajouter un peu de style dans le fichier global.css de votre thème :

/*STORES*/
#list_stores{font-size: 0;text-align: left;}
#list_stores li{display: inline-block;vertical-align: top;width: 33.33%;padding: 0 1%;font-size: 13px;font-weight: normal;margin: 0 0 30px;}
#list_stores li .title{background: #333;color: #fff;padding: 3px 5px;}
#list_stores li p + p{margin-top: 5px;}
@media screen and (max-width: 767px){
#list_stores li{width: 48%;}
}
@media screen and (max-width: 479px){
#list_stores li{width: 98%;}
}

N’oubliez pas de supprimer le fichier www/cache/class_index.php pour que votre override soit bien pris en compte.
Le résultat devrait être sous cette forme avec une stores list précédée de la Google map avec les magasins :

stores-page-prestashop

Avec ça, vos clients trouveront plus facilement le point de vente qui leur correspond, un plus pour vos ventes !
[Edit du 13/06/2016] Voici les fichiers à télécharger directement pour ceux qui n’arriverait pas à mettre en place la personnalisation 🙂

Fichier StoresController.php

Fichier stores.tpl

33 commentaires sur “Tuto : personnaliser la page magasins dans PrestaShop

  1. Bonjour toujours pratiques vos conseils 🙂

    Je cherche à faire quelque chose de simple en apparence mais bien sûr avec prestashop c’est toujours une galère …

    Savez-vous s’il existe un module ou autre, projet en développement git hub etc ?? Qui permettrai au client de trouver des établissement près de chez eux.

    Et de pouvoir également y sélectionner directement des produits sur la carte ( qui seront filtrés en fonction de l’établissement choisi ) ??

    Merci !!

  2. Bonjour,
    j’aurai souhaiter affiché les images des magasins en plus de l’adresse, mais je vois pas trop comment ? un peu d’aide, en vous remerciant

    1. Bonjour Emmanuel, Tu as ce code qui affiche l’image des magasins :
      [code]
      {if $store.has_picture}
      <div class="store-image">
      <img src="{$img_store_dir}{$store.id_store}-medium_default.jpg" alt="{$store.name|escape:’html’:’UTF-8′}" width="{$mediumSize.width}" height="{$mediumSize.height}"/>
      </div>
      {/if}
      [/code]
      A bientôt 🙂

    1. Bonjour Florian,
      Je ne pense pas car il est testé sur les versions 1.6 mais la 1.7 a pas mal évolué 😉
      Je peux regarder au cas par cas via une intervention si besoin, faîtes moi un e-mail.
      Bonne journée.

  3. Bonjour, et tout d’abord merci. L’affichage est correctement modifié, toutefois la fonction de recherche ne semble plus fonctionner… Suis-je le seul à rencontrer ce souci ?

    1. Bonjour Paola,
      Je viens de mettre l’article à jour avec une vidéo tuto pour modifier l’affichage des magasins. Vous le verrez, la recherche sur la carte Google Map fonctionne bien. Je pense donc que vous devez avoir une erreur dans votre page qui bloque la recherche.
      Vous pouvez me faire un mail avec l’url du site pour que je regarde.
      A bientôt 🙂

    2. Hello ! Je rencontre le même soucis. L’affichage est OK mais la recherche ne fonctionne pas… Je suis en local

    3. Bonjour Carlasdn,
      Merci pour le commentaire,
      Première chose, vérifiez que la carte Google Map s’affiche bien. Si non, alors vous devez prendre une licence ici : https://cloud.google.com/maps-platform/?hl=fr
      Deuxième chose, vérifiez qu’il n’y a pas d’erreur dans votre page via l’outil de débug de Google Chrome ou Safari par exemple.
      Si ce n’est pas le cas, vous pouvez m’envoyer le lien de votre page une fois en ligne pour que je jete un oeil 😉

  4. ha ça nettoie le code 🙂

    {foreach from=$magasins|@sortby:'country' item='magasin' name="countryLoop"}
    {$magasin.country|escape:'html':'UTF-8'}

    1. Bonjour Romain, je n’ai pas testé mais c’est sympa de partager votre recherche. C’est testé sur quelle version exactement ?

  5. hé pour ceux qui sont des quiche comme moi: ça peux aider aussi d’ajouter une variable dans la class du type
    {foreach from=$magasins|@sortby:’country’ item=’magasin’ name=”countryLoop”}
    {$magasin.country|escape:’html’:’UTF-8′}
    Voilou 🙂

  6. Avec ça : {foreach $magasin.country as $land}
    fonctionne pas vraiment non plus:
    {foreach $magasin.country as $land}
    {foreach $magasins as $magasin}
    {if $magasin.country}{$magasin.country|escape:’html’:’UTF-8’|nl2br}{/if}
    {$magasin.name|escape:’html’:’UTF-8′}
    {assign value=$magasin.id_store var=”id_store”}
    {foreach from=$addresses_formated.$id_store.ordered name=adr_loop item=pattern}
    {assign var=addressKey value=” “|explode:$pattern}
    {foreach from=$addressKey item=key name=”word_loop”}
    {$addresses_formated.$id_store.formated[$key|replace:’,’:”]|escape:’html’:’UTF-8′}
    {/foreach}
    {/foreach}
    {if $magasin.phone}{l s=’Phone:’} {$magasin.phone|escape:’html’:’UTF-8′}{/if}
    {if $magasin.fax}{l s=’Fax:’} {$magasin.fax|escape:’html’:’UTF-8′}{/if}
    {if $magasin.email}{l s=’Email:’} {$magasin.email|escape:’html’:’UTF-8′}{/if}
    {if $magasin.note}{$magasin.note|escape:’html’:’UTF-8’|nl2br}{/if}
    {/foreach}
    {/foreach}

    1. Bonjour Romain, je n’ai pas testé mais une boucle du genre devrait faire l’affaire :
      [php]
      <ul>
      {foreach $magasin.country as $land}
      {if $magasin.country == "pays 1"}
      <li>contenu</li>
      {/if}
      {if $magasin.country == "pays 2"}
      <li>contenu</li>
      {/if}
      {/foreach}
      </ul>
      [/php]

  7. Hello merci pour la réponse un foreach du genre:
    {foreach $magasins as $magasin.country}
    bla bla bla
    {/foreach}
    Php et smarty c’est vraiment pas ma spécialité

    1. Bonjour Romain, il existe pour $stores la variable country donc tu peux utiliser un foreach avec la condition sur le pays dans la boucle 😉

    1. Hello Germain ! Ton approche est vraiment pas mal du tout aussi, merci pour le partage 🙂

  8. Bonjour Martin, j’ai ajouté les fichiers à télécharger dans l’article pour que ça soit plus simple 🙂

Laisser un avis

Consultez les autres articles