Actions

J3.x

Difference between revisions of "Creating a search plugin"

From Joomla! Documentation

(Use $this->db)
(Marked this version for translation)
 
(4 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{version/tutor|3.x}}
+
<noinclude><languages /></noinclude>
==Description==
+
This document is about how to create a Search Plugin. You can use a Search Plugin to search through the database of your Joomla! site. To create a plugin, you will at least need two files; an XML file and a PHP file. For internationalization it is good to create an INI file as well.
+
  
==XML file==
+
<noinclude>{{Joomla version|version=3.x|comment=<translate><!--T:1-->
 +
series</translate>}}</noinclude>
 +
{{-}}
 +
<translate>
 +
==Description== <!--T:2-->
 +
This document is about how to create a Search Plugin. You can use a Search Plugin to search through the database of your Joomla! site. To create a plugin, you will at least need two files; an XML file and a PHP file. For internationalization it is good to create an INI file as well.
 +
</translate>
 +
 
 +
<translate>
 +
==XML file== <!--T:3-->
 
The XML file is named the same as the PHP file, and is one of the two required files.
 
The XML file is named the same as the PHP file, and is one of the two required files.
 
Always start off with the XML tag and define that it is written in a UTF-8 format.
 
Always start off with the XML tag and define that it is written in a UTF-8 format.
 +
</translate>
  
 
<source lang="xml"><?xml version="1.0" encoding="utf-8"?></source>
 
<source lang="xml"><?xml version="1.0" encoding="utf-8"?></source>
  
To define that the plugin has to be a search plugin, add this line
+
<translate><!--T:4-->
 +
To define that the plugin has to be a search plugin, add this line</translate>
  
 
<source lang="xml">
 
<source lang="xml">
Line 15: Line 24:
 
</source>
 
</source>
  
 +
<translate>
 +
<!--T:5-->
 
The type will define it is a plugin, the group defines the Plugin is in the group of search plugins.
 
The type will define it is a plugin, the group defines the Plugin is in the group of search plugins.
  
 +
<!--T:6-->
 
After that, add some information about yourself and the plugin:
 
After that, add some information about yourself and the plugin:
 +
</translate>
 +
 
<source lang="xml">
 
<source lang="xml">
 
<name>Name of your search plugin</name>
 
<name>Name of your search plugin</name>
Line 29: Line 43:
 
<description>Description of the plugin; shown during installation and when editing  
 
<description>Description of the plugin; shown during installation and when editing  
 
the plugin in the Plugin Manager</description></source>
 
the plugin in the Plugin Manager</description></source>
 +
 +
<translate>
 +
<!--T:7-->
 
And now, include your PHP file to the Search Plugin. The name of this file should be the same as the name of this XML file. Put this name also behind the plugin="" part.  
 
And now, include your PHP file to the Search Plugin. The name of this file should be the same as the name of this XML file. Put this name also behind the plugin="" part.  
  
You could also add more files for your plugin, for example, an image. Just add another row between <files> and </file>, and then place the file between <filename> tags.
+
<!--T:8-->
 +
You could also add more files for your plugin, for example, an image. Just add another row between <files> and </files>, and then place the file between <filename> tags.
 +
</translate>
 +
 
 
<source lang="xml">
 
<source lang="xml">
 
<files>
 
<files>
Line 37: Line 57:
 
</files></source>
 
</files></source>
  
 +
<translate>
 +
<!--T:9-->
 
For the internationalization, we will use language files. This is not required, but people from other countries will love it they can easily translate your plugin to their own language.
 
For the internationalization, we will use language files. This is not required, but people from other countries will love it they can easily translate your plugin to their own language.
 
The language tags can be found here: [http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes] (use the ISO 639-1 column) and here: [http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements]
 
The language tags can be found here: [http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes] (use the ISO 639-1 column) and here: [http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements]
 +
</translate>
 +
 
<source lang="xml">
 
<source lang="xml">
 
<languages>
 
<languages>
 
   <language tag="en-GB">language/en-GB/en-GB.plg_search_nameofplugin.ini</language>
 
   <language tag="en-GB">language/en-GB/en-GB.plg_search_nameofplugin.ini</language>
 
</languages></source>
 
