Blog
轻松一下?

AppleStar

Joomla

如何去掉joomla generator 标签

在模版的 index.php 文件中 将以下代码
$this->setMetaData('generator','You-Text');
添加在defined ( '_JEXEC' ) or die ( 'Restricted access' ); 之后
generator是JDocument的一个属性,它的初始值是“Joomla! - Open Source Content Management”,你当然可以在JDocument类的定义文件中修改这个值,但更优雅的做法是在你的模版中覆盖初始值。

Joomla扩展插件开发文档(plugin)

概述

************************************************************************

Plugins(继承于JPlugin的一系列类)依附于全局事件分派系统的观察者类

无论是系统核心,还是第三方扩展都能触发一个或多个Plugins来执行一些功能

插件系统的实现是一个观察者模式。分为两部分,一部分是观察者(JPlugin),另一部分是被观察者(JEventDispatcher)

Plugins命名规范plg<type><name>

类型

************************************************************************

插件的目录为<root>/plugins

系统核心中提供了以下8种类型的插件

Authentication 插件允许你对不同的来源进行验证。当你登陆的时候可以通过Joomla的用户数据库进行验证。然而有很多其它的方式,也是可以的,例如:Google的 OpenID(开放式用户中心身份标识),LDAP(轻量目录访问协议)和很多其它的方式。无论哪种来源,有其开放API,你都可以写一个验证插件,以确认登陆的身份。例如你可以写一个Twitter账户的验证插件,因为他们提供了开放API。

Content 插件用于在显示文章内容时改变或增加一些内容。例如content插件可以隐藏文章种的email地址,或者用自己的方式格式化URL地址。 content插件也可以在文章种搜索特定的标记,然后将他们替换为其它的文本或者HTML。例如在名为Load Module插件中,将会启动所有在banner1位置的模块,并且把标记,替换成他们的输出内容。

Editor 插件允许你增加新的内容编辑器(常用的有WYSIYWG)

Editor-XTD(扩展)插件允许你editor上增加某些功能按钮。例如现有的默认editor下的几个按钮:Image(增加图片),Pagebreak(插入分页符)和Read more(阅读全文)按钮。

Search 插件允许你在不同的组件,不同的文章中进行搜索。比如文章系统的search插件:Contacts 、Weblinks

System 插件允许你在Joomla站点的各个地方使用PHP代码执行各种动作。

User 插件允许你在不同的时候执行针对于用户的动作。包括登录时、登出时,还有存储用户数据的时候。用户插件中最典型的在不同web应用之间进行桥连接(bridge)。例如建立一个Joomla与Phpbb之间的桥连接。

XML-RPC 插件允许你为网站提供一个XML-RPC服务。当你的网站为其它应用程序(或许是个桌面应用程序)提供网络服务(web services)的时候,它为你提供了远程交互的能力。网络服务真的是一个高深的话题,这里没办法讲的太详细。

每种类型的插件位于<root>/plugins目录下的子目录中

可以在<root>/plugins目录下创建子目录来添加自定义的插件类型

文件

************************************************************************

一个基本的plugin包括两个文件,一个以plugin名称命名的php文件和一个同名的xml配置文件

test.php

示例:

<?php
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.plugin.plugin' );

/**
 * Example system plugin
 */
class plgSystemTest extends JPlugin
{
 /**
  * Constructor
  *
  * @param object $subject The object to observe
  * @param  array   $config  An array that holds the plugin configuration
  * @since 1.0
  */
 function plgSystemTest( &$subject, $config )
 {
	parent::__construct( $subject, $config );
 }

 /**
  * onAfterInitialise 系统事件表示在系统初始化之后触发此事件
  */
 function onAfterInitialise()
 {
	// 执行操作
 }
}

系统事件包括

************************************************************************

Authentication
	onAuthenticate
	Content
	onPrepareContent
	onAfterDisplayTitle
	onBeforeDisplayContent
	onBeforeContentSave (new in 1.5.4)
	onAfterContentSave (new in 1.5.4)
Editors
	onInit
	onGetContent
	onSetContent
	onSave
	onDisplay
	onGetInsertMethod
Editors XTD (Extended)
	onDisplay
	Seach
	onSearch
	onSearchAreas
System
	onAfterInitialise
	onAfterRoute
	onAfterDispatch
	onAfterRender
User
	onLoginUser
	onLoginFailure
	onLogoutUser
	onLogoutFailure
	onBeforeStoreUser
	onAfterStoreUser
	onBeforeDeleteUser
	onAfterDeleteUser
XML-RPC
	onGetWebServices

配置文件

************************************************************************

<?xml version="1.0" encoding="utf-8"?>
<install version="1.5.2" type="plugin" group="system" method="upgrade"><!--group:插件的类型-->
 <name>System - Test</name>
 <author>Author</author>
 <creationDate>Month 2008</creationDate>
 <copyright>Copyright (C) 2008 Holder. All rights reserved.</copyright>
 <authorEmail>email</authorEmail>
 <authorUrl>url</authorUrl>
 <version>1.0.1</version>
 <description>A test system plugin</description>
 <files>
  <filename plugin="example">test.php</filename>
 </files>
 <params>
    <param name="example"
    type="text"
    default=""
    label="Example"
    description="An example text parameter" />
 </params>
