Implementing search feature and filters functionality at backend

create breed.php      /administrator/helpers/breed.php

update controller.php        /administrator/controller.php

update breeds.php        /administrator/models/breeds.php

update view.html.php     /administrator/views/breeds/view.html.php

update default.php       /administrator/views/breeds/tmpl/default.php

Files Detail

/administrator/helpers/breed.php

<?php

defined('_JEXEC') or die;

class BreedHelper
{
	public static function addSubmenu($vName = '')
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_BREED_TITLE_BREEDS'),
			'index.php?option=com_breed&view=breeds',
			$vName == 'breeds'
		);

	}
}

Joomla allows you to set a submenu by using a helper class, as shown in the above code. First, you have to declare a helper class using the component name without com_. In this class, we have simply created a static method called “addSubmenu” and then called the “addEntry” method of the JHtmlSidebar class, passing values like the url, submenu name, and view name.

/administrator/controller.php

require_once JPATH_COMPONENT . '/helpers/breed.php';

We will include the helper file in the display method of the main controller.php file so that it can be accessed throughout our component. Note that we are including it here by using require_once and not the Joomla JLoader::import() method. The reason for this is that this method tries to load a file using include_once, but we need “require_once” because we want our component to stop working when the system is unable to load our helper file. But in future projects, you can use any of these depending on the requirements. You can also use just import(), but keep in mind that JLoader::register() will not work here as it only registers or prepares the file for auto-loading.

/administrator/models/breeds.php

	protected function populateState($ordering = null, $direction = null)
	{
		// Initialise variables.
		$app = JFactory::getApplication('administrator');

		// Load the filter state.
		$search = $app->getUserStateFromRequest($this->context . '.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$published = $app->getUserStateFromRequest($this->context . '.filter.state', 'filter_published', '', 'string');
		$this->setState('filter.state', $published);
		// Filtering breedcat
		$this->setState('filter.breedcat', $app->getUserStateFromRequest($this->context.'.filter.breedcat', 'filter_breedcat', '', 'string'));

		// List state information.
		parent::populateState('a.breedname', 'asc');
	}



	protected function getStoreId($id = '')
	{
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');

		return parent::getStoreId($id);
	}

The first change we have made in this model is that we have first created the populateState() method, like we did while implementing the search feature in the frontend, to hold the state of the variables involved in the searching and filtering processes. To hold the Joomla application object, first we have initialised a variable called $app in this method.

From lines 39 to 45, we are setting and storing the start of the form variables, including search, state, and breed category. The search string is the value it gets from the search field when the user tries to search for something, and publish and preedcat are the values from the filter_publish and filter_breedcat dropdown filter fields. All of these values are pulled out by the getUserStateFromRequest() method, which is then used to set and temporarily store them in the model state.

Then from line 53 to 59, through getStoreId method, we are trying to get the ids from the search field and state or publish field. If that string is an interger, it will add “id:” to it. Next in this step of tutorial, I will show you why it is done and what is its benefit, when we will be building our query.

		// Filter by published state
		$published = $this->getState('filter.state');

		if (is_numeric($published))
		{
			$query->where('a.state = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.state IN (0, 1))');
		}

		// Filter by search in title
		$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 breedcat
		$filter_breedcat = $this->state->get("filter.breedcat");
		if ($filter_breedcat)
		{
			$query->where("a.`breedcat` = '".$db->escape($filter_breedcat)."'");
		}

To implement the search feature, first we have to prepare the proper query so that it can take a value to be searched and know from which column it should check. From lines 100 to 113, we have added the search query code. On line 100, we are getting the search value from the model state. On line 102, we perform a not-empty check on the search variable in order to perform a search on the database table.Next, we are preparing the search string so that it could go to a database query through the escape() method, which will make the search term ready to go to a query. This function prohibits any command from being run through the search field on the database. We are wrapping this string in “%,” which means match the string and anything before and after it. After this, on line 120, we are adding this to the where clause to make it part of our main query.

In this part of our Joomla extension development tutorial, we have added some more lines of code to our query, from lines 83 to 115. First, we have a where clause for publish state, which will return results based on the value returned by the getState(‘filter.state’) method.Normally, it would be an integer value, either 1 or 0. And if the getstate method has returned an empty result, on line 91, the where clause returns all the results, regardless of whether their state is published or unpublished, 0 or 1.

Next, we are getting the value of the search field through the get method, and this is the same value we have set in the populatestate method. Now, we are assigning this to the variable $search, and on line 97, we have actually started to build the search query. First, we assume that the search field value is not empty, and if it is not empty, we check to see if an id number is placed in the search field and the user wants to make a search according to the record id. If this is the case, then we will create the where clause on the basis of the id field. And if this is not the case, i.e., the search field value is a string, then we will create a WHERE clause that would look into the breedname field to make a search. We have also implemented the escape method to escape any HTML or PHP tags that are intentionally or accidentally passed to the $search property.

Next on line, 111, we are trying to filter the records on the basis of breed category. We have gotten and set the value of the breed category filter drop-down selector in the populate state function, and here we are getting this value and passing it to the filter_breedcat property. Then, based on the value of $filter_breedcat, we perform a search on the breedcat database table field.

/administrator/views/breeds/view.html.php

    BreedHelper::addSubmenu('breeds');
		
		JHtmlSidebar::setAction('index.php?option=com_breed&view=breeds');

		$this->extra_sidebar = '';
		JHtmlSidebar::addFilter(

			JText::_('JOPTION_SELECT_PUBLISHED'),

			'filter_published',

			JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), "value", "text", $this->state->get('filter.state'), true)

		);
		//Filter for the field breedcat
		$select_label = JText::sprintf('COM_BREED_FILTER_SELECT_LABEL', 'Breed Category');
		$options = array();
		$options[0] = new stdClass();
		$options[0]->value = "hybrids";
		$options[0]->text = "Hybrids";
		$options[1] = new stdClass();
		$options[1]->value = "purebreeds";
		$options[1]->text = "Pure Breeds";
		JHtmlSidebar::addFilter(
			$select_label,
			'filter_breedcat',
			JHtml::_('select.options', $options , "value", "text", $this->state->get('filter.breedcat'), true)
		);

		$this->sidebar = JHtmlSidebar::render();
		parent::display($tpl);
		
	}
	
	
		protected function getSortFields()
	{
		return array(
			'a.`id`' => JText::_('JGRID_HEADING_ID'),
			'a.`ordering`' => JText::_('JGRID_HEADING_ORDERING'),
			'a.`state`' => JText::_('JSTATUS'),
			'a.`breedname`' => JText::_('COM_BREED_BREEDS_BREEDNAME'),
			'a.`pic`' => JText::_('COM_BREED_BREEDS_PIC'),
			'a.`breedcat`' => JText::_('COM_BREED_BREEDS_BREEDCAT'),
		);
	}

