📜 ⬆️ ⬇️

Magento. We write the module. Add CAPTCHA and additional fields to the registration

I want to share the experience of programming modules for Magento. Many thanks to jeje for the invitation.
The article describes in detail the creation of a module that implements the additional functions of customer registration. Objectives - to give an idea about the development of Magento on a specific example from beginning to end, to show the main approaches, the organization of the code, point out some features. The article focuses more on beginners, but those familiar with Magento can take something useful for themselves. Of course, it’s impossible to describe everything in one article, but if the topic turns out to be relevant, this could be the beginning of a series of articles.
The following points are affected:

As a result, we will get registration with CAPTCHA verification, group selection field and saving invitation code.



Registration page
')

What is conceived


There is a registration page / magento / customer / account / create. We want to add a CAPTCHA check, and also ask the customers for the group and invitation code. The obtained data is stored in the database. By default, Magento defines three groups of General, Wholesale and Retailer clients. Of these, we offer to choose a future client. Magento does not know anything about the invitation code - we will create a new attribute.

I want to note that this is not a ready-made solution , but just an example, compiled for convenience of presentation.

Search


We are looking for where the template files are located, where and how the registration data is saved.
  1. Customer Registration Form Templates
    /magento/app/design/frontend/default/default/template/customer/form/register.phtml - registration form
  2. Attributes add in the installer module, example:
    /magento/app/code/core/Mage/Customer/sql/customer_setup/mysql4-upgrade-0.8.7-0.8.8.php
    the details will be lower when we write the installer for our module.
  3. We find the description of variable fields (attributes) in the module configuration:
    /magento/app/code/core/Mage/Customer/etc/config.xml
    inside <fieldsets> tags
  4. The registration form will post the data to the address:
      http: // localhost / magento / customer / account / createpost / 

    Accordingly, the request is processed by the Mage_ Customer _ Account Controller method createPost Action method (line # 234)


Implementation


The variant with the change of found files is not considered. Create your own theme and module.
The theme is simple:
  1. create a new folder in / magento / app / design / frontend / default / mytheme
    default - interface name
    mytheme is the name of our theme
  2. we copy files with preservation of directory structure in a new theme
  3. edit / create templates at your discretion

The templates of our theme with the same name will block the templates of the standard theme. Thus, we do not make changes to the native Magento files.

With the module a little more interesting:
Create a new module - CustomerMod . The folder structure of all modules is the same:
 magento / app / code / local /
	 Examples
		 CustomerMod
			 - Block
			 - etc
			 - Helper
			 - Model
			 - sql


Do not forget to add a file with the description of our modules:
magento / app / etc / modules / Examples_All.xml
 <config>
     <modules>
         <Examples_CustomerMod>
             <active> true </ active>
             <codePool> local </ codePool>
         </ Examples_CustomerMod>
     </ modules>
 </ config>


Fields on the registration page


Let's start by adding a group selection field to the registration page (“General”, “Wholesale”, “Retailer”). To display information, Magento operates with blocks and templates. A block can be called a template renderer. Each page consists of blocks, a template is indicated for each block.
We will add our block with our template inside the block of the registration form. In other words, our block will be a child of a form block.

1. Actually new template


Group selection template in a separate file:
/magento/app/design/frontend/default/example_theme/template/customer/form/register/groupselect.phtml

with simple content:

 <? php $ customer_groups = Mage :: helper ('customer') -> getGroups () -> toOptionArray ();  ?>

 <fieldset class = "group-select">
 <h4 class = "legend"> <? php echo $ this -> __ ('Customer Group')?> </ h4>
 <ul>
 <? php foreach ($ customer_groups as $ cg) {?>
	 <li class = "f-left" style = "margin: 2px 4px;"  >
		 <input type = "radio" name = "group_id" id = "group_id" 
			 value = "<? php echo $ cg ['value'];?>" 
			 <? php if ($ cg ['value'] == 1) echo 'checked = 1'?> />
		 <label> <? php echo $ cg ['label'];  ?> </ label>
	 </ li>
 <? php} // end foreach?>
 </ ul>
 </ fieldset>


Please note that the name of the field “group_id” must match the name of the attribute.

2. Adjustment layout


The mutual arrangement of blocks and snapping to templates are described in layout. These are xml files that are located in the magento/app/design/_/_/layout folder magento/app/design/_/_/layout .

In our case will be:
/magento/app/design/frontend/default/example_theme/layout/customermod.xml
 <layout version = "0.1.0">
	 <customer_account_create>					
		 <reference name = "customer_form_register">			
			 <block type = "core / template" name = "customergroups-select" template = "customer / form / register / groupselect.phtml" />
			 <block type = "captcha / recaptcha" name = "captcha" />			
		 </ reference>		
	 </ customer_account_create>		
 </ layout>


We refer to the customer_form_register block. We describe our child block inside it:
type is a block class that ultimately renders a pattern. In this case, “core / template”, which means Mage_Core_Block_Template .
name - the name can be any. It is necessary to refer to the block, for example in reference.
template - block template
Do not forget to specify the layout updates in the module configurations so that Magento takes into account the changes specified in customermod.xml :

/magento/app/code/local/Examples/CustomerMod/etc/config.xml
 <frontend>
 <layout>
       <updates>
           <customermod>
               <file> customermod.xml </ file>
           </ customermod>
       </ updates>
  </ layout>
 </ frontend>


3. Block output by parent block.


Our block is not yet visible, because we have to "call" the child block in the parent using the getChildHtml (BLOCK_NAME) method.
Copy register.phtml to our theme from the default theme and add the necessary call in front of the Login Information section:

/magento/app/design/frontend/default/example_theme/template/customer/form/register.phtml
 ...
 <? php echo $ this-> getChildHtml ('customergroups-select')?>
   
  <fieldset class = "group-select wide">
         <h4 class = "legend"> <? php echo $ this -> __ ('Login Information')?> </ h4>
 ...


4. Saving data


The group selection should now appear in the registration form.
“But wait, the customer registers with“ Retailer ”- and in the admin panel it is still in the General group!” - yes, the group_id field is not saved.
To save the entered fields, you need to specify them in the fieldsets in the configuration:

/magento/app/code/local/Examples/CustomerMod/etc/config.xml
     <fieldsets>
             <customer_account>
                 <group_id> <create> 1 </ create> <update> 1 </ update> </ group_id>	                
             </ customer_account>
         </ fieldsets>


Why - ask the developers of Magento, - but this is how the Customer controller works. Who is interested - see /magento/app/code/core/Mage/Customer/controllers/AccountController.php method createPostAction.

New attribute


Attributes are described in the eav_attributes table, respectively, working with attributes is reduced to editing the entries of the eav_attributes table.
There are also static attributes whose values ​​are stored in separate columns (for example, sales_order ).

1. Installation scripts


All actions for modifying the model are performed in installation scripts stored in the sql folder inside each module.
/magento/app/code/core/Mage/Customer/sql/customer_setup
Scripts are of two types - setup and upgrade . Magento runs the corresponding script once when installing or updating the module. After installation, an entry appears in the core_resource table, for example:
'customermod_setup', '0.1.0'

In other words, the scripts are run for two reasons:
  1. no module entry in the core_resource table
  2. the module version specified in core_resource is lower than in the module config.xml


It is worth noting that the uninstall mechanism is not provided . The created attributes will have to be deleted by hand in case of anything.

Scripts are executed by the installer. By default, the installer class is Mage_Core_Model_Resource_Setup , but it does not contain methods for working with the EAV model (and we are going to create the attributes), so in our case we need Mage_Eav_Model_Entity_Setup .

setup class hierarchy

2. Attribute Creation Script


Examples of installation scripts can be found in standard modules. Sometimes there is just a run of SQL commands. But it is desirable to use the methods of the classes of installers to the maximum, and to resort to SQL commands last.

 $ installer = $ this;

 / * @var $ installer Mage_Customer_Model_Entity_Setup * /
 $ installer-> startSetup ();

 $ installer-> addAttribute ('customer', 'invitation_code', array (
	 'type' => 'varchar',
	 'input' => 'text',
	 'label' => 'Invitation Code',
	 'global' => 1,
	 'visible' => 1,
	 'required' => 1,
	 'user_defined' => 1,
	 'default' => null,
	 'visible_on_front' => 1
 ))

 $ installer-> endSetup ();

I think after so many prefaces comments to the script itself are not required.

3. We update the template


Add a new field to the registration form template:

/magento/app/design/frontend/default/example_theme/template/customer/form/register.phtml
 <div class = "input-box">
	 <label for = "invitation_code"> <? php echo $ this -> __ ('Invitation Code')?> <span class = "required"> * </ span> </ label> <br/>
	 <input type = "text" name = "invitation_code" id = "invitation_code" title = "<? php echo $ this -> __ ('Invitation Code')?>" class = "required-entry input-text" />
 </ div>


4. Update the configuration


Add a description of the installation script:
/magento/app/code/local/Examples/CustomerMod/etc/config.xml
 <global>
	 <resources>
		 <customermod_setup>
			 <setup>
				 <module> Examples_CustomerMod </ module>
				 <class> Mage_Eav_Model_Entity_Setup </ class>
			 </ setup>
			 <connection> <use> core_setup </ use> </ connection>
		 </ customermod_setup>
		 <customermod_write> <connection> <use> core_write </ use> </ connection> </ customermod_write>
		 <customermod_read> <connection> <use> core_read </ use> </ connection> </ customermod_read>
	 </ resources>

And do not forget to specify a new field in fieldsets
 <fieldsets>
	 <customer_account>
		 <group_id> <create> 1 </ create> <update> 1 </ update> </ group_id>
		 <invitation_code> <create> 1 </ create> <update> 1 </ update> </ invitation_code>				                
	 </ customer_account>
 </ fieldsets>

Now in the registration form there is an Invitation Code field, the value of which is stored in the invitation_code attribute for each client. Also, a new field appeared in the admin panel on the client account page in the Account Information tab.

Admin Customer Account Screenshot

Captcha



To implement the "captcha" take reCAPTCHA . Further, there may be many ways: include the captcha functionality into an existing module, make it separate, you can push everything into a template and edit the standard controller.

In my opinion it is better to issue in a separate module. The steps to create a new module, a separate template, modifications to the layout (layout) are the same as described above. Let us dwell on what has not yet been affected: the controller and helper.
The values ​​from the registration form are transferred to the controller Mage_Customer_AccountController Magento has a mechanism for redefining the controllers ( since version 1.3, the mechanism has changed somewhat ). Instead of changes in the standard controller, we will create a new one inherited from the standard one.

So in order.

Download the recaptcha-php library and copy it to the / magento / lib folder.

1. Controller



In the configuration of the CustomerMod module we describe the controller:
 <config>
     ...
     <frontend>
     ...
      <routers>
          <customer>
             <args>
                <modules>
                   <Examples_CustomerMod before = "Mage_Customer"> Examples_CustomerMod </ Examples_CustomerMod>
                </ modules>
             </ args>
          </ customer>
       </ routers>
     ...


Actually the controller itself.
/magento/app/code/local/Examples/CustomerMod/controllers/AccountController.php
 require_once ("Mage / Customer / controllers / AccountController.php");
 require_once ('recaptcha / recaptchalib.php');

 class Examples_CustomerMod_AccountController extends Mage_Customer_AccountController {
		
	 public function createPostAction () {		
		 $ request = $ this-> getRequest ();		
		 $ captchaIsValid = Mage :: helper ('captcha') -> captchaIsValid ($ request);
		
		 if ($ captchaIsValid) {
			 parent :: createPostAction ();
		 } else {
			 $ this -> _ getSession () -> setCustomerFormData ($ this-> getRequest () -> getPost ());
			 $ this -> _ getSession () -> addError ($ this -> __ ('Verification code was not correct. Please try again.'));
			 $ this -> _ redirectError (Mage :: getUrl ('* / * / create', array ('_ secure' => true)));
		 }
	 }
 }


Unlike all other classes defined in Magento, for controllers it is necessary to explicitly point to the file containing the parent class and third-party libraries, so two require_once are needed. The code is minimal, we use the standard function from recaptchalib. But the verification of the introduced captcha itself is in a separate helper class. If you need to add the same check to other controllers, then everything will be reduced to checking the result of Mage::helper('captcha')->captchaIsValid($request).
Here you can add, for example, the authenticity of the invitation code.

2. Helper


The helper in Magento is a singleton class that usually contains a set of helper methods. The helper is accessed using the Mage::helper() method with the module name as a parameter. In our case, Examples_Captcha_Helper_Data will contain captcha check functions.

/magento/app/code/local/Examples/Captcha/Helper/Data.php
 require_once ('recaptcha / recaptchalib.php');
 class Examples_Captcha_Helper_Data extends Mage_Core_Helper_Abstract
 {	
	 const CAPTCHA_PUBLIC_KEY = "public-key-for-the-website";
	 const CAPTCHA_PRIVATE_KEY = "private-key-for-the-website";
	
	 public function captchaIsValid (Mage_Core_Controller_Request_Http $ request) {	
		 if ($ request) {
			 $ resp = recaptcha_check_answer (self :: CAPTCHA_PRIVATE_KEY,
		                            $ _SERVER ["REMOTE_ADDR"],
		                            $ request-> getParam ("recaptcha_challenge_field"),
		                            $ request-> getParam ("recaptcha_response_field"));		
			 return $ resp-> is_valid;
		 } 
		 return false;						
	 }
	
	 public function captchaGetError (Mage_Core_Controller_Request_Http $ request) {
		 if ($ request) {
			 $ resp = recaptcha_check_answer (self :: CAPTCHA_PRIVATE_KEY,
			                            $ _SERVER ["REMOTE_ADDR"],
			                            $ request-> getParam ("recaptcha_challenge_field"),
			                            $ request-> getParam ("recaptcha_response_field"));
			 return $ resp-> error;
		 }
		 return false;
		
	 }
	
	 public function getPublicKey () {return Examples_Captcha_Helper_Data :: CAPTCHA_PUBLIC_KEY;  }
	
 }


3. CAPTCHA block


It would not be bad to display a picture of the captcha itself on the page. There is a function for this recaptcha_get_html (). Despite the fact that the function can be called from a template (phtml), we will follow the ideas and architecture of Magento - we will create a new type of block, at the same time we will know how a block can be without a template. To do this, we describe the class Examples_Captcha_Block_Recaptcha . The call to the recaptcha_get_html() function is recaptcha_get_html() into the _toHtml method. This method is called when drawing a block in HTML. (see /magento/app/code/core/Mage/Core/Block/Abstract.php line # 643 )

/magento/app/code/local/Examples/Captcha/Block/Recaptcha.php
 require_once ('recaptcha / recaptchalib.php');
 class Examples_Captcha_Block_Recaptcha extends Mage_Core_Block_Abstract {		
	
	 public function _toHtml () {
		 $ html = recaptcha_get_html (Mage :: helper ('captcha') -> getPublicKey ());
		 return $ html;
	 }
	
 }


Add a new block to the layout. The template for this block is not needed; it already displays the finished captcha.

/magento/app/design/frontend/default/example_theme/layout/customermod.xml
 <? xml version = "1.0"?>
 <layout version = "0.1.0">
 <customer_account_create>					
		 <reference name = "customer_form_register">			
			 <block type = "core / template" name = "customergroups-select" template = "customer / form / register / groupselect.phtml" />
			 <block type = "captcha / recaptcha" name = "captcha" />			
		 </ reference>		
	 </ customer_account_create>
 </ layout>


4. Configuration


It remains only to indicate in the configuration of the Captcha module that it contains a block and a helper

/magento/app/code/local/Examples/Captcha/etc/config.xml
 <? xml version = "1.0" encoding = "UTF-8"?>
 <config>	
	 <modules>
	    <Examples_Captcha>
	        <version> 0.1.0 </ version>
	    </ Examples_Captcha>
	 </ modules>
	
	 <global>        		
		 <blocks>
			 <captcha> <class> Examples_Captcha_Block </ class> </ captcha>
		 </ blocks>				
		 <helpers>
			 <captcha>
				 <class> Examples_Captcha_Helper </ class>
			 </ captcha>
		 </ helpers>				
	 </ global>	
 </ config>


And the captcha is ready.

CAPTCHA screenshot

Conclusion



Thanks to read to the end! I hope you find it interesting or at least helpful :). You can download the finished sample . Magento version 1.3.2.4 was used for writing the article.
If the topic is interesting in Habré, then I will gladly listen to the wishes of the new article.
There are ideas and some materials for articles on the topic:

Source: https://habr.com/ru/post/78003/


All Articles