资源路由
系统提供了一个命令,方便开发者快速生成一个资源控制器,其中自带了很多CRUD的方法:
php think make:controller Blog
生成的方法,参数默认值为id可以修改:
->vars(['blog'=>'blog_id']); //相应的 delete($blog_id)
资源路由,采用固定的常用方法来实现简化 URL的功能:
Route::resource('ads', 'Address');
在路由定义文件下创建一个资源路由,资源名称可自定义,这里的 blog表示资源规则名,Blog表示路由的访问路径:
Route::resource('blog', 'Blog');
资源路由注册成功后,会自动提供以下方法,无须手动注册:
GET访问模式下:index(blog),create(blog/create),read(blog/:id),edit(blog/:id/edit)
POST访问模式下:save(blog)
PUT方式模式下:update(blog/:id)
DELETE方式模式下:delete(blog/:id)
http://localhost:8000/blog/ (index)
http://localhost:8000/blog/5 (read)
http://localhost:8000/blog/5/edit (edit)
对于 POST,是新增,一般是表单的 POST提交,而 PUT和 DELETE用 AJAX访问。
$.ajax({
type : "DELETE",
url : "http://localhost:8000/blog/10",
success : function (res) {
console.log(res);
}
});
也可以通过 only()方法限定系统提供的资源方法,比如(只能用这些操作):
->only(['index','save','create'])
还可以通过 except()方法排除系统提供的资源方法,比如:
->except(['read','delete','update'])
使用 rest()方法,更改系统给予的默认方法,1.请求方式;2.地址;3.操作
Route::rest('create', ['GET', '/:id/add', 'add']);
//批量
Route::rest([
'save' => ['POST', '', 'store'],
'update' => ['PUT', '/:id', 'save'],
'delete' => ['DELETE', '/:id', 'destory'],
]);
使用嵌套资源路由,可以让上级资源对下级资源进行操作,创建 Comment资源:
class Comment
{
public function read($id, $blog_id) {
return 'Comment id:'.$id.',Blog id:'.$blog_id;
}
public function edit($id, $blog_id) {
return 'Comment id:'.$id.',Blog id:'.$blog_id;
}
}
使用嵌套资源路由,可以让上级资源对下级资源进行操作,创建 Comment资源:
Route::resource('blog.comment', 'Comment');
资源嵌套生成的路由规则如下:
http://localhost:8000/blog/:blog_id/comment/:id http://localhost:8000/blog/:blog_id/comment/:id/edit
嵌套资源生成的上级资源默认 id为:blog_id,可以通过 vars更改;
Route::resource('blog.comment', 'Comment')
->vars(['blog'=>'blogid']);
注解路由
路由的注解方式,并非系统默认支持,而是可选方案,需要额外安装扩展:
composer require topthink/think-annotation
安装好后,使用 use引入相关类库:
use think\annotation\Route;
然后在控制器设置注解代码即可,可以使用 PHPDOC生成一段,然后添加路由规则。注意:这里必须使用双引号,单引号会直接报错:
/**
* @param $id
* @return string
* @route("details/:id");
*/
第二或以上参数,可以设置请求类型,比如要求是 GET模式访问:
* @route("ds/:id", method="GET")
更多参数可实现更多功能(不需要考虑顺序),比如 ext、https等:
@route("ds/:id", method="GET", ext="html", https=1) //布尔值 0,1代替
注解模式也支持资源路由,先要 use相关类库,然后声明:
use think\annotation\Route\Resource;
/**
* @Resource("blog")
*/
class Blog ...
注解模式也支持分组,先要 use相关类库,然后声明:
use think\annotation\Route;
use think\annotation\route\Group;
* @Group("ads")
URL生成
首先,创建一个新的控制器:Url.class,创建一个路由方法和 URL生成的方法,然后,路由这两个方法,具体如下:
Route::rule('ds', 'Url/index');
Route::rule('ds/:id', 'Url/details');
使用 Route::buildUrl('地址', [参数]...)方式来获取路由的 URL地址:
return Route::buildUrl('Url/details', ['id'=>5]);
这里的地址和路由的定义是相辅相成的,如果没有定义,地址将会变化。也可以给路由定义取一个别名,然后在生成 URL的时候,直接使用这个别名调用:
Route::rule('ds/:id', 'Url/details')->name('u');
return Route::buildUrl('u', ['id'=>5]);
也可以直接使用路由地址生成 URL,但这个方式并不需要和路由定义相匹配:
return Route::buildUrl('ds/5');
由于,我们默认在配置设置了后缀为.html,所以,生成的 URL会自动加上:
return Route::buildUrl('ds/5')->suffix('shtml');
如果,你想添加完整域名路径,可以再添加 domain方法。也可以直接使用助手函数url()来代替Route::buildUrl():
return Route::buildUrl('ds/5')->domain(true);
return Route::buildUrl('ds/5')->domain('news');
return Route::buildUrl('ds/5')->domain('news.abc.com');
return Route::buildUrl('ds/5@news.abc.com');
容器和依赖注入
依赖注入
手册对依赖注入比较严谨的说明,具体如下:
依赖注入其实本质上是指对类的依赖通过构造器完成自动注入,例如在控制器架构方法和操作 方法中一旦对参数进行对象类型约束则会自动触发依赖注入,由于访问控制器的参数都来自于 URL 请求,普通变量就是通过参数绑定自动获取,对象变量则是通过依赖注入生成。
先看一个小例子,了解一下依赖注入的写法,创建一个模型:
namespace app\model;
use think\Model;
class One extends Model {
public $username = 'Mr.Lee';
}
创建一个控制器 Inject,通过依赖注入将模型One对象引入其内:
amespace app\controller;
use app\model\One; class Inject
{
protected $one;
public function __construct(One $one) {
$this->one = $one;
}
public function index() {
return $this->one->username;
}
}
依赖注入:即允许通过类的方法传递对象的能力,并且限制了对象的类型(约束);而传递的对象背后的那个类被自动绑定并且实例化了,这就是依赖注入。
容器
依赖注入的类统一由容器管理的,大多数情况下是自动绑定和自动实例化的。如果想手动来完成绑定和实例化,可以使用 bind()和 app()助手函数来实现。
class Inject
{
public function bind() {
// bind('one','...')绑定类库标识,这个标识具有唯一性,以便快速调用
bind('one', 'app\model\One');
// app('one')快速调用,并自动实例化对象,标识严格保持一致包括大小写
return app('one')->username;
}
}
自动实例化对象的方式,是采用单例模式实现,如果想重新实例化一个对象,则:
//每次调用总是会重新实例化
$one = app('one',[], true);
return $one->name;
app('one',[])中第二参数,方法实例化对象的时候,传递参数:
bind('one', 'app\model\One');
$one = app('one', [['file']], true);
return $one->username;
当然,你也可以直接通过 app()绑定一个类到容器中并自动实例化。
return app('app\model\One')->username;
使用 bind([])可以实现批量绑定,只不过系统有专门提供批量绑定的文件:
bind([
'one' => 'app\model\One',
'user' => 'app\model\User'
]);
return app('one')->username;
bind([
'one' => \app\model\One::class,
'user' => \app\model\User::class
]);
return app('user')->username;
::class模式,不需要单引号,而且需要在最前面加上\,之前的加不加都行。系统提供了 provider.php文件,用于批量绑定类到容器中,这里不加不报错。
return [
'one' => app\model\One::class, //这里加不加\都正常
'user' => app\model\User::class
];
系统内置了很多常用的类库,以便开发者快速调用,具体如下:
也就是说,实现同一个效果可以由容器的 bind()和 app()实现,也可以使用依赖 注入实现,还有 Facade(下节课重点探讨)实现,以及助手函数实现。