登录 注册

登录

问题 [原创]zend framework 整合smarty 创建 joomla 组件思路

更多
2009年12月18日 19:28 - 2009年12月18日 20:39 #1 作者: 影雪
[原创]zend framework 整合smarty 创建 joomla 组件思路

首先, 我们为什么要用zend framework 而抛弃 joomla 的 MVC 类 ?
很重要一个原因就是: joomla 的MVC 很不规范 ,  里面很多小错误往往采用屏蔽而不是修复的方法:

以search组件为例: 打开components\com_search\search.php :
在defined( '_JEXEC' ) or die( 'Restricted access' ); 后面加上一行: error_reporting(E_ALL|E_STRICT);

最终代码如下:
 
<?php
defined( '_JEXEC' ) or die( 'Restricted access' );
error_reporting(E_ALL|E_STRICT);
require_once (JPATH_COMPONENT.DS.'controller.php');
$controller = new SearchController( );
$controller->execute(JRequest::getCmd('task'));
$controller->redirect();
 

然后在后台菜单管理的任意一个Menu里面加上search组件的内部链接, 点击进入该链接:
就会发现满屏都是报错:
Strict Standards: Non-static method JLoader::import() should not be called statically in D:\usr\xampp\htdocs\libraries\loader.php on line 186
 
Strict Standards: Non-static method JApplicationHelper::getPath() should not be called statically, assuming $this from incompatible context in D:\usr\xampp\htdocs\libraries\joomla\application\component\helper.php on line 168
 
Strict Standards: Non-static method JRequest::getCmd() should not be called statically, assuming $this from incompatible context in D:\usr\xampp\htdocs\libraries\joomla\application\helper.php on line 112
 
Strict Standards: Non-static method JRequest::getVar() should not be called statically, assuming $this from incompatible context in D:\usr\xampp\htdocs\libraries\joomla\environment\request.php on line 255
 
Strict Standards: Non-static method JRequest::_cleanVar() should not be called statically, assuming $this from incompatible context in D:\usr\xampp\htdocs\libraries\joomla\environment\request.php on line 134
 
Strict Standards: Non-static method JFilterInput::getInstance() should not be called statically, assuming $this from incompatible context in D:\usr\xampp\htdocs\libraries\joomla\environment\request.php on line 577
 
......... ..............
 

所以我认为: 为何我们非得要用 joomla 不成熟的 MVC 去开发我们的 joomla 组件呢? 使用 zend framework (本文简称为zf)标准不是更好吗? 于是就有了此文的诞生!

注: 要开发joomla组件, 还是需要我们研究下joomla 的 MVC 类的, 这是我们转用zf的基础;
而研究透彻joomla的数据库结构更是我们成功的必要条件.

思路如下:


首先在joomla上面注册一个组件, 以garden 为例,关键代码是:
<?php
 
$db->query('set names gb2312'); 
$sql = "SELECT `id` FROM `" . $joomla . "components` WHERE `name` = 'garden' Limit 1";
if(!$db->fetchRow($sql)){
	$row = array (
    'name' => 'garden',
    'link' => 'option=com_garden',
    'menuid' => 0,
    'parent' => 0,
    'admin_menu_link' => 'option=com_garden',
    'admin_menu_alt' => 'ShadowGarden',
    'option' => 'com_garden',
    'ordering' => 0,
    'admin_menu_img' => 'js/ThemeOffice/component.png',
    'iscore' => 0,
    'params' => 'enabled=0',
    'enabled' => 1
  );
  $table = $joomla . "components";
  $rows_affected = $db->insert($table, $row);
  if ($rows_affected){
		echo '组件安装成功: ';
	}
	else{
		echo '组件安装失败: ';
	}
}
 

Zend framework环境搭建:

网上下载Zend framework 1.9以上的版本, 我们只需要里面的library/zend目录
最好将zend目录放在网站根目录的上一级目录, 然后设定php.ini的include_path, 或者用
set_include_path()函数指定; (这里本文直接放到组件目录里面了)

Smarty 的整合

 这里我们不用zf默认的phtml模板, 而是用Smarty的tpl模板, 为何? Smarty是一个使用PHP写出来的模板PHP模板引擎,它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目的就是要使PHP程序员同美工分离,使程序员改变程序的逻辑内容不会影响到美工的页面设计,美工重新修改页面不会影响到程序的程序逻辑,这在多人合作的项目中显的尤为重要。
