TinyMVC 中文手册

翻译淡水河边<kissjava#vip.qq.com>

TinyMVC官网:http://www.tinymvc.com/

中文反馈:http://www.tsingfeng.com/

版本:1.0(201022 19:01:47)

目录

概述... 3

文件结构... 3

htdocs/. 3

tinymvc/. 3

安装TinyMVC. 3

快速安装“我只是想看到它”... 3

单个应用的安装(典型)... 3

数据库设置... 5

共享安装... 5

控制器(controllers). 6

控制器是什么?... 6

示例学习... 6

视图(views). 8

视图是什么?... 8

通过示例学习... 8

捕获视图输出到一个变量... 9

分配变量到视图... 9

模型(models). 10

什么是模型?... 10

用示例学习... 10

使用PDO数据库层... 11

直接访问PDO对象... 12

插件(plugins). 13

什么是插件?... 13

用示例学习... 13

加载一个library. 13

加载一个script. 14

自定义数据库插件... 14

扩展TinyMVC... 15

用示例学习... 15

自动加载插件... 15

获得一个实例对象(Getting an Instance). 16

集成一个模板引擎... 16

通过示例来学习... 16

自定义错误处理... 18

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

概述

文件结构

文件结构如下:

/htdocs/

  index.php

 

/tinymvc/

  /myapp/

  /myfiles/

  /sysfiles/

/htdocs/

这是你的根目录的内容,现在里面是index.php默认的入口文件

/tinymvc/

这是TinyMVC的安装主目录。建议安装在网站根目录外面。

/tinymvc/myapp/

这是你应用程序的目录。一般,你的添加和编辑的文件都会在这个目录下。

/tinymvc/myfiles/

这是一个共享安装目录。如果你有多个应用,就可以把都用到的插件从/myapp/plugins/目录,移动到/myfiles/plugins/。单个应用和多个应用的安装,后面会由介绍。

/tinymvc/sysfiles/

这是TinyMVC的系统目录。你不能编辑它,如果你升级TinyMVC,你会在这里找到更新的文件。

安装TinyMVC

快速安装“我只是想看到它”

l  解压到你的网站根目录

l  浏览器中查看 htdocs/index.php 文件

你会看到欢迎界面。

单个应用的安装(典型)

这个是单个网站的安装。如果你有多个站点,需要tinymvc的核心以及一些共享,你需要使用共享安装

解压到某个临时位置,你会看到如下结构:

/htdocs/

  index.php

 

/tinymvc/

  /myapp/

  /myfiles/

  /sysfiles/

l  index.php文件放到网站根目录

Index.php是浏览器直接查看的文件。其他文件无需放到网站的根目录里。

l  /tinymvc/目录(包括其内容)放到网站根目录外面

/tinymvc/目录包含了所有系统文件和应用程序文件。我们建议(更安全,但不是必须这样)放到网站的根目录外面。

如果你要把/tinymvc/放在根目录下,为了安全起见,最好设置权限,使之无法直接从浏览器访问他们。

安装示例:

/var/www.foo.com/htdocs/

  index.php

 

/var/www.foo.com/tinymvc/

  /myapp/

  /myfiles/

  /sysfiles/

l  编辑index.php文件,并配置选项

index.php里你会看到:

/* PHP error reporting level */

//error_reporting(E_ALL);

 

/* if your /tinymvc/ dir is not up one directory, uncomment and set here */

//define('TMVC_BASEDIR','../tinymvc/');

如有需要,可以取消错误报告的注释。开发时,你可能需要的错误报告是E_ALL,直接去掉注释就可以了。

如有需要,可以去掉定义TMVC_BASEDIR路径的注释。如果/tinymvc/目录在index.php文件的上一级,那默认是可以运行的。

配置路径,一定要包含结尾的斜杠。

一旦完成,你就可以从浏览器打开http://localhost/index.php (替换成你自己的路径)。你会看到欢迎界面。如果不是,检查错误信息,重新检查路径和配置设定。

数据库设置

如果你要使用数据库,你需要在这里设定:

/tinymvc/

  /myapp/

    /configs/

      database.php

database.php

$config['plugin'] = 'TMVC_PDO'; // plugin for db access

 

