3

Typecho FrameworkSegmentFault所用的框架,本文将介绍如何用这个框架写一个Hello World程序。如果你不了解Typecho Framework,请先看这篇简介

输出Hello World!

首先我们创建Hello World程序的目录:

mkdir ~/hellow-world

Typecho Framework简介中提到

Action从Service获取所需数据后,传递result给Server的响应对象。

Hello World!不需要获取数据,所以我们直接让Action返回一个result即可。

在hello-world目录下建立app/Action/目录,并在其中创建Hello.php文件:

namespace Hello\Action;

首先我们定义一个命名空间,我们的程序使用Hello为命名空间。

这是一个Action,所以我们需要继承Action的类,翻一下框架的源代码,找到这样一个文件Mvc/Action/AbstractAction.php,那我们就继承AbstractAction这个类好了:

use TE\Mvc\Action\AbstractAction;

/**
 * Hello
 *
 * @use AbstractAction
 */

class Hello extends AbstractAction
{
// 待填充
}

我们看到Mvc/Action/AbstractAction.php里有这样一行代码:

abstract public function execute();

这就告诉我们,需要在自己的类中实现这个execute方法。我们实现一下这个方法,返回一个result数组。这时我们参考下Typecho Framework的示例代码,发现它是这么写的:

public function execute()
    {
        // 只要你把Action的属性设置为public状态,它就会被注入到模板中,你可以直接在模板中使用它们
        $this->word = 'Hello World';
        $this->peoples = new People($this->peopleService->listNewest(1, 20));
        $this->master = new People($this->peopleService->getByName('joyqi'));   // 不论你取出一行还是多行数据,都可以塞到Data对象中进行处理

        return array('template', 'index.php');
    }

嗯,看这行代码的意思,应该是指定返回的result使用模板(index.php是模板文件的名称)。那么我们不用模板,直接返回一个字符串应该怎么写呢?

继续翻源代码,发现Mvc/View目录下是这样的结构:

  • AbstractView.php
  • Back.php
  • Blank.php
  • Content.php
  • Error.php
  • Json.php
  • Jsonp.php
  • NotFound.php
  • Redirect.php
  • Template.php

嗯,我们返回Hello World!,不用模板,也不用什么Json,那么应该是Content了。点进去一看,果然是这个:

/**
 * 渲染一个字符串
 * 

好了,知道了result数组要用content后,我们来完成这个方法的定义:

class Hello extends AbstractAction
{
  public function execute()
  {
    return array('content', 'Hello World!');
  }
}

路由

好了,Action部分已经搞定,接下来我们绑定一下路由。参考示例代码,我们新建一个config目录,然后创建routes.php,内容如下:


return [ '/Hello' => 'Hello\Action\Hello', ];

路由设置很简单,就是返回一个数组,将路径绑定到相应的类。

入口程序

这样基本上就完成了。还剩下一个入口程序了。示例代码的README中提到

直接在浏览器里输入http://app-root/portal/index.php即可, 其中app-root是你的程序目录

所以说portal/index.php就是入口程序。这里我们直接在hello-world目录下面创立一个index.php文件作为入口,参考示例程序的写法,我们的文件内容如下:

const ROOT = __DIR__;

require_once ROOT . '/typecho/Helper/Autoloader.php';

首先我们加载Autoloader,通过这个Autoloader来初始化程序:

use TE\Helper\Autoloader;
use TE\Mvc\Base;
use TE\Mvc\Server\Http\Server;
use TE\Mvc\Router\Simple;


Autoloader::registerNamespace(ROOT . '/typecho', 'TE');
Autoloader::registerNamespace(ROOT . '/app', 'Hello');

注册命名空间,第一个参数是路径,第二个参数是命名空间的名称。

我们把框架放在typecho目录下。如果你还没有下载框架代码,可以克隆一下仓库:

cd ~/hello-world
git clone https://github.com/typecho/framework typecho
new Server(new Simple(require(ROOT . '/config/routes.php')));

启动服务,指定配置文件的路径。

然后在hello-world目录下运行:

php -S 127.0.0.1:8000/Hello 

访问 http://127.0.0.1:8000,发现有问题,说是Server需要两个参数,现在只有一个,缺少了一个InterceptorManager

缺的是拦截器,所以我们就把上面的代码改一下:

new Server(new Simple(require(ROOT . '/config/routes.php')),
  new InterceptorManager(require(ROOT . '/config/interceptors.php')));

然后config/interceptors.php里返回一个空数组(因为我们现在不需要用到拦截器):

return array();

大功告成!访问 http://127.0.0.1:8000/Hello 就能看到输出的 Hello world!

模板

上面是直接输出字符串,接下来我们使用模板输出.

先在路由里增加一条:

return [
  '/Hello' => 'Hello\Action\Hello',
  '/Hi' => 'Hello\Action\Hi'
];

我们打算访问/Hi通过模板输出。

然后是实现Hi类,创建app/Action/Hi.php,内容如下:

namespace Hello\Action;

use TE\Mvc\Action\AbstractAction;

/**
 * Hi
 *
 * @use AbstractAction
 */

class Hi extends AbstractAction
{
  public function execute()
  {
    $this->msg = 'Hi!';
    return array('template', 'hi.php');
  }
}

我们定义了$this->msg,在模板中可以直接使用这个变量。

最后是定义hi.php模板。我们创建一个template目录:

mkdir ~/hello-world/template

然后创建一个hi.php模板文件,直接在HTML中嵌入PHP代码:

<h1><?php echo ($msg . ' ' . $name); ?></h1>

注意,我们并没有指定模板文件的位置!如果你把模板文件放在别的目录下,会报错Template file not found。Typecho Framework会自动在template目录下找模板文件,“约定大于配置”。


撰文 SegmentFault


weakish
24.6k 声望844 粉丝

a vigorously lazy deadbeat with matured immaturity