Il peut être utile d'intégrer à Magento un formulaire, du même type que le formulaire de contact mais avec champs personnalisés. Cet article explique comment développer un module qui intégrera un nouveau formulaire sur le frontend, avec configuration depuis l'administration et gestion du gabarit e-mail.
Pour le développement de notre module nous imaginerons qu'il nous faut ajouter à notre e-commerce un formulaire de demande de brochure, à envoyer au client par courrier. Le client accède à une page ou il renseigne ses coordonnées : nom, prénom, adresse... Un mail où figure les informations saisie est alors envoyé à l'administrateur.
Le module a été développé sous la version 1.3.2.3 de Magento.
Nous commercerons, après avoir créé l'architecture complète du module, par déclarer son existence :
app/etc/modules/Magentix_Brochure.xml
<?xml version="1.0"?>
<config>
<modules>
<Magentix_Brochure>
<active>true</active>
<codePool>local</codePool>
</Magentix_Brochure>
</modules>
</config>
Dans cet exemple le formulaire sera constitué de 3 champs : nom, adresse et téléphone. Les champs nom et adresse seront obligatoires, téléphone sera facultatif.
Nous allons maintenant créer le formulaire depuis le fichier template form.phml, définir sa structure dans le layout défini par brochure.xml, éditer le template de mail par défaut brochure_form.html, et enfin définir les traductions dans le fichier de langue Magentix_Brochure.csv.
Dans le layout, on indique notamment la structure de page à utiliser : 1 column, 2 columns with right bar... Ainsi que le chemin vers le fichier template à utiliser et contenant le code HTML du formulaire :
app/design/frontend/default/default/layout/brochure.xml
<?xml version="1.0"?>
<layout version="0.1.0">
<default></default>
<brochure_index_index>
<reference name="root">
<action method="setTemplate"><template>page/2columns-right.phtml</template></action>
<action method="setHeaderTitle" translate="title" module="brochure"><title>Brochure</title></action>
</reference>
<reference name="content">
<block type="core/template" name="brochureForm" template="brochure/form.phtml"/>
</reference>
</brochure_index_index>
</layout>
Le template contiendra nos 3 champs et le bouton de validation. Une vérification JavaScript des champs obligatoires est possible par l'instanciation de la classe JavaScript VarienForm. Les champs vérifiés sont ceux dont la classe CSS contient required-entry (ajoutez "validate-email" pour vérifier la cohérence d'une adresse e-mail).
app/design/frontend/default/default/template/brochure/form.phtml
<div id="messages_product_view"><?php echo $this->getMessagesBlock()->getGroupedHtml() ?></div>
<form action="<?php echo $this->getFormAction(); ?>" id="brochureForm" method="post">
<div class="input-box">
<label for="name"><?php echo $this->__('Name') ?> <span class="required">*</span></label><br />
<input name="name" id="name" title="<?php echo $this->__('Name') ?>" value="<?php echo $this->htmlEscape(Mage::helper('brochure')->getUserName()) ?>" class="required-entry input-text" type="text" />
</div>
<div class="input-box">
<label for="address"><?php echo $this->__('Address') ?> <span class="required">*</span></label><br />
<input name="address" id="address" title="<?php echo $this->__('Address') ?>" value="" class="required-entry input-text" type="text" />
</div>
<div class="input-box">
<label for="telephone"><?php echo $this->__('Telephone') ?> </label><br />
<input name="telephone" id="telephone" title="<?php echo $this->__('Telephone') ?>" value="" class="input-text" type="text" />
</div>
<div class="button-set">
<p class="required"><?php echo $this->__('* Required Fields') ?></p>
<button class="form-button" type="submit"><span><?php echo $this->__('Submit') ?></span></button>
</div>
</form>
<script type="text/javascript">
var magazineForm = new VarienForm('brochureForm', true);
</script>
Nous allons ensuite éditer le fichier de langue Magentix_Brochure.csv afin d'indiquer les traductions des termes employés dans le formulaire :
app/locale/fr_FR/Magentix_Brochure.csv
"* Required Fields","* Champs obligatoires" "Submit","Envoyer" "Name","Nom" "Address","Adresse" "Telephone","Telephone"
Les informations recueillies seront envoyés par e-mail. Dans Magento, la structure du mail envoyé est définie par un gabarit, que l'on pourra éditer depuis l'administration dans la gestion des Emails transactionnels. Le fichier brochure_form.html correspond au "gabarit par défaut pour la locale".
L'encodage du fichier doit être UTF-8, autrement le mail envoyé sera vide.
app/locale/fr_FR/template/email/brochure_form.html
<!--@subject Demande de brochure@-->
Nom : {{var data.name}}
Adresse : {{var data.address}}
Telephone : {{var data.telephone}}
Nous allons maintenant nous attaquer au controller et définir les différentes actions : l'action à exécuter par défaut indexAction() dans laquelle on récupère le bloc brochureForm précédemment créé, et l'action postAction() exécuté lorsque le formulaire est soumis, avec récupération du POST, vérifications des champs, sélection du template mail, envoie de l'e-mail et affichage d'un message "succès" ou "erreur" à l'internaute. La fonction preDispatch() permet l'affichage d'une page d'erreur 404 si le formulaire brochure est désactivé depuis l'administration :
app/code/local/Magentix/Brochure/controllers/IndexController.php
<?php class Magentix_Brochure_IndexController extends Mage_Core_Controller_Front_Action { const XML_PATH_EMAIL_RECIPIENT = 'brochure/email/recipient_email'; const XML_PATH_EMAIL_SENDER = 'brochure/email/sender_email_identity'; const XML_PATH_EMAIL_TEMPLATE = 'brochure/email/email_template'; const XML_PATH_ENABLED = 'brochure/brochure/enabled'; public function preDispatch() { parent::preDispatch(); if( !Mage::getStoreConfigFlag(self::XML_PATH_ENABLED) ) { $this->norouteAction(); } } public function indexAction() { $this->loadLayout(); $this->getLayout()->getBlock('brochureForm')->setFormAction( Mage::getUrl('*/*/post') ); $this->_initLayoutMessages('customer/session'); $this->_initLayoutMessages('catalog/session'); $this->renderLayout(); } public function postAction() { $post = $this->getRequest()->getPost(); if ($post) { $translate = Mage::getSingleton('core/translate'); /* @var $translate Mage_Core_Model_Translate */ $translate->setTranslateInline(false); try { $postObject = new Varien_Object(); $postObject->setData($post); $error = false; if (!Zend_Validate::is(trim($post['name']) , 'NotEmpty')) $error = true; if (!Zend_Validate::is(trim($post['address']) , 'NotEmpty')) $error = true; if ($error) throw new Exception(); $mailTemplate = Mage::getModel('core/email_template'); /* @var $mailTemplate Mage_Core_Model_Email_Template */ $mailTemplate->setDesignConfig(array('area' => 'frontend')) /* L'adresse de réponse est ici l'adresse de l'expéditeur définie dans l'administration */ ->setReplyTo(Mage::getStoreConfig(self::XML_PATH_EMAIL_SENDER)) ->sendTransactional( Mage::getStoreConfig(self::XML_PATH_EMAIL_TEMPLATE), Mage::getStoreConfig(self::XML_PATH_EMAIL_SENDER), Mage::getStoreConfig(self::XML_PATH_EMAIL_RECIPIENT), null, array('data' => $postObject) ); if (!$mailTemplate->getSentSuccess()) { throw new Exception(); } $translate->setTranslateInline(true); Mage::getSingleton('customer/session')->addSuccess(Mage::helper('brochure')->__('Your inquiry was submitted')); $this->_redirect('*/*/'); return; } catch (Exception $e) { $translate->setTranslateInline(true); Mage::getSingleton('customer/session')->addError(Mage::helper('brochure')->__('Unable to submit your request. Please, try again later')); $this->_redirect('*/*/'); return; } } else { $this->_redirect('*/*/'); } } }
Dans notre Helper, la fonction getUserName() utilisée dans le fichier template form.phtml permet de récupérer le nom du client depuis la session ouverte si celui-ci est déjà connecté. Le champ "nom" du formulaire sera pré-rempli. On peut développer une fonction pour chaque élément associé au customer que l'on souhaite récupérer : prénom, e-mail, adresse...
app/code/local/Magentix/Brochure/Helper/Data.php
<?php class Magentix_Brochure_Helper_Data extends Mage_Core_Helper_Abstract { public function getUserName() { if (!Mage::getSingleton('customer/session')->isLoggedIn()) return ''; $customer = Mage::getSingleton('customer/session')->getCustomer(); return trim($customer->getLastname()); } }
Pour finir, il ne reste plus qu'à éditer nos fichiers de configuration config.xml et system.xml :
app/code/local/Magentix/Brochure/etc/config.xml
<?xml version="1.0"?>
<config>
<modules>
<Magentix_Brochure>
<version>1.0</version>
</Magentix_Brochure>
</modules>
<frontend>
<routers>
<brochure>
<use>standard</use>
<args>
<module>Magentix_Brochure</module>
<frontName>brochure</frontName>
</args>
</brochure>
</routers>
<translate>
<modules>
<Magentix_Brochure>
<files>
<default>Magentix_Brochure.csv</default>
</files>
</Magentix_Brochure>
</modules>
</translate>
<layout>
<updates>
<brochure>
<file>brochure.xml</file>
</brochure>
</updates>
</layout>
</frontend>
<global>
<resources>
<brochure_setup>
<setup>
<module>Mage_Brochure</module>
</setup>
<connection>
<use>core_setup</use>
</connection>
</brochure_setup>
</resources>
<helpers>
<brochure>
<class>Magentix_Brochure_Helper</class>
</brochure>
</helpers>
<template>
<email>
<brochure_email_email_template translate="label" module="brochure">
<label>Brochure Form</label>
<file>brochure_form.html</file>
<type>text</type>
</brochure_email_email_template>
</email>
</template>
</global>
<adminhtml>
<translate>
<modules>
<Magentix_Brochure>
<files>
<default>Magentix_Brochure.csv</default>
</files>
</Magentix_Brochure>
</modules>
</translate>
<acl>
<resources>
<admin>
<children>
<system>
<children>
<config>
<children>
<brochure translate="title" module="brochure">
<title>Brochure Section</title>
</brochure>
</children>
</config>
</children>
</system>
</children>
</admin>
</resources>
</acl>
</adminhtml>
<default>
<brochure>
<brochure>
<enabled>1</enabled>
</brochure>
<email>
<recipient_email><![CDATA[hello@example.com]]></recipient_email>
<sender_email_identity>custom2</sender_email_identity>
<email_template>brochure_email_email_template</email_template>
</email>
</brochure>
</default>
</config>
app/code/local/Magentix/Brochure/etc/system.xml
<config>
<sections>
<brochure translate="label" module="brochure">
<label>Brochure</label>
<tab>general</tab>
<frontend_type>text</frontend_type>
<sort_order>101</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<groups>
<brochure translate="label">
<label>Accept our brochure</label>
<frontend_type>text</frontend_type>
<sort_order>10</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<fields>
<enabled translate="label">
<label>Enable Brochure</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_yesno</source_model>
<sort_order>10</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</enabled>
</fields>
</brochure>
<email translate="label">
<label>Email Options</label>
<frontend_type>text</frontend_type>
<sort_order>50</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<fields>
<recipient_email translate="label">
<label>Send Emails To</label>
<frontend_type>text</frontend_type>
<sort_order>10</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</recipient_email>
<sender_email_identity translate="label">
<label>Email Sender</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_email_identity</source_model>
<sort_order>20</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</sender_email_identity>
<email_template translate="label">
<label>Email Template</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_email_template</source_model>
<sort_order>30</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</email_template>
</fields>
</email>
</groups>
</brochure>
</sections>
</config>
Le nouveau formulaire est maintenant accessible depuis l'URL http://www.site.com/brochure.
Il ne reste plus qu'à configurer le module depuis l'administration : Système > Configuration > Brochure.
Il est également possible d'ajouter un gabarit de mail pour le formulaire Brochure dans la gestion des Emails transactionnels. Si ce gabarit existe, il sera envoyé à la place du gabarit par défaut brochure_form.html.
Vous pouvez enfin continuer l'édition du fichier de traduction Magentix_Brochure.csv afin de le compléter avec l'ensemble des termes utilisés dans ce module.
Commentez cet article Ajouter un nouveau formulaire accessible depuis le frontend
Je trouve votre article très intéressant. Il m'a beaucoup aidé.
Je l'ai suivi de A à Z. J'ai pu créé correctement le module.
Cependant, je voudrais ajouter une table (nommée "brochure") dans ma base de données et l'attaquer depuis le module. Mais je ne réussi pas à le faire et pourtant j'ai bien créé la table manuellement.
Est-ce que vous pouvez me donner une piste pour ça.
Merci.
- J'ai créé la table "brochure" dans ma base de données Magento
- J'ai ajouté le code suivant dans dans mon fichier app/design/frontend/default/default/template/brochure/form.phtml :
echo "******** Affiche enregistrement N°1 de la table Brochure ********";
$object = Mage::getModel('brochure/brochure')->load(1);
$object->setAdresse('This is a changed adresse');
$object->save();
- L'erreur retourné par le système c'est :
Fatal error: Call to a member function load() on a non-object in C:\wamp\www\magento1324\app\code\core\Mage\Core\Model\Abstract.php on line 216
Ceci pourrait vous aider à m'aider.
Merci
Il y aura d'autres petits trucs à créer et configurer. Inspire toi d'un module déjà existant ou génère une extension à partir de module creator : http://www.magentocommerce.com/wiki/custom_module_with_custom_database_table
Tu pourras te baser là dessus pour te guider dans la manière de procéder.
Pour ce qui est du "Module creator", quand je l'installe j'ai un bug qui supprime toute la mise en page CSS de mon installation Magento.
C'est la raison pour laquelle je me suis retourné sur votre article pour essayer d'ajouter une table dans la base de données.
Est-ce-que vous pouvez juste me dire les autres trucs que je dois créer et configurer afin d'accéder à ma table depuis mon module.
Et pourtant, quand je fait une requête sur les tables propres à magento, tout se passe nikel. C'est étonnant.
Franchement Merci Beaucoup pour le temps que vous avez consacré pour mettre en place ce très intéressant Tuto,
sinon je suis sur Magento v1.3.2.4 et j'ai suivi à la lettre de A à Z les instructions, malheureusement en tapant l'URL:
http://localhost/monsite/brochure (je travail en localhost)
il m'affiche l'erreur 404 Not found in this server!!!!
Grand merci d'avance pour votre aide,
<routers> <brochure> <use>standard</use> <args> <module>Magentix_Brochure</module> <frontName>brochure</frontName> </args> </brochure> </routers>Le frontName défini ici est brochure, cela signifie que la page est accessible depuis l'url /brochure. La fonction exécutée est indexAction du fichier IndexController.php (on peut accéder à la page en indiquant l'url /brochure/index/index/). Lorsque le formulaire est soumis j'exécute alors la fonction postAction du même fichier (soit /brochure/index/post/).
Donc dans l'URL /brochure/index/index :
- brochure : désigne le nom défini pour frontname dans le fichier de configuration (config.xml)
- index : désigne le nom du contrôleur (IndexController.php)
- index : désigne la méthode du contrôleur à exécuter (indexAction)
Par défaut c'est toujours index qui sera visé, c'est pourquoi il n'est pas nécessaire de l'indiquer dans l'url.
Avant d'exécuter la fonction spécifiée, la méthode preDispatch est exécutée, elle vérifie ici que le formulaire est bien activé depuis la configuration et affiche une erreur 404 si ce n'est pas le cas.
Voilà pour la petite explication ;) Donc le problème peut venir d'un des cas de figure suivant :
- Le contrôleur n'est pas déclaré dans le fichier config.xml
- La fonction indexAction du contrôleur n'existe pas
- Le formulaire est désactivé depuis la configuration (brochure/brochure/enabled)
- Le cache n'a pas été rafraichi (supprimer le contenu du dossier /var/cache pour être sûre)
J'ai tenté de reproduire ce cas en faisant un "bete" copier/coller du code propose sur cette page pour le placer dans chaque fichier.
Je vois bien le module depuis l'administration : Système > Configuration > Brochure
Mais quand je clic pour le configurer : je perds le menu de configuration a gauche (seule la liste de choix de portee de configuration s'affiche) et la page reste blanche la ou la partie administration du module devrait s'afficher
Merci d'avance
Finalement (sans autre intervention) la partie admin fonctionne
Peut-etre un pb d'acces serveur au moment de mes premiers tests (j'avais pourtant bien vide le cache)
Tout est bien qui fini bien :)
Tutorial tres utile et pedagogique, merci.