Implementing search feature and filters functionality at backend | Joomla 3.x extension development crash course.

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 component name, without com_. In this class, we have simply created a static method called addSubmenu and then have called addEntry method of JHtmlSidebar class and passed values like the url, submenu name and view name.

 

/administrator/controller.php

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

  In the main controller.php file, we are going to include the helper file in the display method, so that it could 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, this method tries to load a file using include_once but we need here "require_once" because we want our component to stop working when the system is unable to load our helper file. But in future project, you can use any of these depending on the requirement. 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, we have first created the populateState() method, like we have created while implementing search feature in the frontend, to hold the state of the variables, involved in the searching and filtering process. To hold the Joomla application object, first we have initialized a variable, called $app in this method. 

From line 39 to 45, we are setting and stroing the starte of the form variables including search, state and breed category. Search string is the value it gets from the search field, when user tries to search something, publish and preedcat are the values from filter_publish and filter_breedcat dropdown filter fields. The values of all of these are extracted by getUserStateFromRequest() method and are then set and temporarily stored in the model state through setstate() method. 

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 it should know, from which column it should check.From line 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 are making a not empty check on search variable, so that a search could be made on the database table. Next we are preparing the search string, so that it could go to database query through escape() method which will made search term ready to go to query. This function prohibits any command to be run through search field on database. We are wrapping this string in "%", means, match the string and anything before and after it. After this, on line 120 we are adding this to where clause to make it the 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 line 83 to 115. First we have made a WHERE clause for publish state and it will give the results on the basis of the value it gets from 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, inspite of what their state is, published or un published, 0 or 1.

Next we are getting the value of search field through get method, and this is the same value we have set in the populatestate method. Now, we are assigning this to a variable $search and on line 97, we have actually started to build the search query. First we are assuming that the search field value is not empty and if it is not empty, we are checking that whether 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 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 which would look into the breedname field, to make a search. We have also implemented the escape method to escape any html or php tags, if they are intentionally or by mistake passed to the $search property.

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

 

/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 addition to this view.html.php file, as compared to what we have added into this file in the previous step. In this part of our tutorial series, we are trying to add search, filter and sorting feature to 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 filter form. Then we are adding our first filter, that is a most commonly used publish / unpublish filter through JHtmlSidebar::addFilter() method. It is taking the text for the blank option, then the name of the filter field and then getting an array of standard published state filter options and passing its values to select options of the select field in terms of values and text and then we are getting the current state of this field through get method.

After that, from line 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 assignment process is field, we are rendering the category filter in the same way, as we have rendered the state filter select field. Then on line 60, we are rendering the sidebar through render() method of JHtmlSidebar class.

 Next, from line 66 to 76, we are creating a two dimensional array in the function getSortFields() which is holding the name of table columns and the language strings which would be shown in a dropdown select box, on the basis of which sorting function could be performed on the listing table. We will call this function in our default.php view template file and will 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 $this specifier which will return an array of field names,on the basis of which sorting feature could be performed. After that, there is a javascript code, related to sorting and search. From line 25 to 35, there is the code for sorting the table so, a field value and direction of sort is being provided in this code. Going deep in javascript is beyond the scope of this tutorial, but you can copy and use this code at joomla backend view, where ever you want to implement column sorting. Next, from line 38 to 43, there is the code related to 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 having the search term to impact 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 breeds list ordering, either it would be ascending or descending and then from line 109 to 115, we are creating a select list of fields on the basis of which sorting process could occur. We are getting these values from the same array of sort fields, that we have created in view.html.php file here, in this step.

 

 

Download Code

You have no rights to post comments

Enjoy best web development services at an affordable price. Looking forward to build a good relationship and serve you better...

Copyright © 2017. All rights reserved.