</install>

Joomla扩展组件开发文档(component)

概述

************************************************************************

扩展组件是系统扩展类型中定制化程度最高也是最复杂的一类扩展

标准的扩展组件包括了MVC的全部内容

目录结构

************************************************************************

扩展组件目录的命名约定是com_<Name>

一个基本的单控制器扩展组件包含以下内容

com_<Name>/hello.php - 入口文件
com_<Name>/controller.php - 控制器
com_<Name>/views/hello/view.html.php - 视图
com_<Name>/views/hello/tmpl/default.php - 模板
com_<Name>/hello.xml - 安装配置文件

一个复杂的多控制器扩展组件包含以下内容

com_<Name>/hello.php - 入口文件
com_<Name>/controller.php - 控制器
com_<Name>/controllers/ - 自定义控制器
com_<Name>/controllers/controllerName1.php
com_<Name>/controllers/controllerName2.php
com_<Name>/controllers/...
com_<Name>/models/ - 模型
com_<Name>/models/modelName1.php
com_<Name>/models/modelName2.php
com_<Name>/models/...
com_<Name>/tables/ - 实体对象
com_<Name>/tables/tableName1.php
com_<Name>/tables/tableName2.php
com_<Name>/tables/...
com_<Name>/views/hello/view.html.php - 视图
com_<Name>/views/hello/tmpl/default.php - 模板
com_<Name>/hello.xml - 安装配置文件
...

程序入口

************************************************************************

Joomla是典型的单一入口系统,所有请求都是通过site/index.php或site/administrator/index.php来处理

例如:index.php?option=com_<Name>

option=com_<Name>,经过处理后会首先进入组件入口程序com_<Name>/hello.php

com_<Name>/hello.php

示例:

<?php
/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 * components/com_hello/hello.php
 */
 
//限制直接访问
defined( '_JEXEC' ) or die( 'Restricted access' );
 
//引入默认的控制器
require_once( JPATH_COMPONENT.DS.'controller.php' );
 
//根据controller参数选择性加载控制器
//在多控制器的情况下动态加载指定控制器
if($controller = JRequest::getVar('controller')) {
    $path = JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php';
    if (file_exists($path)) {
        require_once $path;
    } else {
        $controller = '';
    }
}
 
// 创建控制器
$classname    = 'HelloController'.$controller;//根据控制器命名规范生成类名
$controller   = new $classname( );
 
//根据task参数执行相关操作
//默认情况下控制器会根据task的值调用控制器的相应方法
$controller->execute( JRequest::getVar( 'task' ) );
 
//根据控制器设置重定向
$controller->redirect();

JPATH_COMPONENT是系统定义常量,指定了当前组件的绝对路径

DS是系统定义常量,其值会根据操作系统的不同替换成相应的'\'或'/'

JRequest框架类,封装http请求包括GET和POST请求

控制器

************************************************************************

com_<Name>/controller.php

示例:

<?php
/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 */

defined( '_JEXEC' ) or die( 'Restricted access' );
 
jimport('joomla.application.component.controller');
 
/**
 * Hello World Component Controller
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HelloController extends JController
{
    /**
     * Method to display the view
     *
     * @access    public
     */
    function display()
    {
        parent::display();
    }
 
}

所有的控制器都继承JController

JController的构造器中默认注册了display()方法

JController::display()中根据命名约定设置了默认的view和layout

jimport加载类库文件,可用于libraries目录下的joomla类库及其他第三方类库

默认情况下view与组件名称一致,layout为default

视图

************************************************************************

com_<Name>/views/hello/view.html.php

示例:

<?php
/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
 
defined( '_JEXEC' ) or die( 'Restricted access' );
 
jimport( 'joomla.application.component.view');
 
/**
 * HTML View class for the HelloWorld Component
 *
 * @package    HelloWorld
 */
 
class HelloViewHello extends JView
{
    function display($tpl = null)
    {
        $greeting = "Hello World!";
        $this->assignRef( 'greeting', $greeting );//将变量植入模板
 
        parent::display($tpl);//执行并显示模板
    }
}

在符合命名约定的情况下,该视图会被自动加载

JView::display()会根据命名约定自动加载模板

模板

************************************************************************

com_<Name>/views/hello/tmpl/default.php

示例:

<?php
 
defined('_JEXEC') or die('Restricted access'); ?>
<h1><?php echo $this->greeting; ?></h1>

$this->greeting调用view中植入的$greeting变量并显示

配置文件

系统提供了内置的扩展用于根据配置文件的设置自动安装部署打包好的扩展和数据的初始化

com_<Name>/hello.xml

示例:

