zoukankan      html  css  js  c++  java
  • laravel5.4新特性

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

    laravel 5.4 新特性

    component and slot

    使用:

    1.component panel

    <article class="message">
      <div class="message-header">
        <p>Hello World</p>
        <button class="delete" aria-label="delete"></button>
      </div>
      <div class="message-body">
        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.
      </div>
    </article>
    

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

    <article class="message">
      <div class="message-header">
        <p>{{$title}}</p>
        <button class="delete" aria-label="delete"></button>
      </div>
      <div class="message-body">
        {{$content}}
      </div>
    </article>
    

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

    @component('components.panel')
        @slot('title')
            hello world
        @endslot
        @slot('content')
            have a nice day
        @endslot
    @endcomponent
    

    4.如果要传入默认content

    panel.blade.php修改如下:

     <article class="message">
        <div class="message-header">
          <p>{{$title}}</p>
          <button class="delete" aria-label="delete"></button>
        </div>
        <div class="message-body">
          {{$slot}}
        </div>
      </article>
    

    index.blade.php修改如下

    @component('components.panel')
        @slot('title')
            hello world
        @endslot
            have a nice day
    @endcomponent
    
    //可多来几个:
    
    @component('components.panel')
        @slot('title')
            hello world
        @endslot
        have a nice day123
    @endcomponent
    

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

    panel.blade.php修改如下:
      
         <article class="message">
            <div class="message-header">
              <p>{{$title ?? 'laravel'}}</p>
              <button class="delete" aria-label="delete"></button>
            </div>
            <div class="message-body">
              {{$slot}}
            </div>
          </article>
    index.blade.php修改如下
        
        @component('components.panel')
                have a nice day
        @endcomponent
    

    laravel 邮件

    本文使用qq邮箱

    env邮件配置:

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

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

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

           //发送邮件
           Route::get('/mail',function(){
               IlluminateSupportFacadesMail::to('2861166132@qq.com')->send(new AppMailwelcomeToLaravist());
           });
      
    4. 传参 修改 welcomeToMiya.php

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

       //发送邮件
       Route::get('/mail',function(){
           $user = AppUser::find(1);
           IlluminateSupportFacadesMail::to('2861166132@qq.com')->send(new AppMailwelcomeToLaravist($user));
       });
      

    发邮件还可以这样:

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

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

    notification 通知

    = mail篇 ### =

     public function via($notifiable)
    {
        return ['mail'];
    }
    

    1.新建notification类

    php artisan make:notification PostNotification
    

    2.设置路由

    //notification 注意默认发送到user模型中的email邮箱账号 所以要确认user邮箱可用
    Route::get('/notification',function(){
        $user = AppUser::find(1);
        $post = AppPost::find(2);
        $user->notify(new AppNotificationsPostNotification($post));
    });
    

    3.访问/notification 收到邮件

    4.常用设置方法 PostNotification.php

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

    =database篇 ### =

    将通知都存储在数据库里

    1.修改PostNotification.php

    public function via($notifiable)
    {
        //return ['mail'];
        return ['database'];
    }
    

    2.创建notification迁移文件

     php artisan notifications:table
     php artisan migrate
    

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

    4.修改web.php

    5.查看当前用户下的notifications

    6.新建一个notification

    php artisan make:notification UserSubscribe
    

    7.UserSubscribe.php 修改如下

    public function via($notifiable)
    {
        return ['database'];
    }
    
    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            'subscribed_at' => Carbon::now()
        ];
    }
    

    8.修改web.php

    //notification
    Route::get('/notification', function () {
        $user = AppUser::find(1);
        $post = AppPost::find(2);
        //$user->notify(new AppNotificationsPostNotification($post));
        $user->notify(new AppNotificationsUserSubscribe());
    });
    

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

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

    web.php

    //notification
    Route::get('/show-notification', function () {
        return view('notifications.index');
    });
    
    //标识未读
    Route::delete('user/notification',function (){
        Auth::user()->unreadNotifications->markAsRead();
        return redirect()->back();
    });
    

    notifications.index.blade

    @extends('app')
    
    @section('content')
        <h1>我的通知:</h1>
        <ul>
        @foreach(Auth::user()->unreadNotifications as $notification)
            @include('notifications/'.snake_case( class_basename($notification->type) ))
        @endforeach
        </ul>
        <form action="/user/notification" method="POST">
            {{csrf_field()}}
            {{method_field('DELETE')}}
            <input type="submit" value="标识已读">
        </form>
    @stop
    

    user_subscribe.blade.php

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

    post_notification.blade.php

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

    标识某条已读

    $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

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

    这个命令不仅创建了email类文件 还生成了视图文件 并把视图也写好了 return $this->markdown('emails.published'')
    可根据需要修改 也可修改email markdown模版 php artisan vendor:publish

    发送邮件

    Route::get("sendmail",function(){
        $email = new AppMailLessionPublished(AppUser::first());
        Mail::to(App|User::first())->send($email);
    })
    

    toggle

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

    1.user表

    2.post表 title content

    3.中间表 favoriate user_id post_id

    4.user中定义关系

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

    5.关联关系

    做法一:

    在tinker中操作

    $user = AppUser::find(1);
    $post = AppPost::find(2);
    $user->favorite()->attach($post);
    查看结果:$user->refresh()->favorite
    
    //取消收藏
     $user->favorite()->detach($post);
    

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

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

    实时facade###

    1. 创建一个目录叫services
      创建一个weibo类

       <?php
       namespace AppServices;
       class weibo
       {
           protected $http;
       
           public function __construct(Http $http)
           {
               $this->http = $http;
           }
       
           public function publish($status){
               $this->http->post($status);
           }
       }
      

    创建一个Http类

    <?php
    namespace AppServices;
    class Http
    {
        public function __construct()
        {
        }
    
        public function post($status){
            return dd('I post a post'.$status);
        }
    }
    

    路由修改

    use FacadesAppServicesweibo;
    
    //facade
    Route::get('facade',function (){
       weibo::publish('这是一条微博');
    });
    

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

    事件监听

    方法一:
    web.php

    Event::listen('eloquent.created: Apppost',function(){
        dump('A post was created');
    });
    
    Route::get('/event53',function(){
        Apppost::create(['title'=>'Title','content'=>'My Body']);
    });
    

    方法二:

    注释掉

    Event::listen('eloquent.created: Apppost',function(){
            dump('A post was created');
        });
    

    post模型中定义事件

    <?php
    
    namespace App;
    
    use AppEventsPostWasPublished;
    use IlluminateDatabaseEloquentModel;
    
    class post extends Model
    {
        protected $guarded = array();
        protected $events = [
           'created' => PostWasPublished::class
        ];
    }
    

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

    protected $listen = [
        'AppEventsPostWasPublished' => [
            'AppListenersPostWasPublishedListener',
        ],
    ];
    

    执行 php artisan event:generate

    ** 还可以依赖注入 **

    AppEventsPostWasPublished.php

    public $post;
    
    public function __construct($post)
    {
        $this->post = $post;
    }
    

    AppListenersPostWasPublishedListener.php

     public function handle(PostWasPublished $event)
         {
             dump($event->post->toArray());
         } 
    

    方法三:普通路由触发event

    app/Providers/EventServiceProvider.php

    protected $listen = [
            'AppEventsUserSignUp' => [
                'AppListenersUserSignUpListener',
            ],
        ];
    

    UserSignUp.php

     use AppUser;
     public $user;
     public function __construct(User $user)
     {
         $this->user = $user;
     }   
    

    UserSignUpListener.php

    public function handle(UserSignUp $event)
    {
        dd($event->user->name);
    }
    

    web.php

    Route::get('/eventroute',function(){
        $user = AppUser::find(1);
       event(new AppEventsUserSignUp($user));
    });       
    

    console command

    php artisan make:command hello
    

    进入app/console/commands/hello.php

    修改singniture和handle

    protected $signature = 'lara:hello';
    
    public function handle()
        {
            $this->info('hello my girl');
        }
    

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

    AppConsoleCommandshello::class
    

    传参:php artisan lara:hello alice

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

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

    定时任务

    新建一个test.sh

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

    test.php

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

    laravel 定时任务:

    $ php artisan make:conmmand logInfo
    

    修改 ap/console/command/logInfo.php

    protected $description = 'log Info';
     public function handle()
        {
            Log::info('It works');
        }
    

    kernel中注册 app/console/kernel.php

    protected $commands = [
            //
            hello::class,
            logInfo::class
        ];
    
        /**
         * Define the application's command schedule.
         *
         * @param  IlluminateConsoleSchedulingSchedule  $schedule
         * @return void
         */
        protected function schedule(Schedule $schedule)
        {
             $schedule->command('log:info')
                      ->everyMinute();
        }    
    
    $ crontab -e 
    * * * * * php /var/www/lara/leaning/artisan schedule:run >> /dev/null 2>&1
    

    middleware###

    php artisan make:middleware isAdminMiddleware
    

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

    模型user.php

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

    修改isAdminMiddleware

    public function handle($request, Closure $next)
    {
        info( $request->user()); //等价于 Auth::user()
        if($request->user() && $request->user()->isAdmin()){
            return $next($request);
        }
        return redirect('/');
    }
    

    web.php

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

    controller中可以这样设置

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

    app/Http/Kernel.php

     protected $routeMiddleware = [
            'isAdmin' => isAdminMiddleware::class
        ];
    }
    

    视图绑定变量###

    app下新建一个类 Status

    <?php
    
    namespace App;
    
    class Status
    {
        public function total(){
            return 45;
        }
    }
    

    路由以前的做法是这样

    Route::get('/status',function(AppStatus $status){
        return view('status',compact('status'));
    });
    

    status.blade.php

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

    模板绑定变量这样写:

    路由:不传递任何变量

    Route::get('/status',function(){
        return view('status');
    });
    

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

    @inject('status','AppStatus')
    

    本地化Model Factory###

    tinker:

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

    App/Providers/AppServiceProvider.php

    use FakerGenerator as FakerGenerator;
    use FakerFactory as FakerFactory;
    
     public function boot()
        {
            $this->app->singleton(FakerGenerator::class,function (){
                return FakerFactory::create('zh_CN');
            });
        }
    

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

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

    分页###

    路由:

    Route::get('/lessons',function(){
        $lessons = AppLesson::paginate(15);
        return view('lessons',compact('lessons'));
    });
    

    模板

    @extends('app')
    
    @section('content')
        <h1>Lessons</h1>
        @foreach($lessons->chunk(3) as $row)
        <div class="row">
            @foreach($row as $lesson)
                <div class="col-md-4">
                    <h2>{{ $lesson->title  }}</h2>
                    <img style="100%; " src="{{$lesson->imageUrl}}" alt="">
                    <div class="body">
                        {{$lesson->intro}}
                    </div>
                </div>
            @endforeach
        </div>
        @endforeach
    
        {!! $lessons->render() !!}
        {{ $lessons->appends(['type'=>'article'])->links('vendor.pagination.bootstrap-4')  }}
    @stop
    

    分页两种方式都可以

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

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

    $factory->define(AppArticle::class, function (FakerGenerator $faker) {
        $userIds= AppUser::pluck('id')->toArray();
        return [
            'title' => $faker->sentence,
            'content' => $faker->paragraph,
            'user_id' => $faker->randomElements($userIds)[0]
        ];
    });
    

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

    AppUser::find([2,3])  
    

    with eager loading###

    user.php

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

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

     这里的post只的就是对应的关系
     $posts = AppUser::with('posts')->get()
    

    多态关联###

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

    php artisan make:model comment -m
    

    comment migration

     public function up()
        {
            Schema::create('comments', function (Blueprint $table) {
                $table->increments('id');
                $table->integer('commentable_id');
                $table->string('commentable_type');
                $table->text('body');
                $table->timestamps();
            });
        }
    

    comment.php 模型

     class comment extends Model
     {
         public function commentable(){
             return $this->morphTo();
         }
     }
    

    post.php 模型

     use Appcomment;
     class post extends Model
     {
         protected $guarded = array();
         protected $events = [
            'created' => PostWasPublished::class
         ];
         public function comments(){
             return $this->morphMany(comment::class,'commentable');
         }
     }
    

    lesson.php 模型

    class Lesson extends Model
    {
        protected $guarded = array();
    
        public function comments(){
            return $this->morphMany(comment::class,'commentable');
        }
    }
    

    使用:

    • 给某个lesson添加评论

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

        $comment = Appcomment::find(1);
        $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

    public function boot()
        {
            $this->registerPolicies();
    
            Gate::define('show-post',function ($user,$article){
                return $user->id ###  $article->user_id;
            });
        }
    

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

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

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

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

    模版中使用

         @extends('app')
            
            @section('content')
                <h2>{{$article->title}}</h2>
                <div>{{$article->content}}</div>
            
                @can('show-post',$article)
                    <a href="">编辑</a>
                @endcan
            
        @stop
    

    使用policy###

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

       php artisan make:policy ArticlePolicy
    

    添加policy 规则:

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

    AuthServiceProvider.php中注册该ArticlePolicy

       protected $policies = [
               'AppArticle' => 'AppPoliciesArticlePolicy',
           ];
    

    控制器使用:

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

    模版中使用:

        @extends('app')
                    
                @section('content')
                    <h2>{{$article->title}}</h2>
                    <div>{{$article->content}}</div>
                
                    @can('editArticle',$article)
                        <a href="">编辑</a>
                    @endcan
                
                @stop 
    

    用户权限

    php artisan make:model Permission
    php artisan make:model Role
    php artisan make:migration create_roles_table --create=roles
    

    编辑迁移文件:

     public function up()
        {
            Schema::create('roles', function (Blueprint $table) {
                $table->increments('id');
                $table->string('name');//admin.member
                $table->string('label')->nullable();//注册会员
                $table->timestamps();
            });
            Schema::create('permissions', function (Blueprint $table) {
                $table->increments('id');
                $table->string('name');//admin.member
                $table->string('label')->nullable();//注册会员
                $table->timestamps();
            });
            Schema::create('permission_role', function (Blueprint $table) {
                $table->integer('permission_id')->unsigned();
                $table->integer('role_id')->unsigned();
    
                $table->foreign('permission_id')
                        ->references('id')
                        ->on('permissions')
                        ->onDelete('cascade');
    
                $table->foreign('role_id')
                    ->references('id')
                    ->on('roles')
                    ->onDelete('cascade');
    
                $table->primary(['permission_id','role_id']);
            });
            Schema::create('role_user', function (Blueprint $table) {
                $table->integer('user_id')->unsigned();
                $table->integer('role_id')->unsigned();
    
                $table->foreign('user_id')
                    ->references('id')
                    ->on('users')
                    ->onDelete('cascade');
    
                $table->foreign('role_id')
                    ->references('id')
                    ->on('roles')
                    ->onDelete('cascade');
    
                $table->primary(['user_id','role_id']);
    
            });
        }
    

    定义关系:

    • role.php

      public function permissions(){
      return $this->belongsToMany(Permission::class);
      }
      public function givePermission(Permission $permission){
      return $this->permissions()->save($permission);
      }

    • permission.php

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

          public function roles(){
                return $this->belongsToMany(Role::class);
            }
        
            public function hasRole($role){
                //如果传入的是字符串
                if( is_string($role) ){
                    return $this->roles->contains('name',$role);
                }
                //如果传入的是collection  intersect 只的是 $role 和 $this->roles()有没有交集
                return !!$role->intersect( $this->roles )->count();
            }
      

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

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

    authServiceProvider.php

           public function boot()
              {
                  $this->registerPolicies();
          
                  foreach ( $this->getPermission() as $permission ){
                      Gate::define( $permission->name,function (User $user) use($permission){
                          return $user->hasRole($permission->roles);
                      });
                  }
              }
              protected function getPermission(){
                  return Permission::with('roles')->get();
              }
    

    blade中这样使用:

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

    service container:

    class Barz{}
    
    class Foo{
        public $bar;
    
        public function __construct(Barz $barz)
        {
            $this->bar = $barz;
        }
    }
    //如果有app绑定的优先找绑定的
    App::bind('Foo',function (){
        dd(12);
        return new Foo(new BarZ());
    });
    Route::get('container',function (Foo $foo){
        dd($foo);
    });
    

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

    Route::get('container1',function (){
        dd(app('Foo'));
    });
    

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

    • 添加一个自己的类

    AppServicesBillingStripe.php

    <?php 
    namespace AppServicesBilling;
    class Stripe
    {
        public function charge(){
            dd('charged') ;
        }
    }
    
    • 新建一个provider

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

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

        Route::get('container2',function (){
            dd(app('billing')->charge());
        });
        
        //或
        
        Route::get('container2',function (AppServicesBillingStripe $stripe){
            dd($stripe->charge());
        });
      

    结合interface

    重构代码:

    • 定义接口:AppBillingBillingInterface.php
      public function charge(array $data);

    • 定义类:AppBilingPingBilling.php

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

    $this->app->bind('billing','AppBilingPingBilling')

    • app.php 添加 BillingServiceProvider

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

    =facade### =

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

    Facade.php

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

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

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

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

    AjaxResponse::success();
    

    返回

    {
        code: "0"
        result: {
    
        }
    }
    

    步骤:

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

        <?php namespace AppServices;
        
        class AjaxResponse {
        
            protected function ajaxResponse($code, $message, $data = null)
            {
                $out = [
                    'code' => $code,
                    'message' => $message,
                ];
        
                if ($data !== null) {
                    $out['result'] = $data;
                }
        
                return response()->json($out);
            }
        
            public function success($data = null)
            {
                $code = ResultCode::Success;
                return $this->ajaxResponse(0, '', $data);
            }
        
            public function fail($message, $extra = [])
            {
                return $this->ajaxResponse(1, $message, $extra);
            }
        }
      

      这个AjaxResponse是具体的实现类

    • step2: 创建provider

        <?php namespace AppProviders;
        
        use IlluminateSupportServiceProvider;
        
        class AjaxResponseServiceProvider extends ServiceProvider {
        
            public function register()
            {
                $this->app->singleton('AjaxResponseService', function () {
                    return new AppServicesAjaxResponse();
                });
            }
        }
      

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

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

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

        <?php
        
        return [
        
            ...
        
            'providers' => [
                ...
                'AppProvidersRouteServiceProvider',
        
                'AppProvidersAjaxResponseServiceProvider',
        
            ],
        
        
            'aliases' => [
                ...
        
                'Validator' => 'IlluminateSupportFacadesValidator',
                'View'      => 'IlluminateSupportFacadesView',
        
                'AjaxResponse' => 'AppFacadesAjaxResponseFacade',
        
            ],
        
        ];
      

    使用name和email登录

    postLogin 方法:

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

    api

    $lessons = Lesson::all();
    Response::json([
    	'status' => 'success',
    	'status_code' => 200,
    	'data'   => $lessons->toArray()
    ]);
    

    = 字段映射 ### =

    $lessons = Lesson::all();
    Response::json([
    	'status' => 'success',
    	'status_code' => 200,
    	'data'   => $this->transform($lessons->toArray())
    ]);
    
    public function transform($lessons){
    	return array_map(function($lesson){
    		return [
    			'title' => $lesson['title'],
    			'content' => $lesson['body'],
    			'is_free' => (boolean)$lesson['free']
    		];
    	},$lessons);
    }
    

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

    public function transformCollection($lessons){
    	return array_map([$this,'transform'],$lessons);
    }
    
    public function transform($lesson){
    	return [
    			'title' => $lesson['title'],
    			'content' => $lesson['body'],
    			'is_free' => (boolean)$lesson['free']
    		];
    }
    

    = 代码重构 ### =

    比如有个article也需要使用transform

    • 新建一个类 AppTransformerTransformer.php

        <?php
      
        namespace AppTransformer;
        
        abstract class Transformer
        {
            /**
             * @param $items
             * @return array
             */
            public function transformCollection($items){
                return array_map([$this,'transform'],$items);
            }
        
            /**
             * @param $item
             * @return mixed
             */
            public abstract function transform($item);//抽象方法不用写大括号
        }
      
    • 新建LessonTransform 并继承Transformer类 AppTransformerLessonTransform .php

      namespace AppTransformer; class LessonTransformer extends Transformer { /** * @param $lesson * @return array */ public function transform($lesson){ return [ 'title' => $lesson['title'], 'content' => $lesson['intro'] ]; } }
    • Lesson控制器中依赖注入 并调用Transformer中的方法

      protected $lessonTransformer;

        public function __construct(LessonTransformer $lessonTransformer)
        {
            $this->lessonTransformer = $lessonTransformer;
        }
        /**
         * Display a listing of the resource.
         *
         * @return IlluminateHttpResponse
         */
        public function index()
        {
            $lessons = Lesson::all();
            return Response::json([
                'status' => 'success',
                'status_code' => 200,
                'data'   => $this->lessonTransformer->transformCollection($lessons->toArray())
            ]);
        }
        
        public function show($id)
        {
            $lesson = Lesson::find($id);
            return Response::json([
                'status' => 'success',
                'status_code' => 200,
                'data'   => $this->lessonTransformer->transform($lesson)
            ]);
        }	
      

    = 错误提示 ### =

    1.新建一个ApiController.php

    <?php
    
    namespace AppHttpControllers;
    
    use IlluminateHttpRequest;
    
    class ApiController extends Controller
    {
        protected $statusCode = 200;
    
        /**
         * @return int
         */
        public function getStatusCode(): int
        {
            return $this->statusCode;
        }
    
        /**
         * @param int $statusCode
         */
        public function setStatusCode(int $statusCode)
        {
            $this->statusCode = $statusCode;
            return $this;
        }
        public function responseNotFound( $message = 'Not Found' ){
            return $this->responseError($message);
        }
        private function responseError($message){
            return $this->response([
                'status' => 'fail',
                'status_code' => $this->getStatusCode(),
                'message' => $message
            ]);
        }
        public function response($data){
            return Response::json($data);
        }
    }
    

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

     public function show($id)
        {
            $lesson = Lesson::find($id);
            if( !$lesson ) {
               return  $this->setStatusCode(500)->responseNotFound();
            }
            return $this->response([
                'status' => 'success',
                'data'   => $this->lessonTransformer->transform($lesson)
            ]);
        }
    

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

    {
    	"status": "fail",
    	"status_code": 404,
    	"message": "Not Found"
    }
    

    = postman禁用token ### =

    appkernel.php 注释掉verifyCsrfToken.php

    api验证有三种:

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

    控制器构造方法中:

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

    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/",
      "LaravistHasher":"package/Laravist/Hasher/src/"
      }
      },

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

       <?php
       namespace LaravistHasher;
       class Md5hasher
       {
           public function make($value,array $options = []){
               $salt = isset($options['salt']) ? $options['salt'] : '';
               return hash('md5',$value.$salt);
           }
           public function check($value,$hashvalue,array $options = []){
               $salt = isset($options['salt']) ? $options['salt'] : '';
               return hash('md5',$value.$salt) ###  $hashvalue;
           }
       }
      
    4. 加载这个类:
      php artisan make:provider Md5HashProvider 移到 src下

    5. Md5HashProvider 中注册使用方法:

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

       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下新建文件 AppMarkdownParser.php 注意命名空间

    2. AppMarkdownMarkdown.php

      <?php
       
      namespace AppMarkdown;
      
      
      class Markdown
      {
          protected $parser;
       
          public function __construct(Parser $parser)
          {
              $this->parser = $parser;
          }
          public function markdown($text){
               $html = $this->parser->makeHtml($text);
               return $html;
          }
      }
      
      
      composer dump-autoload
      
    3. 控制器中使用

        protected $markdown;
           public function __construct(Markdown $markdown)
           {
               $this->markdown = $markdown;
               $this->middleware('auth',['only'=>['create','store','edit','update']]);
           }
       public function show($id)
           {
               $discussion = Discussion::findOrFail($id);
               $html = $this->markdown->markdown($discussion->body) ;
               return view('forum.detail',compact('discussion','html'));
           }
      
    4. view中使用
      {!! $html !!}

    storage###

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

    模糊查询###

    $topics = AppTopic::select(['id','name'])
        ->where('name','like','%'.$request->query('q').'%')
        ->get();
    

    helper###

    App下建 Support/hellper.php

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

    helper.php

    <?php
    
    if(!!function_exists('user')){
        function user($driver=null){
            if ($driver){
                return app('auth')->guard($driver)->user();
            }
            return app('auth')->user();
        }
    }
    

    composer.json

    "autoload": {
            "files":[
              "App/Support/helper.php"
            ],
            "classmap": [
                "database/seeds",
                "database/factories"
            ],
            "psr-4": {
                "App\": "app/"
            }
        },	
    

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

    with 和 wherehas###

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

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

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

    $this->model->whereHas('translations', function($q)use($query){
                  $q->where('title', 'like', "%{$query}%");
        })->get();
  • 相关阅读:
    mkfs
    Nginx配置指令location匹配符优先级和安全问题
    Nginx 403 Forbidden
    nginx 开机启动脚本 可以使用systemctl enable service 添加开机启动
    systemctl
    Pycharm 项目设置Github账户
    sql存储过程
    vim 替换模式
    python--爬虫小案例
    python--正则表达式
  • 原文地址:https://www.cnblogs.com/webskill/p/9486311.html
Copyright © 2011-2022 走看看