</languages></source>
Optionally, you could add some parameters to the plugin. These will look like this
+
 
 +
<translate><!--T:10-->
 +
Optionally, you could add some parameters to the plugin. These will look like this:</translate>
  
 
<source lang="xml">
 
<source lang="xml">
Line 71: Line 97:
 
</source>
 
</source>
  
Do not forget to end your XML file with the following tag
+
<translate><!--T:11-->
 +
Do not forget to end your XML file with the following tag:</translate>
  
 
<source lang="xml"></extension></source>
 
<source lang="xml"></extension></source>
  
==PHP file==
+
<translate>
The PHP file of your plugin is the most important file of the plugin. This is an example PHP file of a search plugin. The comments are included.  
+
==PHP file== <!--T:12-->
 +
The PHP file of your plugin is the most important file of the plugin. This is an example PHP file of a search plugin. The comments are included.
 +
</translate>
  
 
<source lang="PHP"><?php
 
<source lang="PHP"><?php
Line 96: Line 125:
  
 
/**
 
/**
  * Constructor
+
  * All functions need to get wrapped in a class
 
  *
 
  *
  * @access      protected
+
  * The class name should start with 'PlgSearch' followed by the name of the plugin. Joomla calls the class based on the name of the plugin, so it is very important that they match
* @param      object  $subject The object to observe
+
* @param      array  $config  An array that holds the plugin configuration
+
* @since      1.6
+
 
  */
 
  */
public function __construct(& $subject, $config)
+
class PlgSearchNameofplugin extends JPlugin
 
