我直接参考了joomla 自带的组件:com_banners(administrator\components\com_banners)的代码. 个人觉得1.5版本的目录还是比较随意的,但很符合MVC三层的概念. 自己还没开始做组件,想先等研究透了再说.
controllers/
elements/
helpers/
tables/
views/
admin.banners.php
banners.xml
config.xml
index.html

1. index.html 空文件不做任何处理

2. config.xml 配置文件,如果没有特别的配置可以不需要这个文件

3. banners.xml 这个是安装以及卸载时要上传的文件以及SQL语句.跟1.0差不多.banners组件基本上啥都没, 所以用另外一个组件来分析下

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/component-install.dtd">
<install type="component" version="1.5.0">
  
<name>helloworld</name><!--组件名字-->
  
<!-- The following elements are optional and free of formatting conttraints -->
  
<creationDate>February 2008</creationDate><!--组件创建时间-->
  
<author>Petr Vojtechovsky</author><!--作者-->
  
<authorEmail>vojtechovsky@gmail.com</authorEmail><!--EMAIL-->
  
<authorUrl>http://www.vojtechovsky.net</authorUrl><!--网站-->
  
<copyright>(C) 2007 All rights reserved.</copyright>
  
<license>GNU/GPL</license> <!--这个不要修改-->
  
<!--  The version string is recorded in the components table -->
  
<version>1.5.0</version><!--版本,这个也不要修改-->
  
<!-- The description is optional and defaults to the name 描述 出现在安装成功后的一些提示-->
  
<description><![CDATA[<p>write you description here! And it will show when you install this component!</p>]]></description>
  
<install>
    
<sql folder="admin/sql"><!--folder="admin/sql" SQL语句文件在安装包的文件所在位置-->
      
<file driver="mysql" charset="utf8">install.helloworld.sql</file>
    
</sql>
  
</install>
  
<uninstall>
    
<sql  folder="admin/sql">
      
<file driver="mysql" charset="utf8">uninstall.helloworld.sql</file>
    
</sql>
  
</uninstall>
 
  
<!--前台要安装的文件-->
  
<files folder="component">
    
<filename>index.html</filename>
    
<filename>helloworld.php</filename>
  
</files>
  
  
<languages folder="component/lang">
    
<language tag="en-GB">en-GB.com_helloworld.ini</language>
    
<language tag="cs-CZ">cs-CZ.com_helloworld.ini</language>
  
</languages>
  
  
<!--后台要安装的文件-->
  
<administration>
    
<!-- Administration Menu Section 后台的菜单-->
    
<menu img="components/com_helloworld/images/helloworld.png">Hello World</menu>
    
<submenu>
      
<!-- Note that all & must be escaped to &amp; for the file to be valid XML and be parsed by the installer 需要子菜单的必须把连接写上去,并且要求&符号用&amp;代替-->
      
<menu link="option=com_helloworld&amp;controller=helloworld">Hello World!</menu>
      
<menu link="option=com_helloworld&amp;controller=helloagain">Hello Again!</menu>
      
<menu link="option=com_helloworld&amp;controller=hellotestfoo">Testing Foo Function</menu>
    
</submenu>
    
<!-- Administration Main File Copy Section -->
    
<!-- Note the folder attribute: This attribute describes the folder to copy FROM in the package to install therefore files copied in this section are copied from /admin/ in the package -->
    
<files folder="admin">
      
<filename>index.html</filename>
      
<filename>admin.helloworld.php</filename>
      
<filename>toolbar.helloworld.php</filename>
      
<filename>toolbar.helloworld.html.php</filename>
      
      
<!-- install controllers -->
      
<filename>controllers/default.php</filename>
      
<filename>controllers/helloagain.php</filename>
      
<filename>controllers/hellotestfoo.php</filename>
      
<filename>controllers/helloworld.php</filename>
      
      
<!-- install model - one for all -->
      
<filename>models/helloworld.php</filename>
      
      
<!-- install views -->
      
<filename>views/default/view.php</filename>
      
<filename>views/helloagain/view.php</filename>
      
<filename>views/hellotestfoo/view.php</filename>
      
<filename>views/helloworld/view.php</filename>
      
<filename>images/helloworld.png</filename>
    
</files>
    
    
<files folder="admin/sql">
      
<!-- database script -->
      
<filename>install.helloworld.sql</filename>
      
<filename>uninstall.helloworld.sql</filename>
    
</files>
 
    
<!-- Administration Language File Copy Section -->
    
<languages folder="admin/lang">
      
<language tag="en-GB">en-GB.com_helloworld.ini</language>
      
<language tag="cs-CZ">cs-CZ.com_helloworld.ini</language>
    
</languages>
  
</administration>
</install>

4.admin.banners.php 这个文件的主要作用就是把MVC三层里面的文件调用起来.
M:是指数据库的类文件,文件夹可以为table, module
table文件夹里的文件class TableBanner extends JTable 继承 JTable, TableBanner定义表的基本字段,表字段的检查函数比如check, 并可以重写JTable里面的函数;
module文件夹里的文件class ModuleBanner extends JModel 继承 JModel

C:连接M和V的控制层, controllers里面的类文件. $row =& JTable::getInstance('banner', 'Table');生成数据库类的实例对表进行操作, require_once(JPATH_COMPONENT.DS.'views'.DS.'banner.php');把HTML页面包含进来.

V:视图层,HTML代码页面.

<?php
/**
 * @version        $Id: admin.banners.php 10381 2008-06-01 03:35:53Z pasamio $
 * @package        Joomla
 * @subpackage    Banners
 * @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.
 
*/

