http://www.cnblogs.com/webskill/category/1067140.html

laravel 5.4 新特性

component and slot

使用:

1.component panel

  1. <article class="message">
  2. <div class="message-header">
  3. <p>Hello World</p>
  4. <button class="delete" aria-label="delete"></button>
  5. </div>
  6. <div class="message-body">
  7. Lorem ipsum dolor sit amet, consectetur adipiscing elit. <strong>Pellentesque risus mi</strong>, tempus quis placerat ut, porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla. Nullam gravida purus diam, et dictum <a>felis venenatis</a> efficitur. Aenean ac <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi magna a neque. Donec dui urna, vehicula et sem eget, facilisis sodales sem.
  8. </div>
  9. </article>

2.其中header和body需要传入变量

  1. <article class="message">
  2. <div class="message-header">
  3. <p>{{$title}}</p>
  4. <button class="delete" aria-label="delete"></button>
  5. </div>
  6. <div class="message-body">
  7. {{$content}}
  8. </div>
  9. </article>

3.views.components.index 中 需要引用component模版panel

  1. @component('components.panel')
  2. @slot('title')
  3. hello world
  4. @endslot
  5. @slot('content')
  6. have a nice day
  7. @endslot
  8. @endcomponent

4.如果要传入默认content

panel.blade.php修改如下:

  1. <article class="message">
  2. <div class="message-header">
  3. <p>{{$title}}</p>
  4. <button class="delete" aria-label="delete"></button>
  5. </div>
  6. <div class="message-body">
  7. {{$slot}}
  8. </div>
  9. </article>

index.blade.php修改如下

  1. @component('components.panel')
  2. @slot('title')
  3. hello world
  4. @endslot
  5. have a nice day
  6. @endcomponent
  7. //可多来几个:
  8. @component('components.panel')
  9. @slot('title')
  10. hello world
  11. @endslot
  12. have a nice day123
  13. @endcomponent

5.还可以这样给默认值:title默认为laravel

  1. panel.blade.php修改如下:
  2. <article class="message">
  3. <div class="message-header">
  4. <p>{{$title ?? 'laravel'}}</p>
  5. <button class="delete" aria-label="delete"></button>
  6. </div>
  7. <div class="message-body">
  8. {{$slot}}
  9. </div>
  10. </article>
  11. index.blade.php修改如下
  12. @component('components.panel')
  13. have a nice day
  14. @endcomponent

laravel 邮件

本文使用qq邮箱

env邮件配置:

  1. MAIL_FROM_ADDRESS = 17******92@qq.com
  2. MAIL_FROM_NAME = listen~
  3. MAIL_DRIVER=smtp
  4. MAIL_HOST=smtp.qq.com
  5. MAIL_PORT=465
  6. MAIL_USERNAME=17*******2@qq.com
  7. MAIL_PASSWORD= ****** //这个是你的qq授权码
  8. MAIL_ENCRYPTION=ssl
  9. MAIL_ENCRYPTION=ssl
  1. 创建邮件类

    1. php artisan make:mail welcomeToMiya
  2. 修改welcomeToMiya.php视图

    1. public function build()
    2. {
    3. return $this->view('email.welcome');
    4. }
  3. 使用

    1. //发送邮件
    2. Route::get('/mail',function(){
    3. \Illuminate\Support\Facades\Mail::to('2861166132@qq.com')->send(new \App\Mail\welcomeToLaravist());
    4. });
  4. 传参 修改 welcomeToMiya.php

    1. public $user;
    2. public function __construct(User $user)
    3. {
    4. $this->user = $user;
    5. }
  5. 传参 修改 web.php

    1. //发送邮件
    2. Route::get('/mail',function(){
    3. $user = \App\User::find(1);
    4. \Illuminate\Support\Facades\Mail::to('2861166132@qq.com')->send(new \App\Mail\welcomeToLaravist($user));
    5. });

发邮件还可以这样:

  1. public function sendTo($user,$subject,$view,$data){
  2. //也可以使用Mail::send
  3. Mail::send($view,$data,function ($message) use ($user,$subject){
  4. $message->to($user->email)->subject($subject);
  5. });
  6. }

使用sendcloud:

参考github: https://github.com/NauxLiu/Laravel-SendCloud

notification 通知

= mail篇 ### =

  1. public function via($notifiable)
  2. {
  3. return ['mail'];
  4. }

1.新建notification类

  1. php artisan make:notification PostNotification

2.设置路由

  1. //notification 注意默认发送到user模型中的email邮箱账号 所以要确认user邮箱可用
  2. Route::get('/notification',function(){
  3. $user = \App\User::find(1);
  4. $post = \App\Post::find(2);
  5. $user->notify(new \App\Notifications\PostNotification($post));
  6. });

3.访问/notification 收到邮件

4.常用设置方法 PostNotification.php

  1. public function toMail($notifiable)
  2. {
  3. return (new MailMessage)
  4. ->subject('A post published'.$this->post->title) //自定义主体
  5. ->success() //定义按钮颜色
  6. ->line('The introduction to the notification.')
  7. ->action('Notification Action', url('/'))
  8. ->line('Thank you for using our application!');
  9. }

=database篇 ### =

将通知都存储在数据库里

1.修改PostNotification.php

  1. public function via($notifiable)
  2. {
  3. //return ['mail'];
  4. return ['database'];
  5. }

2.创建notification迁移文件

  1. php artisan notifications:table
  2. php artisan migrate

3.PostNotification.php 中可添加 toDatabase方法 如果没写的话默认用的是toArray方法

4.修改web.php

5.查看当前用户下的notifications

6.新建一个notification

  1. php artisan make:notification UserSubscribe