{
 
{
parent::__construct($subject, $config);
+
/**
$this->loadLanguage();
+
* Constructor
}
+
*
 +
* @access      protected
 +
* @param      object  $subject The object to observe
 +
* @param      array  $config  An array that holds the plugin configuration
 +
* @since      1.6
 +
*/
 +
public function __construct(& $subject, $config)
 +
{
 +
parent::__construct($subject, $config);
 +
$this->loadLanguage();
 +
}
  
// Define a function to return an array of search areas. Replace 'nameofplugin' with the name of your plugin.
+
// Define a function to return an array of search areas. Replace 'nameofplugin' with the name of your plugin.
// Note the value of the array key is normally a language string
+
// Note the value of the array key is normally a language string
function onContentSearchAreas()
+
function onContentSearchAreas()
{
+
{
static $areas = array(
+
static $areas = array(
'nameofplugin' => 'Nameofplugin'
+
'nameofplugin' => 'Nameofplugin'
);
+
);
return $areas;
+
return $areas;
}
+
}
  
// The real function has to be created. The database connection should be made.  
+
// The real function has to be created. The database connection should be made.  
// The function will be closed with an } at the end of the file.
+
// The function will be closed with an } at the end of the file.
/**
+
/**
* The sql must return the following fields that are used in a common display
+
* The sql must return the following fields that are used in a common display
* routine: href, title, section, created, text, browsernav
+
* routine: href, title, section, created, text, browsernav
*
+
*
* @param string Target search string
+
* @param string Target search string
* @param string mathcing option, exact|any|all
+
* @param string mathcing option, exact|any|all
* @param string ordering option, newest|oldest|popular|alpha|category
+
* @param string ordering option, newest|oldest|popular|alpha|category
* @param mixed An array if the search it to be restricted to areas, null if search all
+
* @param mixed An array if the search it to be restricted to areas, null if search all
*/
+
*/
function onContentSearch( $text, $phrase='', $ordering='', $areas=null )
+
function onContentSearch( $text, $phrase='', $ordering='', $areas=null )
{
+
{
$user = JFactory::getUser();  
+
$user = JFactory::getUser();  
$groups = implode(',', $user->getAuthorisedViewLevels());
+
$groups = implode(',', $user->getAuthorisedViewLevels());
  
// If the array is not correct, return it:
+
// If the array is not correct, return it:
if (is_array( $areas )) {
+
if (is_array( $areas )) {
if (!array_intersect( $areas, array_keys( $this->onContentSearchAreas() ) )) {
+
if (!array_intersect( $areas, array_keys( $this->onContentSearchAreas() ) )) {
return array();
+
return array();
 +
}
 
}
 
}
}
 
  
// Now retrieve the plugin parameters like this:
+
// Now retrieve the plugin parameters like this:
$text = $this->params->get('nameofparameter', defaultsetting );
+
$nameofparameter = $this->params->get('nameofparameter', defaultsetting );
  
// Use the PHP function trim to delete spaces in front of or at the back of the searching terms
+
// Use the PHP function trim to delete spaces in front of or at the back of the searching terms
$text = trim( $text );
+
$text = trim( $text );
  
// Return Array when nothing was filled in.
+
// Return Array when nothing was filled in.
if ($text == '') {
+
if ($text == '') {
return array();
+
return array();
}
+
}
  
// After this, you have to add the database part. This will be the most difficult part, because this changes per situation.
+
// After this, you have to add the database part. This will be the most difficult part, because this changes per situation.
// In the coding examples later on you will find some of the examples used by Joomla! 3.1 core Search Plugins.
+
// In the coding examples later on you will find some of the examples used by Joomla! 3.1 core Search Plugins.
//It will look something like this.
+
//It will look something like this.
$wheres = array();
+
$wheres = array();
switch ($phrase) {
+
switch ($phrase) {
  
// Search exact
+
// Search exact
case 'exact':
+
case 'exact':
$text = $this->db->Quote( '%'.$this->db->escape( $text, true ).'%', false );
+
$text = $this->db->Quote( '%'.$this->db->escape( $text, true ).'%', false );
$wheres2 = array();
+
$wheres2 = array();
$wheres2[] = 'LOWER(a.name) LIKE '.$text;
+
$wheres2[] = 'LOWER(a.name) LIKE '.$text;
$where = '(' . implode( ') OR (', $wheres2 ) . ')';
+
$where = '(' . implode( ') OR (', $wheres2 ) . ')';
break;
+
break;
  
// Search all or any
+
// Search all or any
case 'all':
+
case 'all':
case 'any':
+
case 'any':
  
// Set default
+
// Set default
default:
+
default:
$words = explode( ' ', $text );
+
$words = explode( ' ', $text );
$wheres = array();
+
$wheres = array();
foreach ($words as $word)
+
foreach ($words as $word)
{
+
{
$word = $this->db->Quote( '%'.$this->db->escape( $word, true ).'%', false );
+
$word = $this->db->Quote( '%'.$this->db->escape( $word, true ).'%', false );
$wheres2 = array();
+
$wheres2 = array();
$wheres2[] = 'LOWER(a.name) LIKE '.$word;
+
$wheres2[] = 'LOWER(a.name) LIKE '.$word;
$wheres[] = implode( ' OR ', $wheres2 );
+
$wheres[] = implode( ' OR ', $wheres2 );
}
+
}
$where = '(' . implode( ($phrase == 'all' ? ') AND (' : ') OR ('), $wheres ) . ')';
+
$where = '(' . implode( ($phrase == 'all' ? ') AND (' : ') OR ('), $wheres ) . ')';
break;
+
break;
}
+
}
  
// Ordering of the results
+
// Ordering of the results
switch ( $ordering ) {
+
switch ( $ordering ) {
  
//Alphabetic, ascending
+
//Alphabetic, ascending
case 'alpha':
+
case 'alpha':
$order = 'a.name ASC';
+
$order = 'a.name ASC';
break;
+
break;
  
// Oldest first
+
// Oldest first
case 'oldest':
+
case 'oldest':
  
// Popular first
+
// Popular first
case 'popular':
+
case 'popular':
  
// Newest first
+
// Newest first
case 'newest':
+
case 'newest':
  
// Default setting: alphabetic, ascending
+
// Default setting: alphabetic, ascending
default:
+
default:
$order = 'a.name ASC';
+
$order = 'a.name ASC';
}
+
}
  
// Replace nameofplugin
+
// Replace nameofplugin
$section = JText::_( 'Nameofplugin' );
+
$section = JText::_( 'Nameofplugin' );
  
// The database query; differs per situation! It will look something like this (example from newsfeed search plugin):
+
// The database query; differs per situation! It will look something like this (example from newsfeed search plugin):
$query = $this->db->getQuery(true);
+
$query = $this->db->getQuery(true);
$query->select('a.name AS title, "" AS created, a.link AS text, ' . $case_when."," . $case_when1);
+
$query->select('a.name AS title, "" AS created, a.link AS text, ' . $case_when."," . $case_when1);
$query->select($query->concatenate(array($this->db->Quote($section), 'c.title'), " / ").' AS section');
+
$query->select($query->concatenate(array($this->db->Quote($section), 'c.title'), " / ").' AS section');
$query->select('"1" AS browsernav');
+
$query->select('"1" AS browsernav');
$query->from('#__nameofcomponent AS a');
+
$query->from('#__nameofcomponent AS a');
$query->innerJoin('#__categories as c ON c.id = a.catid');
+
$query->innerJoin('#__categories as c ON c.id = a.catid');
$query->where('('. $where .')' . 'AND a.published IN ('.implode(',', $state).') AND c.published = 1 AND c.access IN ('. $groups .')');
+
$query->where('('. $where .')' . 'AND a.published IN ('.implode(',', $state).') AND c.published = 1 AND c.access IN ('. $groups .')');
$query->order($order);
+
$query->order($order);
  
// Set query
+
// Set query
$this->db->setQuery( $query, 0, $limit );
+
$this->db->setQuery( $query, 0, $limit );
$rows = $this->db->loadObjectList();
+
$rows = $this->db->loadObjectList();
  
// The 'output' of the displayed link. Again a demonstration from the newsfeed search plugin
+
// The 'output' of the displayed link. Again a demonstration from the newsfeed search plugin
foreach($rows as $key => $row) {
+
foreach($rows as $key => $row) {
$rows[$key]->href = 'index.php?option=com_newsfeeds&view=newsfeed&catid='.$row->catslug.'&id='.$row->slug;
+
$rows[$key]->href = 'index.php?option=com_newsfeeds&view=newsfeed&catid='.$row->catslug.'&id='.$row->slug;
}
+
}
  
//Return the search results in an array
+
//Return the search results in an array
return $rows;
+
return $rows;
 +
}
 
}</source>
 
}</source>
  