There are some new additions to this view.html.php file, as compared to what we added to this file in the previous step. In this part of our tutorial series, we are trying to add search, filter, and sorting features to the table list view, so we are updating this file accordingly. Let me go through the changes we have made here in this file.

On line 33, we are setting the value of the action attribute of the filter form. Then we are adding our first filter, which is a most commonly used publish/unpublish filter, through the JHtmlSidebar::addFilter() method. It takes the text for the blank option, then the name of the filter field, then an array of standard published state filter options and passes its values to select options of the select field in terms of values and text, and finally we get the current state of this field via the get method.

After that, from lines 46 to 58, we are doing the same thing, but with the breed category filter. First, we have created a two-dimensional options array to hold the values and text of the breed category filter. When the assignment process is in the field, we are rendering the category filter in the same way we have rendered the state filter select field. Then on line 60, we are rendering the sidebar through the render() method of the JHtmlSidebar class.

Next, from lines 66 to 76, we are creating a two-dimensional array in the function getSortFields() that is holding the names of table columns and the language strings that would be shown in a drop-down select box, on the basis of which a sorting function could be performed on the listing table. We will call this function in our default.php view template file and then display the array contents in the form of a select field.

/administrator/views/breeds/tmpl/default.php

	jQuery(document).ready(function () {
		jQuery('#clear-search-button').on('click', function () {
			jQuery('#filter_search').val('');
			jQuery('#adminForm').submit();
		});
	});
</script>

<?php

if (!empty($this->extra_sidebar))
{
	$this->sidebar .= $this->extra_sidebar;
}

?>