网上下载smarty, 我这里将libs目录改为 libraries


目录结构(假设htdocs是根目录)
 
-htdocs
   -administrator           //后台管理文件,我没有演示
      -components
          -com_garden
             -garden.php
             -garden.xml
             -index.xml
    -components
          -com_garden
               -application
                      -controllers
                           -ErrorController.php
                           -IndexController.php
                      -models
                      -views
                           -filters
                           -helpers
                           -scripts
                                -error
                                     -error.phtml
                                -index
                                     -index.phtml  //空的index.phtml
              -config
                  -smarty_c
                  -zend_c
                          -config.ini  //zf的配置文件
              -html                //放图片,css,js的地方
                   -css
                   -image
                   -js
              -library
                   -Smarty
                           -libraries           //原smarty的libs目录 
                           -main.php          
                    -Zend                  //原zf的 library/zend目录   
              -template
                    -cache
                    -templates
                    -index.tpl           //smarty的模板
                    -templates_c
               -views                        //这个不是给zf而是给joomla调用的 
                    -garden
                         -tmpl
                                -default.php
                                -default.xml
                                -index.html
                         -index.html
                         -metadata.xml
                         -view.php
                    -index.html
           -.htaccess
           -garden.php                 //joomla调用入口文件
           -garden.xml
           -index.html
           -index.php
 


5. 文件.htaccess
#RewriteEngine on
#RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
#
RewriteEngine on 
RewriteCond %{REQUEST_FILENAME}  !-f 
RewriteRule  .*  index.php
Options -Indexes
php_flag magic_quotes_gpc  off 
php_flag register_globals  off 
php_flag short_open_tag    off

6. zf入口程序 index.php

其他代码就不一一贴出了,只贴出zf入口程序index.php和library/smarty 里面的 main.php
注: 这里的php标记只有开头的 '<?php' 而没有结尾的 '?> ', 参见拙文<<Joomla的 PHP文件末尾为何没有加上 '?>'  >>
另外joomla和zf有冲突,解决方法是用iframe调用, 见components/com_garden/garden.php,里面内嵌了调用的代码
 
<?php
 
define( 'S_GARDEN' , 1);                
//入口的常量, 配合defined('S_GARDEN') or exit('403 Forbidden'); 若没有指定调用会提示
define( 'DS', DIRECTORY_SEPARATOR ); //路径分隔符
define( 'H_ROOT', dirname(__FILE__) );  //网站根目录的路径
error_reporting(E_ALL|E_STRICT);   //设定错误报告级别
ini_set('display_errors',1);            //设定是否报告错误
date_default_timezone_set('Asia/Shanghai');  //设定时区
 
 
$ini_paths  = '.'.PATH_SEPARATOR. H_ROOT . DS . 'library'. DS ;
$ini_paths .= PATH_SEPARATOR. H_ROOT . DS . 'application'. DS ;
$ini_paths .= PATH_SEPARATOR. H_ROOT . DS . 'application'. DS . 'models' . DS ;
$ini_paths .= get_include_path();      //加上原来的include_path  
set_include_path($ini_paths);        //设定include_path
 
require_once 'Zend/Loader/Autoloader.php';           //初始化加载
require_once 'Zend/Db.php';                       //zf的db类
require_once( H_ROOT . '/library/smarty/main.php' );  //引入smarty入口程序
 
Zend_Loader_Autoloader::getInstance()->setFallbackAutoloader(true);
$config = new Zend_Config_Ini( H_ROOT  .  '/config/zend_c/config.ini', 'staging' );
Zend_Registry::set('smarty',$tpl);
Zend_Registry::set('config', $config);   //读取zf的config.ini数据库链接参数
 
/*
//Config.ini参数
; 生产站点配置数据
[production]
database.adapter         = pdo_mysql
database.webhost         = [url=http://www.shadowsnow.com]www.shadowsnow.com[/url]
database.params.host     = db.shadowsnow.com
database.params.username = dbuser
database.params.password = secret
database.params.dbname   = dbname
database.joomla   = jos_
database.garden   = gdn_
 
; 开发站点配置数据从生产站点配置数据集成并如果需要可以重写
[staging : production]
database.params.host     = localhost
database.params.username = root
database.params.password = 
database.params.dbname   = garden
database.joomla   = jos_
database.garden   = gdn_
 
//使用db类的例子:
$login = array ('host' =>'localhost',
 'username' => 'root',
 'password'=>'',
'dbname'=>'garden'
);
$db = Zend_Db::factory($config->database->adapter, $login); 
*/
 
