-
Notifications
You must be signed in to change notification settings - Fork 14
Creating your own filters
One major advantage of this extension is that creating a custom filter is quite easy and once done they are automatically reusable across all tables that use the field you filter by.
A filter always works by taking a database select object provided by the parent object (which can be a filter or a recipient provider) and then altering that query to return only the object IDs matching the filter.
Imagine you want to create a filter for the customer name. Your filter will only require the “customer_id”. Since the customer table provides a customer_id, but also the quote, order and newsletter table provide the same field, all will have access to your filter. This will make your filters reusable without doing any additional coding.
This is accomplished by using a database select object that provides bindings to common fields like customer_id. For instance the customer object creates a select object with a binding for “customer_id” on the field e.entity_id while the order object creates the same binding “customer_id” but on the field main_table.customer_id.
Your filter does not need to know the details, it only cares about the fact that there is a binding for ‘customer_id’ and it will join the tables on this binding.
You need to register a filter first in the config XML under global/mzax_emarketing/filters and give it a unique name and the path to your filter model.
<global>
[...]
<mzax_emarketing>
<filters>
<mynamespace_myfilter>
<model>mynamespace/emarketing_filter_name</model>
</mynamespace_myfilter>
</filters>
</mzax_emarketing>
</global>
This will register the filter class Mynamespace_Myfilter_Model_Emarketing_Filter_Name.
Next step is to create the filter class and make it extend Mzax_Emarketing_Model_Object_Filter_Abstract.
Now the bare minimum methods you want to define to get a filter running are:
-
acceptParent(Mzax_Emarketing_Model_Object_Filter_Component $parent)This method is called to check if we can use your filter on the current parent. This is where you would check if the parent has a binding that your require, for instance in our case this would be the ‘customer_id’.
-
public function getTitle()Returns a string with the title for your filter. You can use one pipe character ‘|’ to create or add it to any select group. (e.g. “Customer | Full Name”)
-
protected function prepareForm()Generates the form html that is displayed in the magento admin to configure your filter.
-
protected function _prepareQuery(Mzax_Emarketing_Db_Select $query)When your filter is used, it will basically ask the parent for a select query (extends Zend_Db_Select) and gives your filter a chance to prepare it and then return the prepared select query. All your sql filter logic goes in this method.
Lets look at each method and how we could implement it to make our customer name filter work.
public function acceptParent(Mzax_Emarketing_Model_Object_Filter_Component $parent)
{
return $parent->hasBinding('customer_id');
}
All what our filter need, is access to the customer_id. So all we need to do is check if our parent has a binding for customer_id, if thats the case, return true and the parent knows that we can handle its query object.
Bye the way, you could also extend from the class Mzax_Emarketing_Model_Object_Filter_Customer_Abstract which takes care of that bit.
public function getTitle()
{
return "Customer | Full Name";
}
Since we are filtering for customer names we place it in the “Customer” group by prefixing the title with “Customer |”. The title can be anything you want, but remember only one group prefix works.
protected function prepareForm()
{
return $this->__('Customer name %s.',
$this->getInputHtml('name')
);
}
This methods above creates something like: Customer name [is|is not|contains|…] […].
The best is to go and check out the Mzax_Emarketing_Model_Object_Filter_Abstract methods. There are bunch of little helper methods that makes creating forms quite easy.
The above will create a form with a select element for the operator you want to use (e.g does contain, does not contain, matches, is greater than,…) and a input field that will hold the value you want to compare to.
The key name is used as the name for the fields and the selected values will later be stored in $_data['name'] and $_data['name_operator']
protected function _prepareQuery(Mzax_Emarketing_Db_Select $query)
{
$firstname = $query->joinAttribute('customer_id', 'customer/firstname');
$lastname = $query->joinAttribute('customer_id', 'customer/lastname');
$query->where($this->getWhereSql('name', "CONCAT_WS(' ', $firstname, $lastname)"));
}
The method _prepareQuery() receives the select query object from its parent object, this could be a recipient provider or a filter if used in a nested filter scenario.
The query object has some useful methods that makes things a lot easier when working with Magento. Here we can use the joinAttribute() method to join the attribute table and automatically link it to the customer_id binding. The method will then return a db expression that points to the field in your query.
Once we have joined both attributes, we simple can create a where expression for both names and last name.
The method getWhereSql() is used to generate a where expression from the value provided by the form and your database field or in this case the concat of first and last name. In this case it will look for the values in '$_data[’name']and $_data['name_operator']to generated the where expression. Remember those values are defined by theprepareForm()` method.
That's it, you just created your first filter, you can see a full example here of the filter. Also good idea is to just look at the existing filters to get an idea of what is possible. A filter class can also register more then one filter, so for example do the abstract classes Mzax_Emarketing_Model_Object_Filter_Attribute and Mzax_Emarketing_Model_Object_Filter_Table provide access to a few filter that share all the same properties like attributes or column in a table. Those filters also dispatch events for you to register your own fields.
Lets say you have developed an extension for your company that has a custom column in the order table which you want to filter by. In this case you don’t need to create a new filter from scratch but instead use the existing order table filter Mzax_Emarketing_Model_Object_Filter_Order_Table which is setup to work with that table and its columns and you can easily add new columns via the event mzax_emarketing_email_filter_prepare_table_sales_order where you can use $observer->getEvent()->getFilter()->addColumn() to register any columns you want.
All product and customer attributes are handled automatically by retrieving the data from the eav module.
If you have your own EAV implementation and would like to add attribute filters, then I suggest to extend from the abstract class Mzax_Emarketing_Model_Object_Filter_Attribute, have a look how it is done for product and customer entities.
Install extension via Magento Connect or find out more at http://www.mzax.de