你现在的位置:首页 > PHP网站建设知识库 > Joomla > 正文

Joomla1.5组件开发:类和方法

JDocument
在google搜索我的网站就会发现一些,因为没有注意meta和title所有的开源项目相关的页面title和meta都一样,对用户很不友好,根本无法分清那个链接是说什么内容的,那么这里就需要JDocuement类来解决问题

用法很简单,首先取得document对象 $document =&JFactory::getDocument();

然后:
$document->setTitle(*****);

$document->setDescription(*****); //添加 meta

$document->addStyleSheet(*****) //添加CSS文件

$document->addScript(*****) //添加js脚本

$document->setLanguage(***)  //设置语言文件

其他还有一些setModifiedDate等,其他基本就不常用了,记住这些就行啦!

JFactory
JFactory类,正如其名,这是一个工厂类,应该是简单工厂模式的标准实现。这个类几个重要的函数分别返回几个重要的实例。

1、getACL 调用_createACL返回 joomla.user.authorization 的实例,数据来源

2、getApplication 调用 joomla.application.application 的实例获取函数JApplication::getInstance,也就是我们在index.php中提到的 $mainframework

3、getConfig 调用_createConfig 返回 joomla.registry.registry 实例,返回配置参数

4、getDBO 调用_createDBO,返回数据连接JDatabase的实例,这个是以后扩展模块要经常用到的

5、getDocument 调用 _createDocument 根据请求的格式,返回JDocumentRaw或者JDocumentHtml实例

6、返回 Juser 实例

7、getLanguage 调用 _createLanguage 返回 joomla.i18n.language的实例,以后在多语言环境经常用到。

其他的比如getMailer,getCache 等就不在写了

JDatabase
这是数据库connector类,封装了与数据库操作的一系列操作。目前有两个子类,JDatabaseMysql,JDatabaseMysqli,这个类为以后扩展到其他数据库留出了接口。

关于一些具体函数没有什么特殊的,基本对应mysql的函数的一些特征,对于这个类应用基本都是首先 setquery,然后load或者直接执行 executequery ,主要还是不要混淆load开头的几个函数的具体功能:

1、loadObject以对象的形式返回结果集的第一行数据

2、loadObjectList对应上一个函数,返回一个对象的集合

3、loadResult返回第一行的第一个字段或者NULL

4、loadResultArray返回某一字段的数据到一个数组中

5、loadRow返回第一行数据,应该是数组形式

6、loadRowList对应上一个函数,返回行数据的集合

还有一个函数很重要就是 setUTF,这个函数决定了数据库能显示中文。

JUser
user 类处理所有程序中与用户交互的相关事情。

这个类的构造函数调用load函数,输入的参数是用户id,可以初始化用户的相关信息,这些信息包括 aid,gid,usertype,username,name,id等等,这些信息在扩展中经常用到。

同时,在程序中,用刚刚说过的getUser,取得当前登录用户实例。具体用法如下:

$user  =&JFactory::getUser();
$userId  = (int) $user->get('id');

根据gid 可以判断用户的相关的组以及组权限。

了解了Juser类,还需要了解一下 JUserHelper类,这个类包括了与用户活动相关的几个函数,比如获得随机密码以及取得加密密码等。

同样 getUserId 根据用户名取得用户ID 也是经常用到的。

JPath JFileJFolder类
这几个类都是filesystem包中的重要类,具体的使用看我在模块快速生成器中的代码,函数意义都非常明确:

  if(JFolder::exists($targetpath))JFolder::delete($targetpath);
  JFolder::create($targetpath);
  JFolder::create($targetpath.DS.'tmpl');
 

  以上是目录使用的例子

  $sfile=$sourcepath.DS.'index.html';
  $tfile=$targetpath.DS.'index.html';
  JFile::copy($sfile,$tfile);
  $files[]=$tfile;
  文件拷贝

  $sfile=$sourcepath.DS.'helper.php';
  $data=JFile::read($sfile);
   $tfile = $targetpath.'/helper.php';
  JFile::write($tfile,$data);
  $files[]=$tfile;
  unset($data);

文件读取和写入

JHtml类
JHtml 没有几个函数,但是在组成页面已经模板书写过程中经常用到,比如:

JHTML::_('date',$this->item->date, JText::_('DATE_FORMAT_LC5'))

以及在后台管理中常用到的

来看看这几个函数:

calendar 显示一个日历插件

date 显示格式化日期

iframe 插入一个iframe

image  插入一个图片

link 插入一个超链

以上是常用的函数,函数的以用方式就如例子。