7.UserSubscribe.php 修改如下

  1. public function via($notifiable)
  2. {
  3. return ['database'];
  4. }
  5. /**
  6. * Get the array representation of the notification.
  7. *
  8. * @param mixed $notifiable
  9. * @return array
  10. */
  11. public function toArray($notifiable)
  12. {
  13. return [
  14. 'subscribed_at' => Carbon::now()
  15. ];
  16. }

8.修改web.php

  1. //notification
  2. Route::get('/notification', function () {
  3. $user = \App\User::find(1);
  4. $post = \App\Post::find(2);
  5. //$user->notify(new \App\Notifications\PostNotification($post));
  6. $user->notify(new \App\Notifications\UserSubscribe());
  7. });

9.再次查看当前用户的notifications

10.列出未读notifications并标识为已读

web.php

  1. //notification
  2. Route::get('/show-notification', function () {
  3. return view('notifications.index');
  4. });
  5. //标识未读
  6. Route::delete('user/notification',function (){
  7. Auth::user()->unreadNotifications->markAsRead();
  8. return redirect()->back();
  9. });

notifications.index.blade

  1. @extends('app')
  2. @section('content')
  3. <h1>我的通知:</h1>
  4. <ul>
  5. @foreach(Auth::user()->unreadNotifications as $notification)
  6. @include('notifications/'.snake_case( class_basename($notification->type) ))
  7. @endforeach
  8. </ul>
  9. <form action="/user/notification" method="POST">
  10. {{csrf_field()}}
  11. {{method_field('DELETE')}}
  12. <input type="submit" value="标识已读">
  13. </form>
  14. @stop

user_subscribe.blade.php

  1. <h2>user</h2>
  2. {{$notification->data['subscribed_at']['date']}}

post_notification.blade.php

  1. <h2>post</h2>
  2. <li>{{$notification->data['title']}}</li>

标识某条已读

  1. $user->refresh()->unreadNotifications->where('id','57bb0e0e-8d35-4da8-850b-121a5317c9b9')->first()->markAsRead();

总结:

database

  • php artisan make:notification someNotification
  • 对于需要传入的参数做修改 例如依赖模式 Post $post
  • php artisan notification:table
  • 获取notification $user->notifications
  • 标识已读 所有的 $user->unreadNotifications->markAsRead()

    单条标识:$user->refresh()->unreadNotifications->where('id','57bb0e0e-8d35-4da8-850b-121a5317c9b9')->first()->markAsRead();

laravel 邮件使用markdown

  1. php artisan make:mail lessonPublished --markdown="emails.published"

