创建model
php artisan make:entity Article
Would you like to create a Presenter? [y|N] (yes/no) [no]:
y
App\Transformers\ArticleTransformerPresenter created successfully.
Would you like to create a Transformer? [y|N] (yes/no) [no]:
y
Transformer created successfully.
Would you like to create a Validator? [y|N] (yes/no) [no]:
y
Validator created successfully.
Would you like to create a Controller? [y|N] (yes/no) [no]:
y
Request created successfully.
Request created successfully.
Controller created successfully.
Repository created successfully.
Bindings created successfully
生成或修改了以下文件
- Model 模型文件
- Presenters 常用于前端模板格式化输出 (可能不准确)
Presenters function as a wrapper and renderer for objects.
- Transformer 用于model数据格式化输出
- Validator 验证器
- CreateRequest 创建数据请求
- UpdateRequest 更新数据请求
- Controller RESTfull控制器
- Repository 资料库与资料库接口
php artisan make:repository "Blog\Post"
php artisan make:repository "Blog\Post" --fillable="title,content"
php artisan make:entity Cat --fillable="title:string,content:text" --rules="title=>required|min:2, content=>sometimes|min:10"
- Bindings 在Providers/RepositoryServiceProvider.php中注册
php artisan make:bindings Cats //可单独使用
$this->app->bind(\App\Repositories\ArticleRepository::class, \App\Repositories\ArticleRepositoryEloquent::class);
- 添加了对应的数据库迁移文件
添加模型字段 数据库迁移 测试数据填充
- 修改迁移文件 具体方法参考 http://laravelacademy.org/post/6964.html
$table->increments('id');
$table->String('title',150)->comment('标题');
$table->String('author',50)->comment('作者');
$table->text('article')->comment('文章');
$table->softDeletes()->comment('软删除');
$table->timestamps();
- 修改model文件添加字段
protected $fillable = [
'title',
'author',
'article'
];
- 为了方便数据库的填充使用factories工厂文件与seeds种子文件
=>工厂文件
$factory->define(App\Entities\Article::class, function (Faker\Generator $faker) {
return [
'title' => $faker->sentence,
'author'=> $faker->name,
'article'=> $faker->text,
// 'img' => $faker->url,
// 'content' => $faker->text,
// 'sort' => $faker->randomDigit,
// 'pageviews' => $faker->randomDigit,
// 'tag' => $faker->randomDigit,
// 'status' => $faker->randomElement([-1, 0, 1]),
];
});
=>种子文件
//创建种子文件
artisan make:seeder ArticleTableSeeder
//修改种子文件
public function run()
{
$article = factory('App\Entities\Article',50)->create();
}
//修改DatabasesSeeder
public function run()
{
//$this->call(UsersTableSeeder::class);
$this->call(ArticleTableSeeder::class);
}
执行迁移与填充
php artisan migrate
php artisan db:seed
//或者直接使用下面的
php artisan migrate:refresh --seed
注册服务 添加路由 尝试输出
- 注册服务
//在AppServiceProvider的register中添加
$this->app->register(RepositoryServiceProvider::class);
- 添加路由
//在路由文件中添加
Route::resource('article', ArticlesController::class);
- 修改控制器并访问地址
public function index()
{
$this->repository->pushCriteria(app('Prettus\Repository\Criteria\RequestCriteria'));
$articles = $this->repository->all();
if (request()->wantsJson()) {
return response()->json([
'data' => $articles,
]);
}
dd($articles);
return $articles->toJSON();
// return view('articles.index', compact('articles'));
}
访问 http://192.168.10.10:90/article
正常返回json格式数据
简单的搜索功能实现
- 在ArticleRepositoryEloquent中添加允许搜索字段
//格式 字段=>搜索方式 默认搜索方式为 =
protected $fieldSearchable = [
'id'=>'=',
'title'=>'like',
'author'
];
- 几种不同搜索方式中数据库查询的差别
http://192.168.10.10:90/article?search=Ratione
select * from `articles` where (`articles`.`id` = 'Ratione' or `articles`.`title` like '%Ratione%' or `articles`.`author` = 'Ratione') and (`articles`.`id` = 'Ratione' or `articles`.`title` like '%Ratione%' or `articles`.`author` = 'Ratione')
或
http://192.168.10.10:90/article?search=Ratione&searchFields=title:like
select * from `articles` where (`articles`.`title` like '%Ratione%') and (`articles`.`title` like '%Ratione%')
或
http://192.168.10.10:90/article?search=id:15;title:Ratione&searchFields=title:like;id:=
select * from `articles` where (`articles`.`id` = '15' or `articles`.`title` like '%Ratione%') and (`articles`.`id` = '15' or `articles`.`title` like '%Ratione%')
正常返回json格式数据
过滤功能的实现
select `id`, `author` from `articles`
或
http://192.168.10.10:90/article?filter=id;author&orderBy=id&sortedBy=desc
select `id`, `author` from `articles` order by `id` desc, `id` desc
关联查询功能实现
- TODO
普通的删除添加与修改功能的实现
- 为了方便测试可以关闭csrf验证并修改updateRepository与createRepository中的用户权限验证
1.注释掉http/Kernel.php中的
\App\Http\Middleware\VerifyCsrfToken::class
2.修改updateRepository与createRepository中的authorize()
public function authorize()
{
return true;
}
- 删除
使用postman用delete方法访问http://192.168.10.10:90/article/6
数据库中文章被直接删除并没有软删除 - 修改
使用postman用put方法访问http://192.168.10.10:90/article/7?title=xxxxxxxxxxxx
数据库中文章被修改 - 添加
使用postman用post方法访问http://192.168.10.10:90/article?title=yyyyyyyyyy&author=XloodHunter&article=全球全球十大十大快乐啊大大
数据库添加文章成功 - 软删除
修改model文件引入软删除
namespace App\Entities;
use Illuminate\Database\Eloquent\Model;
use Prettus\Repository\Contracts\Transformable;
use Prettus\Repository\Traits\TransformableTrait;
use Illuminate\Database\Eloquent\SoftDeletes;
class Article extends Model implements Transformable
{
use TransformableTrait;
use SoftDeletes;
protected $fillable = [
'title',
'author',
'article'
];
}
使用postman用delete方法访问http://192.168.10.10:90/article/7
数据库中文章并没有被直接删除,而且搜索与访问均失败
软删除后如果想要强制删除可在控制器中添加,或者在资料库与资料库接口中扩展
public function forceDestroy($id)
{
$deleted = $this->repository->find($id)->forceDelete();
if (request()->wantsJson()) {
return response()->json([
'message' => 'Article forceDelete.',
'deleted' => $deleted,
]);
}
return redirect()->back()->with('message', 'Article forceDelete.');
}
数据库中文章被删除
缓存的使用
- 这里需要在repository中添加缓存trait
use Prettus\Repository\Contracts\CacheableInterface;
use Prettus\Repository\Traits\CacheableRepository;
class ArticleRepositoryEloquent extends BaseRepository implements ArticleRepository
{
/**
* 开启缓存
*
*/
use CacheableRepository;
......
}
- 为了方便查看结果,我们不用默认的文件缓存,而改使用redis进行缓存http://laravelacademy.org/post/6974.html
//为了方便,修改redis配置文件,使其可以后台运行,并可以远程连接
//关于远程连接bind
//这里很多人会误以为绑定的ip应该是请求来源的ip。其实不然,这里应该绑定的是你redis服务器本身接受请求的ip。http://www.2cto.com/database/201507/419799.html
redis-server ./redis.conf
然后修改.env文件,如果之前使用过file缓存更换为redis后,redis无法使用,则说明laravel配置被缓存了,需要删除该缓存
artisan config:clear
artisan cache:clear
- 可以发现如果重复上述查找,修改,删除,添加测试,数据库并不会每次都会进行查询,而且通过RedisDesktopManager可以清楚的看见会有对象缓存进去。
- 进行不同条件的检索时会有不同的对象缓存进redis,所以如果不是相同条件进行检索,还是会对数据库进行操作
- 在任何的修改,删除(包括软删除),添加后,redis缓存都会被清除
- 并发性能测试
安装siege后进行测试,执行命令
siege -c 255 -r 1 http://192.168.10.10:90/article
不使用缓存时
vagrant@homestead:/usr/local/etc$ ../siege/src/siege -c 255 -r 1 http://192.168.10.10:90/article
** SIEGE 4.0.3rc3
** Preparing 255 concurrent users for battle.
The server is now under siege...
Transactions: 255 hits
Availability: 100.00 %
Elapsed time: 39.52 secs
Data transferred: 5.50 MB
Response time: 18.80 secs
Transaction rate: 6.45 trans/sec
Throughput: 0.14 MB/sec
Concurrency: 121.30
Successful transactions: 255
Failed transactions: 0
Longest transaction: 39.45
Shortest transaction: 1.44
使用缓存时
vagrant@homestead:/usr/local/etc$ ../siege/src/siege -c 255 -r 1 http://192.168.10.10:90/article
** SIEGE 4.0.3rc3
** Preparing 255 concurrent users for battle.
The server is now under siege...
Transactions: 255 hits
Availability: 100.00 %
Elapsed time: 52.13 secs
Data transferred: 5.33 MB
Response time: 34.30 secs
Transaction rate: 4.89 trans/sec
Throughput: 0.10 MB/sec
Concurrency: 167.77
Successful transactions: 255
Failed transactions: 0
Longest transaction: 52.08
Shortest transaction: 16.37
结果让我有点吃惊。。。开了比没开居然还稍微差点,关闭调试模式也一样。不知道是我电脑性能不行还是因为查询结构太简单导致的。。。。。。也可能是其他地方没有使用redis比如session之类
TODO
过滤器
- 可以修改Validator文件,也可以分别修改Create与Update的Request文件。其中Request优先级高于Validator,而且Validator文件中无法正常添加使用自定义错误信息,原因可能是Valitdator插件对应版本为laravel4,作者已经不再维护了。。。。。不过可以尝试使用这个方法https://github.com/andersao/laravel-validator/issues/21
Validator中
protected $rules = [
ValidatorInterface::RULE_CREATE => [
'title' => 'required|max:50',
'text' => 'min:3',
'author'=> 'required|max:8'
],
ValidatorInterface::RULE_UPDATE => [
'title' => 'required',
],
];
// 错误信息不能正常调出。
// protected $messages= [
// 'title.required' => 'attt.',
// 'min' => 'minnn.',
// 'author.max' => 'maxxxx.',
// ];
// public function messages()
// {
// return $this->messages;
// }
CreateRequest中
public function rules()
{
return [
'title' => 'required|max:15',
'text' => 'min:6',
'author'=> 'required|max:7'
];
}
public function messages()
{
return [
'title.required' => '请填写标题.',
'min' => '低于最小字数.',
'author.max' => '超过字数限制.',
];
}
- 使用postman访问http://192.168.10.10:90/article?author=XloodHunter&article=455jnk551 后返回自定义的错误信息
格式化输出
- 顾名思义他只控制输出格式,因此即便是只输出部分字段,他还是会从数据库中选择所有字段。通过修改Transform文件然后在仓库中或者控制器中注册Presenter,即可格式化输出。默认为json格式输出。
修改Transform文件如下后,访问
public function transform(Article $model)
{
return [
'id' => (int) $model->id,
/* place your other model properties here */
'标题' =>$model->title,
'作者' =>$model->author,
'article' =>$model->article,
'created_at' => $model->created_at,
// 'updated_at' => $model->updated_at
];
}
修改仓库
public function presenter()
{
return "App\\Presenters\\ArticlePresenter";
}
或者修改控制器
public function __construct(ArticleRepository $repository, ArticleValidator $validator)
{
$this->repository = $repository;
$this->repository->setPresenter("App\\Presenters\\ArticlePresenter");
$this->validator = $validator;
}
- 当然也可以通过修改Model文件来格式化输出。但优先级比Transform文件低。
Model文件
namespace App\Entities;
use Illuminate\Database\Eloquent\Model;
use Prettus\Repository\Contracts\Transformable;
use Prettus\Repository\Traits\TransformableTrait;
use Illuminate\Database\Eloquent\SoftDeletes;
use Prettus\Repository\Traits\PresentableTrait;
class Article extends Model implements Transformable
{
use TransformableTrait;
use SoftDeletes;
use PresentableTrait;
protected $fillable = [
'title',
'author',
'article'
];
public function transform()
{
return [
'id' => (int) $this->id,
/* place your other model properties here */
'标题' =>$this->title,
'作者' =>$this->author,
'文章' =>$this->article,
'created_at' => $this->created_at,
'updated_at' => $model->updated_at
];
}
}
控制器
public function __construct(ArticleRepository $repository, ArticleValidator $validator)
{
$this->repository = $repository;
//$this->repository->setPresenter("App\\Presenters\\ArticlePresenter");
$this->repository->setPresenter("Prettus\\Repository\\Presenter\\ModelFractalPresenter");
$this->validator = $validator;
}
或者修改仓库
public function presenter()
{
return "Prettus\\Repository\\Presenter\\ModelFractalPresenter";
}
- 当然也可以跳过该自定义格式或者只在部分地方使用
public function show($id)
{
//部分函数内跳过
$this->repository->skipPresenter();
//在部分函数内使用
$this->repository->setPresenter("App\\Presenters\\ArticlePresenter");
$article = $this->repository->find($id);
if (request()->wantsJson()) {
return response()->json([
'data' => $article,
]);
}
// return $article->toJSON();
return $article;
// return view('articles.show', compact('article'));
}
- 使用postman访问http://192.168.10.10:90/article/31 后返回自定义格式输出
转载请注明出处,谢谢=.=