JToolBarHelperJToolBar类
这个两个类是后台管理过程经常用到的,比如:

  JToolBarHelper::title(  JText::_( '{{component}} Manager' ), 'generic.png' );

  JToolBarHelper::deleteList();

  JToolBarHelper::editListX();

  JToolBarHelper::addNewX();

 这几句就添加了三个按钮,添加,删除,修改

其实还有几个常用的

preview  //预览

publish //发布

cancel //取消

比较常用的就这几个了,主要是在后台管理toolbar上的按钮。相关按钮的动作对应后台管理的task,相应的对做要在controller中生命。

JText类
Joomla 最常用的类之一,使用方式JTEXT::_('JJJJJ')

JJJJJ对应语言文件中的相应字符串。

为了实现多语言这个是常用的。当然如果你以utf-8字符集存储php文件,对于中文就不用考虑那么多了,不过不够规范喓。

要是只是自己用,也无所谓啦,开发要快点。

呵呵!推荐还是用吧!

JRequest类
这是另一个Joomla扩展中最常用的类,这个类封装了客户端提交的请求相关的信息,通过这个类你可以得到用户提交的相关信息和数据,有几个重要的函数:

首先是get($hash),我们看看部分源码就知道,get得到什么了

  switch ($hash)
  {
   case 'GET' :
    $input = $_GET;
    break;

   case 'POST' :
    $input = $_POST;
    break;

   case 'FILES' :
    $input = $_FILES;
    break;

   case 'COOKIE' :
    $input = $_COOKIE;
    break;
 
   case 'ENV'    :
    $input = &$_ENV;
    break;
   
   case 'SERVER'    :
    $input = &$_SERVER;
    break;

   default:
    $input = $_REQUEST;
    break;
  }

 我们通过get('post')等取得用户提交的数据数组。

还有getVar ,取得某一request变量

getURI ,返回请求的URI

setVar和set则对应着getVar 和get

在程序中使用的方式是:JRequest::getVar(',');

组件是如何被调用并渲染的
Joomla代码中,组件是如何被调用并渲染的呢?

在描述 /index.php的时候,我们看到根据option参数,$mainframework->dispatch(),就进入了组件的调用并渲染的过程,我们来看看JSite的dispatch都做了什么工作。

dispatch 最关键的是这几句话:

  $document->setTitle($params->get('page_title') );   //设置标题
  $document->setDescription( $params->get('page_description'));  //设置meta

  $contents =JComponentHelper::renderComponent($component);
  $document->setBuffer( $contents, 'component');

可以看到最为关键的是JComponentHelper::renderComponent($component);

再看看这一行程序完成了那些工作

  $task = JRequest::getString('task' );

  // Build the component path
  $name = preg_replace('/[^A-Z0-9_\.-]/i', ', $name);
  $file = substr( $name, 4 );

  // Define component path
  define('JPATH_COMPONENT',     JPATH_BASE.DS.'components'.DS.$name);
  define('JPATH_COMPONENT_SITE',    JPATH_SITE.DS.'components'.DS.$name);
  define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR.DS.'components'.DS.$name);

  // get component path
  if ( $mainframe->isAdmin() &&file_exists(JPATH_COMPONENT.DS.'admin.'.$file.'.php') ) {
   $path = JPATH_COMPONENT.DS.'admin.'.$file.'.php';
  } else {
   $path = JPATH_COMPONENT.DS.$file.'.php';
  }

这部分实际上确定了那个compoent下的组件文件被引入,并取得了task,中间一部分兼容代码就不看了

我们来看关键代码:

  ob_start();
  require_once $path;
  $contents = ob_get_contents();
  ob_end_clean();

这部分代码就是包含了组件的开始文件,而这个文件,我们在组件开发的时候用到的。这个文件引入了controller文件,并根据task决定进入那个分支。

再深入下去就是组件的整个生成过程,以后再看了。

JTable是什么
JTable是什么?肯定不是对应html中的table,在做com_helloworld的时候,没有仔细理解,后来一位同事问我Jmodel,JTable,JDatabase有什么区别?一时语塞

JTable是数据库中数据表在程序中的表达,不知道这句话怎么说,其实JTable更对应着表中的一行,以及相应的操作。Joomla中的JTable**对应中数据库中 **表,我们在使用的时候要针对我们自己所使用的表扩展自己的JTable.我们需要关注的是JTable的函数checkin,checkout ,着两个函数对更新的数据进行合法性检查,我个人觉得对于数据完整性的检查应该放在Jtable的check中。

Jtable 比较常用的函数,看名字就明白了,记住几个吧:

delete,store,bind,load,setError等,具体还是需要用的时候看看源代码吧。

 JModel是什么
