Adding search feature to Component Frontend list view
update: breeds.php /site/models/breeds.php
update: view.html.php /site/views/breeds/view.html.php
update: default.php /site/views/breeds/tmpl/default.php
update: en-GB.com_breed.ini /languages/site/en-GB/en-GB.com_breed.ini
File Details
/site/models/breeds.php
if ($filters = $app->getUserStateFromRequest($this->context . '.filter', 'filter', array(), 'array'))
{
foreach ($filters as $name => $value)
{
$this->setState('filter.' . $name, $value);
}
}
Adding the search filters to populateState in the model
In the populatestate method, as I have described in the previous two steps, first of all, we initialise a variable called $app, which will actually hold the Joomla application object. I have described $limit, $limitstart, $ordering, and $ordering The last two steps go over the direction properties in detail. So, if you have directly come to this part of the tutorial, I will suggest that you go through the last two steps of the tutorial to gain a full understanding of what this populatestate method is doing and what we have done with listing ordering and pagination.
In this part of the tutorial, I am primarily focusing on the code from lines 21 to 27 of the above-mentioned breeds.php model file, which resides in the models directory. This would be somewhat difficult for a newcomer, but I am explaining it as simply as I can.
This code is primarily related to the implementation of search features and category filtering on breed listings in this section. On line 21, we are getting the state of all the form objects whose name attribute is declared as a filter array, like, filter[], so for the search field, it would be like, “filter [search],” for category, it would be like, “filter [category],” and for language, it would be like, “filter [language].” So, on line 21, we are getting all the values of the filter fields and passing these to an array, which will temporarily hold them.
After that, on line 23, there is a foreach loop on a two-dimensional array of $filters, holding field names and values. Then on line 25, we are assigning those values to the current state of the request by calling the setstate method through the $this specifier. Lines 29 and 32 of the code have been commented. In the instance where you only have a search filter and no other filters are there, this piece of code would be a good replacement for the previously mentioned foreach code, i.e., getting all filter field values in an array.
The reason why I am saying this is because the foreach process would be a little slower than getting the field individually because it will go for all the filter fields first and then apply a loop on the array to get and assign only a single value. So, it makes the process a little bit slow.
The structure of the code of two lines, 30 and 31 is similar to that of $limit and $limitstart properties on 15 and 19. If you want more explanation regarding it, you can go through previous two steps where I have explaianed each and every argument of getUserStateFromRequest in great detail.
$search = $this->getState('filter.search');
if (!empty($search))
{
if (stripos($search, 'id:') === 0)
{
$query->where('a.id = ' . (int) substr($search, 3));
}
else
{
$search = $db->Quote('%' . $db->escape($search, true) . '%');
$query->where('( a.breedname LIKE '.$search.' )');
}
}
// Filtering breed category
$filter_breedcat = $this->state->get("filter.breedcat");
if ($filter_breedcat != '') {
$query->where("a.breedcat = '".$db->escape($filter_breedcat)."'");
}
Now we have to make the adjustments to the query in the getListQuery() method according to what we have added to the populateState() method. In the getListQuery() method from lines 93 to 112, we have added some new code regarding the search and category filter options. Let us go through it. The first filter, from lines 93 to 101, is for the search filter. We have gotten the search value from populatestate() and assigned it to a $search variable. After that, we will check to see whether the variable is empty or not, and if it is, we will leave it; if it is not, we will try to setup a search query.
First, we will set up a case for searching an item through its unique ID. If it is true, we will add a WHERE clause to the main query where we are taking id equal to the string part after the prefix “id:” and will take this postfix value as an integer because we would require an integer value to be searched in the ID column of our table. If we didn’t find any prefix in the previous step, we will create a search for the breed title. First, we will sanitise the input string because the user’s input cannot be trusted.
There could be malicious code injection in the search string, which can create security issues. To achieve this, we will use the quote and escape method. The escape function properly escapes all the unnecessary or malicious characters and thus stops the errors being generated by the query by stopping SQL injection attacks. Now, what the quote method does is first filter the search string through the escape method, and then, according to the database engine, wrap this string in proper quotes. As we are using MySQL, it would be single quotes.
Similarly, from lines 108 to 112, we have done the same as we have done for the search query. Here, we are making a search on the basis of the selected breed category. We are assigning the value of the breedcat field to the $filter_breedcat variable and making a query on its basis, assuming that this is not an empty variable or that its value is not equal to blank.
/site/views/breeds/view.html.php
$this->filterForm = $this->get('FilterForm');
$this->activeFilters = $this->get('ActiveFilters');
In this step, we have added two lines of code to our view.html.php as shown in lines 20 and 21. These code lines are fetching FilterForm and ActiveFilters objects from model and assigning these so that these could be used in the default.php template file fir getting the filter form fields and active filters.
/site/views/breeds/tmpl/default.php
<?php
echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this));
?>
To display the search filters, we need to add the above mentioned code to our list view, default.php file.
/languages/site/en-GB/en-GB.com_breed.ini
COM_BREED_SEARCH_FILTER_SUBMIT="Search"
COM_BREED_BREEDS_BREEDCAT_FILTER="- Select Breed Category -"
COM_BREED_BREEDS_BREEDCAT_OPTION_HYBRIDS="Hybrids"
COM_BREED_BREEDS_BREEDCAT_OPTION_PUREBREEDS="Pure Breeds"
According to the language strings that we have created in this step, we are adding these strings and their respective values to our en-GB.com_breed.ini config file.