这个命令不仅创建了email类文件 还生成了视图文件 并把视图也写好了 return $this->markdown('emails.published'')

可根据需要修改 也可修改email markdown模版 php artisan vendor:publish

发送邮件

  1. Route::get("sendmail",function(){
  2. $email = new \App\Mail\LessionPublished(\App\User::first());
  3. Mail::to(\App|User::first())->send($email);
  4. })

toggle

toggle方法主要用于多对多关系中,attach detach 比如点赞 收藏

1.user表

2.post表 title content

3.中间表 favoriate user_id post_id

4.user中定义关系

  1. public function favorites(){
  2. return $this->belongsToMany(Post::class,'favoriates'); //第二个参数中间表
  3. }

5.关联关系

做法一:

在tinker中操作

  1. $user = App\User::find(1);
  2. $post = App\Post::find(2);
  3. $user->favorite()->attach($post);
  4. 查看结果:$user->refresh()->favorite
  5. //取消收藏
  6. $user->favorite()->detach($post);

做法二:toggle 不用去判断用户有没有收藏该文章 用户收藏了则取消收藏 反之则收藏

  1. $user->favorite()->toggle($post);

实时facade###

  1. 创建一个目录叫services

    创建一个weibo类

    1. <?php
    2. namespace App\Services;
    3. class weibo
    4. {
    5. protected $http;
    6. public function __construct(Http $http)
    7. {
    8. $this->http = $http;
    9. }
    10. public function publish($status){
    11. $this->http->post($status);
    12. }
    13. }

创建一个Http类

  1. <?php
  2. namespace App\Services;
  3. class Http
  4. {
  5. public function __construct()
  6. {
  7. }
  8. public function post($status){
  9. return dd('I post a post'.$status);
  10. }
  11. }

路由修改

  1. use Facades\App\Services\weibo;
  2. //facade
  3. Route::get('facade',function (){
  4. weibo::publish('这是一条微博');
  5. });

现在访问就有了:"I post a post这是一条微博"

事件监听

方法一:

web.php

  1. Event::listen('eloquent.created: App\post',function(){
  2. dump('A post was created');
  3. });
  4. Route::get('/event53',function(){
  5. \App\post::create(['title'=>'Title','content'=>'My Body']);
  6. });

方法二:

注释掉

  1. Event::listen('eloquent.created: App\post',function(){
  2. dump('A post was created');
  3. });

post模型中定义事件

  1. <?php
  2. namespace App;
  3. use App\Events\PostWasPublished;
  4. use Illuminate\Database\Eloquent\Model;
  5. class post extends Model
  6. {
  7. protected $guarded = array();
  8. protected $events = [
  9. 'created' => PostWasPublished::class
  10. ];
  11. }

修改EventServiceProvider.php 中的$listen属性 创建事件和事件监听文件

  1. protected $listen = [
  2. 'App\Events\PostWasPublished' => [
  3. 'App\Listeners\PostWasPublishedListener',
  4. ],
  5. ];

执行 php artisan event:generate

** 还可以依赖注入 **

App\Events\PostWasPublished.php

  1. public $post;
  2. public function __construct($post)
  3. {
  4. $this->post = $post;
  5. }

App\Listeners\PostWasPublishedListener.php

  1. public function handle(PostWasPublished $event)
  2. {
  3. dump($event->post->toArray());
  4. }

方法三:普通路由触发event

app/Providers/EventServiceProvider.php

  1. protected $listen = [
  2. 'App\Events\UserSignUp' => [
  3. 'App\Listeners\UserSignUpListener',
  4. ],
  5. ];

UserSignUp.php

  1. use App\User;
  2. public $user;
  3. public function __construct(User $user)
  4. {
  5. $this->user = $user;
  6. }

UserSignUpListener.php

  1. public function handle(UserSignUp $event)
  2. {
  3. dd($event->user->name);
  4. }

web.php

  1. Route::get('/eventroute',function(){
  2. $user = \App\User::find(1);
  3. event(new \App\Events\UserSignUp($user));
  4. });

console command

  1. php artisan make:command hello

进入app/console/commands/hello.php

修改singniture和handle

  1. protected $signature = 'lara:hello';
  2. public function handle()
  3. {
  4. $this->info('hello my girl');
  5. }

app/console/kernel.php $commands属性修改 添加刚才的类

  1. App\Console\Commands\hello::class

传参:php artisan lara:hello alice

  1. protected $signature = 'lara:hello{name=Bool}'; //? 可有可无
  2. protected $signature = 'lara:hello{name=Bool}'; //? 可有可无
  3. public function handle()
  4. {
  5. $this->info('hello my girl '.$this->argument('name'));
  6. }

默认值:protected $signature = 'lara:hello{name=Bool}';

定时任务

新建一个test.sh

  1. #!/bin/bash
  2. echo "hello world";
  3. php test.php

test.php

  1. this is a test for crontab
  2. $ cronatab -e
  3. * * * * * /var/www/test.sh 2>&1 >> /var/www/test.log

laravel 定时任务:

  1. $ php artisan make:conmmand logInfo

修改 ap/console/command/logInfo.php

  1. protected $description = 'log Info';
  2. public function handle()
  3. {
  4. Log::info('It works');
  5. }

kernel中注册 app/console/kernel.php

  1. protected $commands = [
  2. //
  3. hello::class,
  4. logInfo::class
  5. ];
  6. /**
  7. * Define the application's command schedule.
  8. *
  9. * @param \Illuminate\Console\Scheduling\Schedule $schedule
  10. * @return void
  11. */
  12. protected function schedule(Schedule $schedule)
  13. {
  14. $schedule->command('log:info')
  15. ->everyMinute();
  16. }
  17. $ crontab -e
  18. * * * * * php /var/www/lara/leaning/artisan schedule:run >> /dev/null 2>&1

middleware###

  1. php artisan make:middleware isAdminMiddleware

user表增加is_admin字段 值为 Y/N

模型user.php

  1. public function isAdmin(){
  2. return $this->is_admin == 1;
  3. }

修改isAdminMiddleware

  1. public function handle($request, Closure $next)
  2. {
  3. info( $request->user()); //等价于 Auth::user()
  4. if($request->user() && $request->user()->isAdmin()){
  5. return $next($request);
  6. }
  7. return redirect('/');
  8. }

web.php

  1. Auth::loginUsingId(2);
  2. Route::group(['prefix'=>'admin','middleware'=>'isAdmin'],function (){
  3. Route::get('users',function (){
  4. return 'admin only';
  5. });
  6. });

controller中可以这样设置

  1. public function __construct(){
  2. $this->middleware('admin',['only'=>['store','update']]);
  3. }

app/Http/Kernel.php

  1. protected $routeMiddleware = [
  2. 'isAdmin' => isAdminMiddleware::class
  3. ];
  4. }

视图绑定变量###

app下新建一个类 Status

  1. <?php
  2. namespace App;
  3. class Status
  4. {
  5. public function total(){
  6. return 45;
  7. }
  8. }

路由以前的做法是这样

  1. Route::get('/status',function(\App\Status $status){
  2. return view('status',compact('status'));
  3. });

status.blade.php

  1. <h1>Status</h1>
  2. {{$status->total()}}

模板绑定变量这样写:

路由:不传递任何变量

  1. Route::get('/status',function(){
  2. return view('status');
  3. });

模板中注入变量:status.blade.php

  1. @inject('status','App\Status')

本地化Model Factory###

tinker:

  1. factory(User::class,5)->create() //会写库
  2. //或
  3. factory(User::class,5)->make() //不会写库

App/Providers/AppServiceProvider.php

  1. use Faker\Generator as FakerGenerator;
  2. use Faker\Factory as FakerFactory;
  3. public function boot()
  4. {
  5. $this->app->singleton(FakerGenerator::class,function (){
  6. return FakerFactory::create('zh_CN');
  7. });
  8. }

再次用tinker生成的数据就是中文的了

DB::table('users')->truncate() 会将user表的数据全部删除

分页###

路由:

  1. Route::get('/lessons',function(){
  2. $lessons = \App\Lesson::paginate(15);
  3. return view('lessons',compact('lessons'));
  4. });

模板

  1. @extends('app')
  2. @section('content')
  3. <h1>Lessons</h1>
  4. @foreach($lessons->chunk(3) as $row)
  5. <div class="row">
  6. @foreach($row as $lesson)
  7. <div class="col-md-4">
  8. <h2>{{ $lesson->title }}</h2>
  9. <img style="width:100%; " src="{{$lesson->imageUrl}}" alt="">
  10. <div class="body">
  11. {{$lesson->intro}}
  12. </div>
  13. </div>
  14. @endforeach
  15. </div>
  16. @endforeach
  17. {!! $lessons->render() !!}
  18. {{ $lessons->appends(['type'=>'article'])->links('vendor.pagination.bootstrap-4') }}
  19. @stop