// no direct access 单入口控制
defined'_JEXEC' ) or die'Restricted access' );

// Make sure the user is authorized to view this page
//确认该用户访问此组件的权限

$user = & JFactory::getUser();
if (!$user->authorize( 'com_banners', 'manage' )) {
    
$mainframe->redirect( 'index.php', JText::_('ALERTNOTAUTH') );
}

// Set the table directory
//把组件的数据库表类包括进来

JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components'.DS.'com_banners'.DS.'tables');

//获取URL(/administrator/index.php?option=com_banners&c=client)中controller的内容
$controllerName = JRequest::getCmd( 'c', 'banner' );

if($controllerName == 'client') {
    JSubMenuHelper
::addEntry(JText::_('Banners'), 'index.php?option=com_banners');
    JSubMenuHelper
::addEntry(JText::_('Clients'), 'index.php?option=com_banners&c=client', true );
    JSubMenuHelper
::addEntry(JText::_('Categories'), 'index.php?option=com_categories&section=com_banner');
else {
    JSubMenuHelper
::addEntry(JText::_('Banners'), 'index.php?option=com_banners', true );
    JSubMenuHelper
::addEntry(JText::_('Clients'), 'index.php?option=com_banners&c=client');
    JSubMenuHelper
::addEntry(JText::_('Categories'), 'index.php?option=com_categories&section=com_banner');
}

switch ($controllerName)
{
    
default:
        
$controllerName = 'banner';
        
// allow fall through

    
case 'banner' :
    
case 'client':
        
// Temporary interceptor
        $task = JRequest::getCmd('task');
        
if ($task == 'listclients') {
            
$controllerName = 'client';
        }
        
        
//通过controller决定调用controllers里的哪个文件
        require_once( JPATH_COMPONENT.DS.'controllers'.DS.$controllerName.'.php' );
        
$controllerName = 'BannerController'.$controllerName;

        
// Create the controller
        $controller = new $controllerName();

        
// Perform the Request task调用controller层定义的函数,如果task为空的话就直接执行控制层里定义的'display'方法
        $controller->execute( JRequest::getCmd('task') );

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

5. tables/
上面说过这个文件夹下面是数据库类文件, 一般以数据库表命名(jos_banner) banner.php

<?php
/**
 * @version        $Id: banner.php 10381 2008-06-01 03:35:53Z pasamio $
 * @package        Joomla
 * @subpackage    Banners
 * @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.
 
*/

// no direct access
defined'_JEXEC' ) or die'Restricted access' );

/**
 * @package        Joomla
 * @subpackage    Banners
 
*/
class TableBanner extends JTable
{
    
//下面的类的私有属性都是数据库表的字段,并赋上初始化的值, 一般都是null,0,''
    /** @var int */
    
var $bid                = null;
    
/** @var int */
    
var $cid                = null;
    
/** @var string */
    
var $type                = '';
    
/** @var string */
    
var $name                = '';
    
/** @var string */
    
var $alias                = '';
    
/** @var int */
    
var $imptotal            = 0;
    
/** @var int */
    
var $impmade            = 0;
    
/** @var int */
    
var $clicks                = 0;
    
/** @var string */
    
var $imageurl            = '';
    
/** @var string */
    
var $clickurl            = '';
    
/** @var date */
    
var $date                = null;
    
/** @var int */
    
var $showBanner            = 0;
    
/** @var int */
    
var $checked_out        = 0;
    
/** @var date */
    
var $checked_out_time    = 0;
    
/** @var string */
    
var $editor                = '';
    
/** @var string */
    
var $custombannercode    = '';
    
/** @var int */
    
var $catid                = null;
    
/** @var string */
    
var $description        = null;
    
/** @var int */
    
var $sticky                = null;
    
/** @var int */
    
var $ordering            = null;
    
/** @var date */
    
var $publish_up            = null;
    
/** @var date */
    
var $publish_down        = null;
    
/** @var string */
    
var $tags                = null;
    
/** @var string */
    
var $params                = null;
    
    
//构造函数.
    function __construct( &$_db )
    {
        parent
::__construct( '#__banner', 'bid', $_db );


        
$now =& JFactory::getDate();
        
$this->set( 'date', $now->toMySQL() );
    }

    
function clicks()
    {
        
$query = 'UPDATE #__banner'
        
. ' SET clicks = ( clicks + 1 )'
        
. ' WHERE bid = ' . (int) $this->bid
        ;
        
$this->_db->setQuery( $query );
        
$this->_db->query();
    }

    
/**
     * Overloaded check function
     *
     * @access public
     * @return boolean
     * @see JTable::check
     * @since 1.5
     * 确认传递进来的字段值是否合法
     
*/
    
function check()
    {
        
// check for valid client id
        if (is_null($this->cid) || $this->cid == 0) {
            
$this->setError(JText::_( 'BNR_CLIENT' ));
            
return false;
        }

        
// check for valid name
        if(trim($this->name) == '') {
            
$this->setError(JText::_( 'BNR_NAME' ));
            
return false;
        }

        
if(empty($this->alias)) {
            
$this->alias = $this->name;
        }
        
$this->alias = JFilterOutput::stringURLSafe($this->alias);

        
/*if(trim($this->imageurl) == '') {
            $this->setError(JText::_( 'BNR_IMAGE' ));
            return false;
        }
        if(trim($this->clickurl) == '' && trim($this->custombannercode) == '') {
            $this->setError(JText::_( 'BNR_URL' ));
            return false;
        }
*/

        
return true;
    }
}
?>