Archive for the ‘Magento’ Category

Magento: Stop returning NULL or false

Thursday, October 17th, 2013

There are a lot of cases when we create a method in Magento which is supposed to return a Model. Let’s take this one as example:

The above method is called getCustomer() and it’s supposed to return a Mage_Customer_Model_Customer object.  If a valid bonus model is not found, then NULL is returned.

I see this pattern a lot. A lot of methods returning NULL or false if something is not found or not valid.

I also see this on collection classes, in methods like this one:

The above method will return a collection class filtered by customer_id or NULL if the customer is not a valid object.

Rober C. Martin in his book Clean Code is against returning NULL from methods because “when we return null, we are essentially creating work for ourselves and foisting problems upon our callers. All it takes is one missing null check to send an application spinning out of control”.

What should we do?

Now that we know that returning NULL from our methods is not a good idea, what should we do? Well I can see two alternatives:

  1. throw an exception. In my second code sample we return null when we pass an invalid customer object. Well if it’s invalid, throw an exception and other callers should be aware of this, and should try to catch it.
  2. return an object. To be more precise let’s refactor a bit the second code:

Now we can see that if the customer object is valid we will add the filter, and if not, than $this is returned, which is the collection class but without filters.

Other callers will not be forced to check that is not NULL, they will just do a count or something on the returned collection. The idea is that further code will be made so that it can work with a collection class. And nobody is forced to check the type and miss it. Also by returning $this we allow the chaining method pattern which is really used in Magento.

Magento: Add methods to your collection class

Friday, August 30th, 2013

From my experience I saw that are a lot of Magento developers who don’t make use of collection class as they should. Most of them just create the collection class for their model and that’s it. Then when they need the collection in blocks, controllers or helpers they do something like this:

This is wrong in my opinion:

  • I can’t reuse it. So you got your collection, add some filters and load it in your controller class. What if I need the same type of functionality in my helper? First of all, I wouldn’t know if someone from my team already did this. And second, if I knew, maybe I would copy paste it and increase the duplicate code.
  • I don’t know what it does. Maybe the code above is easier to understand, but what if I would have 6 filters from a vague model? At first, I would try to grasp what word should I give in my mind to this functionality adding more complexity in reading my code.
  • It takes a lot of space. I like to have as few lines as I can in my code. It improves readability and it helps a lot when you debug your code.

Ok, now that we know what is wrong with this type of implementation what should we do?

Answer: Add a method to the collection class:

Now, my problematic code will look like this:

My team can use this method if they want similar results, when I read it I know that I get the active parties, and it takes two lines :)

Magento Adminhtml: System Configuration

Wednesday, August 21st, 2013

Hello again. Today, we are going into Magento System Configuration by creating a new tab, section and field into our store. Although, this is a post from my adminhtml series, it can be a good tutorial on how to create a field in Magento system config.

What we will do: because my module was regarding a bunch of students, let’s create a text field in our system config called Maximum age.

system.xml file

The definition for the tabs, sections, groups and fields go into a new file from our etc/ folder of our module called system.xml. Bellow, I added my file, with all the contents:

 Add ACL resources

If we try to access our new tab by going to Magento admin > System > Configuration we will probably get a 404 Error page. That is because we didn’t define our ACL resource so our admin user doesn’t have access to our new section.

The ACL resources are done in our module’s etc/adminhtml.xml file. Bellow you can see how my adminhtml looks like:

If  you log out, and then log in you Magento admin, you should see your new section by going into System > Config section:

systemconfig

core_config_data table

All the data from Magento System config is saved in core_config_data table by scope, path and value. The path is created from system.xml nodes defined in my case ‘students/info/max_age’.

We can find out a system config value by store and path by using Mage::getStoreConfig() method:

That’s it. I know I went really fast trough this topic, but I will leave you with some further reading:

XML for admin configuration

Custom Magento System configuration

If you have other questions please leave a comment bellow and I’ll try to help everyone of you. Thanks :)

Magento Adminhtml: Forms in Magento

Tuesday, August 20th, 2013

Hello, again!

Last time I wrote about working with grids in Magento. Now it’s time to continue our series by creating a form into Magento admin. So what we will do: we will continue our last post by creating a form for adding a new student or edit an existing one.

To do this, we will go through the following steps:

  1. add a row url to our existing grid
  2. create the edit action
  3. create the form container
  4. create the form class

As you can see, we meet again with the concept of containers: we have a form container and a form class. The flow is like on the grids: we add our form container to our layout, and the form container will know how to instantiate the form class based on some of its protected properties. But I’m getting ahead of myself, so let’s start with the beginning.

1. Add a row url to our existing grid