分页两种方式都可以

{!! $lessons->render() !!}

{{ $lessons->appends(['type'=>'article'])->links('vendor.pagination.bootstrap-4') }}

造测试数据 给article分配userId###

  1. $factory->define(\App\Article::class, function (Faker\Generator $faker) {
  2. $userIds= \App\User::pluck('id')->toArray();
  3. return [
  4. 'title' => $faker->sentence,
  5. 'content' => $faker->paragraph,
  6. 'user_id' => $faker->randomElements($userIds)[0]
  7. ];
  8. });

find 可以传入 id 也可以传入数组

  1. App\User::find([2,3])

with eager loading###

user.php

  1. public function posts(){
  2. return $this->hasMany(Post::class)
  3. }

路由:获取当前用户下的所有post

  1. 这里的post只的就是对应的关系
  2. $posts = \App\User::with('posts')->get()

多态关联###

应用场景:评论属于文章 属于lesson

  1. php artisan make:model comment -m

comment migration

  1. public function up()
  2. {
  3. Schema::create('comments', function (Blueprint $table) {
  4. $table->increments('id');
  5. $table->integer('commentable_id');
  6. $table->string('commentable_type');
  7. $table->text('body');
  8. $table->timestamps();
  9. });
  10. }

comment.php 模型

  1. class comment extends Model
  2. {
  3. public function commentable(){
  4. return $this->morphTo();
  5. }
  6. }

post.php 模型

  1. use App\comment;
  2. class post extends Model
  3. {
  4. protected $guarded = array();
  5. protected $events = [
  6. 'created' => PostWasPublished::class
  7. ];
  8. public function comments(){
  9. return $this->morphMany(comment::class,'commentable');
  10. }
  11. }

lesson.php 模型

  1. class Lesson extends Model
  2. {
  3. protected $guarded = array();
  4. public function comments(){
  5. return $this->morphMany(comment::class,'commentable');
  6. }
  7. }

使用:

  • 给某个lesson添加评论

    1. $lesson = App\Lesson::find(1);
    2. $lesson->unguard();
    3. $lesson->comments()->create(["body"=>"nice lesson"]);
  • 通过评论来查看属于哪个post

    1. $comment = App\comment::find(1);
    2. $comment->commentable

有用的小方法###

  • dd( $article->created_at->diffForHumans() ); //几分钟前
  • Config::get('database.default');
  • app('config')['database']['default']
  • Hash::make('password')
  • app('hash')->make('password')
  • config('services')
  • \Auth::login($user) //自动登录
  • Auth::check() //检查是否登录
  • 密码;bcrypt(str_random(16))
  • model中设置 $hidden = ['title'] //有时您可能想要限制能出现在数组或 JSON 格式的属性数据,比如密码字段。只要在模型里增加 hidden 属性即可

acl权限

AuthServiceProvider.php

  1. public function boot()
  2. {
  3. $this->registerPolicies();
  4. Gate::define('show-post',function ($user,$article){
  5. return $user->id ### $article->user_id;
  6. });
  7. }

controller.php 测试当前用户是否有权限(当前post的id是否是当前用户)访问当前post,如果没权限访问则报错403

  1. public function show($id){
  2. $article = Article::findOrFail($id);
  3. //dd( $article->created_at->diffForHumans() );
  4. //12 minits ago 如果需要中文可以
  5. //可以在app/Providers/AppServiceProvider.php的boot()方法加上:
  6. //\Carbon\Carbon::setLocale('zh');
  7. if(Gate::denies('show-post',$article)){
  8. abort(403,'sorry');
  9. };
  10. //也可以这么写
  11. // $this->authorize('show-post',$article);
  12. return view('articles.show',compact('article'));
  13. }

如果要在blade中运用 则全部注释掉

  1. public function show($id){
  2. $article = Article::findOrFail($id);
  3. //dd( $article->created_at->diffForHumans() );
  4. //12 minits ago 如果需要中文可以
  5. //可以在app/Providers/AppServiceProvider.php的boot()方法加上:
  6. //\Carbon\Carbon::setLocale('zh');
  7. //if(Gate::denies('show-post',$article)){
  8. //abort(403,'sorry');
  9. //};
  10. //也可以这么写
  11. // $this->authorize('show-post',$article);
  12. return view('articles.show',compact('article'));
  13. }

模版中使用

  1. @extends('app')
  2. @section('content')
  3. <h2>{{$article->title}}</h2>
  4. <div>{{$article->content}}</div>
  5. @can('show-post',$article)
  6. <a href="">编辑</a>
  7. @endcan
  8. @stop

使用policy###

policy的使用是为了更方便的创建用户权限规则 避免了在AuthServiceProvider中定义一长串的规则

  1. php artisan make:policy ArticlePolicy

添加policy 规则:

  1. public function editArticle($user,$article){
  2. return $user->id ### $article->user_id;
  3. }

AuthServiceProvider.php中注册该ArticlePolicy

  1. protected $policies = [
  2. 'App\Article' => 'App\Policies\ArticlePolicy',
  3. ];

控制器使用:

  1. if(Gate::denies('editArticle',$article)){
  2. abort(403,'sorry');
  3. };

模版中使用:

  1. @extends('app')
  2. @section('content')
  3. <h2>{{$article->title}}</h2>
  4. <div>{{$article->content}}</div>
  5. @can('editArticle',$article)
  6. <a href="">编辑</a>
  7. @endcan
  8. @stop