<?xml version="1.0" encoding="utf-8"?>
<install type="component" version="1.5.0"><!-- 扩展类型:type=[component|module|plugin] version=<joomla版本> [method="upgrade"] 以更新方式安装-->
 <name>Hello</name>
 <version>1.01</version><!-- 扩展的版本信息 -->
 
 <!-- 文件列表
      安装过程中会根据列表拷贝文件 -->
 <!-- 前台部分 -->
 <files folder="site">
  <filename>controller.php</filename>
  <filename>hello.php</filename>
  <filename>index.html</filename>
  <filename>views/index.html</filename>
  <filename>views/hello/index.html</filename>
  <filename>views/hello/view.html.php</filename>
  <filename>views/hello/tmpl/default.php</filename>
  <filename>views/hello/tmpl/index.html</filename>
 </files>
 
 <!-- 后台部分 -->
 <administration>
  <!-- 添加菜单项 -->
  <menu>Hello World!</menu>
 
  <!-- 文件列表 -->
  <files folder="admin">
   <filename>hello.php</filename>
   <filename>index.html</filename>
  </files>
 
 </administration>
</install>

在joomla中出于访问安全的考虑,每个目录下都有一个index.html,其内容为:

<html><body bgcolor="#FFFFFF"></body></html>

以上是扩展组件的简单实现,对于复杂的应用我们可以增加一个model将业务逻辑和数据操作分离出来

模型

************************************************************************

com_<Name>/models/hello.php

示例:

<?php
/**
 * Hello Model for Hello World Component
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
 
defined( '_JEXEC' ) or die( 'Restricted access' );
 
jimport( 'joomla.application.component.model' );
 
/**
 * Hello Model
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HelloModelHello extends JModel
{
    /**
    * Gets the greeting
    * @return string The greeting to be displayed to the user
    */
    function getGreeting()
    {
        return 'Hello, World!';
    }
}

在view中使用model

function display($tpl = null)
{
    $model = &$this->getModel();
    $greeting = $model->getGreeting();
    $this->assignRef( 'greeting',        $greeting );

    parent::display($tpl);
}

数据操作

************************************************************************

扩展组件在安装过程中可以执行相应SQL用来初始化数据

首先生成SQL文件

com_<Name>/install.sql

示例:

DROP TABLE IF EXISTS `#__hello`;
 
CREATE TABLE `#__hello` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `greeting` VARCHAR(25) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
 
INSERT INTO `#__hello` (`greeting`) VALUES ('Hello, World!'), ('Bonjour, Monde!'), ('Ciao, Mondo!');

com_<Name>/uninstall.sql
DROP TABLE IF EXISTS `#__hello`;

然后在配置文件中进行以下设置

<install>
  <sql>
    <file charset="utf8" driver="mysql">install.sql</file>
  </sql>
</install>
<uninstall>
  <sql>
    <file charset="utf8" driver="mysql">uninstall.sql</file>
  </sql>
</uninstall>

使用数据库的新版本getGreeting()

function getGreeting()
{
   $db =& JFactory::getDBO();//获取数据库操作对象JDatabase
 
   $query = 'SELECT greeting FROM #__hello';
   $db->setQuery( $query );//执行SQL语句
   $greeting = $db->loadResult();//获取结果集
 
   return $greeting;
}

JFactory是joomla框架下的一个静态类,用于生成一些框架中的常用对象

以上是扩展组件前台部分,前台部分主要用于展示或简单的操作数据,后台部分则主要用于对数据的操作和管理

后台部分的命名规则与前台一致

如果在模板中有可以重用的部分,可以将重用部分提取出来用include或者require进行引用

************************************************************************

示例:

文件结构

./com_compname/views/general/navigate.header.php  <-- 共用的header
./com_compname/views/general/navigate.footer.php  <-- 共用的footer
./com_compname/views/mngtable1/view.html.php
./com_compname/views/mngtable1/tmpl/default.php 
./com_compname/views/mngtable2/view.html.php
./com_compname/views/mngtable2/tmpl/default.php

通过以下引用语句在模板中调用

$pathToGeneralView = strchr(dirname(__FILE__), dirname($_SERVER['SCRIPT_NAME']));
$pathToGeneralView = str_replace(dirname($_SERVER['SCRIPT_NAME']),'.',$pathToGeneralView );
$pathToGeneralView = $pathToGeneralView . "/../../general/";  <-- returning path from current position. 
...
<?php require_once $pathToGeneralView . 'navigation.header.php'; ?>
<P>Do something    
<?php require_once $pathToGeneralView . 'navigation.footer.php'; ?>

在Joomla中使用JModel,JView,JController来实现MVC,所有具体的应用都继承这三个类

三个重要的参数

************************************************************************

option --设定扩展,值为组件的名称 eg com_content

controller --设定控制器,值为控制器的名称 eg banner

task --设定任务,值为操作的名称,通常是控制器方法的名称 eg add

工作流程

************************************************************************

1.框架分为前台后台两部分,分别以<root>/index.php和<root>/administrator/index.php两种形式访问

2.特定组件入口<root>/administrator/components/com_<componentname>/<componentname>.php

3.特定控制器入口<root>/administrator/components/com_<componentname>/controllers/<dedicatedcontroller>.php

4.特定控制器的方法处理特定的task