$config['type'] = 'mysql';      // connection type

$config['host'] = 'localhost'// db hostname

$config['name'] = 'dbname';     // db name

$config['user'] = 'dbuser';     // db username

$config['pass'] = 'dbpass';     // db password

 

$config['persistent'] = false// db connection persistence?

Plugin设定为TMVC_PDO,除非你使用自定义的数据库library。根据你的数据库服务器设定类型(type),主机(host),数据库名(name),数据库用户(user),数据库用户密码(pass)和是否持久连接(persistent)。

共享安装

每个网站都有自己的index.php/myapp/目录与之关联。他们共享TinyMVC的基础代码。

/sysfiles/是你更新TinyMVC的目录,永远都不要动他。/myfiles/是你自定义的想要跨站共享的插件目录。

对每个网站,你都要安装一个index.php文件和一个/myapp/目录。

l  安装/tinymvc/目录到一个中央位置

l  复制根目录下的index.php文件

l  /tinymvc/下,复制/myapp/index.php同一位置,使之对应

l  编辑index.phpTMVC_BASEDIRTMVC_MYAPPDIR的路径

例如设置三个不同的网站:

# shared code

/usr/local/lib/tinymvc/

  /myfiles/

  /sysfiles/

 

#website 1

/var/www.foo1.com/htdocs/index.php

/var/www.foo1.com/myapp/

 

#website 2

/var/www.foo2.com/htdocs/index.php

/var/www.foo2.com/myapp/

 

#website 3

/var/www.foo3.com/htdocs/index.php

/var/www.foo3.com/myapp/

为每个网站,编辑index.phpTMVC_BASEDIRTMVC_MYAPPDIR的路径。例如:

Index.php

/* TinyMVC base library path */
define('TMVC_BASEDIR','/usr/local/lib/tinymvc/');
 
/* application library path */
define('TMVC_MYAPPDIR','../myapp/');

确认包含了结尾的斜线。

控制器(controllers)

控制器是什么?

控制器文件是应用程序的粘合剂。他们加载模型(model),显示视图(view),还要配合插件工作等。可以说他就是个交警(指挥调度)。

一个TinyMVC页面的典型URL如下:

http://[host]/index.php/[controller]/[action]/[param1]/[param2]/[param3...]

controller是控制器的文件名/类名,action是你要访问的控制器的方法名。其他的是你的应用程序的参数。所以,一个真实的URL看上去如下:

http://localhost/index.php/hello/intro/name/joe

示例学习

控制器文件在controllers目录下。我们建立一个控制器:

/myapp/

  /controllers/

    hello.php

hello.php

class Hello_Controller extends TinyMVC_Controller
{
  function index()
  {
    echo "Hello World.";
  }
}

url的控制器名称是区分大小写的,并且没有.php后缀。

类名前缀(prefix_Controller)必须符合控制器文件名。

现在我们可以看看这个,直接浏览:

http://localhost/index.php/hello

请使用你自己的安装路径访问到index.php

你会在浏览器里看到“Hello World.”字符

如果你在URL中不提供控制器名称,default就是默认值。你可以在/myapp/configs/application.php 文件里修改。

为简洁起见,我们直接在控制器里输出了。一般会是通过一个视图(view)输出,下一章我们将进行介绍。

现在,在控制器里新建一个方法:

Hello.php

class Hello_Controller extends TinyMVC_Controller
{
  function index()
  {
    echo "Hello World.";
  }
  function time()
  {
    echo "The time is now.";
  }
}

现在访问:

http://localhost/index.php/hello/time

如你所见,URL里方法名的改变,产生了对应的输出。

如果URL里没有方法名,默认的方法就是index

用下面的Apache重写规则,你可以隐藏index.php

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php/$1 [L]

这个保存为.htaccess文件,放到根目录下,或是写道apache的配置里。

现在你可以直接访问http://localhost/hello这样的url了。

这将重写一切不是真正的文件或是目录的访问到index.php。务必创建一个robots.txt文件供网络爬虫浏览。还要创建一个favicon.ico文件,以便浏览器没有重定向而尝试加载网站图标文件。

视图(views)

视图是什么?

视图文件就是你要显示的内容,包括htmlcss

