2022年joomla组件开发 .pdf
Joomla 组件开发Joomla 中组件是最大的最复杂的扩展类型,可以被看为小型的应用。 如果把 Joomla比作操作系统, 组件就是一个个的桌面应用程序。每一个页面都调用一个组件生成页面的主体部分。比如,com_content组件处理所有跟内容相关的小应用,而注册组件处理所有跟注册相关的部分。一个组件包含管理部分和前台页面部分,前台页面部分是站点运行时正常生成的页面,管理部分是管理员的管理入口。我们以 Hello World 这个经典的例子,给出如何创建自己的组件。1. 怎样创建组件Hello WorldMVCComponent - frameJoomla 1.5的新框架为开发者解除了束缚,代码彻底的修改和整理过了。本文给出了采用新框架的开发过程。我们将开发一个hello world 的组件,接下来的教程中,在这个简单框架的基础上将展现MVC 设计模式的力量。MVC模式尽管这个组件非常简单,可是随着添加新的功能或者自定义界面,代码可以非常复杂。MVC 就是数据表示和商业逻辑分开的软件设计模式,这样的前提就是商业逻辑在一起,而界面和用户交互能够被自定义或者修改而不会改变商业逻辑的程序。一个 MVC 自建有三个主要的部分, 这里做了简要说明, 更加详细的解释请看本教程给出的参考连接。ModelModel 封装了应用的数据,同时提供了管理和操作数据的功能。在例子中Model 包含了 add,remove和 update数据库中的 greeting信息,同时包含了从数据库返回greeting的 list. 通常来说数据的访问应该封装在 Model 中,这样假如系统从一个文件数据系统中迁移到一个数据库中,那么仅仅需要修改Model,而View 和 Controller 都不必修改。ViewView 是组件的一部分,用来以一种适合用户交互的方式来组织和展示数据。对于 web 应用, 通常 View就是 html 页面, View 从 Model 获得数据,并传递给模板。View 不做任何的数据修改,他仅仅是展示从 Model获得的数据。ControllerController 负责用户的操作,对于一个web 应用,一个用户的操作就是页面的请求,controller 根据请求决定调用合适 Model 并传递数据到 View 。Joomla!MVCJoomla实现了 MVC 模式,主要包括以下三个类JModel, JView,JController. 更详细的信息请参考API文档.下面我们就以具体的例子来展示Joomla的组件开发。创建组件对于这个简单的组件,只需5 个文件:hello.php - 组件的入口文件controller.php - Controller 基类,根据 task决定如何操作 Model 和 View名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 24 页 - - - - - - - - - views/hello/view.html.php - 返回数据,传递给模板views/hello/tmpl/default.php - 模板文件hello.xml - 组件安装文件创建入口文件Joomla!总是有一个单一的入口,比如对于站点应用是/index.php,而对于管理应用是/administrator/index.php,入口文件 根据 URL 或者 POST数据中 option 参数,来决定载入必要的组件。我们开发的这个组件的入口: index.php?option=com_hello&view=hello这就会载入我们的主文件,也就是组件的入口文件components/com_hello/hello.php.以下的代码对于所有的组件是相当典型的:execute(JRequest:getVar(task) );/ Redirect if setby the controller$controller-redirect();?第一句声明是一个安全检查。JPATH_COMPONENT 是 Joomla定义的当前组件的绝对路径的常量, 对于这个组件是components/com_hello.DS 是系统目录分隔符 :/ 或 ,由系统自动设置,从而开发者不必担心系统和版本的问题。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 24 页 - - - - - - - - - 在 controller 载入后,要检查是否有特别的controller 需要载入。本例中没有,但是我们保留以备后用。JRequest:getVar() 是获取 get 或 post的数据 . 如果 url:index.php?option=com_hello&controller=controller_name,JRequest:getVar(controller)就可以返回 controller的名字;controller 命名规则是 ComponentnameControllerControllername创建了 controller 后, 就要执行任务, url: index.php?option=com_hello&task=sometask.如果没有指定task,那么就执行 display,这时 view 决定显示什么。controller 可以转向 , 比如保存任务完成后 . 最后一行程序就是监测转向.创建 Controller组件例子只有一个任务- greetthe world。因此 controller 非常简单。不需要数据操作,所做的只是决定调用那个合适的 view。 我们只有一个方法display()。以下是源代码 :JController 构造函数注册display() 任务,除非用registerDefaultTask() 指定默认任务,否则dislpaly作为默认的任务。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 24 页 - - - - - - - - - 事实上这里调用 display 也不是必须的,因为 display 仅仅是调用父类的display。 JController:display() 确定合适的 view 和模板,并且载入他们。例子组件中,我们只有一个view-hello,一个模板 default。view 的工作很简单,就是获取数据,用assignRef传递给模板。view 代码如下 :assignRef(greeting, $greeting);parent:display($tpl);?Joomla!模板使用用来以特定方式布置从view 获取数据的 php文件,在模板中可以用$this propertyname 获取 view 通过 assignref传递的数据。例子中模板非常简单,以下是代码:greeting; ?打包 创建 hello.xml可以通过上传文件,然后修改数据表来安装组件。更有效的方式是创建一个安装包,让Joomlainstaller帮你做安装。这个安装文件包含以下内容:组件的基本信息要拷贝的文件执行安装和卸载的php文件.(刘注: 应该是 SQL 文件)语言包 (国际化用的 )sql 语句名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 24 页 - - - - - - - - - xml 文件格式如下 :Hello200702 22JohnDoe john.doeexample.org http:/www.example.orgCopyright InfoLicenseInfoComponentVersion StringDescription of thecomponent.index.htmlhello.phpcontroller.phpviews/index.htmlviews/hello/index.htmlviews/hello/view.html.phpviews/hello/tmpl/index.htmlviews/hello/tmpl/default.phpHello World!subsubindex.htmladmin.hello.php你可能注意到了文件index.html,文件主要是浏览目录的时候显示这个文件,而不是显示目录下的文件结构。这个文件仅仅包含一行:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 24 页 - - - - - - - - - 就是一个空白页面另外一个文件是admin.hello.php,这是管理组件的入口,目前我们没有这部分内容,所以他的内容和index.html 内容相同添加一个Model序言在上一文章中,我们做了一个Joomla 1.5 MVC 模式的 hello world 组件。在例子中, greeting 是直接写在 view 中的,这并不完全遵守MVC 的原则,按照 MVC 的要求, view 仅仅是展示数据而不是包含数据。现在,我们来展示如何将数据迁移到Model 中。接下来的例子中,你可以看到MVC 设计模式的强大和灵活性。创建 Model正如其名,Model 这个类是代表一些实体的。 例子中,这个 Model 代表 hello或者一个 greeting。Model的命名约定是component namneModelmodelname,我们的例子中就是HelloModelHello 。目前为止,hello model只有一个行为,就是返回greeting。因此只有一个方法, getGreeting(),这个方法仅仅返回字串Hello, World! 。以下是 Model 的代码 :getModel();$greeting= $model-getGreeting();完整的 view 代码如下 :getModel();名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 24 页 - - - - - - - - - $greeting= $model-getGreeting();$this-assignRef(greeting, $greeting);parent:display($tpl);?添加文件到安装包中。我们要做就是把这个hello.php 加入在 xml 相应部分models/hello.php新的 hello.xml 完整清单如下 :Hello200702 22JohnDoe john.doeexample.org http:/www.example.orgCopyright InfoLicenseInfoComponentVersion StringDescription of thecomponent.index.htmlhello.phpcontroller.phpviews/index.htmlviews/hello/index.htmlviews/hello/view.html.phpviews/hello/tmpl/index.htmlviews/hello/tmpl/default.phpmodels/index.htmlmodels/hello.phpHello World!名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 24 页 - - - - - - - - - index.htmladmin.hello.phpJTable数据库操作序言前两个例子展示了如何创建简单的MVC 组件,在第二个例子中View 获取从 Model 中返回的数据。本教程中,我们继续关注Model,我们将直接从数据库获得数据,而不是直接写在Model 中。我们将演示如何利用 JDatbase从数据库中取得数据取得数据第二个例子中只有一个方法getGreeting(),这个方法所做的仅仅是返回写在代码中的greeting。稍后将演示如何创建 sql 文件,并加入到 xml 安装文件中,从而在安装的时候自动创建数据表,加入初始的样板数据。现在我们将演示的是用什么代码替换就可以从数据库获得合适的数据。首先要获得数据库的引用,你这样做就可以得到了$db=& JFactory:getDBO();JFactory 是一个静态类,通过它可以取得很多的实例(请参见源代码解析,JFactory类)。 getDBO 就是 getDataBaseObject 的缩写 , 很容易记住吧。接下来我们取回数据吧,这需要两步,一是存储query,一是载入结果。以下是getGreeting的代码:function getGreeting()$db =& JFactory:getDBO();$query = SELECT greetingFROM #_hello;$db-setQuery($query);$greeting= $db-loadResult();return $greeting;hello 是我们以后要创建的表名,greeting是存储数据的字段名。如果你不熟悉sql,最好找个教程手册速成一下,可以在 w3schools找到这样的教程。$db-loadResult()执行查询,返回结果集中第一行的第一个字段. .创建 sql 文件JoomlaInstaller 支持执行 sql,这些 sql 语句都保存在标准的文本文件中。在安装文件有三个语句, 一个如果表已经存在那么就删除,第二个是创建表,第三是插入样例数据。以下是全部文本:DROP TABLE IF EXISTS #_hello;CREATE TABLE #_hello (id int(11) NOT NULL auto_increment,greetingvarchar(25)NOT NULL,PRIMARY KEY(id) ENGINE=MyISAMAUTO_INCREMENT DEFAULT CHARSET=utf8;名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 24 页 - - - - - - - - - INSERT INTO #_hello (greeting) VALUES (Hello, World!),(Bonjour, Monde!),(Ciao, Mondo!);你可能看到了表的前缀非常奇怪。Joomla将替换这个前缀,用安装时候指定的内容。对于通常的安装,这个表名将是 jos_hello,这样可以多个安装使用一个数据库,并且能够避免表名冲突。表中有两个字段,一是 id,是主键,一是 greeting。以上内容保存在install.utf.sql。创建卸载 sql 文件尽管我们希望永远不必卸载组件,然而卸载也是重要的。Joomla将自动找到需要删除的文件和目录,可是必须要将删除表的sql 语句写在安装文件中。语句如下:DROP TABLE IF EXISTS #_hello;保存在 uninstall.utf.sql 中.新的安装文件如下:Hello200702 22JohnDoe john.doeexample.org http:/www.example.orgCopyright InfoLicenseInfoComponentVersion StringDescription of the component.index.htmlhello.phpcontroller.phpviews/index.htmlviews/hello/index.htmlviews/hello/view.html.phpviews/hello/tmpl/index.htmlviews/hello/tmpl/default.phpmodels/hello.phpinstall.sql名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 24 页 - - - - - - - - - uninstall.sqlHello World!index.htmladmin.hello.phpinstall.sqluninstall.sql在 install 和 uninstall 部分, file 标签中指定了 charset和 driver,目前唯一合法的charset是 utf-8,如果想在非 utf8 数据库创建表,可以忽略这个属性。driver 属性目前只能是 mysql,将来 Joomla可能支持更多数据库。组件管理入口序言前三个例子我们开发了一个从数据库中获取数据的MVC 组件。 可是除了手工添加数据或者使用其他工具外,我们没有办法添加数据。本教程中,我们将开发一个管理部分从而能够管理数据。创建基本框架后台管理基本框架与前台站点部分基本相同。管理部分的主入口是admin.hello.php。这个文件与我们在前面部分使用的 hello.php 是一样的,除了 controller 改为 HellosController.默认的 controller 也是controller.php,并且除了 controller 名字是 HellosController 以外,其他与前台部分的controller.php 都一样,还有不同就是将 默认调用 hellosView,这个 View 显示 greetings的列表以下 admin.hello.php代码清单:execute(JRequest:getVar(task) );/ Redirect if setby the controller$controller-redirect();?View 和 Model 都是以 hellos开头的,下面将介绍Model 和 View.Hellos ModelHellos Model 非常简单,我们需要的是从数据库返回hellos 列表,这通过 getData()方法实现。还有一个_getList()的保护方法,这个方法用来简化从数据库返回数据的任务,我们只是简单的传递query 并且返回记录列表。也许以后某个时候,我们在另一个方法中使用这个查询,因而我们创建了一个私有方法_buildQuery(),这个方法返回 query,并且传递给 _getList()。 这样可以集中在一处来修改查询语句。getData()和_buildQuery()方法是必须需要的。 _buildQuery() 仅仅是返回语句,代码如下:function _buildQuery()$query= SELECT * . FROM #_hello ;return $query;getData() 将用这个 sql 从数据库返回数据。也许我们需要两次获取同样数据,重复运行查询是非常浪费的,因而我们保存结果在一个保护属性_data中,这样只需查询一次就可以了。以下是getData() 方法:function getData()/ Lets load thedataif it doesntalreadyexistif (empty( $this-_data)$query= $this-_buildQuery();名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 24 页 - - - - - - - - - $this-_data= $this-_getList( $query );return $this-_data;完整 model代码如下( models/hellos.php ):_data)$query= $this-_buildQuery();$this-_data= $this-_getList( $query );return$this-_data;Hellos View现在 Model 已经返回了数据,那么就需要View 来显示数据。 View 与前台的 View 也相似。与前台一样,这里的 Model 也是自动初始化的。 View 主要有三行程序,一是得到Model 返回的数据,二是传递数据给模板,三是调用display 方法,显示输出。以下是views/hellos/view.html.php. 代码清单:get(Data);$this-assignRef(items, $items);名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 24 页 - - - - - - - - - parent:display($tpl);Hellos Template模板获取 View 传递的数据,并生成输出。我们用一个表格显示输出,尽管前台的模板非常简单,可是后台的管理复杂一些从而能处理数据。这是views/hellos/tmpl/default.php 的代码清单:items); $i items$i;?tr class=id; ?greeting; ?你看到我们的输出用一个form 包含,现在并不是必须的,但是以后有用处。以下是新增的5 个文件,你可以把这些文件添加到xml 中,并试试。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 15 页,共 24 页 - - - - - - - - - admin.hello.phpcontroller.phpmodels/hellos.phpviews/hellos/view.html.phpviews/hellos/tmpl/default.php直到目前为止,管理界面没有什么实际用户,除了显示数据。我们需要增加一些按钮和链接,从而能执行管理功能。TheToolbarToolbar 是 Joomla组件管理控制面板的顶部。 这个组件同样也需要一个, 在 Joomla中这是非常简单的。现在来增加按钮来处理添加,修改,删除记录,还需要增加一个toolbar 上的标题。以下的代码就可以添加按钮了,为添加按钮,我们使用了Joomla的 JToolBarHelper 静态类。JToolBarHelper:title( JText:_( Hello Manager), generic.png);JToolBarHelper:deleteList();JToolBarHelper:editListX();JToolBarHelper:addNewX();以上的三个方法创建了三个按钮,deleteList()有三个可选参数,一是提示用户确认删除的字符串,二是请求中需要发送的task,默认是 remove,三是显示在删除按钮下边的文字。editListX() 和 addNewX()方法有两个参数,一是 task(默认的是 edit 和 add),二是按钮下显示的文字。请注意JText:_()方法,这是一个处理多语言的方便的函数,这个寻找你语言文件中对应的字符串,并返回转换后的字符串,如果没有找到字符串,将直接返回传递给JText:_()的字符串。如果你要翻译你的组件,你要做的工作就是创建一个语言文件,这个语言文件包含字符串的map集合。复选框和链接按钮现在有了,可是修改和删除是要针对已存在的记录。但是需要用户选择那些记录需要进行这些操作。因此,我们在模板中添加了复选框。我们在表格中添加额外的一列。在这一个列的表头中,我们添加了一个复选框,这个复选框用来选中和清除所有复选框的装提案。input type=checkbox name=toggle value= onclick=checkAll(items ); ?);/Joomla的 Javascript包含了一个函数 checkAll ,这里我们使用了这个函数。接下来需要给每一行添加一个复选框, Joomla的 JHTML 类有一个函数 JHTML:_() ,以下就是代码:$checked= JHTML:_( grid.id, $i, $row-id );$row =& $this-items$i;需要修改记录的时候,先选中复选框,然后再点击上边的edit 按钮,这样的操作比较繁琐,因此,我们要添加一个链接,直接进入编辑界面。以下是代码:$link = JRoute:_(index.php?option=com_hello&controller=hello&task=edit&cid=.$row-id );名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 16 页,共 24 页 - - - - - - - - - ahref=greeting; ?值得注意的是,链接中的controller 指向 hello controller,这个 controller 处理数据操作。在返回看一下form, 其中有四个隐藏的输入域。 第一个是 option, 这是进入 component必须的,第二是 task, 对应这 Toolbar上的按钮操作,如果没有这个字段,Javascript将报错,从而操作失败。第三个字段是boxchecked ,主要是有多少复选框被选中, edit 和 delete按钮操作会检查这个字段不小于0,最后一个是 controller,这个输入决定采用那个 controller。以下是模板 default.php的代码清单 :items); $i items$i;?tr class=id; ?greeting; ?hellos View 的模版完成了,现在需要完成hello Controller 和 Model, 他们实际是处理复杂数据工作。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 17 页,共 24 页 - - - - - - - - - Hello Controller默认的 controller 仅仅是展示数据,现在需要controller 能处理从 hellosView 发出的添加,删除,修改任务,添加和编辑本质是相同的任务,他们都是显示给用户一个form 来做 greeting编辑,不同的是添加是一个空的 form,而 edit 有数据,因此我们把add任务映射给 edit 钩子函数。下面的构造器中做了这个操作:/* constructor(registersadditional tasksto methods)* return void*/function _construct()parent:_construct();/ RegisterExtra tasks$this-registerTask(add ,edit );JController:registerTask是将 add映射到 edit 钩子函数上。现在我们处理编辑任务,controller 处理 edit任务相当简单,所要做的仅仅是指定View 和模板,这里在编辑的同时要禁用主菜单,从而用户不能离开而不保存数据。 edit 任务的钩子函数清单 :/* display theedit form* return void*/function edit()JRequest:setVar(view, hello );JRequest:setVar(layout, form);JRequest:setVar(hidemainmenu, 1);parent:display();Hello ViewHello view 显示一个表单允许用户编辑。display 要完成下面一些简单任务:从 model 获取数据创建 toolbar给模板 template传递数据调用 display()填充模板因为要处理编辑和添加,所以稍稍有点复杂。在Toolbar 中需要用户知道是否在添加或编辑,从而我们决定触发那个任务。因为我们已经从Model 获取了数据,因而可以推断是那个任务被触发,如果是编辑,那么 id 字段是有数据的,否则,这个字段就是空的,由此可以确定是添加还是编辑记录。在 toolbar 中还添加了两个按钮,保存和取消。display 方法的清单如下 :/* display methodof Hello view* return void*/function display($tpl = null)/get the hello名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 18 页,共 24 页 - - - - - - - - - $hello=& $this-get(Data);$isNew= ($hello-id 1);$text = $isNew ? JText:_( New ) : JText:_( Edit );JToolBarHelper:title(JText:_( Hello ).: . $text. );JToolBarHelper:save();if ($isNew) JToolBarHelper:cancel(); else/ for existing itemsthe button is renamedcloseJToolBarHelper:cancel(cancel,Close);$this-assignRef(hello,$hello);parent:display($tpl);Hello Model现在我们来创建 Model。Model 有两个属性 _id 和_data。 _id 存贮 id,_data存储 greeting数据。构造器中首先从 request中取得 id:/* Constructorthat retrievesthe ID from therequest* accesspublic* returnvoid*/function _construct()parent:_construct();$array= JRequest:getVar(cid,0, , array);$this-setId(int)$array0);JRequest:getVar() 方法用来从 request中获取数据。第一个参数是form 变量的名称,第二个参数是参数默认值,第三个参数henameof thehashto retrieve thevalue from,第四个是数据类型。构造器将取得 cid 数组中的第一个值并赋给id.setId()被用来设置 id,如果 id 变化了,那么对应的data也应该变化,否则就出错了,因此当我们设置id的值的时候,清空data的数据。/* Method to setthehello identifier* accesspublic* paramint Hello identifier* returnvoid*/function setId($id)/ Setid andwipe data$this-_id= $id;名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 19 页,共 24 页 - - - - - - - - - $this-_data= null;最后还要有 getData()来获取数据, getData检查 data是否已经设置,如果已经设置,仅仅返回,如果没有,就从数据库载入。/* Method to geta hello* return object with data*/function &getData()/ Load the dataif (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= newstdClass();$this-_data-id= 0;$this-_data-greeting= null;return $this-_data;表单 Form以下是表单的代码清单::input class=text_areatype=text name=greetingid=greeting size=32 maxlength=250value=hello-greeting;? /名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 20 页,共 24 页 - - - - - - - - - input type=hidden name=id value=hello-id; ? /注意,有一个 id 隐藏项,我们不应该改变id,而仅仅是传递。到目前为止,我们仅处理了编辑和添加,还有保存,删除,取消没处理,现在要写执行这些任务的代码。保存记录理论上我们需要实现保存数据的功能,可能需要一些逻辑分支处理不同情况。幸运的是Joomla接管了很多这样的工作。 JTable类实现了数据操作功能,而不必关心实际的sql 语句,并且把数据从form 加入数据库更简单了。创建 Table 类JTable是一个抽象类,对于指定的数据库表我们要从JTable继承类,这里我们只需要创建一个类,添加字段作为属性 ,重写 constructor指定表名和主键就可以了。以下是JTable的代码清单 :这里定义了 id 和 greeting,构造器中指定了表名hello 和主键 id在 M odel 中实现数据操作现在添加一个 store方法用来保存数据, store要绑定 form 传递的数据到 TableHello 对象,检查数据格式是否正确,保存数据。 store方法代码如下 :/* Method to storea record* accesspublic* returnbooleanTrue onsuccess*/function store()$row =& $this-getTable();$data= JRequest:get(post);/ Bind theform fields to the hello tableif (!$row-bind($data) $this-setError($this-_db-getErrorMsg();returnfalse;/ Make surethehello recordis validif (!$row-check() $this-setError($this-_db-getErrorMsg();r