J3.x

建立一個搜尋外掛

From Joomla! Documentation

This page is a translated version of the page J3.x:Creating a search plugin and the translation is 96% complete.
Other languages:
English • ‎Nederlands • ‎español • ‎français • ‎中文(台灣)‎
Joomla! 
3.x
系列

描述

這個文件是關於如何建立一個搜尋外掛,您可以使用搜尋外掛來搜尋您 Joomla! 網站的資料庫。要建立這個外掛,您至少要新增兩個檔案:一個 XML 檔案以及一個 PHP 檔案。若是要支援其他語言,那還需要一個 INI 檔案。

XML 檔案

XML 檔案 的命名需要與PHP 檔案相同。另外XML是兩個必需的檔案之一。 請使用 XML標籤並定義為 UTF-8 格式。

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

要定義這個外掛為一個搜尋外掛,加入這一行:

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

type 會定義它是一個外掛,這群組定義了這個外掛處於搜尋外掛群組當中。

在這之後,新增一些關於您自己以及外掛的相關資訊:

<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>

現在,把PHP檔案加到搜尋外掛,這個檔案的名稱必需要相同於XML檔案名稱。將這個名稱放到plugin=""部分。

您也可以在外掛中加入更多的檔案,例如圖檔。請在<files> 以及 </files>之間多加一行,然後把檔案名稱放在<filename> 標籤之間。

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

為了支援多國語言,我們會使用語言檔案。這並不是必要的,但是可以讓其他國家的用戶愛上您的外掛,此外,他們也會容易將內容翻譯成它們的語言。 請在這裡找到語言碼: [1] (請用 ISO 639-1 欄) 在以下找到國家碼 : [2]

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

接著,雖非必要,您可以新增一些屬性到外掛,這會看起來像是:

	<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>

不要忘記使用以下的標籤來結束XML檔案:

</extension>

PHP 檔案

您的外掛的 PHP 檔案是整個外掛最重要的部份。這是一個搜尋外掛 PHP 範例檔案。以下還包含一些說明:

<?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 檔案(s)

想要讓擴充套件支援多種語言,使用 INI 檔案就對了。您可以加入任何內容來讓它們出現在頁面上,順序是這樣:

  • XML 裡頭是描述標籤 (tag)
  • XML 標籤(label) and description attributes from parameters
  • JText::_( 'string' ) 用於外掛之內

在 INI 檔案開頭會有這樣的內容:

# $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

當然,您可以加入其他資訊,例如作者。

例如,這個參數:

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

將會在INI檔案中輸出以下的內容:

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

這個檔案看起來可能有點累贅,但是對於翻譯來說是很有用的。

當您想要讓您的外掛能夠支援更多語言,第一件事事要在Xml檔案中加入languages標籤。然後建立相同的INI檔案,並且修改之後的部份。用德文版本來作例子:

JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC=Zoek limiet
JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL=Aantal weer te geven zoekresultaten

小撇步

  • 在 PHP 檔案中,人們常常忘記在行尾加上分號 (;),這會造成錯誤,請在測試外掛之前檢查一下。
  • 請確定XML檔案的參數都有使用合適的關閉標籤。例如您加了一個選項,您需要使用關閉標籤</param>
  • 編輯開發外掛時,在自己的本機上測試會比較方便
  • 包裝 zip 檔案時,不要忘記生成語言路徑,一個典型的ZIP會包含以下:
    • nameofplugin.xml
    • nameofplugin.php
    • language\en-GB\en-GB.plg_search_nameofplugin.ini