近来研究joomla的源码,很多地方很迷惑。可能是以前没有用过PHP,很多东西一时半会还不能做到很清晰,故在这里记录一些点滴,也算是作个笔记吧。
在自定义一个component时,可能使用MVC的方式来做,这时就很自然地从JController、JModel、JView派生自己定义的类。这里说的“名称”包括两种:(1)自定义类的类名称 (2)定义类的文件名称和路径
(1)[b]自定义类的类名称[/b]
首先看[b]JController[/b]:
function getName()
{
$name = $this->_name;
if (empty( $name ))
{
$r = null;
if ( !preg_match( '/(.*)Controller/i', get_class( $this ), $r ) ) {
JError::raiseError(500, "JController::getName() : Cannot get or parse class name.");
}
$name = strtolower( $r[1] );
}
return $name;
}
由正则表达式/(.*)Controller/i可以看出:自己定义Controller派生类时,需要包含[i]Controller[/i],用getName()得到的Controller名是整个类名的前缀(即[i]Controller[/i]前面的部分)。这个名称的对取Model和View都是有影响的:
function &getModel( $name = '', $prefix = '', $config = array() )
{
if ( empty( $name ) ) {
$name = $this->getName();
}
if ( empty( $prefix ) ) {
$prefix = $this->getName() . 'Model';
}
/*其它代码*/
function &getView( $name = '', $type = '', $prefix = '', $config = array() )
{
static $views;
if ( !isset( $views ) ) {
$views = array();
}
if ( empty( $name ) ) {
$name = $this->getName();
}
if ( empty( $prefix ) ) {
$prefix = $this->getName() . 'View';
}
/*其它代码*/
由上面可以看出,如果取Model或View时,如果$name或者$prefix不指名时,Controller的类名称前缀会成为Model、View类名称的一部分。
再看[b]JModel[/b]:
function getName()
{
$name = $this->_name;
if (empty( $name ))
{
$r = null;
if (!preg_match('/Model(.*)/i', get_class($this), $r)) {
JError::raiseError (500, "JModel::getName() : Can't get or parse class name.");
}
$name = strtolower( $r[1] );
}
return $name;
}
从正则表达式/Model(.*)/i看出:Model名需要包含[i]Model[/i],此时geName()得到的Model名是整个类名的后缀(即[i]Model[/i]后面的部分)。
接着看[b]JView[/b]:
function getName()
{
$name = $this->_name;
if (empty( $name ))
{
$r = null;
if (!preg_match('/View((view)*(.*(view)?.*))$/i', get_class($this), $r)) {
JError::raiseError (500, "JView::getName() : Cannot get or parse class name.");
}
if (strpos($r[3], "view"))
{
JError::raiseWarning('SOME_ERROR_CODE',"JView::getName() : Your classname contains the substring 'view'. ".
"This causes problems when extracting the classname from the name of your objects view. " .
"Avoid Object names with the substring 'view'.");
}
$name = strtolower( $r[3] );
}
return $name;
}
JView中取名字的正则表达式为:/View((view)*(.*(view)?.*))$/i,比Controller和Model的都复杂一些。即类名必须包含[i]View[/i](注意第一个字母是大写的),如果在[i]View[/i]后面还带"view"时,可以有0个到多个"view"。用getName()取得的名称是[i](.*(view)?.*)[/i]中取得匹配的部分,即[i]View[/i]后面如果不直接带"view"时,取得的是[i]View[/i]后面的所有字符串;如果[i]View[/i]后面直接带"view"(一个或多个)时,取得的是除去所连接"view"后面的所有字符串(不包含"view")。
之前就试过自定义View类中不带[i]View[/i],结果找不到这个类。
例子:
/*下面是摘自《Learning Joomla! 1.5 Extension Development》的例子*/
//Controller名带前缀"Review"
class ReviewController extends JController
{
function display()
{
$document =& JFactory::getDocument();
$viewName = JRequest::getVar('view', 'all'); //此时$viewName="all"
$viewType = $document->getType(); //此时$viewType="html"
//由于getView()只给了两个参数,故$preffix使用默认:Controller名前缀加$viewName
//即"Review"."View"."All"
$view = &$this->getView($viewName, $viewType);
//getModel()中"ModelReviews"为前缀,加上$viewName
$model =& $this->getModel( $viewName, 'ModelReviews' );
if (!JError::isError( $model )) {
$view->setModel( $model, true );
}
$view->setLayout('default');
$view->display();
}
}
//Model名带"Model"
class ModelReviewsAll extends JModel
{}
//View名带View
class ReviewViewAll extends JView
{}
[b]小结[/b]
(1) Controoler类名可以先指定一个前缀如:CtrlName
(2) Model类名的指定分情况:getModel( $name = '', $prefix = '', $config = array() )
a.如果指定$name,不指定$prefix,则Model类名为:CtrlName.'Model'.$name
b.如果$name和$prefix都指定,则Model类名为:$prefix.$name
(3) View类名的指定也分情况:getView( $name = '', $type = '', $prefix = '', $config = array() ) ($type主要是在找文件路径中用到)
a.如果指定$name,不指定$prefix,则View类名为:CtrlName.'View'.$name
b.如果$name和$prefix都指定,则View类名为:$prefix.$name
此外,定义这些类的时候,可以在Controller::__construct()中指定名字$this->_name,这时Controller的类名前缀就可以与Model、View没有关系,而是与$this->_name有关系。如果不是在构造函数中给$this->_name,则Model类名中必须带"Model",View类名中必须带"View",否则在getName()方法中会抛异常。
(2)[b]定义类的文件名称和路径[/b]
这个留到下篇写吧。