我们经常提到MVC模式,JModel在Joomla的MVC组件中是重要的一个环节,JModel是MVC中的数据视图层,我们需要明白的是JModel不同于JTable,数据视图是由一个或者几个table构成,或者多条数据记录构成的数据集合,以及数据集合的相关操作,对于JModel我们不必了解太多的具体函数,在组件开发过程中,通常都要继承JModel,在子类中完成数据集合的生成以及相关的操作,保存,删除。

我个人倾向对于几个表之间的数据完整性,要在JModel中验证,而对于单一表的数据完整性要通过JTable check函数完成。

同事对于那些有逻辑操作的验证则最好在MVC的 controller层完成。

Jview
MVC模式中,重要的一环,JView和 tmpl目录中的模板,共同决定了,页面html的代码,Jview是在Jmodel和template之间的桥梁。我们扩展做自己的组件,都需要扩展Jview的子类。这个类其实需要看看它的变量和函数也就理解:

跟数据相关的部分: 

_defaultModel  默认的model,可以通过 setModel进行设置。同时function &get可以从指定的model调用函数返回相应的数据

_models 存贮model的数组,getModel,可以从中返回指定的Model

 assign assignref,数据赋值函数,这两个函数的任务是赋值变量给模板。

跟模板相关部分:

loadTemplate,setLayout,setLayoutExt看名字就知道了

还有一个函数:display  ,大部分的view子类都要继承这个。

JController
同样 JController是MVC中重要的起点,正式这个类决定的动作的下一步流向,我们来看看表格提交数据的典型的controller的代码:

 

1.       function edit()  

2.       {  

3.        JRequest::setVar( 'view', 'hello' );  

4.        JRequest::setVar( 'layout', 'form'  );  

5.        JRequest::setVar('hidemainmenu', 1);  

6.        parent::display();  

7.       }  

8.       /** 

9.        * save a record (and redirect to main page) 

10.      * @return void 

11.      */  

12.     function save()  

13.     {  

14.      $model = $this->getModel('hello');  

15.      if ($model->store($post)) {  

16.       $msg = JText::_( 'Greeting Saved!' );  

17.      } else {  

18.       $msg = JText::_( 'Error Saving Greeting' );  

19.      }  

20.      // Check the table in so it can be edited.... we are done with it anyway  

21.      $link = 'index.php?option=com_hello';  

22.      $this->setRedirect($link, $msg);  

23.     }  

24.     /** 

25.      * remove record(s) 

26.      * @return void 

27.      */  

28.     function remove()  

29.     {  

30.      $model = $this->getModel('hello');  

31.      if(!$model->delete()) {  

32.       $msg = JText::_( 'Error: One or More Greetings Could not be Deleted' );  

33.      } else {  

34.       $msg = JText::_( 'Greeting(s) Deleted' );  

35.      }  

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

37.     }  

38.     /** 

39.      * cancel editing a record 

40.      * @return void 

41.      */  

42.     function cancel()  

43.     {  

44.      $msg = JText::_( 'Operation Cancelled' );  

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

46.     }  

 


实际上 controller跟提交的task参数,调用controller中的不同的函数,当然默认会调用display,我觉得还需要记住的就是

getModel,和setRedirect,其余函数用到再看就可以了。

MVC组件的执行
以前的文章中,我们曾经说过 $mainframework->dispatch是如何最终调用组件的,通过这个dispatch,最终 include相应组件目录下的组件名称.php文件,现在我们来看看,这个文件是怎么按部就班的联系了MVC模式相关的各个文件。

require_once(JPATH_COMPONENT.DS.'controller.php');