$db = Zend_Db::factory($config->database->adapter, $config->database->params); 
$joomla = $config->database->joomla;
$garden = $config->database->garden; 
$db->query('set names gb2312'); 
$sql = "SELECT `id` FROM `" . $joomla . "components` WHERE `name` = 'garden' Limit 1";
if(!$db->fetchRow($sql)){
	$row = array (
    'name' => 'garden',
    'link' => 'option=com_garden',
    'menuid' => 0,
    'parent' => 0,
    'admin_menu_link' => 'option=com_garden',
    'admin_menu_alt' => 'ShadowGarden',
    'option' => 'com_garden',
    'ordering' => 0,
    'admin_menu_img' => 'js/ThemeOffice/component.png',
    'iscore' => 0,
    'params' => 'enabled=0',
    'enabled' => 1
  );
  $table = $joomla . "components";
  $rows_affected = $db->insert($table, $row);
  if ($rows_affected){
		echo '组件安装成功: ';
	}
	else{
		echo '组件安装失败: ';
	}
}
 
$frontController = Zend_Controller_Front::getInstance(); 
$frontController->throwExceptions(true); 
$frontController->setControllerDirectory('application/controllers'); 
$frontController->dispatch();
 
 

7. Smarty入口程序main.php

library/smarty 里面的 main.php:
 
<?php
 
defined('S_GARDEN') or exit('403 Forbidden');
define( 'S_ROOT', dirname(__FILE__) ); 
require_once( S_ROOT . DS .'libraries' . DS . 'Smarty.class.php' );
 
$tpl = new Smarty();
$tpl->template_dir    = H_ROOT . DS . 'template' . DS . 'templates' . DS;
$tpl->compile_dir     = H_ROOT . DS . 'template' . DS . 'templates_c' . DS;
$tpl->config_dir      = H_ROOT . DS . 'template' . DS . 'conf_smarty' . DS;
$tpl->cache_dir       = H_ROOT . DS . 'template' . DS . 'cache' . DS;
$tpl->caching         = false; 
$tpl->left_delimiter  = '<{';
$tpl->right_delimiter = '}>';
 