5.模型在控制器中实例化并使用

6.视图在控制器中设定并转发

后台部分的文件位于<root>/administrator/components/

程序入口

************************************************************************

com_<Name>/hello.php

示例:

<?php
/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
 
//限制直接访问
defined( '_JEXEC' ) or die( 'Restricted access' );
 
//引入默认的控制器
require_once( JPATH_COMPONENT.DS.'controller.php' );
 
//根据controller参数选择性加载控制器
//在多控制器的情况下动态加载指定控制器
if($controller = JRequest::getWord('controller')) {
    $path = JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php';
    if (file_exists($path)) {
        require_once $path;
    } else {
        $controller = '';
    }
}
 
// 创建控制器
$classname    = 'HellosController'.$controller;
$controller   = new $classname( );
 
//根据task参数执行相关操作
//默认情况下控制器会根据task的值调用控制器的相应方法
$controller->execute( JRequest::getVar( 'task' ) );
 
//根据控制器设置重定向
$controller->redirect();

控制器(默认)

************************************************************************

com_<Name>/controller.php

示例:

<?php
/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
 
defined( '_JEXEC' ) or die( 'Restricted access' );
 
jimport('joomla.application.component.controller');
 
/**
 * Hello World Component Controller
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HelloController extends JController
{
    /**
     * Method to display the view
     *
     * @access    public
     */
    function display()
    {
        parent::display();
    }
 
}

本例中默认控制器只负责默认的列表显示,没有更多的操作基本和前台默认控制器一致

模型(hellos)

************************************************************************

com_<Name>/models/hellos.php

示例:

<?php
/**
 * Hellos Model for Hello World Component
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
 
defined('_JEXEC') or die();
 
jimport( 'joomla.application.component.model' );
 
/**
 * Hello Model
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HellosModelHellos extends JModel
{
    /**
     * Hellos data array
     *
     * @var array
     */
    var $_data;
 
    /**
     * 生成SQL查询语句
     *
     * 将生成SQL语句的功能分离出来是为了在复杂条件增加SQL语句组合的灵活性和程序的可读性
     *
     * @return string 获取hello表中全部数据的SQL语句
     */
    function _buildQuery()
    {
        $query = ' SELECT * '
            . ' FROM #__hello '
        ;
        return $query;
    }
 
    /**
     * 获取hello数据
     * @return array 返回一个hello数据的数组
     */
    function getData()
    {
        if (empty( $this->_data ))
        {
            $query = $this->_buildQuery();
            //将结果集储存与model的属性中,减少数据库查询次数
            $this->_data = $this->_getList( $query );//JModel::_getList(),对JDatabase::loadObjectList()的封装,返回一个查询结果集的对象数组
        }
 
        return $this->_data;
    }
}

hellos模型主要用于获取hello表中的全部数据

视图(hellos)

************************************************************************

com_<Name>/views/hellos/view.html.php

示例:

<?php
/**
 * Hellos View for Hello World Component
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
 
defined('_JEXEC') or die();
 
jimport( 'joomla.application.component.view' );
 
/**
 * Hellos View
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HellosViewHellos extends JView
{
    /**
     * Hellos view display method
     * @return void
     **/
    function display($tpl = null)
    {
		//设置后台页面页头toolbar
		//JToolBarHelper类提供一系列静态方法用于生成后台常用操作的一些功能按钮
		//JText::_()用于程序的国际化
        JToolBarHelper::title( JText::_( 'Hello Manager' ), 'generic.png' ); //设置标题及图标
        JToolBarHelper::deleteList();                                        //添加删除按钮
        JToolBarHelper::editListX();                                         //添加编辑按钮
        JToolBarHelper::addNewX();                                           //添加创建按钮
 
        // Get data from the model
        $items =& $this->get( 'Data');//JView::get(),可使用该方法调用与视图绑定的模型中以get开头的方法 eg get('Data') = getDate()
 
        $this->assignRef( 'items', $items );//将变量植入模板
 
        parent::display($tpl);
    }
}

模板(hellos)

************************************************************************

com_<Name>/views/hellos/tmpl/default.php

示例:

<?php defined('_JEXEC') or die('Restricted access'); ?>
<form action="index.php" method="post" name="adminForm">
<div id="editcell">
    <table class="adminlist">
    <thead>
        <tr>
            <th width="5">
                <?php echo JText::_( 'ID' ); ?>
            </th>
            <th width="20">
              <input type="checkbox" name="toggle" value="" onclick="checkAll(<?php echo count( $this->items ); ?>);" />
              <!--checkAll()是系统内置的javascript函数,用于选中或取消列表中的所有项目-->
            </th>
            <th>
                <?php echo JText::_( 'Greeting' ); ?>
            </th>
        </tr>            
    </thead>
    <?php
    $k = 0;
    for ($i=0, $n=count( $this->items ); $i < $n; $i++)
    {
        $row =& $this->items[$i];
        $checked    = JHTML::_( 'grid.id', $i, $row->id );<!--JHTML是封装了HTML元素的类,可以使用JHTML::_()等一系列方法设置并生成HTML元素-->
        $link = JRoute::_( 'index.php?option=com_hello&controller=hello&task=edit&cid[]='. $row->id );
        <!--JRoute::_()用于将系统内部链接转换为外部链接-->
 
        ?>
        <tr class="<?php echo "row$k"; ?>">
            <td>
                <?php echo $row->id; ?>
            </td>
            <td>
              <?php echo $checked; ?>
            </td>
            <td>
                <a href="/<?php echo $link; ?>"><?php echo $row->greeting; ?></a>
            </td>
        </tr>
        <?php
        $k = 1 - $k;
    }
    ?>
    </table>