// Require specific controller ifrequested
if($controller = JRequest::getVar('controller')) {
 require_once (JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php');
}

// Create the controller
$classname = 'HelloController'.$controller;
$controller = new $classname( );

// Perform the Request task
$controller->execute( JRequest::getVar('task'));

// Redirect if set by the controller
$controller->redirect();

 其实就是根据request提交的controller参数,创建相应的JController对象,然后由controoler对象执行相应的任务。

这样我们就完全理解了,一个组件是如何被调用,MVC组件是如何执行,并最后返回html代码的。

Joomla源代码解析(二十一)模块是如何被调用执行并渲染?
以前的文章中,关于/index.php我们已经分析完了 $mainframe->dispatch()是引入了组件,并被执行。我们知道对于Joomla,一个页面只能有一个或者0个组件,而上,下左右的碎片都是module,module是页面丰富的有效补充。比如我们知道菜单是  mod_mainmenu,而footer是mod_footer等等,那么这些module是怎么被引入的,并最后执行的?

秘密都在$mainframe->render()这个函数上,我们看看这个函数都做了什么工作。

以下是JSite的render 函数的内容

  

 

1.       $document =& JFactory::getDocument();  

2.         $user     =& JFactory::getUser();  

3.         // get the format to render  

4.         $format = $document->getType();  

5.         switch($format)  

6.         {  

7.          case 'feed' :  

8.          {  

9.           $params = array();  

10.        } break;  

11.        case 'html' :  

12.        default     :  

13.        {  

14.         $template = $this->getTemplate();  

15.         $file   = JRequest::getCmd('tmpl', 'index');  

16.         if ($this->getCfg('offline') && $user->get('gid') < '23' ) {  

17.          $file = 'offline';  

18.         }  

19.         if (!is_dir( JPATH_THEMES.DS.$template ) && !$this->getCfg('offline')) {  

20.          $file = 'component';  

21.         }  

22.         $params = array(  

23.          'template'  => $template,  

24.          'file'  => $file.'.php',  

25.          'directory' => JPATH_THEMES  

26.         );  

27.        } break;  

28.        }  

29.       $data = $document->render( $this->getCfg('caching'), $params);  

30.       JResponse::setBody($data);  

 


其实重要的部分是引入了相应的模板文件(template/***/index.php),并调用了JDocumentHtml的 render 函数。

看到这里,我们终于明白了,模板的index.php原来是这个时候被引入的。

我们再看看 JDocumentHtml的render函数。

这个函数中最重要的两句程序是

  $data= $this->_loadTemplate($directory.DS.$template, $file);载入模板文件
  $data = $this->_parseTemplate($data); 解析模板

再继续看看解析模板是什么过程:

  

 

1.       $replace = array();  

2.         $matches = array();  

3.         if(preg_match_all('#<jdoc:include\ type="([^"]+)" (.*)\/>#iU', $data, $matches))  

4.         {  

5.          $matches[0] = array_reverse($matches[0]);  

6.          $matches[1] = array_reverse($matches[1]);  

7.          $matches[2] = array_reverse($matches[2]);  

8.          $count = count($matches[1]);  

9.          for($i = 0; $i < $count; $i++)  

10.        {  

11.         $attribs = JUtility::parseAttributes( $matches[2][$i] );  

12.         $type  = $matches[1][$i];  

13.         $name  = isset($attribs['name']) ? $attribs['name'] : null;  

14.         $replace[$i] = $this->getBuffer($type, $name, $attribs);  

15.        }  

16.        $data = str_replace($matches[0], $replace, $data);  

17.       }  

18.       return $data;  

19.      }  

 


对了,就是这部分,对模板中 JDOC标签进行了解析,获得了相应的module名称和参数,并调用getBuffer函数执行。

至此调用 $renderer->render($name, $attribs, $result); 

模块是如何被调用执行并渲染(下)
上一文章中提到了getBuffer函数,在函数中实际上调用了render,这个对象是JDocumentRendererModule类的实例,我们看看JDocumentRendererModule的render函数。

 

1.       if (!is_object($module))  

2.         {  

3.          $module =& JModuleHelper::getModule($module);  

4.          if (!is_object($module))  

5.          {  

6.           if (is_null($content)) {  

7.            return ';  

8.           } else {  

9.            /** 

10.           * If module isn't found in the database but data has been pushed in the buffer 

11.           * we want to render it 

12.           */  

13.          $tmp = $module;  

14.          $module = new stdClass();  

15.          $module->params = null;  

16.          $module->module = $tmp;  

17.          $module->id = 0;  

18.          $module->user = 0;  

19.         }  

20.        }  

21.       }  

22.       // get the user and configuration object  

23.       $user =& JFactory::getUser();  

24.       $conf =& JFactory::getConfig();  

25.       // set the module content  

26.       if (!is_null($content)) {  

27.        $module->content = $content;  

28.       }  

29.       //get module parameters  

30.       $mod_params = new JParameter( $module->params );  

31.       $contents = ';  

32.       if ($mod_params->get('cache', 0) && $conf->getValue( 'config.caching' ))  

33.       {  

34.        $cache =& JFactory::getCache( $module->module );  

35.        $cache->setLifeTime( $mod_params->get( 'cache_time', $conf->getValue( 'config.cachetime' ) * 60 ) );  

36.        $cache->setCacheValidation(true);  

37.        $contents =  $cache->get( array('JModuleHelper', 'renderModule'), array( $module, $params ), $module->id. $user->get('aid', 0) );  

38.       } else {  

39.        $contents = JModuleHelper::renderModule($module, $params);  

40.       }  

这段代码完成了找到对应的module,和helper文件,兑取参数,并最后由'JModuleHelper'执行,并渲染。

至此,我们也完全了解了模板是如何被调用,模块是如何并调用并渲染的。