使用方法:
下载后将administrator和components 目录覆盖到joomla根目录, 然后访问
[url=http://yourdomain/components/com_garden/index.php]http://yourdomain/components/com_garden/index.php[/url]即可安装成功!
在后台菜单管理的任意一个Menu里面加上garden组件的内部链接即可访问

9. 所有文件代码打包下载:

http://www.shadowsnow.com/garden/zf-sy-jm.rar

路漫漫而修远兮,吾将上下而求索 [本人开发的免费网赚程序  www.shadowsnow.cn/GetForFree/index.asp ]

登录 或者   注册一个会员帐号 来参与讨论

更多
2009年12月18日 20:21 #2 作者: 影雪
views/garden目录文件

1. view.php
 
<?php
/**
* @version		$Id: view.php 10498 2008-07-04 00:05:36Z ian $
* @package		Joomla
* @subpackage	Garden
* @copyright	Copyright (C) 2005 - 2008 Open Source Matters. All rights reserved.
* @license		GNU/GPL, see LICENSE.php
* Joomla! is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/
 
// Check to ensure this file is included in Joomla!
defined( '_JEXEC' ) or die( 'Restricted access' );
 
jimport( 'joomla.application.component.view');
 
/**
* @package		Joomla
* @subpackage	Garden
*/
class GardenViewGarden extends JView
{
	function display( $tpl = null )
	{
		$mainframe	= &JFactory::getApplication();
		$document	= &JFactory::getDocument();
 
		// auto height control
		if ( $this->params->def( 'height_auto' ) ) {
			$this->Garden->load = 'onload="iFrameHeight()"';
		} else {
			$this->Garden->load = '';
		}
 
		// Get the page/component configuration
		$params = &$mainframe->getParams();
 
		$menus	= &JSite::getMenu();
		$menu	= $menus->getActive();
 
		// because the application sets a default page title, we need to get it
		// right from the menu item itself
		$document->setTitle( $params->get( 'page_title' ) );
 
		$this->assignRef('params',		$params);
 
		parent::display($tpl);
	}
}
 

2. tmpl/default.php
 
<?php // no direct access
defined('_JEXEC') or die('Restricted access'); ?>
<script language="javascript" type="text/javascript">
function iFrameHeight() {
	var h = 0;
	if ( !document.all ) {
		h = document.getElementById('blockrandom').contentDocument.height;
		document.getElementById('blockrandom').style.height = h   60   'px';
	} else if( document.all ) {
		h = document.frames('blockrandom').document.body.scrollHeight;
		document.all.blockrandom.style.height = h   20   'px';
	}
}
</script>
<div class="contentpane<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
<?php if ( $this->params->get( 'show_page_title', 1 ) ) : ?>
	<div class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
	<?php echo $this->escape($this->params->get( 'page_title' )); ?>
	</div>
<?php endif; ?>
<iframe <?php echo $this->Garden->load; ?>
	id="blockrandom"
	name="iframe"
	src="<?php echo $this->Garden->url; ?>"
	width="<?php echo $this->params->get( 'width' ); ?>"
	height="<?php echo $this->params->get( 'height' ); ?>"
	scrolling="<?php echo $this->params->get( 'scrolling' ); ?>"
	align="top"
	frameborder="0"
	class="Garden<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
	<?php echo JText::_( 'NO_IFRAMES' ); ?>
</iframe>
</div>
 

路漫漫而修远兮,吾将上下而求索 [本人开发的免费网赚程序  www.shadowsnow.cn/GetForFree/index.asp ]

登录 或者   注册一个会员帐号 来参与讨论

更多
2009年12月18日 20:25 #3 作者: 影雪
application/controllers/IndexController.php
 
<?php
 
class IndexController extends Zend_Controller_Action
{ 
protected $smarty;
function init() {
   $this->smarty = Zend_Registry::get('smarty');
   $this->smarty->assign('title','ShadowGarden');
}
    public function indexAction(){
 
    $this->smarty->assign('content','欢迎来到影雪家园');
         $this->smarty->display( H_ROOT . '/template/templates/index.tpl' );
    }
    
    public function baibaiAction(){
    		 $this->smarty->assign('content','再见');
   			 $this->smarty->display( H_ROOT . '/template/templates/index.tpl' );
    }
    
    public function errorAction(){
        $this->smarty->assign('content','错误了');
        $this->smarty->display( H_ROOT . '/template/templates/index.tpl' );
    }
}
 


application/controllers/ErrorController.php

<?php
/** Zend_Controller_Action */
 
require_once('Zend/Controller/Action.php');
 
class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
    }
}
 
 

路漫漫而修远兮,吾将上下而求索 [本人开发的免费网赚程序  www.shadowsnow.cn/GetForFree/index.asp ]

登录 或者   注册一个会员帐号 来参与讨论

更多
2009年12月18日 20:28 - 2009年12月18日 20:34 #4 作者: 影雪
config/zend_c/config.ini 数据库链接配置文件

若安装不成功,很可能是因为您的config.ini没有配置好
; 生产站点配置数据
[production]
database.adapter         = pdo_mysql
database.webhost         = [url=http://www.shadowsnow.com]www.shadowsnow.com[/url]
database.params.host     = db.shadowsnow.com
database.params.username = dbuser
database.params.password = secret
database.params.dbname   = dbname
database.joomla   = jos_
database.garden   = gdn_
 
; 开发站点配置数据从生产站点配置数据集成并如果需要可以重写
[staging : production]
database.params.host     = localhost
database.params.username = root
database.params.password = 
database.params.dbname   = garden
database.joomla   = jos_
database.garden   = gdn_
 

template/templates/index.tpl
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title><{$title}></title>
</head>
<body>
<{$content}>
</body>
</html>
 

路漫漫而修远兮,吾将上下而求索 [本人开发的免费网赚程序  www.shadowsnow.cn/GetForFree/index.asp ]

登录 或者   注册一个会员帐号 来参与讨论

更多
2009年12月18日 20:36 #5 作者: 影雪
smarty中文手册:  http://www.hbcms.com/main/smarty/

zend framework 中文手册: http://www.phpeye.com/zf/index.html

路漫漫而修远兮,吾将上下而求索 [本人开发的免费网赚程序  www.shadowsnow.cn/GetForFree/index.asp ]

登录 或者   注册一个会员帐号 来参与讨论