</div>
 
<input type="hidden" name="option" value="com_hello" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="boxchecked" value="0" />
<input type="hidden" name="controller" value="hello" />
 
</form>

模板中使用了少量的逻辑编码来遍历数据,并且将所有内容置于form中用于添加操作任务

控制器(hello)

************************************************************************

com_<Name>/controllers/hello.php

示例:

<?php
/**
 * Hello Controller for Hello World Component
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 */

defined( '_JEXEC' ) or die( 'Restricted access' );

/**
 * Hello Hello Controller
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HellosControllerHello extends HellosController
{
	/**
	 * constructor (registers additional tasks to methods)
	 * @return void
	 */
	function __construct()
	{
		parent::__construct();

		// 将add请求映射到edit方法
		$this->registerTask( 'add'  , 	'edit' );
	}

	/**
	 * display the edit form
	 * @return void
	 */
	function edit()
	{
		JRequest::setVar( 'view', 'hello' );   //指定视图
		JRequest::setVar( 'layout', 'form'  ); //指定布局
		JRequest::setVar('hidemainmenu', 1);   //主菜单不可用

		parent::display();
	}

	/**
	 * save a record (and redirect to main page)
	 * @return void
	 */
	function save()
	{
		$model = $this->getModel('hello');

		if ($model->store($post)) {
			$msg = JText::_( 'Greeting Saved!' );
		} else {
			$msg = JText::_( 'Error Saving Greeting' );
		}

		// Check the table in so it can be edited.... we are done with it anyway
		$link = 'index.php?option=com_hello';
		$this->setRedirect($link, $msg);
	}

	/**
	 * remove record(s)
	 * @return void
	 */
	function remove()
	{
		$model = $this->getModel('hello');
		if(!$model->delete()) {
			$msg = JText::_( 'Error: One or More Greetings Could not be Deleted' );
		} else {
			$msg = JText::_( 'Greeting(s) Deleted' );
		}

		$this->setRedirect( 'index.php?option=com_hello', $msg );
	}

	/**
	 * cancel editing a record
	 * @return void
	 */
	function cancel()
	{
		$msg = JText::_( 'Operation Cancelled' );
		$this->setRedirect( 'index.php?option=com_hello', $msg );
	}
}

实体对象(hello)

************************************************************************

com_<Name>/tables/hello.php

示例:

<?php
/**
 * Hello World table class
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 */

defined('_JEXEC') or die('Restricted access');
 
/**
 * Hello Table class
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class TableHello extends JTable
{
    /**
     * Primary Key
     *
     * @var int
     */
    var $id = null;
 
    /**
     * @var string
     */
    var $greeting = null;
 
    /**
     * Constructor
     *
     * @param object Database connector object
     */
    function __construct( &$db ) {
        parent::__construct('#__hello', 'id', $db); //设置数据表,唯一标识和数据库对象
    }
}

实体对象(hello)继承自抽象类JTable,JTable对基本的数据操作进行了封装 eg JTable::store()

模型(hello)

************************************************************************

com_<Name>/models/hello.php

示例:

<?php
/**
 * Hello Model for Hello World Component
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 */

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport('joomla.application.component.model');

/**
 * Hello Hello Model
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HellosModelHello extends JModel
{
	/**
	 * Constructor that retrieves the ID from the request
	 *
	 * @access	public
	 * @return	void
	 */
	function __construct()
	{
		parent::__construct();

		$array = JRequest::getVar('cid',  0, '', 'array');
		$this->setId((int)$array[0]); //设定id
	}

	/**
	 * Method to set the hello identifier
	 *
	 * @access	public
	 * @param	int Hello identifier
	 * @return	void
	 */
	function setId($id)
	{
		// Set id and wipe data
		$this->_id		= $id;
		$this->_data	= null; //清空_data
	}

	/**
	 * Method to get a hello
	 * @return object with data
	 */
	function &getData()
	{
		// Load the data
		if (empty( $this->_data )) {
			$query = ' SELECT * FROM #__hello '.
					'  WHERE id = '.$this->_id;
			$this->_db->setQuery( $query );
			$this->_data = $this->_db->loadObject();
		}
		if (!$this->_data) {
			$this->_data = new stdClass();
			$this->_data->id = 0;
			$this->_data->greeting = null;
		}
		return $this->_data;
	}

	/**
	 * Method to store a record
	 *
	 * @access	public
	 * @return	boolean	True on success
	 */
	function store()
	{	
		$row =& $this->getTable();                      //根据默认设置获取JTable对象(规范的命名 eg 实体对象命名为TableHello,文件命名为hello.php)

		$data = JRequest::get( 'post' );                //获取表单数据

		// 将表单数据与JTable对象绑定
		if (!$row->bind($data)) {
			$this->setError($this->_db->getErrorMsg());
			return false;
		}

		// 数据完整性效验
		if (!$row->check()) {
			$this->setError($this->_db->getErrorMsg());
			return false;
		}

		// 储存数据
		// JTable::store()会根据id是否设置来判断应该插入或者更新记录
		if (!$row->store()) {
			$this->setError( $row->getErrorMsg() );
			return false;
		}

		return true;
	}

	/**
	 * Method to delete record(s)
	 *
	 * @access	public
	 * @return	boolean	True on success
	 */
	function delete()
	{
		$cids = JRequest::getVar( 'cid', array(0), 'post', 'array' );

		$row =& $this->getTable();

		if (count( $cids )) {
			foreach($cids as $cid) {
				if (!$row->delete( $cid )) {
					$this->setError( $row->getErrorMsg() );
					return false;
				}
			}
		}
		return true;
	}

}