通过示例学习

视图文件保存在views目录下。我们建立一个视图:

/myapp/

  /views/

    hello_view.php

在文件名后添加_view是推荐做法,不是必须这样。这样在编辑器里你一眼就可以看出这是什么文件。

hello_view.php

<html>
  <head><title>Hello</title></head>
  <body>
    Hello World.
  </body>
</html>

我们通过控制器调用视图文件。

/myapp/controllers/hello.php

class Hello_Controller extends TinyMVC_Controller

{

  function index()

  {

    $this->view->display('hello_view');

  }

}

不需要提供视图文件名的.php后缀。

在浏览器里加载:

http://localhost/index.php/hello

你可以看到hello_view视图文件的内容。

捕获视图输出到一个变量

视图输出到一个变量,使用$this->view->fetch().

/myapp/controllers/hello.php

class Hello_Controller extends TinyMVC_Controller

{

  function index()

  {

    $output = $this->view->fetch('hello_view');

  }

}

分配变量到视图

有几种方法可以指定变量到视图。第一种方法使用assign().

/myapp/controllers/hello.php

class Hello_Controller extends TinyMVC_Controller

{

  function index()

  {

    $this->view->assign('title','Hello');

    $this->view->assign('body_text','Hello World.');

    $this->view->display('hello_view');

  }

}

Hello_view.php

<html>
  <head><title><?=$title?></title></head>
  <body>
    <?=$body_text?>
  </body>
</html>

你可以看到一样的输出,但是这次内容是变量赋值的。

