etenil / assegai
一个完整的PHP MVC框架。
- dev-master
- 3.0.x-dev
- v2.2.9
- v2.2.8
- v2.2.7
- v2.2.6
- v2.2.5
- v2.2.4
- v2.2.3
- v2.2.2
- v2.2.1
- v2.2
- v2.1.6
- v2.1.5
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0
- v1.4
- v1.3
- v1.2
- v1.1
- v1.0
- 0.1
- dev-silex-base
- dev-38-php7-port
- dev-fix-33-cookies-maxage
- dev-Modular-assegai
- dev-dev-bundles
- dev-dev
- dev-feature/event-processing
This package is not auto-updated.
Last update: 2024-09-14 15:01:51 UTC
README
更新日期:2014年8月3日
简介
Assegai是一个功能齐全的PHP MVC框架。它是基于MIT许可的免费软件。
该框架曾经依赖于微框架Atlatl。这个依赖关系在2.0版本中被移除。
安装
注意:有一个完整的演示视频,展示了安装和入门部分的内容。请访问youtube观看视频。
要安装Assegai,您首先需要安装composer。然后为您的项目创建一个composer.json文件,其中需要etenil/assegai。一个示例composer.json文件应该如下所示
{ "name": “YOUR_NAME/helloworld”, "require": { "etenil/assegai": "2.*" } }
现在保存并退出composer.json文件,然后在您的项目根目录(使用命令行)运行以下命令
$ composer install
一旦Assegai安装完成,您将在项目文件夹中安装一个完全功能的MVC框架。
入门指南
有几种可能的设置和使用Assegai框架的方法。以下部分展示了当前最简单的设置。推荐的设置文档将很快发布。
引导
您需要为项目创建一个引导器或使用默认的引导器。框架附带了一个示例引导器,您可以根据需要进行修改。
要使用默认的引导器,请在您的项目根目录中运行以下命令
$ cp vendor/etenil/assegai/bootstrapper.example.php index.php
这将把已提供的示例引导器文件复制到项目根目录,并将文件重命名为index.php。
基本配置
尽管Assegai有默认的配置选项,但如果不创建配置文件,则不会工作,即使它是空的。您可以使用框架附带的conf.example.php文件。为此,从项目根目录使用以下命令
$ cp vendor/etenil/assegai/conf.example.php conf.php
现在您已经完全配置了框架。为了测试设置,下面的部分将展示如何使用Assegai创建应用程序。
Hello World应用程序
在本章中,我们将看到如何为assegai编写一个非常简单的应用程序,它将在HTML页面上显示著名的“Hello, World”消息。
要创建应用程序,首先进入您项目的根目录中的conf.php文件,并将应用程序名称添加到apps数组中。您可以根据需要删除或重命名现有的示例应用程序。
您的配置文件应如下所示
<?php $conf['apps_path'] = __DIR__ . '/apps'; $conf['apps'] = [ 'helloworld', ];
现在让我们创建实际的应用程序。从项目的根目录中输入以下命令
$ vendor/etenil/assegai/assegai app helloworld
这将为您创建应用程序的文件系统结构。默认的应用程序结构如下所示
apps
- helloworld
|- conf.php
|- controllers
|- exceptions
|- models
|- views
现在在controllers目录中创建一个名为Hello.php的文件,并放入以下代码
<?php namespace helloworld\controllers; class Hello extends \assegai\Controller { function sayHello() { return "Hello, World!"; } }
请注意在\assegai\Controller上放置第一个反斜杠,否则您会遇到问题。
我们还需要让框架知道当访问网站时需要调用此控制器。这通过将以下内容添加到应用程序的conf.php文件中来实现。请注意,此conf.php文件不同于通用配置文件。
<?php $app['route'] = [ '/' => 'helloworld\controllers\Hello::sayHello', ];
测试它
现在,使用以下命令启动PHP内部web服务器(或配置您首选的web服务器)
php -S localhost:8080 -t ./
然后,当您用浏览器访问您的web服务器时,应该会看到打印的 你好,世界 信息。
命名空间约定
Assegai鼓励使用多个专用应用程序来共享模型,以便实现网站。该框架依赖于PSR-0命名标准。
类需要这样命名
app\type\Name
例如
myapp\models\DemoCode
您还可以使用子文件夹来存放模型和控制台,并相应地扩展命名空间
myapp\models\demo\SomeModel
使用模型
现在让我们尝试通过引入一个模型来修改练习。模型通过将所有数据管理委托给专用类,是一种强大且方便的方式来组织代码。
创建一个名为 models/hello.php 的文件,其中包含以下代码
namespace hello\models;
class Hello extends \assegai\Model
{
function hello()
{
return 'Hello, Model';
}
}
现在我们需要从控制器中加载模型。让我们在 controllers/hello.php 中创建一个新函数
namespace hello\controllers;
class Demo extends \assegai\Controller
{
function hello()
{
return "Hello, World!";
}
function hello_model()
{
$hello = $this->model('Hello');
return $hello->hello();
}
}
最后,我们需要在 conf.php 中创建一个指向此新函数的路由
$app['route'] = [
'/' => 'hello\controllers\Demo::hello',
'/model' => 'Demo::hello_model',
];
现在尝试使用 /model 段访问您的安装,例如 https:///index.php/model。您应该看到显示的消息“Hello, Model”。
请注意,我们为'/model'路径使用了隐式命名空间路由。这很方便,可以节省打字。
视图
现在让我们尝试用视图来做我们之前做过的事情。我们将从现有的模型中获取数据,然后将其输入到视图中并显示。
我们首先创建视图。创建一个名为 views/hello.phtml 的文件,并包含以下代码
<DOCTYPE html>
<html>
<head>
<title>Assegai Tutorial</title>
</head>
<body>
<p><?=$vars->message?></p>
</body>
</html>
注意 $vars->message 变量。
让我们在控制器体内创建另一个函数
function hello_view()
{
$hello = $this->model('Hello');
return $this->view('hello', array('message' => $hello->hello()));
}
最后,我们将在这个新函数中创建一个路由 conf.php
$app['route'] = [
'/' => 'Demo::hello',
'/model' => 'Demo::hello2',
'/view' => 'Demo::hello_view',
];
尝试访问带有 /view 段的url,例如 https:///index.php/view,您应该看到带有 Hello, Model 替换消息变量的视图。
视图助手
视图助手是方便的函数,它们返回或输出一些HTML,并在视图中用于格式化和显示数据。考虑以下
<?php $h->form->input('text', 'foobar') ?>
=> <input type="text" name="foobar" id="foobar"/>
您可能会这样实现这个函数
function input($type, $name) {
echo "<input type=\"$type\" name=\"$name\" id=\"$name\"/>";
}
默认情况下,助手不会被加载;视图必须声明它所使用的必要助手,如下所示
<?php $load_helper('form'); ?>
目前,Assegai不提供任何助手。但您可以轻松实现自己的。
助手始终对所有应用程序可用,并作为 helpers_path 文件夹(默认情况下为项目根目录中的 helpers 文件夹)中的类的一部分声明。
助手类必须遵循通常的约定,并命名为 helpers\SomeName。将相关的助手打包在一起是个好主意。以下是一个示例
namespace helpers;
class Form {
function input($type, $name) {
echo "<input type=\"$type\" name=\"$name\" id=\"$name\"/>";
}
}
路由
路由基于每个应用程序定义,并且较后加载的应用程序会覆盖冲突的路由。
路由是基于正则表达式的。因此,可以很容易地通配任何路由的一部分,并将其指向同一处理器。路由中的捕获花括号映射为处理器的参数。因此,可以使用以下
// Handler for route '/foo/([0-9]+)'
function foo($num)
{
return $num;
}
您还可以通过在路由前加上所需方法的前缀来为特定HTTP方法定义路由
$app['route'] = [
'GET:/bar' => 'app\controllers\Foo::bar_get',
'POST:/bar' => 'app\controllers\Foo::bar_post',
'/bar' => 'app\controllers\Foo::bar',
];
请注意,路由也支持隐式命名空间,如下所示
$app['route'] = [
'/bar' => 'Foo::bar', // This will be assumed as 'app\controllers\Foo'.
];
在大型路由表中,使用路由组很方便。它们使表格更清晰,并减少打字量
$app['route'] = [
'@/test' => [
'/foo' => 'Test::testFoo', // This is understood as '/test/foo'.
'/bar' => 'Test::testBar',
],
'@/real' => [
'/foo' => 'Real::foo',
'/bar' => 'Real::bar',
],
];
首先搜索方法特定的路由,如果没有找到,再搜索其他路由。
URL前缀
如果您的网站从子文件夹运行,那么路由最终会有一个常数前缀,例如,网站将在 foo
文件夹中运行,并产生类似 http://host.com/foo/myroute
的URL。在这种情况下,请按如下方式设置配置中的URL前缀
$conf['prefix'] = '/foo'
然后路由将被自动解析为 /myroute
。
通用路由
捆绑的路由器包含几个内置处理程序。这些处理程序可以用于对URL执行即时操作。
通用路由是在路由器内部定义的,不能扩展或修改。它们接受参数,因此看起来与普通路由不同。
一个典型的通用路由可能很简单,就像
'::access_denied'
或者使用参数作为
['::view', 'baz', ['foo' => 'bar']]
重定向
重定向只是实现301 HTTP重定向的一种简单方式,无需触摸Web服务器的配置文件,或创建专用控制器。重定向路由接受两个参数,第一个是重定向目标,第二个是重定向的HTTP代码(通常是301或有时是302)。如果省略第二个参数,则默认为301。
$app['route'] = [
'/foo' => ['::redirect', '/bar', 301],
'/bar' => 'app\\controllers\\Bar::bar',
];
视图
视图通用路由非常适合所有网站都有的准静态文件。视图路由接受两个参数,第一个是视图的名称,最后一个是一个传递给视图的关联数组。
$app['route'] = [
'/foo' => ['::view', 'foo', ['text' => 'Hello, world!']],
'/bar' => ['::view', 'bar'],
];
配置
框架和应用配置作为服务器属性的一部分轻松访问。您可以像这样访问它们
$this->server->main->get('apps');
$this->server->app->get('my_very_important_setting');
这些配置字典只是包装了解析后的配置文件,因此您可以轻松定义自己的设置。
控制器
控制器是Assegai应用程序的核心。它们提供对模型、视图和模块的访问。
初始化
Assegai为其控制器提供了一个基本的实现,您的控制器应该扩展此实现。此实现包含一个不能重载的最终构造函数。因此,您应该将初始化代码放在提供的 _init() 方法中,该方法始终由父构造函数调用。
视图
控制器包含一个名为 view() 的辅助方法,它加载一个视图并返回填充的内容。该 view() 辅助方法接受视图的名称作为参数,以及一个值关联数组作为第二个参数。
模型
控制器有一个名为 model() 的辅助函数,可以轻松地加载模型。该函数接受模型类名作为参数,并返回实例化的模型。
模型辅助函数支持隐式命名空间,从而节省了大量输入。
class MyController extends \assegai\Controller
{
function foo()
{
$my_model = $this->model('app\models\Foo');
$my_short_model = $this->model('Foo');
}
}
模块
模块在应用程序之间共享,成员变量 modules 从控制器提供了对这些模块的轻松访问。有关更多信息,请参阅专用章节。
其他实用程序
dump() 方法允许轻松地将值包装在一个 pre HTML块中,从而使其易于阅读。
appPath() 方法可以用来获取到应用程序相关路径的绝对路径。该方法期望一个相对路径作为参数。
模型
模型是提供对某些数据提供程序抽象的对象。它们的角色通常是确保数据有效性、存储和检索。
Assegai让您自由地以您喜欢的任何方式组织您的模型,基 Model 类只提供了一个 _init() 方法,以及成员变量 $modules 以访问加载的模块。
应用程序模型
每个应用程序都可以在其 models 文件夹中拥有自己的模型。这些模型遵循命名约定
<application>\models\<Model>
共享模型
如果您的网站足够小,只需一个应用程序,那么您可能只想在您的应用程序中使用模型。然而,对于非平凡的网站,通常使用共享模型会更容易。
所有共享模型都位于由 models_path 配置确定的单个文件夹中,默认情况下是assegai根目录中的 models 文件夹。它们可以由任何应用程序轻松加载。
通常,您在共享文件夹中会有很多模型。根据您的组织方式,您可能为单个模型拥有多个类。因此,共享模型的命名约定略有不同,下划线字符用作分隔符,以确定模型源文件的位置。这样,您可以在文件夹中组织您的模型。
models\polls\Negative\Mapper
models/poll/negative/Mapper.php
异常
应用程序包含一个异常文件夹。该文件夹旨在包含可能在应用程序的任何地方抛出并处理的异常类。
异常的命名约定很简单
<app>\exceptions\<Name>
单元测试
Assegai支持对您的应用程序进行单元测试,并提供必要的粘合代码,以便PHPUnit能够正常运行。
为了测试您的代码,您需要安装PHPUnit,并在测试文件夹中创建一个phpunit.xml和一个引导文件。
phpunit.xml通常是这样的
<phpunit bootstrap="./bootstrap.php" colors="true">
<testsuite name="Unit">
<directory>./</directory>
</testsuite>
</phpunit>
以及写入bootstrap.php文件的引导代码是这样的
<?php
define('APP_PATH', dirname(__DIR__) . '/');
define('ROOT_PATH', dirname(dirname(dirname(__DIR__))) . '/');
require(ROOT_PATH . 'lib/testloader.php');
您可能需要更新APP_PATH和ROOT_PATH的定义,以便与您的实际设置相匹配。
然后您可以使用以下命令运行您的测试
phpunit -c phpunit.xml
模块
模块提供从提供的$modules辅助变量在Controller或Model中,或者从挂钩上的动作来修改框架行为的高级功能。
模块在Assegai中全局可用,尽管您也可以在应用程序配置以及主配置中声明它们。如果当前应用程序包含已加载模块的配置,则该配置将具有优先级,高于全局配置文件。
Assegai附带了一些预安装的模块。以下各节将描述每个模块。
ACL
此模块为Assegai提供简单的访问控制列表支持。
列表必须在应用程序的conf.php文件中声明。控制列表实际上是某些角色对资源的操作权限。首先必须定义角色和资源,然后定义它们的交互。以下是一个简短的示例列表。
$app['acl'] = array(
'roles' => array(
'user' => null,
),
'resources' => array(
'article' => null,
),
'privileges' => array(
'user' => array(
'article' => array('view', 'comment'),
),
),
);
角色和资源也支持继承。以下是一个示例。
$app['acl'] = array(
'roles' => array(
'user' => null,
'author' => array('user'),
),
'resources' => array(
'article' => null,
'admin' => array('article'),
),
'privileges' => array(
'user' => array(
'article' => array('view', 'comment'),
),
'admin' => array(
'article' => array('edit'),
'admin' => array('access'),
),
),
);
一旦建立了列表,您就可以使用模块的isAllowed()辅助函数来查找角色是否允许在资源上执行操作。以下是一个简短的示例。
$article = new Article();
$user = new User();
if($this->modules->acl->isAllowed('user', 'article', 'view')) {
$article->show();
}
Mustache
此模块用修改后的Mustache引擎替换标准视图。请注意,此模块期望视图文件具有.tpl扩展名,而不是常用的.phtml。
有关模板引擎语法的更多信息,请参阅项目网站上的官方文档。
PDO
这提供了PDO数据库连接的抽象。
数据库连接必须在应用程序的conf.php文件中定义,如下所示
$app['pdo'] = array(
'myNiceConnection' => array(
'dsn' => 'mysql:host=localhost;dbname=somedb',
'username' => 'root',
'password' => 'somepassword!',
),
'conn2' => array(
'dsn' => 'mysql:host=localhost;dbname=otherdb',
'username' => 'root',
'password' => 'somepassword!',
),
);
这将实例化两个连接,可以像这样访问
$this->modules->pdo->myNiceConnection->exec('INSERT INTO demo VALUES('1', '2', '3')');
有关PDO连接的更多信息,请参阅PHP文档。
Paginator
此模块提供方便的分页器以处理结果。该模块目前仅支持对数组进行分页。
以下提供了以下函数
- getPage($num) 获取第$num页
- getCurrentPage() 返回当前页
- count() 计算元素数量。
- setPage($num) 将分页器设置为第$num页
- setPageLength($length) 将页长设置为$length。默认为10。
- getPageNum() 获取当前页码
- getPages() 返回可用页面的总数
- getPagesList($length) 获取当前页周围的页面列表
用法示例
$data = range(0, 100);
$paginator = new \assegai\modules\paginator\Paginator::fromArray($data);
$paginator->setPage(3);
foreach($paginator->getCurrentPage() as $item) {
echo $item;
}
foreach($paginator->getPagesList() as $page) {
echo $page;
}
ESI
ESI模块将ESI兼容性引入Assegai。ESI是一个标准,该标准允许将页面片段单独缓存,并由边缘服务重新构建最终的页面。例如,Squid实现了ESI。
此模块目前尚不可用。如果您有时间并且有动力,欢迎您对其进行开发。
验证器
验证器模块允许您轻松地将表单数据与一组格式和过滤器进行校验。
快速示例
以下示例展示了如何使用自定义异常抛出验证异常。然后您可以从调用方法中检索错误信息。在控制器中验证数据不是好的做法,这应该在模型中处理。这只是一个快速示例。
$validator = new \assegai\modules\validator\Validator($post);
$validator
->required('You must supply a name.')
->validate('name', 'Name');
$validator
->required('You must supply an email address.')
->email('You must supply a valid email address')
->validate('email', 'Email');
// check for errors
if ($validator->hasErrors()) {
throw new Validator_Exception(
'There were errors in your form.',
$validator->getAllErrors()
);
}
可用的验证方法
- exists($message = null) - 字段必须存在,无论其内容如何。
- required($message = null) - 字段值是必需的。
- email($message = null) - 字段值必须是一个有效的电子邮件地址字符串。
- float($message = null) - 字段值必须是一个浮点数。
- integer($message = null) - 字段值必须是一个整数。
- digits($message = null) - 字段值必须是一个数字(没有上限的整数)。
- min($limit, $include = TRUE, $message = null) - 字段值必须大于 $limit(数值)。$include 定义值是否可以等于限制。
- max($limit, $include = TRUE, $message = null) - 字段值必须小于 $limit(数值)。$include 定义值是否可以等于限制。
- between($min, $max, $include = TRUE, $message = null) - 字段值必须在 $min 和 $max(数值)之间。$include 定义值是否可以等于 $min 和 $max。
- minLength($length, $message = null) - 字段值必须大于或等于 $length 个字符。
- maxLength($length, $message = null) - 字段值必须小于或等于 $length 个字符。
- length($length, $message = null) - 字段必须是 $length 个字符长。
- matches($field, $label, $message = null) - 一个字段与另一个字段匹配(例如密码匹配)
- notMatches($field, $label, $message = null) - 字段值必须不匹配 $field 的值。
- startsWith($sub, $message = null) - 字段必须以字符串 $sub 开头。
- notStartsWith($sub, $message = null) - 字段必须不以字符串 $sub 开头。
- endsWith($sub, $message = null) - 字段必须以字符串 $sub 结尾。
- notEndsWith($sub, $message = null) - 字段必须不以字符串 $sub 结尾。
- ip($message = null) - 字段值是一个有效的 IP,使用 filter_var 确定。
- url($message = null) - 字段值是一个有效的 URL,使用 filter_var 确定。
- date($message = null) - 字段值是一个有效的日期,可以是 DateTime() 接受的任何格式。
- minDate($date, $format, $message = null) - 日期必须大于 $date。$format 必须是页面上的格式 https://php.ac.cn/manual/en/datetime.createfromformat.php
- maxDate($date, $format, $message = null) - 日期必须小于 $date。$format 必须是页面上的格式 https://php.ac.cn/manual/en/datetime.createfromformat.php
- ccnum($message = null) - 字段值必须是一个有效的信用卡号。
- oneOf($allowed, $message = null) - 字段值必须是 $allowed 中的其中一个值。$allowed 可以是一个数组或以逗号分隔的值列表。如果以逗号分隔,除非有意用于匹配,否则不要包含空格。
- callback($callback, $message = '', $params = null) - 定义您自己的自定义回调验证函数。$callback 必须通过 is_callable() 检查。$params 可以是任何值,或者如果必须传递多个参数,则是一个数组。
验证数组和数组索引
此验证类已扩展,允许验证数组以及多维数组的嵌套索引。
要验证数组的特定索引,请使用点表示法,例如。
// load the validator
$validator = new \assegai\modules\validator\Validator($this->request->allPost());
// ensure $_POST['field']['nested'] exists
$validator
->required('The nested field is required.')
->validate('field.nested');
// ensure we have the first two numeric
// indices of $_POST['links'][]
$validator
->required('This field is required')
->validate('links.0');
$validator
->required('This field is required')
->validate('links.1');
可用的预验证过滤
您可以将预验证过滤器应用于您的数据(例如,trim、strip_tags、htmlentities)。只要通过 is_callable()
检查,这些过滤器也可以自定义。
- filter($callback)
示例
// standard php filter for valid user ids.
$validator
->filter('intval')
->min(1)
->validate('user_id');
// custom filter
$validator
->filter(function($val) {
// bogus formatting of the field
$val = rtrim($val, '/');
$val .= '_custom_formatted';
})
->validate('field_to_be_formatted');