视图(hello)

************************************************************************

com_<Name>/views/hello/view.html.php

示例:

<?php
/**
 * Hello View for Hello World Component
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 */

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.application.component.view' );

/**
 * Hello View
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HellosViewHello extends JView
{
	/**
	 * display method of Hello view
	 * @return void
	 **/
	function display($tpl = null)
	{
		//从模型获取数据
		$hello		=& $this->get('Data'); 
		$isNew		= ($hello->id < 1);

		//设置toolbar
		$text = $isNew ? JText::_( 'New' ) : JText::_( 'Edit' );
		JToolBarHelper::title(   JText::_( 'Hello' ).': <small><small>[ ' . $text.' ]</small></small>' );
		JToolBarHelper::save();
		if ($isNew)  {
			JToolBarHelper::cancel();
		} else {
			// for existing items the button is renamed `close`
			JToolBarHelper::cancel( 'cancel', 'Close' );
		}

		//将数据植入模板
		$this->assignRef('hello',		$hello);

		parent::display($tpl);
	}
}

模板(hello-form)

************************************************************************

com_<Name>/views/hello/tmpl/form.php

示例:

<?php defined('_JEXEC') or die('Restricted access'); ?>

<form action="index.php" method="post" name="adminForm" id="adminForm">
<div class="col100">
	<fieldset class="adminform">
		<legend><?php echo JText::_( 'Details' ); ?></legend>

		<table class="admintable">
		<tr>
			<td width="100" align="right" class="key">
				<label for="greeting">
					<?php echo JText::_( 'Greeting' ); ?>:
				</label>
			</td>
			<td>
				<input class="text_area" type="text" name="greeting" id="greeting" size="32" maxlength="250" 
                                       value="<?php echo $this->hello->greeting;?>" />
			</td>
		</tr>
	</table>
	</fieldset>
</div>
<div class="clr"></div>

<input type="hidden" name="option" value="com_hello" />
<input type="hidden" name="id" value="<?php echo $this->hello->id; ?>" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="controller" value="hello" />
</form>

 

 

Joomla扩展模块开发文档(module)

概述

************************************************************************

扩展模块用于简单的页面展示,可以应用于多个不同的组件

扩展模块可以使页面构建更加灵活并且可以提高程序的重用性

模块分为前台和后台两种

在配置文件的install元素中设置属性client="administrator"即为后台模块

前台的模块的目录为<root>/modules,后台模块的目录为<root>/administrator/modules

扩展组件目录的命名约定是mod_<Name>

文件

************************************************************************

一个基本的模块包括四个文件

mod_helloworld.php - 入口文件,执行相关初始化操作,通过helper.php获取数据并设置模板

mod_helloworld.xml - 配置文件,设置模块安装相关参数

helper.php - 一般是模块的一个helper类,进行实际的数据读取,逻辑运算的相关操作

tmpl/default.php - 模板文件,设置模块的显示效果

mod_helloworld.php

示例:

<?php
/**
 * Hello World! Module Entry Point
 * 
 * @package    Joomla.Tutorials
 * @subpackage Modules
 */
 
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
 
// 引入helper
require_once( dirname(__FILE__).DS.'helper.php' );

// 获取数据
$hello = modHelloWorldHelper::getHello( $params );
// 加载模板
require( JModuleHelper::getLayoutPath( 'mod_helloworld' ) );

helper.php

示例:

<?php
/**
 * Helper class for Hello World! module
 * 
 * @package    Joomla.Tutorials
 * @subpackage Modules
 */
class modHelloWorldHelper                // helper类的命名mod<name>Helper(非强制性的命名约定)
{
    /**
     * Retrieves the hello message
     *
     * @param array $params              // 一个填充了模块参数的JParameter对象
     * @access public
     */    
    function getHello( $params )
    {
    	$hello = $params->get( 'hello' );// 获取hello参数的值
        return $hello;
    }
}