用户权限

  1. php artisan make:model Permission
  2. php artisan make:model Role
  3. php artisan make:migration create_roles_table --create=roles

编辑迁移文件:

  1. public function up()
  2. {
  3. Schema::create('roles', function (Blueprint $table) {
  4. $table->increments('id');
  5. $table->string('name');//admin.member
  6. $table->string('label')->nullable();//注册会员
  7. $table->timestamps();
  8. });
  9. Schema::create('permissions', function (Blueprint $table) {
  10. $table->increments('id');
  11. $table->string('name');//admin.member
  12. $table->string('label')->nullable();//注册会员
  13. $table->timestamps();
  14. });
  15. Schema::create('permission_role', function (Blueprint $table) {
  16. $table->integer('permission_id')->unsigned();
  17. $table->integer('role_id')->unsigned();
  18. $table->foreign('permission_id')
  19. ->references('id')
  20. ->on('permissions')
  21. ->onDelete('cascade');
  22. $table->foreign('role_id')
  23. ->references('id')
  24. ->on('roles')
  25. ->onDelete('cascade');
  26. $table->primary(['permission_id','role_id']);
  27. });
  28. Schema::create('role_user', function (Blueprint $table) {
  29. $table->integer('user_id')->unsigned();
  30. $table->integer('role_id')->unsigned();
  31. $table->foreign('user_id')
  32. ->references('id')
  33. ->on('users')
  34. ->onDelete('cascade');
  35. $table->foreign('role_id')
  36. ->references('id')
  37. ->on('roles')
  38. ->onDelete('cascade');
  39. $table->primary(['user_id','role_id']);
  40. });
  41. }

定义关系:

  • role.php

    public function permissions(){

    return $this->belongsToMany(Permission::class);

    }

    public function givePermission(Permission $permission){

    return $this->permissions()->save($permission);

    }

  • permission.php

    1. public function roles(){
    2. return $this->belongsToMany(Role::class);
    3. }
  • user.php

    1. public function roles(){
    2. return $this->belongsToMany(Role::class);
    3. }
    4. public function hasRole($role){
    5. //如果传入的是字符串
    6. if( is_string($role) ){
    7. return $this->roles->contains('name',$role);
    8. }
    9. //如果传入的是collection intersect 只的是 $role 和 $this->roles()有没有交集
    10. return !!$role->intersect( $this->roles )->count();
    11. }

tinker 创建一个role 一个permission 并把permission指派给这个role

  1. $role->givePermission($permission)
  2. 也可以直接
  3. $role->permissions()->save($permission)
  4. $user->roles()->save($role) 给用户分配角色
  5. $user->roles()->detach($role) 删除角色

authServiceProvider.php

  1. public function boot()
  2. {
  3. $this->registerPolicies();
  4. foreach ( $this->getPermission() as $permission ){
  5. Gate::define( $permission->name,function (User $user) use($permission){
  6. return $user->hasRole($permission->roles);
  7. });
  8. }
  9. }
  10. protected function getPermission(){
  11. return Permission::with('roles')->get();
  12. }

blade中这样使用:

  1. @can('edit')
  2. <a href="">编辑edit</a>
  3. @endcan

service container:

  1. class Barz{}
  2. class Foo{
  3. public $bar;
  4. public function __construct(Barz $barz)
  5. {
  6. $this->bar = $barz;
  7. }
  8. }
  9. //如果有app绑定的优先找绑定的
  10. App::bind('Foo',function (){
  11. dd(12);
  12. return new Foo(new BarZ());
  13. });
  14. Route::get('container',function (Foo $foo){
  15. dd($foo);
  16. });

App绑定后路由里不再需要依赖注入

  1. Route::get('container1',function (){
  2. dd(app('Foo'));
  3. });

service实战 向IOC 容器添加自己的类

  • 添加一个自己的类

App\Services\Billing\Stripe.php

  1. <?php
  2. namespace App\Services\Billing;
  3. class Stripe
  4. {
  5. public function charge(){
  6. dd('charged') ;
  7. }
  8. }
  • 新建一个provider

    1. php artisan make:provider BillingServiceProvider
  • 注入服务 BillingServiceProvider.php , 注意要在app.php中注入这个provider

    1. public function register()
    2. {
    3. $this->app->bind('billing',function(){
    4. return new Stripe();
    5. });
    6. }
  • 访问 两种方法均可:

    1. Route::get('container2',function (){
    2. dd(app('billing')->charge());
    3. });
    4. //或
    5. Route::get('container2',function (\App\Services\Billing\Stripe $stripe){
    6. dd($stripe->charge());
    7. });

结合interface

重构代码:

  • 定义接口:App\Billing\BillingInterface.php

    public function charge(array $data);

  • 定义类:App\Biling\PingBilling.php

    1. class PingBilling implements BillingInterface{
    2. public function charge($data){
    3. //todo
    4. }
    5. }
  • 声明serviceprovider 把PingBilling这个类放到ioc container中 BillingServiceProvider

$this->app->bind('billing','App\Biling\PingBilling')

  • app.php 添加 BillingServiceProvider

控制器中调用 app('billing')->charge($data)

=facade### =

每个facade例如 Route 类 返回的其实都是个字符串,关键是继成了Facade类, Facade有个 __callStatic 方法,在一个类中执行一个不存在的静态方法时 该方法会被触发

Facade.php

  1. public static function __callStatic($method, $args)
  2. {
  3. $instance = static::getFacadeRoot();
  4. if (! $instance) {
  5. throw new RuntimeException('A facade root has not been set.');
  6. }
  7. return $instance->$method(...$args);
  8. }