<form action="<?php echo JRoute::_('index.php?option=com_breed&view=breeds'); ?>" method="post"
	  name="adminForm" id="adminForm">
	  
	  <?php if (!empty($this->sidebar)): ?>
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="span10">
		<?php else : ?>
		<div id="j-main-container">
			<?php endif; ?>

			<div id="filter-bar" class="btn-toolbar">
				<div class="filter-search btn-group pull-left">
					<label for="filter_search"
						   class="element-invisible">
						<?php echo JText::_('JSEARCH_FILTER'); ?>
					</label>
					<input type="text" name="filter_search" id="filter_search"
						   placeholder="<?php echo JText::_('JSEARCH_FILTER'); ?>"
						   value="<?php echo $this->escape($this->state->get('filter.search')); ?>"
						   title="<?php echo JText::_('JSEARCH_FILTER'); ?>"/>
				</div>
				<div class="btn-group pull-left">
					<button class="btn hasTooltip" type="submit"
							title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>">
						<i class="icon-search"></i></button>
					<button class="btn hasTooltip" id="clear-search-button" type="button"
							title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>">
						<i class="icon-remove"></i></button>
				</div>
				<div class="btn-group pull-right hidden-phone">
					<label for="limit"
						   class="element-invisible">
						<?php echo JText::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); ?>
					</label>
					<?php echo $this->pagination->getLimitBox(); ?>
				</div>
				<div class="btn-group pull-right hidden-phone">
					<label for="directionTable"
						   class="element-invisible">
						<?php echo JText::_('JFIELD_ORDERING_DESC'); ?>
					</label>
					<select name="directionTable" id="directionTable" class="input-medium"
							onchange="Joomla.orderTable()">
						<option value=""><?php echo JText::_('JFIELD_ORDERING_DESC'); ?></option>
						<option value="asc" <?php echo $listDirn == 'asc' ? 'selected="selected"' : ''; ?>>
							<?php echo JText::_('JGLOBAL_ORDER_ASCENDING'); ?>
						</option>
						<option value="desc" <?php echo $listDirn == 'desc' ? 'selected="selected"' : ''; ?>>
							<?php echo JText::_('JGLOBAL_ORDER_DESCENDING'); ?>
						</option>
					</select>
				</div>
				<div class="btn-group pull-right">
					<label for="sortTable" class="element-invisible"><?php echo JText::_('JGLOBAL_SORT_BY'); ?></label>
					<select name="sortTable" id="sortTable" class="input-medium" onchange="Joomla.orderTable()">
						<option value=""><?php echo JText::_('JGLOBAL_SORT_BY'); ?></option>
						<?php echo JHtml::_('select.options', $sortFields, 'value', 'text', $listOrder); ?>
					</select>
				</div>
			</div>

On line 12, we are calling the getSortFields() method through the $this specifier, which will return an array of field names, on the basis of which a sorting feature could be performed. After that, there is javascript code related to sorting and searching. From lines 25 to 35, there is the code for sorting the table, so a field value and direction of sort are provided in this code. Going deep into javascript is beyond the scope of this tutorial, but you can copy and use this code at the Joomla backend view, or wherever you want to implement column sorting. Next, from lines 38 to 43, there is the code related to the “search field clear button,” so that when the clear button is pressed, the search field value will be removed or cleared, and then the form will be resubmitted to reload the results with the search term having an impact on them.

Search Box:  In the default.php file listed above, the search box code is from line 73 to 92.  The code <?php echo $this->escape($this->state->get(‘filter.search’)); ?> will auto populate the search field with search term. After this, we have a buttons for submit and clear the search form field respectively.

Next from line 86 to 92, we have added the code to populate a select box through which we can limit the search results., by calling getLimitBox() method of pagination class.

After that, from line 93 to 108, we are displaying a select list for breed list ordering, either ascending or descending, and then, from line 109 to 115, we are creating a select list of fields on the basis of which sorting could occur. We are getting these values from the same array of sort fields that we have created in the view.html.php file here in this step.

Download Code

Next –>  Implementing change state functionality at backend

Add a Comment

Your email address will not be published. Required fields are marked *

ABOUT CODINGACE

My name is Nohman Habib and I am a web developer with over 10 years of experience, programming in Joomla, Wordpress, WHMCS, vTiger and Hybrid Apps. My plan to start codingace.com is to share my experience and expertise with others. Here my basic area of focus is to post tutorials primarily on Joomla development, HTML5, CSS3 and PHP.

Nohman Habib

CEO: codingace.com

Request a Quote









PHP Code Snippets Powered By : XYZScripts.com