1

sobipro是joomla上的CCK组件,之所以会有这样的组件是因为joomla并没有为内容添加字段的功能,joomla虽然是CMS,但它的内容组件可定制性十分弱,内容表现性并不丰富,所以不得不依赖第三方CCK组件。而sobipro是joomla cck组件中算得上比较专业的一款。

说它专业,除了它有强大的内容管理功能之外还有可扩展性,可以根据实现需要购买与下载官方提供的扩展模块,代码质量与稳健性也不错。但我在对它进行二次开发时发现了不少问题,往往会导致开发效率低下。以下是我总结的几点。

基于joomla框架之上再建框架,而官方并没有开发文档

joomla由于joomla1.5至joomla2.5过渡框架差异比较大,而且joomla框架提供的架构也不够灵活,所以不少组件会在joomla之上再建造兼容框架,为了可以同时兼容joomla新旧版本。而sobipro虽然也是MVC结构,但与joomla框架差异很大如果官方没有提供开发文档,只凭自己消耗时间阅读代码。

├─base
│  └─fs
├─cms (joomla兼容层)
│  ├─joomla15
│  │  ├─base
│  │  └─html
│  ├─joomla16
│  │  ├─base
│  │  ├─elements
│  │  └─html
│  └─joomla_common
│      ├─base
│      ├─elements
│      └─html
├─ctrl (控制器)
│  └─adm
├─env
├─helpers (辅助)
│  └─adm
├─js
│  ├─adm
│  ├─calendar
│  │  └─lang
│  └─codemirror
├─mlo
├─models (模型)
│  ├─adm
│  └─fields
├─plugins (插件)
├─services
│  └─installers
│      └─schemas
├─types
└─views (视图)
    └─adm

模板使用xslt

我第一次使用xslt就是在sobipro上,才知道xslt有多么难用,语法冗长、模板不灵活、调试难度大等问题严重影响开发效率。假设你只需要小修改它的模板,你必须先学习xslt语法,以下是我做一个动态链接的代码

<a class="field_positon_ordering" href="{$url}&amp;ordering=field_position.asc">
<xsl:if test="contains($ordering_classes, 'field_position') and contains($ordering_classes, 'asc')">
        <xsl:attribute name="href">
            <xsl:value-of select="concat($url, '&amp;ordering=field_position.desc')" />
        </xsl:attribute>
</xsl:if>
    Position <small class="arrow"></small>
</a>

这仅仅只是改模板,如果你需要添加一些数据属性,而XML并没有输出,那你只能修改view层给它添加数据,以下是sobipro输出XML之前的部分代码

$data[ 'name' ] = array(
                '_complex' => 1,
                '_data' => $this->get( 'listing_name' ),
                '_attributes' => array( 'lang' => Sobi::Lang( false ) )
            );
            if( Sobi::Cfg( 'category.show_desc' ) ) {
    $desc = $current->get( 'description' );
    if( Sobi::Cfg( 'category.parse_desc' ) ) {
        Sobi::Trigger( 'prepare', 'Content', array( &$desc, $current ) );
    }
    $data[ 'description' ] = array(
        '_complex' => 1,
        '_cdata' => 1,
        '_data' => $desc,
        '_attributes' => array( 'lang' => Sobi::Lang( false ) )
    );
}
$data[ 'meta' ] = array(
    'description' => $current->get( 'metaDesc' ),
    'keys' => $this->metaKeys( $current ),
    'author' => $current->get( 'metaAuthor' ),
    'robots' => $current->get( 'metaRobots' ),
);
$data[ 'entries_in_line' ] = $this->get( '$eInLine' );
$data[ 'categories_in_line' ] = $this->get( '$cInLine' );

这只是很小的一部分,其它简直是不知所云。如果官方有文档提供,这里的数据属性应该会比较好理解。

只是这种难度可能对于大多数人来是可以接受的,但你还得先找到你所见页面的view层在哪里,因为它真的很难找。joomla一般可以通过URL找到对应代码

index.php?option=com_content&view=article&id=1788

以上地址很容易可以知道代码在components/com_content/views/article/view.html.php
但sobipro并不总是这样,例如这个地址

index.php?option=com_sobipro&sid=5980

这个页面是分类列表页?分类页?内容页?都可能是!sobipro把三大数据类型section, category, content都叫entity,并且放在同一个数据表中,而且都用sid作为主键。所以你给它一个sid,它先在数据库查这个entity是什么类型,如果是category,就会给你category的Controller, Model, View, template。而因为这三大类型具有许多相同属性,所以它们的MVC是会放上继承的。例如category的view层其实是使用了section的view层,找起来像面条似的,你不做一些标记很容易会漏掉。幸好它只有这三种层次,所以我给所有的view层都加debug代码还是能找出来的,只是debug信息它都会屏敝。也由于输出是XML再用xslt转为HTML,像var_dump这样粗暴的方法会直接破坏xml代码,让xslt转换失败直接给你反馈空白页。sobipro改错一点就出现空白页,所以很难知道是什么原因导致的。

数据查询

joomla2开始已经有CRUD可用了,不像joomla 1.5需要写SQL。但如果要兼容新旧版本就可能需要再造CRUD的轮子。但造轮子也不至于这么难看吧

$table = $db->join(
    array(
        array( 'table' => 'spdb_field_option_selected', 'as' => 'opts' ),
        array( 'table' => 'spdb_language', 'as' => 'lang', 'key' => array( 'opts.optValue', 'lang.sKey' ) ),
        array( 'table' => 'spdb_object', 'as' => 'spo', 'key' => array( 'opts.sid', 'spo.id' ) ),
        array( 'table' => 'spdb_relations', 'as' => 'sprl', 'key' => array( 'opts.sid', 'sprl.id' ) ),
    )
);
try {
    $db->select( $oPrefix . 'id', $table, $conditions, $eOrder, $eLimit, $eLimStart, true );
    $results = $db->loadResultArray();
}
catch ( SPException $x ) {
    Sobi::Error( 'AlphaListing', SPLang::e( 'DB_REPORTS_ERR', $x->getMessage() ), SPC::WARNING, 0, __LINE__, __FILE__ );
}

这样的数据操作代码比SQL丑太多了,填一堆array的出错率高得很。不喜欢它可以使用joomla原生的查询方法,但二次开发情况有复杂,直接修改它会比重新写要稳定得多。特别是很多时候你不得不修改插件。

MVC层次组织不合理

一般C层作为入口都代表页面或者功能入口,但sobipro而数据类型为入口,我真不知道这种层次有什么优点,但缺点倒是不少。例如alpha插件(字母列表)只不过在原来的分类列表页加上字母筛选,用的都是同一套template,但alpha的M层竟然需要仿照分类页的M层重写一次,也就是我如果在列表页上添加新功能,我就需要在alpha插件再加一次。那是因为alpha不能复用M层,不得不在C层写SQL代码,并且还是很近似的代码,这样做成MVC有何用?

结论

sobipro如此美丽又专业的外观,却隐藏如此不合理的设计,但这在joomla的扩展群里是个普遍现象,好看不好使,好使不好改,sobipro也已经是其中做得不错的一个组件了,建议在做joomla二次开发时最好不要做太复杂的功能,也许简单的修改你都有可能改到吐血。


猫之良品
2.5k 声望139 粉丝

资深Drupal, magento与Joomla