 +
<translate>
 +
<!--T:13-->
 
There are four variables that get passed in. They are evident by their names and use in the above code.
 
There are four variables that get passed in. They are evident by their names and use in the above code.
 
What's not obvious is what the function should return: an array of objects that the search tool uses to display the results. The results could alternatively have been assembled like this.
 
What's not obvious is what the function should return: an array of objects that the search tool uses to display the results. The results could alternatively have been assembled like this.
 +
</translate>
 +
 
<source lang="PHP">
 
<source lang="PHP">
 
$rows[] = (object) array(
 
$rows[] = (object) array(
Line 247: Line 288:
 
</source>
 
</source>
  
==INI file(s)==
+
<translate>
 +
==INI file(s)== <!--T:14-->
 
For internationalization it is good to use the INI files. You can add everything to the language file that outputs text to the user, in this order:
 
For internationalization it is good to use the INI files. You can add everything to the language file that outputs text to the user, in this order:
 
*XML description tag
 
*XML description tag
Line 253: Line 295:
 
*JText::_( 'string' ) used by the plugin
 
*JText::_( 'string' ) used by the plugin
  
 +
<!--T:15-->
 
Start your INI file with something like this:
 
Start your INI file with something like this:
 +
</translate>
 +
 
<source lang="INI"># $Id: en-GB.plg_search_nameofplugin.ini
 
<source lang="INI"># $Id: en-GB.plg_search_nameofplugin.ini
 
# Joomla! Project
 
# Joomla! Project
Line 259: Line 304:
 
# License http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL, see LICENSE.php
 
# License http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL, see LICENSE.php
 
# Note : All ini files need to be saved as UTF-8 - No BOM</source>
 
# Note : All ini files need to be saved as UTF-8 - No BOM</source>
 +
 +
<translate>
 +
<!--T:16-->
 
Of course, you could also add other information, like the author.  
 
Of course, you could also add other information, like the author.  
  
 +
<!--T:17-->
 
For example, this parameter:
 
For example, this parameter:
 +
</translate>
 +
 
<source lang="XML"><field name="search_limit" type="text"
 
<source lang="XML"><field name="search_limit" type="text"
 
   default="50"
 
   default="50"
Line 268: Line 319:
 
   size="5"
 
   size="5"
 
/></source>
 
/></source>
Will cause the following output in the INI file:
+
 
 +
<translate><!--T:18-->
 +
Will cause the following output in the INI file:</translate>
 +
 
 
<source lang="INI">
 
<source lang="INI">
 
JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC=Search Limit
 
JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC=Search Limit
 
JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL=Number of Search items to return</source>
 
JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL=Number of Search items to return</source>
 +
 +
<translate>
 +
<!--T:19-->
 
The file looks repetitive, but will be very useful for translators.
 
The file looks repetitive, but will be very useful for translators.
  
When you want to make your search plugin available in more languages, first add them to the <languages> tag in the XML file. Then create the same INI file, and change the part after the =, for example the Dutch version would be:
+
<!--T:20-->
 +
When you want to make your search plugin available in more languages, first add them to the <tt>languages</tt> tag in the XML file. Then create the same INI file, and change the part after the =, for example the Dutch version would be:
 +
</translate>
 +
 
 
<source lang="INI">
 
<source lang="INI">
 
JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC=Zoek limiet
 
JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC=Zoek limiet
 
JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL=Aantal weer te geven zoekresultaten</source>
 
JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL=Aantal weer te geven zoekresultaten</source>
  
==Quick tips==
+
<translate>
 +
==Quick tips== <!--T:21-->
 
*In the PHP file, people often forget to place a semicolon (;) at the end of a line. This causes errors. Check this before you test your plugin.
 
*In the PHP file, people often forget to place a semicolon (;) at the end of a line. This causes errors. Check this before you test your plugin.
 
*Make sure the parameters in the XML file are closed correctly. When you add an option, for example, you need to close it with </param>.
 
*Make sure the parameters in the XML file are closed correctly. When you add an option, for example, you need to close it with </param>.
 
*It is easy to test on a localhost when you are editing your plugin.
 
*It is easy to test on a localhost when you are editing your plugin.
 
*When making a zip-file,do not forget to make the directories for the language files. A typical zip will contain the following:
 
*When making a zip-file,do not forget to make the directories for the language files. A typical zip will contain the following:
 +
</translate>
 +
 
**nameofplugin.xml
 
**nameofplugin.xml
 
**nameofplugin.php
 
**nameofplugin.php
 
**language\en-GB\en-GB.plg_search_nameofplugin.ini
 
**language\en-GB\en-GB.plg_search_nameofplugin.ini
  
 +
<noinclude>
 +
<translate>
 +
<!--T:22-->
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]
 
[[Category:Plugin Development]]
 
[[Category:Plugin Development]]
 +
</translate>
 +
</noinclude>

Latest revision as of 09:13, 5 April 2015

Other languages:
English • ‎français
Joomla! 
3.x
series

Description

This document is about how to create a Search Plugin. You can use a Search Plugin to search through the database of your Joomla! site. To create a plugin, you will at least need two files; an XML file and a PHP file. For internationalization it is good to create an INI file as well.

XML file

The XML file is named the same as the PHP file, and is one of the two required files. Always start off with the XML tag and define that it is written in a UTF-8 format.

<?xml version="1.0" encoding="utf-8"?>

To define that the plugin has to be a search plugin, add this line

<extension version="3.1" type="plugin" group="search">

The type will define it is a plugin, the group defines the Plugin is in the group of search plugins.

After that, add some information about yourself and the plugin:

<name>Name of your search plugin</name>
<creationDate>Creation date</creationDate>
<author>Your name</author>
<authorEmail>Your e-mail address</authorEmail>
<authorUrl>Your website</authorUrl>
<copyright>Copyright information</copyright>
<license>License, for example GNU/GPL</license>
<version>Version of the plugin</version>
<description>Description of the plugin; shown during installation and when editing 
the plugin in the Plugin Manager</description>

And now, include your PHP file to the Search Plugin. The name of this file should be the same as the name of this XML file. Put this name also behind the plugin="" part.

You could also add more files for your plugin, for example, an image. Just add another row between <files> and </files>, and then place the file between <filename> tags.

<files>
   <filename plugin="nameofplugin">nameofplugin.php</filename>
</files>

For the internationalization, we will use language files. This is not required, but people from other countries will love it they can easily translate your plugin to their own language. The language tags can be found here: [1] (use the ISO 639-1 column) and here: [2]

<languages>
   <language tag="en-GB">language/en-GB/en-GB.plg_search_nameofplugin.ini</language>
</languages>

Optionally, you could add some parameters to the plugin. These will look like this:

	<config>
		<fields name="params">
 
			<fieldset name="basic">
				<field name="search_limit" type="text"
					default="50"
					description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
					label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
					size="5"
				/>
 
				<field name="search_content" type="radio"
					default="0"
					description="JFIELD_PLG_SEARCH_ALL_DESC"
					label="JFIELD_PLG_SEARCH_ALL_LABEL"
				>
					<option value="0">JOFF</option>
					<option value="1">JON</option>
				</field>
 
			</fieldset>
		</fields>
	</config>

Do not forget to end your XML file with the following tag:

</extension>

PHP file

The PHP file of your plugin is the most important file of the plugin. This is an example PHP file of a search plugin. The comments are included.

<?php
//First start with information about the Plugin and yourself. For example:
/**
 * @package     Joomla.Plugin
 * @subpackage  Search.nameofplugin
 *
 * @copyright   Copyright
 * @license     License, for example GNU/GPL
 */
 
//To prevent accessing the document directly, enter this code:
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
 
// Require the component's router file (Replace 'nameofcomponent' with the component your providing the search for
require_once JPATH_SITE .  '/components/nameofcomponent/helpers/route.php';
 
/**
 * All functions need to get wrapped in a class
 *
 * The class name should start with 'PlgSearch' followed by the name of the plugin. Joomla calls the class based on the name of the plugin, so it is very important that they match
 */
class PlgSearchNameofplugin extends JPlugin
{
	/**
	 * Constructor
	 *
	 * @access      protected
	 * @param       object  $subject The object to observe
	 * @param       array   $config  An array that holds the plugin configuration
	 * @since       1.6
	 */
	public function __construct(& $subject, $config)
	{
		parent::__construct($subject, $config);
		$this->loadLanguage();
	}
 
	// Define a function to return an array of search areas. Replace 'nameofplugin' with the name of your plugin.
	// Note the value of the array key is normally a language string
	function onContentSearchAreas()
	{
		static $areas = array(
			'nameofplugin' => 'Nameofplugin'
		);
		return $areas;
	}
 
	// The real function has to be created. The database connection should be made. 
	// The function will be closed with an } at the end of the file.
	/**
	 * The sql must return the following fields that are used in a common display
	 * routine: href, title, section, created, text, browsernav
	 *
	 * @param string Target search string
	 * @param string mathcing option, exact|any|all
	 * @param string ordering option, newest|oldest|popular|alpha|category
	 * @param mixed An array if the search it to be restricted to areas, null if search all
	 */
	function onContentSearch( $text, $phrase='', $ordering='', $areas=null )
	{
		$user	= JFactory::getUser(); 
		$groups	= implode(',', $user->getAuthorisedViewLevels());
 
		// If the array is not correct, return it:
		if (is_array( $areas )) {
			if (!array_intersect( $areas, array_keys( $this->onContentSearchAreas() ) )) {
				return array();
			}
		}
 
		// Now retrieve the plugin parameters like this:
		$nameofparameter = $this->params->get('nameofparameter', defaultsetting );
 
		// Use the PHP function trim to delete spaces in front of or at the back of the searching terms
		$text = trim( $text );
 
		// Return Array when nothing was filled in.
		if ($text == '') {
			return array();
		}
 
		// After this, you have to add the database part. This will be the most difficult part, because this changes per situation.
		// In the coding examples later on you will find some of the examples used by Joomla! 3.1 core Search Plugins.
		//It will look something like this.
		$wheres = array();
		switch ($phrase) {
 
			// Search exact
			case 'exact':
				$text		= $this->db->Quote( '%'.$this->db->escape( $text, true ).'%', false );
				$wheres2 	= array();
				$wheres2[] 	= 'LOWER(a.name) LIKE '.$text;
				$where 		= '(' . implode( ') OR (', $wheres2 ) . ')';
				break;
 
			// Search all or any
			case 'all':
			case 'any':
 
			// Set default
			default:
				$words 	= explode( ' ', $text );
				$wheres = array();
				foreach ($words as $word)
				{
					$word		= $this->db->Quote( '%'.$this->db->escape( $word, true ).'%', false );
					$wheres2 	= array();
					$wheres2[] 	= 'LOWER(a.name) LIKE '.$word;
					$wheres[] 	= implode( ' OR ', $wheres2 );
				}
				$where = '(' . implode( ($phrase == 'all' ? ') AND (' : ') OR ('), $wheres ) . ')';
				break;
		}
 
		// Ordering of the results
		switch ( $ordering ) {
 
			//Alphabetic, ascending
			case 'alpha':
				$order = 'a.name ASC';
				break;
 
			// Oldest first
			case 'oldest':
 
			// Popular first
			case 'popular':
 
			// Newest first
			case 'newest':
 
			// Default setting: alphabetic, ascending
			default:
				$order = 'a.name ASC';
		}
 
		// Replace nameofplugin
		$section = JText::_( 'Nameofplugin' );
 
		// The database query; differs per situation! It will look something like this (example from newsfeed search plugin):
		$query	= $this->db->getQuery(true);
		$query->select('a.name AS title, "" AS created, a.link AS text, ' . $case_when."," . $case_when1);
				$query->select($query->concatenate(array($this->db->Quote($section), 'c.title'), " / ").' AS section');
				$query->select('"1" AS browsernav');
				$query->from('#__nameofcomponent AS a');
				$query->innerJoin('#__categories as c ON c.id = a.catid');
				$query->where('('. $where .')' . 'AND a.published IN ('.implode(',', $state).') AND c.published = 1 AND c.access IN ('. $groups .')');
				$query->order($order);
 
		// Set query
		$this->db->setQuery( $query, 0, $limit );
		$rows = $this->db->loadObjectList();
 
		// The 'output' of the displayed link. Again a demonstration from the newsfeed search plugin
		foreach($rows as $key => $row) {
			$rows[$key]->href = 'index.php?option=com_newsfeeds&view=newsfeed&catid='.$row->catslug.'&id='.$row->slug;
		}
 
	//Return the search results in an array
	return $rows;
	}
}

There are four variables that get passed in. They are evident by their names and use in the above code. What's not obvious is what the function should return: an array of objects that the search tool uses to display the results. The results could alternatively have been assembled like this.

$rows[] = (object) array(
			'href'        => 'index.php?option=com_newsfeeds&view=newsfeed&catid='.$row->catslug.'&id='.$row->slug,
			'title'       => $row['name'],
			'section'     => $nameofcomponent,
			'created'     => $row['date'],
			'text'        => $row['name'],
			'browsernav'  => '1'
		);

INI file(s)

For internationalization it is good to use the INI files. You can add everything to the language file that outputs text to the user, in this order:

  • XML description tag
  • XML label and description attributes from parameters
  • JText::_( 'string' ) used by the plugin

Start your INI file with something like this:

# $Id: en-GB.plg_search_nameofplugin.ini
# Joomla! Project
# Copyright (C) 2005 - 2007 Open Source Matters. All rights reserved.
# License http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL, see LICENSE.php
# Note : All ini files need to be saved as UTF-8 - No BOM

Of course, you could also add other information, like the author.

For example, this parameter:

<field name="search_limit" type="text"
  default="50"
  description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
  label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
  size="5"
/>

Will cause the following output in the INI file:

JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC=Search Limit
JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL=Number of Search items to return

The file looks repetitive, but will be very useful for translators.

When you want to make your search plugin available in more languages, first add them to the languages tag in the XML file. Then create the same INI file, and change the part after the =, for example the Dutch version would be:

JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC=Zoek limiet
JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL=Aantal weer te geven zoekresultaten

Quick tips

  • In the PHP file, people often forget to place a semicolon (;) at the end of a line. This causes errors. Check this before you test your plugin.
  • Make sure the parameters in the XML file are closed correctly. When you add an option, for example, you need to close it with </param>.
  • It is easy to test on a localhost when you are editing your plugin.
  • When making a zip-file,do not forget to make the directories for the language files. A typical zip will contain the following:
    • nameofplugin.xml
    • nameofplugin.php
    • language\en-GB\en-GB.plg_search_nameofplugin.ini