tmpl/default.php

示例:

<?php // no direct access
defined( '_JEXEC' ) or die( 'Restricted access' ); ?>
<?php echo $hello; ?>

模板中可以直接使用入口文件中定义的变量

mod_helloworld.xml

示例:

<?xml version="1.0" encoding="utf-8"?>
<install type="module" version="1.5.0">
<!-- 扩展类型:type=[component|module|plugin] version=<joomla版本> [client="administrator"] 后台模块 [method="upgrade"] 以更新方式安装-->
    <name>Hello, World!</name>
    <version>1.5.0</version><!-- 扩展的版本信息 -->
    <description>A simple Hello, World! module.</description>
    <!-- 文件列表 -->
    <files>
        <filename>mod_helloworld.xml</filename>
        <filename module="mod_helloworld">mod_helloworld.php</filename>
        <filename>index.html</filename>
        <filename>helper.php</filename>
        <filename>tmpl/default.php</filename>
        <filename>tmpl/index.html</filename>
    </files>
    <!--设置模块参数-->
    <params>
		<param name="hello" type="text" default="hello,world!" label="hello" description="hello string" />
    </params>
</install>

参数的相关设置可以应用于所有类型的扩展

Joomla编码规范

文件格式

************************************************************************

文件统一使用UTF-8编码

缩进和每行代码的长度

************************************************************************

使用制表符完成缩进,制表符的长度为4。

每行代码的长度没有硬性标准,可根据该行的性质和代码的可读性自行把握。

赋值语句

************************************************************************

赋值语句的等号前后都至少要有一个空格

示例:

$var = 0;

在多个相关的赋值语句中,使用制表符将等号对齐以增加代码的可读性

示例:

$short          = 0;
$long_variable  = $short;

流程控制语句

************************************************************************

在流程控制语句中,关键词、参数、花括号之间应该有一个空格以便与函数调用格式区分

在任何时候都必须使用花括号,以增加代码的可读性,避免添加新行时造成的逻辑错误

if语句

示例:

if ((condition1) || (condition2)) {
    action1();
} elseif ((condition3) && (condition4)) {
    action2();
} else {
    defaultAction();
    anotherAction();
}

在页面布局中使用流程控制的替代语法,条件语句逻辑运算符也应该使用大写的单词(AND,OR,等),而不是使用符号($,|,等)

示例:

if ((condition1) OR (condition2)) :
    action1();
elseif ((condition3) AND (condition4)) :
    action2();
else :
    defaultAction();
    anotherAction();
endif;
 
foreach ($array as $element) :
    echo $element;
endforeach;

switch语句

示例:

switch (condition) {
    case 1:
        doAction1();
        break;
 
    case 2:
        doAction2();
        break;
 
    default:
        doDefaultAction();
        break;
}

使用缩进代替case语句的花括号来增加代码的可读性

case语句中条件和冒号之间不能有空格

函数调用

************************************************************************

函数名和圆括号之间不能有空格

圆括号和第一个参数以及最后一个参数之间不能有空格

参数和逗号之间不能有空格(多个参数的情况下)

每个参数的逗号后要有一个空格(多个参数的情况下)

示例:

$var = foo($bar, $baz, $quux);

函数声明

************************************************************************

函数或类的声明遵循“one true brace”原则(开始的花括号单独占一行,而不是跟在其他语句后面)

示例:

function fooFunction($arg1, $arg2 = '')
{
    if (condition) {
        statement;
    }
    return $val;
}
 
class fooClass
{
    function fooMethod($arg1)
    {
        if ($arg) {
            $result = true;
        } else {
            $result = false;
        }
        return $result;
    }
}

有默认值的参数要放在参数列表的最后

当函数有返回值时,必须保证函数返回一个有意义的值

示例:

function connect(&$dsn, $persistent = false)
{
    if (is_array($dsn)) {
        $dsninfo = &$dsn;
    } else {
        $dsninfo = DB::parseDSN($dsn);
    }
 
    if (!$dsninfo OR !$dsninfo['phptype']) {
        return $this->raiseError();
    }
 
    return true;
}

注释

************************************************************************

类,属性和方法,函数,常量都应该提供适当的DocBlocks。

示例:

/**
 * 类的简短描述
 *
 * 类的详细描述(可选)
 *
 * @package    PackageName
 * @subpackage SubPackageName
 * @auther     <作者>
 * @since      <起始版本>
 * @deprecated                    --不被推荐的过期的(可选)
 */

属性

示例:

/**
 * 简短描述
 *
 * @var 类型
 */

函数和方法

示例:

/**
 * 简短描述
 *
 * @since	<起始版本>
 * @param   <类型> <变量名> <描述>   --参数
 * @return  <类型>         <描述>	  --返回值
 */
Joomla核心中使用的package

  Joomla.Administrator - 用于后台(administrator or backend)的所有文件  
  Joomla.Installation - 用于安装程序的所有文件  
  Joomla.Plugin - 用于plugin的所有文件  
  Joomla.Site - 用于前台(site or frontend)的所有文件 
  Joomla.XML-RPC - 用于XML-RPC的所有文件