__callStatic 执行了 $instance = static::getFacadeRoot(); 生成一个实例,解析的结果是 app('mailer')

  1. public static function getFacadeRoot()
  2. {
  3. //static::getFacadeAccessor() 指的就是 mailer, 这句解析的结果就是 app('mailer') 其实就是Mailer这个类,到这里就必然有个provider绑定mailer 可在provider中查找
  4. return static::resolveFacadeInstance(static::getFacadeAccessor());
  5. }

目标:我希望我创建一个AjaxResponse的facade,这样能直接在controller中这样使用:

  1. \AjaxResponse::success();

返回

  1. {
  2. code: "0"
  3. result: {
  4. }
  5. }

步骤:

  • step1: 在app/Services文件夹中创建类

    1. <?php namespace App\Services;
    2. class AjaxResponse {
    3. protected function ajaxResponse($code, $message, $data = null)
    4. {
    5. $out = [
    6. 'code' => $code,
    7. 'message' => $message,
    8. ];
    9. if ($data !== null) {
    10. $out['result'] = $data;
    11. }
    12. return response()->json($out);
    13. }
    14. public function success($data = null)
    15. {
    16. $code = ResultCode::Success;
    17. return $this->ajaxResponse(0, '', $data);
    18. }
    19. public function fail($message, $extra = [])
    20. {
    21. return $this->ajaxResponse(1, $message, $extra);
    22. }
    23. }

    这个AjaxResponse是具体的实现类

  • step2: 创建provider

    1. <?php namespace App\Providers;
    2. use Illuminate\Support\ServiceProvider;
    3. class AjaxResponseServiceProvider extends ServiceProvider {
    4. public function register()
    5. {
    6. $this->app->singleton('AjaxResponseService', function () {
    7. return new \App\Services\AjaxResponse();
    8. });
    9. }
    10. }

这里我们在register的时候定义了这个Service名字为AjaxResponseService

  • step3:在app/Facades文件夹中创建类

    1. <?php namespace App\Facades;
    2. use Illuminate\Support\Facades\Facade;
    3. class AjaxResponseFacade extends Facade {
    4. protected static function getFacadeAccessor() { return 'AjaxResponseService'; }
    5. }
  • step4:好了,下面我们只需要到app.php中挂载上这两个东东就可以了

    1. <?php
    2. return [
    3. ...
    4. 'providers' => [
    5. ...
    6. 'App\Providers\RouteServiceProvider',
    7. 'App\Providers\AjaxResponseServiceProvider',
    8. ],
    9. 'aliases' => [
    10. ...
    11. 'Validator' => 'Illuminate\Support\Facades\Validator',
    12. 'View' => 'Illuminate\Support\Facades\View',
    13. 'AjaxResponse' => 'App\Facades\AjaxResponseFacade',
    14. ],
    15. ];

使用name和email登录