In order to edit our students, we must tell our grid what to do when we click one of its rows. Let’s see how the grid is rendering it’s rows. The template file for each grid is app/design/adminhtml/default/default/template/widget/grid.phtml. If we go to line 154 we will see the following lines:

So in order to add an url to our grid rows we must create the getRowUrl($_item) method on our grid where $_item is an object from the collection we set on the grid. Let’s do that: Go to Certification_Student_Block_Adminhtml_Student_Grid class and add the following method:

The */*/edit means sameRoute/sameController/editAction(). So basically this will get us to the edit action from our StudentController. Now let’s create that action.

2. Create the edit action

Go to StudentController and create the editAction:

The code is pretty self explanatory: we load our student model based on the id parameter from request. If model doesn’t exists we throw an error message and redirect to index action. Otherwise, we register or student model into registry, then we load our layout. This layout is defined in app/design/adminhtml/default/default/student.xml under <adminhtml_student_edit> handle:

As you can see in our edit action we just add the form container which will know what form class to instantiate. Let’s create that form container:

3. Create the form container

Each form container extends from Mage_Adminhtml_Block_Widget_Form_Container class. The block defined by the type student/adminhtml_student_edit, will have the following contents:

If we go to _prepareLayout() method of Mage_Adminhtml_Block_Widget_Form_Container class, we will see how the form container uses the $_blockGroup, $_controller and $_mode properties to instantiate the form class. In our case, it will try to create a block of type student/adminhtml_student_edit_form. Now we must create that class, and that class will be the form class.

 4. Create the form class

Each form class from admin will extend the Mage_Adminhtml_Block_Widget_Form class. Our form class will have the following contents:

This class will have only one method, _prepareForm(), which will prepare our form.  First it will check if there is student data into our registry: which will mean that we edit an existing student. Then, a Varien_Data_Form class is instantiated and we set its id, action and method. The we set use container to true, which means that the form will be wrapped into <form> </form> elements.

Each form is composed from fieldsets, and each fieldset has one or more fields. Fieldsets extend from Varien_Data_Form_Element_Fieldset. 

Field class is depending on its type. If we go in Varien_Data_Form_Abstract class, we see how a field is added:

In other words, based on the type of the field a class from lib/Varien/Data/Form/Element/ will be instantiated.

Conclusion

Creating a form in Magento admin is not that hard as you think it is, but you must follow Magento’s convention if you want to make your life easier. I hope I didn’t go too fast in my explanations. However I attached the archive of this module, so you can have a full working demo. Forms.tar

If you have any questions, please leave a comment bellow and I will try to help you in the matter. Thanks for reading, and come again. My next topic will be about Magento System configuration. See you soon!

Magento Adminhtml: Grids in Magento

Wednesday, August 14th, 2013

Today, I will explain you how to create a simple grid in the Magento admin. And the premise is this: we have a student table, where we have data about some students, and we want to show this data in a Magento grid like this:

grid

In order to do this, we will make the following steps:

  1. create our table and populate it with some data
  2. create our module
  3. create our controller and action for displaying the grid
  4. create the grid container
  5. create the grid class

1. Create our table and populate it with some data

Here is the sql dump for you do to in your database:

 2. Create our module

We said that I will create a Students module. Here will be the directory structure for our module:

direct-struct

Some explanations:

Student/Block/Adminhtml/Student.php – this is the grid container.

Student/Block/Adminhtml/Student/Grid.php – this is the actually grid.

We will see what every file contains but I must explain the concept of containers. Magento admin is pretty much organized in containers. And in each container we have some functionality. For example we have grid containers which contain the grid. We have form containers which contain…forms. Also the tabs from a left navigation from admin have a container class which will wrap all the tabs together.

In our case the main role of the grid container is to dynamically instantiate the grid class. And we will see how it’s done bellow.

Student/Model/ contains the Student model and its resource model and resource collection. I already wrote how to create a model and its resource model and collection.

Student/controllers/Adminhtml/StudentController.php is the controller class responsible for displaying the grid. I already wrote how to make your controller work under the admin route.

Student/etc/config.xml – this is our module config file which will have the following content:

Student/etc/adminhtml.xml – will contain de definition data for our admin menu:

3. Create our controller and action for displaying the grid

We will create our StudentController.php which will have the following content:

As you can see our list action will only load and render the layout. Nothing more. And the definitions for the layout of listAction() will go in app/design/adminhtml/default/default/student.xml file because we defined in our config.xml file at line 41. This file will have the following content:

What we do is just add a block in the content which will be the grid container. The container will know how to instantiated and display the grid class. Let’s create this class defined by type=”student/adminhtml_student”.

4. Create the grid container

This will be the Student/Block/Adminhtml/Student.php file which will have the following content:

All grid containers extend the Mage_Adminhtml_Block_Widget_Grid_Container class. The $_addButtonLabel and $_headerText are just a way to customize the add new button and the header text. What it’s more interesting are the $_controller and $_blockGroup properties. Don’t think that $_controller defines the controller class because it doesn’t.

I stated above that the main role of the grid container is to instantiate the grid class. And this two variables define what block will be instantiate.

The grid instantiation is done in Mage_Adminhtml_Block_Widget_Grid_Container class in _prepareLayout() method:

So what the container does here is creating a child for him with a type defined by $_blockGroup and $_controller variables, in my case will create a child of the the type: student/adminhtml_student_grid. And that will be the grid class.

5. Create the grid class

The block type of student/adminhtml_student_grid will be the Student/Block/Adminhtml/Student/Grid.php file which will have the following content:

All grid classes extend from Mage_Adminhtml_Block_Widget_Grid class. If we go to that class in _prepareGrid() method we can see the flow of the grid initialization:

Besides _prepareMassactionBlock() we already defined our _prepareColumns() and _prepareCollection() methods to our grid class.

In _prepareCollection we just get the student collection and set it on the grid. So all grids work with a Magento collection set on them.

In _prepareColumns we just add the columns from the collection which we want to be shown on our grid. Now you should have a working grid.

If you are interested in creating a mass action please check this article.

Conclusion

Maybe it seem like a long post because of the code samples, but the idea its pretty simple: Once we have our admin action created we add a class extending from Mage_Adminhtml_Block_Widget_Grid_Container to our layout file, we set the $_blockGroup and $_controller variables which will instantiate a grid class extending from Mage_Adminhtml_Block_Widget_Grid. That’s it. If you have any questions or suggestions please leave a comment bellow.

Here are the source files for the module: Grid module.tar

Working with Adminhtml in Magento

Tuesday, August 13th, 2013

Hi guys, sorry for this long break :) I had a lot of work at my current job and I was pretty busy in my spare time also. But now I’m back with the intent to finish Magento Adminhtml by the end of this month.

What we will do: For the purpose of this tutorial, I will create a Students module and on it we will go through the following topics:

  1. Grids in Magento
  2. Forms in Magento adminhtml
  3. System configuration
  4. ACL and permissions in Magento
  5. Working with extensions

In the end I will give you the zip files for this module. So I hope you can learn with me the basic stuff when working with Magento Adminhtml. I already wrote a post about common structure of Magento adminhtml so you can check it if you haven’t did this by now. So, see you soon :)

Add an OR condition inside a WHERE when working with Magento collection

Tuesday, July 23rd, 2013

Let’s say you have a flat table with the following columns: test_id | flag_newsletter | flag_customer.

and you want to select all the records where test_id = 1 and (flag_newsletter = 1 or flag_customer = 1).

This is the way to do it:

 

Basic testing for your model, resource and collection in Magento

Tuesday, July 16th, 2013

Sometimes, you create your model, its resource class and collection and you don’t know for sure if you created them right, or set up the right configuration for the tables. I often had problems such as: the model wasn’t saving my data, or when I was looping through collection I got Varien_Object class instead of my model class, or the primary key wasn’t set up right from the beginning.
So here is how I make a simple test for my model, resource and collection:

I placed this file on my magento-root/test/test-mode.php. By running this in my browser, I make sure that my model, resource and collection are doing the basic operations for which they were made.

Magento Adminhtml: Make your controller work under the /admin route

Thursday, May 9th, 2013

Hello again :) Last time, I wrote about Common structure and architecture of Magento Adminhtml. Now, it’s time to go further and show you how can you make a controller work under /admin route. This question was raised on Magento certification guide, so I’ll try to be short and specific. Working with controllers in any area inside Magento is a must know so I decided to be more practical in this post.

Create your module

I’m not going into details here. I think if you’re reading this post you should already know how to create a module in Magento. I wrote about the basics of creating a Magento module in the beginning of this post. To follow me more easily, you should note that my namespace is Certification, and the module name is May(because is May when I’m writing this post).

Create your controller

In Certification/May/controllers/Adminhtml/ I created a new file called TestController.php and added the following content:

As you can see is a regular Test controller which extends the Mage_Adminhtml_Controller_Action class.

Add the controller to the admin route

My full config.xml file looks like below:

The most important part is the full <admin>…</admin> node. Inside this node, wee add our module’s Certification_May_Adminhtml space into the Magento Adminhtml controllers space. In other words, when looking for admin controllers, Magento will also look into our module’s controllers/Adminhtml/ space.

Test that controller is working

In my module’s etc folder I created a new file called adminhtml.xml which looks like bellow:

This will create a new menu item in admin, so we can test our controller. I will talk more about creating menu items in Magento in other posts, so don’t be scared if you don’t understand.

Now, if I go in admin to May > Test and click I should see the admin and an empty content. If somehow you are redirected to the 404 page, something is wrong. Read again and try to figure it out what you’ve missed. If you still have problems, leave a comment here and I’ll try to help if I have the time.

Good. Now you know how to create a controller for the Magento admin. Things are beginning to look good :) In no time you’ll start building grids and form for the admin. But those topics will be covered in future posts. Cheers :)

Magento Adminhtml: Common structure/architecture

Thursday, May 2nd, 2013

After a long break, we continue our journey into Magento certification study and we start with Magento Adminhtml. There will be a couple of posts about common structure/architecture, forms and grids, system configuration, ACL and permissions and working with extensions. In this post we will focus on Common structure and architecture.

Two things before we start

Let me answer these 2 questions:

Q: What’s the big fuss about Adminhtml? Is it that hard?

A: Not really. Magento team developed this area pretty good, allowing us to do funny stuff very easily if we thrive to follow their conventions. As long as you follow the rules magic will happen :)

Q: Where do we add things?

A: Not in Adminhtml module. If you go to core/Adminhtml/Block for example you will see there a lot of blocks regarding different modules. So you’ll think that in order to develop something in adminhtml you should create an Adminhtml module and put stuff there. No. This was done in ancient times when they didn’t have an admin route. Now, you must create and Adminhtml folder depending the place where you want to work. So if you want to create a block, you will have a path like YourModule/Block/Adminhtml/Yourblock.php, if you have a controller you will have a path like YourModule/controllers/Adminhtml/YourController.php. You got the idea.

notadmin

Differences between admin and frontend controllers

Admin controllers must extend Mage_Adminhtml_Controller_Action class. This class extend from the same class which frontend controllers(Mage_Core_Controller_Front_Action) extend. So we can say that admin controllers share some basic information with the frontend ones. Let’s see some specific properties and methods of the admin controllers:

Inside admin controllers the adminhtml area is used. The frontend controllers use the frontend area instead.

Controller predispatch. If we analyse a little bit the admin controller predispatch we see that in the first step the current area is set on the store as adminhtml. The theme is set. An event is dispatched, ‘adminhtml_controller_action_predispatch_start’. And then the form key and the secret key are validated:

Is allowed check. We see a method called _isAllowed() which returns true. This method can be override when we want to check the ACL permission inside an action. But I will talk more about this when I will write about ACL permissions. For now is suffice to say that this method is used for checking if access is allowed.

Admin session. If we want to fetch the adminthml session, we can use _getSession() method.

Admin base helper. If we want to have access to the base adminhtml helper we can use the _getHelper() method which return the Mage_Adminhtml_Helper_Data class.

Active menu. If we want for a certain menu item to be highlighted we can use the _setActiveMenu() method by supplying the menu path. But more on that in a future post where I will talk about creating menu items in the admin area.

Getting an URL. If we want to get an URL from admin we can use the getUrl() method which will use the base adminhtml helper to get an URL for admin. This will add the secret key if we use one to the URL.

Differences between admin and frontend blocks

The blocks from the adminhtml area extend from Mage_Adminhtml_Block_Template class, which extends the Mage_Core_Block_Template class(base class for frontend blocks). So the admin blocks share the same information as frontend blocks. You can see that Mage_Adminhtml_Block_Template class has very few methods, and they are not so hard to understand. I will not talk about them, but if you have any questions you can leave your hat on  a comment to this post and I will explain.

config.xml nodes regarding adminhtml area

<admin> …</admin> This is the node for definition of back-end routers and fieldsets for data flow functionality.

<adminhtml>…</adminhtml> Admin panel scope. Usually contains translations, layout files and event observers configuration for back-end. There were also definitions of menu and ACL resources before 1.4 version, but now they are placed in separate adminhtml.xml file.

system.xml and adminhtml.xml files

These files are set in our module’s etc folder with some information about adminhtml area:

system.xml = Here, we configure the system config tabs, sections and groups.

adminhtml.xml = Here, we configure menu items, and define acl resources lists.

I think this is OK for now. In my next article I will show you exactly how to create a controller for the admin area. Maybe it seems complicated right now but I wrote here in a general way about creating functionality for the Magento admin. I promise you that it will get much simpler as we go into this topic in the next posts about Magento adminhtml area. Cheers :)