Joomla各种扩展中使用的sub-package

  Components - 组件文件, eg com_content  
  Modules - 模块文件, eg mod_latest_news  
  Plugins - 插件文件, eg content.pagebreak  
  Templates - 模板文件, eg rhuk_milkyway  
  Framework - eg factory.php, eg utilities for joomla/utitilies/date.php, html.html for joomla/html/html/email.php

保证适当的非文档注释量(原则:当你看到一段代码,然后想:“Wow, I don't want to try and describe that”,那么你就应该在你忘记程序的工作流程之前为这段代码添加非文档注释) 内联的类文件的注释应遵循PHPDoc惯例, 详见http://www.phpdoc.org/

PHP标签

************************************************************************

使用<?php ?>不要使用<? ?>

当文件中只包含php代码时不要使用结束标记?>

SQL语句

************************************************************************

关键词必须大写,其他字符必须小写

SQL语句中不能包含回车符

使用缩进来提高SQL语句可读性

使用单引号提高执行效率

所有整型和浮点型变量都要进行强制类型转换

所有字符变量使用Quote()方法(Joomal 特有)

所有表明使用#_前缀(Joomal 特有)

示例:

$state = 1;
$name  = 'bill';
$db    = &JFactory::getDBO();
$query = 'SELECT COUNT( c.id ) AS num_articles, u.id, u.username'.
    ' FROM #__content AS c'.
    ' LEFT JOIN #__users AS u ON u.id = c.created_by'.
    ' WHERE c.state = '.(int) $state
    '  AND u.id IS NOT NULL'.
    '  AND u.username <> '.$db->Quote( $name ).
    ' GROUP BY u.id'.
    '  HAVING COUNT( c.id ) > 0';
$db->setQuery();
// Output formated query:
if ($debug) {
    echo $db->getQuery();
}
$stats = $db->loadObjectList();

命名约定

************************************************************************

类要以描述性的名称命名

类名使用完整单词不要使用缩写

类名首字母大写

类名使用CamelCase拼写法

类名可以使用全部大写的特殊名词(eg HTML,XML)

Joomla框架类,都是以大写的J开头(eg JHtmlHelper,JXmlParser,JModel)

函数和方法

函数和方法使用 "studly caps" 样式命名

名字的首字母应该是小写,每一个新单词应该以大写字母开头

Joomla框架中的函数,都是以小写的j开头

示例:

connect();
getData();
buildSomeWidget();
jImport();
jDoSomething();

类的私有成员以_开头,单词间以_连接,全部小写

示例:

class JFooBar
{
    // Joomla 1.5 and earlier format
    var $_status = null;
 
    function _sort()
    {
    }
 
    // Joomla 1.6 format
    private $_status = null;
 
    protected $field_name = null;
 
    protected function _sort()
    {
    }
}

常量

全部大写,单词间以_连接,使用所在的类或包做为前缀 例如JError类中的常量都以"JERROR_"做为前缀

全局变量 以下划线开头,连接类名或包名,再连接下划线和变量名(eg $_JERROR_LEVELS)

控制器

对于单控制器组件,命名约定是<Name>Controller

示例:

/**
 * Content Controller
 * @package Joomla
 */
class ContentController extends JController
{
    // Methods
}

文件名称一般会是controller.php,并在组件根目录中

com_content
 / controller.php

对于多控制器组件,命名约定是<Component>Controller<Name>

示例:

/**
 * Banner Client Controller
 * @package Joomla
 */
class BannerControllerClient extends JController
{
    // Methods
}

文件位于组件文件夹下的/controllers/ 目录下,以控制器的名称命名

示例:

com_banner
  /controllers/
    / banner.php
    / client.php

模型

命名约定是<Component>Model<Name>

示例:

/**
 * Banner Client Model
 * @package Joomla
 */
class BannerModelClient extends JModel
{
    // Methods
}

文件位于组件文件夹下的/models/ 目录下,以模型的名称命名

示例:

com_banner
  /models/
    / banner.php
    / client.php

视图

命名约定是<Component>View<Name>

示例:

/**
 * Contact Category View
 * @package Joomla
 */
class ContactViewCategory extends JView
{
    // Methods
}

文件位于组文件夹下的/views/ 目录下,以模型的名称命名

示例:

com_contact
 /views/
   /view name 1/
     / view.html.php
   /view name 2/
     / view.html.php

插件

命名约定是<Folder>Plugin<Element>

示例:

class ContentPluginPagebreak extends JPlugin
{
    // Methods
}
?>

页面布局

组件可以支持由视图和模型提供的数据以不同的布局呈现

一个布局文件通常包含标记和一些PHP代码显示逻辑,不包含函数和类

一个布局至少包含一个php文件和一个同名的xml文件,文件位于/tmpl/视图的文件夹,默认布局文件为default.php

示例:

com_content
  /views/
    /article/
      /tmpl/
        / default.php
        / default.xml
        / form.php
        / form.xml
        / pagebreak.php
        / pagebreak.xml