你还可以通过数组(array)赋值,而不是键/值对(key/value:

$data['title'] = 'Hello';

$data['body_text'] = 'Hello world.';

$this->view->assign($data);

当你通过$this->view->assign()分配数组,他会在内部通过$this->view->view_vars自动分配到各个变量。

通过$this->view->assign()指派变量,这些变量对之后的每个视图都是适用的(display(‘a’)后,还可以display(‘b’))。如果你想只对当前视图有效,可以使用$this->view->display()方法调用,把变量放入第二个参数传入。

$data['title'] = 'Hello';

$data['body_text'] = 'Hello world.';

$this->view->display('hello_view',$data);

为简洁起见,值都来源于控制器。实际应用中一般来源于model(database)等。

模型(models)

什么是模型?

模型是MVC中汇总数据的那一层。基础数据源是典型的数据库,其他如LADP或文本文件等都可以是数据源。

用示例学习

模型文件在models目录下。我们建立一个模型:

/myapp/

  /models/

    page_model.php

page_model.php

class Page_Model extends TinyMVC_Model

{

  function get_title()

  {

    return 'Hello';

  }

  function get_body_text()

  {

    return 'Hello World.';

  }

}

模型文件名必须和模型类名匹配。类名无所谓,但是文件名必须小写。_model不是必须的后缀,但是这有助于组织结构。

我们从控制器加载一个模型,看看例子:

/myapp/controllers/hello.php

class Hello_Controller extends TinyMVC_Controller

{

  function index()

  {

    // load the model

    $this->load->model('Page_Model','page');

    // use the model to gather data

    $title = $this->page->get_title();

    $body_text = $this->page->get_body_text();

 

    $this->view->assign('title',$title);

    $this->view->assign('body_text',$body_text);

    $this->view->display('hello_view');

  }

}

$this->load->model()的第一个参数是模型的类名。第二个参数是可选的别名。加载模型类,得到他的成员属性,然后就可以使用这些属性收集数据了。如果你在前面的章节里保留了同样的视图文件。你就会看到这次来源于模型的变量指派还是一样的结果。

使用PDO数据库层

TinyMVC使用PDO进行数据库的访问,这需要PHP5.1以上的版本。确认你的myapp/configs/database.php已经根据你的数据库进行了配置。

示例:

members_model.php

class Members_Model extends TinyMVC_Model

{

  function get_members()

  {

    $this->db->query('select * from members');

    while($row = $this->db->next())

      $results[] = $row;

    return $results;

  }

}

假设你有一个members数据表,get_members()方法将返回members表的全部记录。

class Members_Model extends TinyMVC_Model
{
  function get_member($id)
  {
    return $this->db->query_one('select * from members where id=?',array($id));
  }
}

上面将从数据库返回一天记录。这个示例展现了如何将变量传递给查询参数。query_one() 返回一天记录。

class Members_Model extends TinyMVC_Model

{

  function get_members()

  {

    return $this->db->query_all('select * from members');

  }

}

query_all()返回所有记录从查询。实际上和第一个query()例子一样。

你可以选择传值的方式用PDO::FETCH_ASSOC , PDO::FETCH_NUM或是 PDO::FETCH_BOTH . PDO::FETCH_ASSOC 是默认方式。

可用方法:

l  $this->db->query($sql,$params) 执行一个查询,用 $this->db->next() 循环

l  $this->db->query_one($sql,$params,$format) 返回一条记录

l  $this->db->query_all($sql,$params,$format) 返回所有记录

l  $this->db->next($format) 用于结果集的循环

l  $this->db->last_insert_id() 获得最后插入数据库的id

l  $this->db->num_rows() 返回上次查询的记录数

直接访问PDO对象

如果你想直接使用PDO对象,可以用 $this->db->pdo

这样你就可以充分使用PDO的特性了,但是你必须遵守他的语法和规则。例如:

class Members_Model extends TinyMVC_Model
{
  function get_members()
  {
    $results = null;
    try {
      foreach ($this->db->pdo->query('SELECT * from members') as $row)
        $results[] = $row;
      $this->db->pdo = null;
    } catch (PDOException $e) {
      trigger_error($e->getMessage());
      return false;
    }
    return $results;    
  }
}

插件(plugins)

什么是插件?

插件是用来扩展框架功能的。目前有两个类型的插件:librariesscriptsLibrariesphp类,框架实例化它后使用。Scripts就是php脚本,直接包含进来。

用示例学习

加载一个library

插件文件存放在/myapp/plugins/目录下。我们建立一个library插件名叫demo

/myapp/

  /plugins/

    library.demo.php

library的名称随意,但是类名必须匹配library名。

library.demo.php

class Demo {

  function test()

  {

    return "This is a test.";

  }

}

使用我们的新插件,我们通过控制器加载他.

/myapp/controllers/hello.php

class Hello_Controller extends TinyMVC_Controller

{

  function index()

  {

    $this->load->library('demo','mydemo');

    $this->view->assign('output', $this->mydemo->test());

    $this->view->display('hello_view');

  }

}

第二个参数是设定属性别名,可选项。

为测试demo的输出,你必须有个变量$output在你的视图文件中。

加载一个script

我们建立一个script插件叫myhelpers

/myapp/

  /plugins/

    script.myhelpers.php

script命名随意。

Script.myhelpers.php

function esc($string)
{
  return htmlentities($string);
}
function anchor($url,$text)
{
  return "<a href=\"$url\">$text</a>";
}

使用我们的新插件,我们在控制器加载他.

/myapp/controllers/hello.php

class Hello_Controller extends TinyMVC_Controller

{

  function index()

  {

    $this->load->script('myhelpers');

    $this->view->display('hello_view');

  }

}

现在,script中的php函数,你都可以在视图文件中使用了。

Librariesscripts可以有选择的自动加载。详情见 自动加载插件。

自定义数据库插件

如果想用其他数据库插件而不是内置的PDO,执行下列操作:

假设你的数据库插件名为 MYDB :

l  /sysfiles/plugins/ 复制db.TMVC_PDO.php /myapp/plugins/db.MYDB.php

l  编辑这个文件,重命名类名把TMVC_PDO 改为 MYDB .

l  按自己的喜欢编辑添加功能

l  编辑 /myapp/configs/database.php 更改plugin MYDB

扩展TinyMVC

用示例学习

我们扩展TinyMVC_Controller类:

myapp/plugins/internal.My_Controller.php

class My_Controller extends TinyMVC_Controller

{

  function __construct()

  {

    parent::__construct();

  }

  // do your class extensions here

}

然后你的应用控制器,只要继承你扩展的自定义控制器就可以了:

class Hello_Controller extends My_Controller

{

  function index()

  {

    $this->view->display('hello_view');

  }

}

你不必包含你的扩展文件,TinyMVC会自动加载,只是命名必须是internal.classname.php plugins目录下。

同样的方法可以扩展TinyMVC_ModelTinyMVC_View.

自动加载插件

代替在控制器中使用 $this->load->library() $this->load->script() 方法加载插件,他们自动加载。这样你可以在每个控制器中随意使用他们了。

myapp/configs/autoload.php

/* auto-loaded libraries */
$config['libraries'] = array('mylib','myotherlib');
 
/* auto-loaded scripts */
$config['scripts'] = array('myhelpers','myscripts');

只要添加你的插件到自动加载数组。

如果你想用别名自动加载library,可以使用数组方式:

/* auto-loaded libraries */
$config['libraries'] = array(
  array('mylib','myalias'),
  array('myotherlib','otheralias')
  );

获得一个实例对象(Getting an Instance)

有时你会需要获得一个当前对象的实例,比如在library里,这样你就可以使用控制器的功能了。你可以在任何时候获得这个实例对象:

$tmvc = tmvc::instance();

 

$myvars['foo'] = 'bar';

$myvars['baz'] = 'gaz';

 

$output = $tmvc->view->fetch('some_view',$myvars);

 

集成一个模板引擎

模板引擎虽非必要,但是你也可以集成进去使用。下面的例子中我们将集成smarty作为视图层。我们把smartyclass作为一个library加载。

通过示例来学习

首先,我们使用快速但是难看的方式来做,一切都在控制器里。

请确认你的Smarty已经正确安装和部署。在这里,我们如下放置:

/var/smarty/

  /libs/

    Smarty.class.php

    ...

  /templates_c/

  /configs/

  /cache/

 

这里我们没有建立smarty template 目录,因为我们的视图文件在 /myapp/views/ 目录下。

myapp/controllers/hello.php

class Hello_Controller extends TinyMVC_Controller

{

  function index()

  {

    // require the Smarty class

    require('/var/smarty/libs/Smarty.class.php');

    // instantiate the library

    $this->load->library('Smarty','smarty');

    // configure Smarty

    $this->smarty->compile_dir = '/var/smarty/templates_c/';

    $this->smarty->config_dir = '/var/smarty/configs/';

    $this->smarty->cache_dir = '/var/smarty/cache/';

    // we will use our view directory for template files

    $this->smarty->template_dir = TMVC_MYAPPDIR . 'views/';

 

    // now just use smarty for the view layer

    $this->smarty->assign('foo','bar');

    $this->smarty->display('hello_view.tpl');

  }

}

如果library名称已经存在了,那么TinyMVC将不会尝试加载这个plugin

现在控制器里有很多的代码,而且也许你还想在其他地方使用smarty。所以,更好的方案是建立一个library包:

myapp/plugins/library.Smarty_Wrapper.php

// require the Smarty class

require('/var/smarty/libs/Smarty.class.php');

 

class Smarty_Wrapper Extends Smarty

{

  function __construct()

  {

    parent::Smarty();

    $this->compile_dir = '/var/smarty/templates_c/';

    $this->config_dir = '/var/smarty/configs/';

    $this->cache_dir = '/var/smarty/cache/';

    // we will use our view directory for template files

    $this->template_dir = TMVC_MYAPPDIR . 'views/';

  }

}

myapp/controllers/hello.php

class Hello_Controller extends TinyMVC_Controller

{

  function index()

  {

    $this->load->library('Smarty_Wrapper','smarty');

    // now just use smarty for the view layer

    $this->smarty->assign('foo','bar');

    $this->smarty->display('hello_view.tpl');

  }

}

现在,在控制器里你可以用一行代码加载smarty了。当然,你还可以使他自动加载,放到 /myapp/configs/autoload.php 里。

自定义错误处理

要设定自定义错误处理程序,执行以下步骤:

假设你的错误处理类叫 My_ErrorHandler :

l  /sysfiles/plugins/ 复制 internal.TinyMVC_ErrorHandler.php /myapp/plugins/internal.My_ErrorHandler.php

l  编辑文件,类名从 TinyMVC_ErrorHandler 改为 My_ErrorHandler

l  编辑添加你想要的功能

l  编辑 /myapp/configs/application.php 错误处理改为 My_ErrorHandler .