postLogin 方法:

  1. $field = filter_var($request->input('username'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
  2. $request->merge([$field => $request->get('username')]);
  3. if(Auth::guard('admin')->attempt( $request->only($field, 'password'),
  4. $request->remember)
  5. ){
  6. //if successful,then intend the user to their intended location
  7. return redirect()->intended(route('admin.dashboard'));
  8. }else{
  9. //if unsuccessful,then redirect back to the login with the form data
  10. return redirect()->back()->withInput($request->only('username','remember'));
  11. }

api

  1. $lessons = Lesson::all();
  2. \Response::json([
  3. 'status' => 'success',
  4. 'status_code' => 200,
  5. 'data' => $lessons->toArray()
  6. ]);

= 字段映射 ### =

  1. $lessons = Lesson::all();
  2. \Response::json([
  3. 'status' => 'success',
  4. 'status_code' => 200,
  5. 'data' => $this->transform($lessons->toArray())
  6. ]);
  7. public function transform($lessons){
  8. return array_map(function($lesson){
  9. return [
  10. 'title' => $lesson['title'],
  11. 'content' => $lesson['body'],
  12. 'is_free' => (boolean)$lesson['free']
  13. ];
  14. },$lessons);
  15. }

注意 这个transform 是处理 collection的数据 all()

如果要处理elequent model 比如 Lesson::find(1)这样的数据需要这么处理transform方法,collection 用transformCollection方法:

  1. public function transformCollection($lessons){
  2. return array_map([$this,'transform'],$lessons);
  3. }
  4. public function transform($lesson){
  5. return [
  6. 'title' => $lesson['title'],
  7. 'content' => $lesson['body'],
  8. 'is_free' => (boolean)$lesson['free']
  9. ];
  10. }

= 代码重构 ### =

比如有个article也需要使用transform

  • 新建一个类 App\Transformer\Transformer.php

    1. <?php
    2. namespace App\Transformer;
    3. abstract class Transformer
    4. {
    5. /**
    6. * @param $items
    7. * @return array
    8. */
    9. public function transformCollection($items){
    10. return array_map([$this,'transform'],$items);
    11. }
    12. /**
    13. * @param $item
    14. * @return mixed
    15. */
    16. public abstract function transform($item);//抽象方法不用写大括号
    17. }
  • 新建LessonTransform 并继承Transformer类 App\Transformer\LessonTransform .php

    namespace App\Transformer;

    class LessonTransformer extends Transformer
    {
    /**
    * @param $lesson
    * @return array
    */
    public function transform($lesson){
    return [
    'title' => $lesson['title'],
    'content' => $lesson['intro']
    ];
    }
    }

  • Lesson控制器中依赖注入 并调用Transformer中的方法

    protected $lessonTransformer;

    1. public function __construct(LessonTransformer $lessonTransformer)
    2. {
    3. $this->lessonTransformer = $lessonTransformer;
    4. }
    5. /**
    6. * Display a listing of the resource.
    7. *
    8. * @return \Illuminate\Http\Response
    9. */
    10. public function index()
    11. {
    12. $lessons = Lesson::all();
    13. return \Response::json([
    14. 'status' => 'success',
    15. 'status_code' => 200,
    16. 'data' => $this->lessonTransformer->transformCollection($lessons->toArray())
    17. ]);
    18. }
    19. public function show($id)
    20. {
    21. $lesson = Lesson::find($id);
    22. return \Response::json([
    23. 'status' => 'success',
    24. 'status_code' => 200,
    25. 'data' => $this->lessonTransformer->transform($lesson)
    26. ]);
    27. }

= 错误提示 ### =

1.新建一个ApiController.php

  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. class ApiController extends Controller
  5. {
  6. protected $statusCode = 200;
  7. /**
  8. * @return int
  9. */
  10. public function getStatusCode(): int
  11. {
  12. return $this->statusCode;
  13. }
  14. /**
  15. * @param int $statusCode
  16. */
  17. public function setStatusCode(int $statusCode)
  18. {
  19. $this->statusCode = $statusCode;
  20. return $this;
  21. }
  22. public function responseNotFound( $message = 'Not Found' ){
  23. return $this->responseError($message);
  24. }
  25. private function responseError($message){
  26. return $this->response([
  27. 'status' => 'fail',
  28. 'status_code' => $this->getStatusCode(),
  29. 'message' => $message
  30. ]);
  31. }
  32. public function response($data){
  33. return \Response::json($data);
  34. }
  35. }

2.控制器:LessonController.php 集成ApiController.php

  1. public function show($id)
  2. {
  3. $lesson = Lesson::find($id);
  4. if( !$lesson ) {
  5. return $this->setStatusCode(500)->responseNotFound();
  6. }
  7. return $this->response([
  8. 'status' => 'success',
  9. 'data' => $this->lessonTransformer->transform($lesson)
  10. ]);
  11. }

这时候访问 transformer/2689 就会返回ApiController中的错误信息

  1. {
  2. "status": "fail",
  3. "status_code": 404,
  4. "message": "Not Found"
  5. }

= postman禁用token ### =

app\kernel.php 注释掉verifyCsrfToken.php

api验证有三种:

= auth.basic 基础验证### =

控制器构造方法中:

  1. public function __construct(){
  2. $this->middleware('auth.basic',['only'=>['store','update']]);
  3. }

laravel 有用的小方法

[http://www.cnblogs.com/webskill/p/7463488.html ]

laravel package

  1. 根目录下新建目录 packages/Laravist/Hasher/src

  2. composer 自动加载 并 设置命名空间

    "autoload": {

    "classmap": [

    "database/seeds",

    "database/factories"

    ],

    "psr-4": {

    "App\": "app/",

    "Laravist\Hasher\":"package/Laravist/Hasher/src/"

    }

    },

  3. src下新建一个类:Md5Hasher.php

    1. <?php
    2. namespace Laravist\Hasher;
    3. class Md5hasher
    4. {
    5. public function make($value,array $options = []){
    6. $salt = isset($options['salt']) ? $options['salt'] : '';
    7. return hash('md5',$value.$salt);
    8. }
    9. public function check($value,$hashvalue,array $options = []){
    10. $salt = isset($options['salt']) ? $options['salt'] : '';
    11. return hash('md5',$value.$salt) ### $hashvalue;
    12. }
    13. }
  4. 加载这个类:

    php artisan make:provider Md5HashProvider 移到 src下

  5. Md5HashProvider 中注册使用方法:

    1. public function register()
    2. {
    3. $this->app->singleton('md5hash',function (){
    4. return new Md5hasher();
    5. });
    6. }
  6. tinker中使用

    1. app('md5hasher')->make('password')

自定义错误提示

resources/lang/en/validation.php

找到custom



'custom' => [

'attribute-name' => [

'rule-name' => 'custom-message',

],

],

改成:

'custom' => [

'name' => [

'required' => '用户名不能为空',

],

],

使用第三方插件 markdown

  1. hyperDown github上 找到Parser.php app下新建文件 App\Markdown\Parser.php 注意命名空间

  2. App\Markdown\Markdown.php

    1. <?php
    2. namespace App\Markdown;
    3. class Markdown
    4. {
    5. protected $parser;
    6. public function __construct(Parser $parser)
    7. {
    8. $this->parser = $parser;
    9. }
    10. public function markdown($text){
    11. $html = $this->parser->makeHtml($text);
    12. return $html;
    13. }
    14. }
    15. composer dump-autoload
  3. 控制器中使用

    1. protected $markdown;
    2. public function __construct(Markdown $markdown)
    3. {
    4. $this->markdown = $markdown;
    5. $this->middleware('auth',['only'=>['create','store','edit','update']]);
    6. }
    7. public function show($id)
    8. {
    9. $discussion = Discussion::findOrFail($id);
    10. $html = $this->markdown->markdown($discussion->body) ;
    11. return view('forum.detail',compact('discussion','html'));
    12. }
  4. view中使用

    {!! $html !!}

storage###

图片上传使用 storage_path('app/public') 这种的时候 默认图片上传到 storage/app/public 下面 , 需要 php artisan storage:link 链到 public目录下

模糊查询###

  1. $topics = \App\Topic::select(['id','name'])
  2. ->where('name','like','%'.$request->query('q').'%')
  3. ->get();

helper###

App下建 Support/hellper.php

比如 Auth::guard('api')->user()->id 用的非常多,把它做成helper

helper.php

  1. <?php
  2. if(!!function_exists('user')){
  3. function user($driver=null){
  4. if ($driver){
  5. return app('auth')->guard($driver)->user();
  6. }
  7. return app('auth')->user();
  8. }
  9. }

composer.json

  1. "autoload": {
  2. "files":[
  3. "App/Support/helper.php"
  4. ],
  5. "classmap": [
  6. "database/seeds",
  7. "database/factories"
  8. ],
  9. "psr-4": {
  10. "App\\": "app/"
  11. }
  12. },

可直接在控制器或blade中使用 user() 或者 user('api')

with 和 wherehas###

with: 选择所有的model, 每个model 关联的translations 根据条件进行过滤,结果只有 title like $query 的translations不为空, 其他model的translations为空

  1. return $this->model->with([
  2. 'translations' => function($q)use($query){
  3. $q->where('title','like',"%{$query}%")
  4. ->select('product_id','title');
  5. }
  6. ])

wherehas: 选出满足条件的 model, 不是所有的model

  1. $this->model->whereHas('translations', function($q)use($query){
  2. $q->where('title', 'like', "%{$query}%");
  3. })->get();

laravel5.4新特性的更多相关文章

  1. Laravel5.5新特性

    1.新的报错页面 报错更加美观,并标记显示出错误的代码 2.包的自动配置 在conposer.json文件中加入包中的配置,下载后就会自动配置到app.php 文件中,使用更方便 在之前的 Larav ...

  2. 如何升级laravel5.4到laravel5.5并使用新特性?

    如何升级laravel5.4到laravel5.5并使用新特性? 修改composer.json: "laravel/framework": "5.5.*", ...

  3. SQL Server 2014 新特性——内存数据库

    SQL Server 2014 新特性——内存数据库 目录 SQL Server 2014 新特性——内存数据库 简介: 设计目的和原因: 专业名词 In-Memory OLTP不同之处 内存优化表 ...

  4. ElasticSearch 5学习(10)——结构化查询(包括新特性)

    之前我们所有的查询都属于命令行查询,但是不利于复杂的查询,而且一般在项目开发中不使用命令行查询方式,只有在调试测试时使用简单命令行查询,但是,如果想要善用搜索,我们必须使用请求体查询(request ...

  5. [干货来袭]C#6.0新特性

    微软昨天发布了新的VS 2015 ..随之而来的还有很多很多东西... .NET新版本 ASP.NET新版本...等等..太多..实在没消化.. 分享一下也是昨天发布的新的C#6.0的部分新特性吧.. ...

  6. CSS3新特性应用之结构与布局

    一.自适应内部元素 利用width的新特性min-content实现 width新特性值介绍: fill-available,自动填充盒子模型中剩余的宽度,包含margin.padding.borde ...

  7. 【译】Meteor 新手教程:在排行榜上添加新特性

    原文:http://danneu.com/posts/6-meteor-tutorial-for-fellow-noobs-adding-features-to-the-leaderboard-dem ...

  8. 跨平台的 .NET 运行环境 Mono 3.2 新特性

    Mono 3.2 发布了,对 Mono 3.0 和 2.10 版本的支持不再继续,而且这两个分支也不再提供 bug 修复更新. Mono 3.2 主要新特性: LLVM 更新到 3.2 版本,带来更多 ...

  9. Atitit opencv版本新特性attilax总结

    Atitit opencv版本新特性attilax总结 1.1. :OpenCV 3.0 发布,史上功能最全,速度最快的版1 1.2. 应用领域2 1.3. OPENCV2.4.3改进 2.4.2就有 ...

随机推荐

  1. 【译】x86程序员手册40-10.5初始化的例子

    10.5 Initialization Example初始化的例子 译注:本来想把这个例子全部注释完,但由于对intel汇编实不熟悉,有太多的伪指令,本人也是免强看懂,所以就不再做翻译了. $TITL ...

  2. QQ感叹号是什么鬼?原来是服务器波动,腾讯官方来辟谣了

    今天晚上很多网友在用QQ发送消息的时候发现,自己发送的消息一直是感叹号❗到底是怎么回事呢?是消息都发不出去了吗?马浩周通过手机测试后发现,其实消息是可以发出去的,而官方手机QQ出来已经通知了,是服务器 ...

  3. python compare with other language

    java http://dirtsimple.org/2004/12/python-is-not-java.htmlhttp://twistedmatrix.com/users/glyph/rant/ ...

  4. windows/linux 更新python pip

    linux环境下 pip install -U pip windows环境下 python -m pip install -U pip python -m pip install --upgrade ...

  5. CF919F A Game With Numbers

    题目:(luogu翻译错的很多) Alice和Bob玩游戏,每人有8张牌,牌的值为0~4.每一轮当前玩家选择自己的牌A和对手的牌B,然后将A的值变为( A + B )%5,其中A和B都不是0. 当一个 ...

  6. Java中Date类型的工具类

    package com.mytripod.util; import java.text.DateFormat; import java.text.SimpleDateFormat; import ja ...

  7. Spring接收web请求参数的几种方式

    1 查询参数 请求格式:url?参数1=值1&参数2=值2...同时适用于GET和POST方式spring处理查询参数的方法又有几种写法: 方法一:方法参数名即为请求参数名 // 查询参数1 ...

  8. jq ajax请求error: Maximum call stack size exceeded

    原因是data中参数iconUrl这个变量未声明导致的.jq在内部循环时报错

  9. docker安装配置lnmp

    一.安装配置docker 1.下载docker:yum install -y docker 2.设置docker远程镜像地址为国内路径:curl -sSL https://get.daocloud.i ...

  10. python3 监控代码变化 自动重启 提高开发效率

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = 'Michael Liao' import os, sys, time, sub ...