转载

Laravel Composer Package 开发实战 toastr-for-laravel5

本文最早发表于本人博客: Laravel Composer Package 开发实战 toastr-for-laravel5

在Laravel的文档中有 Package Development ,对于入门开发人员来说还是比较抽象,因为开发一个包需要了解 Service Providers , Service ProvidersFacade 已经够抽象的了对刚接触Laravel的开发人员来说,所以我来写一个简单的Laravel 包开发的实例教程吧。

toastr.js 是一个很方便的通知效果,最近刚发布了laravel 5.2,所以就来开发一个toastr for laravel 5的包吧,主要用toastr结合laravel的 flash session 来实现页面的一次性消息提醒,其实这个在我们日常开发中页面操作提醒还是很常用到的业务。

一般的laravel 包开发过程是这样的,开发好以后打包push到gitlab,然后在 packagist 上提交,下面我们就来一步一步实现这个过程。

1.在新建的laravel项目中建立如下目录 packages/yuansir/toastr/src ,packages 目录和 app 目录同级。我们开发包的代码都放在这个src目录中,yuansir和toastr完全自定义。

2.修改项目的composer.json,设定PSR-4命名空间:

"autoload": {         "classmap": [             "database"         ],         "psr-4": {             "App//": "app/",             "Yuansir//Toastr//": "packages/yuansir/toastr/src/"         }     },

别忘了执行autoload

$ composer dump-autoload

3.为我们的包初始化一个composer.json文件,熟悉composer的应该都知道这玩意是干嘛的了

$ cd pacages/yuansir/toastr/src $ composer init

按照提示填写相关信息,有些信息可以不用填写,后面自己在composer.json中添加就可以了,生成的示例如下:

{     "name": "ryan/toastr-for-laravel",     "description": "toastr.js for laravel5",     "authors": [         {             "name": "Ryan",             "email": "yuansir@live.cn"         }     ],     "require": {} }

4.开始开发,新建Service Provider

$ php artisan make:provider ToastrServiceProvider

将生成的 app/Providers/ToastrServiceProvider.php 文件移动到我们的 packages/yuansir/toastr/src 目录下面,并注册 ToastrServiceProviderconfig/app.phpproviders 中。

 'providers' => [          /*          * Laravel Framework Service Providers...          */          ......          /*          * Application Service Providers...          */          ......         Yuansir/Toastr/ToastrServiceProvider::class,     ],

5.新建packages/yuansir/toastr/src/config/toastr.php 来保存 toastr.js 的options,options配置还蛮多的,具体可以看它的demo。

<?php return [     'options' => [] ];

关于这个配置在我们包中如何调用的,我们过会来说.

6.新建Toastr类,来实现toastr 的info,success,error,warning的相关实现,代码还是很简单的, packages/yuansir/toastr/src/Toastr.php :

<?php namespace Yuansir/Toastr;  use Illuminate/Session/SessionManager; use Illuminate/Config/Repository;  class Toastr {     /**      * @var SessionManager      */     protected $session;      /**      * @var Repository      */     protected $config;      /**      * @var array      */     protected $notifications = [];      /**      * Toastr constructor.      * @param SessionManager $session      * @param Repository $config      */     public function __construct(SessionManager $session, Repository $config)     {         $this->session = $session;         $this->config = $config;     }      public function render()     {         $notifications = $this->session->get('toastr:notifications');          if(!$notifications) {             return '';         }          foreach ($notifications as $notification) {             $config = $this->config->get('toastr.options');             $javascript = '';             $options = [];             if($config) {                 $options = array_merge($config, $notification['options']);             }              if($options) {                 $javascript = 'toastr.options = ' . json_encode($options) . ';';             }              $message = str_replace("'", "//'", $notification['message']);             $title = $notification['title'] ? str_replace("'", "//'", $notification['title']) : null;             $javascript .= " toastr.{$notification['type']}('$message','$title');";         }          return view('Toastr::toastr', compact('javascript'));     }      /**      * Add notification      * @param $type      * @param $message      * @param null $title      * @param array $options      * @return bool      */     public function add($type, $message, $title = null, $options = [])     {         $types = ['info', 'warning', 'success', 'error'];         if(!in_array($type, $types)) {             return false;         }          $this->notifications[] = [             'type' => $type,             'title' => $title,             'message' => $message,             'options' => $options         ];         $this->session->flash('toastr:notifications', $this->notifications);     }      /**      * Add info notification      * @param $message      * @param null $title      * @param array $options      */     public function info($message, $title = null, $options = [])     {         $this->add('info', $message, $title, $options);     }      /**      * Add warning notification      * @param $message      * @param null $title      * @param array $options      */     public function warning($message, $title = null, $options = [])     {         $this->add('warning', $message, $title, $options);     }      /**      * Add success notification      * @param $message      * @param null $title      * @param array $options      */     public function success($message, $title = null, $options = [])     {         $this->add('success', $message, $title, $options);     }      /**      * Add error notification      * @param $message      * @param null $title      * @param array $options      */     public function error($message, $title = null, $options = [])     {         $this->add('error', $message, $title, $options);     }      /**      * Clear notifications      */     public function clear()     {         $this->notifications = [];     } }

7.我们看到view(‘Toastr::toastr’, compact(‘javascript’));,那么就是需要一个视图文件了,关于Toastr::toastr是什么鬼我们过会来说,新建 packages/yuansir/toastr/src/views/toastr.blade.php 视图文件:

<link href="http://cdn.bootcss.com/toastr.js/latest/css/toastr.min.css" rel="stylesheet"> <script src="http://cdn.bootcss.com/toastr.js/latest/js/toastr.min.js"></script> <script type="text/javascript">{!! $javascript !!}</script>

就是引入了tastr插件,输出我们render方法中的$javascript

8.建立Facade,新建packages/yuansir/toastr/src/Facades/Toastr.php

<?php namespace Yuansir/Toastr/Facades;  use Illuminate/Support/Facades/Facade;  class Toastr extends Facade {     protected static function getFacadeAccessor()     {         return 'toastr';     } }

9.修改ToastrServiceProvider:

<?php namespace Yuansir/Toastr;  use Illuminate/Support/ServiceProvider;  class ToastrServiceProvider extends ServiceProvider {     /**      * Bootstrap the application services.      *      * @return void      */     public function boot()     {         $this->loadViewsFrom(__DIR__ . '/views', 'Toastr');          $this->publishes([             __DIR__.'/views' => base_path('resources/views/vendor/toastr'),             __DIR__.'/config/toastr.php' => config_path('toastr.php'),         ]);     }      /**      * Register the application services.      *      * @return void      */     public function register()     {         $this->app['toastr'] = $this->app->share(function ($app) {             return new Toastr($app['session'], $app['config']);         });     }      /**      * Get the services provided by the provider.      *      * @return array      */     public function provides()     {         return ['toastr'];     } }

$this->loadViewsFrom(__DIR__ . ‘/views’, ‘Toastr’);就是表示Toastr命名空间的视图文件冲当前目录的views目录中渲染,所以我们上面用 return view(‘Toastr::toastr’, compact(‘javascript’));

$this->publishes在执行php artisan vendor:publish 时会将对应的目录和文件复制到对应的位置

10.测试下是否可行,修改 config/app.php 添加如下:

/*     |--------------------------------------------------------------------------     | Class Aliases     |--------------------------------------------------------------------------     |     | This array of class aliases will be registered when this application     | is started. However, feel free to register as many as you wish as     | the aliases are "lazy" loaded so they don't hinder performance.     |     */      'aliases' => [         ......          'Toastr' => Yuansir/Toastr/Facades/Toastr::class,      ],

写个控制器放进去试试:

<?php  namespace App/Http/Controllers;  use App/Http/Requests; use Illuminate/Http/Request; use Toastr;  class HomeController extends Controller {     /**      * Create a new controller instance.      *      * @return void      */     public function __construct()     {         //略     }      /**      * Show the application dashboard.      *      * @return /Illuminate/Http/Response      */     public function index(Request $request)     {         Toastr::error('你好啊','标题');         return view('home');     } }

反正我测试是OK了,就不截图了!!

11.修改命名空间到包的composer.json,因为别人安装这个包的时候不可能也去改项目composer.json的PSR-4的autoload,所以我们把PSR-4的命名空间加到这个包的composer.json中去,修改 packages/yuansir/toastr/src/composer.json 如下:

{     "name": "ryan/toastr-for-laravel",     "description": "toastr.js for laravel5",     "authors": [         {             "name": "Ryan",             "email": "yuansir@live.cn"         }     ],     "require": {},     "autoload": {         "psr-4": {             "Yuansir//Toastr//": "src/"         }     } }

12.建立Github项目

Laravel Composer Package 开发实战 toastr-for-laravel5 ]( http://website-static.qiniudn.com/wp-content/uploads/2016/01/EE32D501-A968-4D6C-9F77-0661137F7360.png)

将代码push到项目中去:

$ cd packages/yuansir/toastr/ $ git init $ git add . $ git commit -m "add package source files." $ git remote add origin git@github.com:yuansir/toastr-for-laravel5.git $ git push -u origin master $ git tag -a 1.0.0 -m "version 1.0.0" $ git push --tags 

13.提交到Packagist,打开到 packagist.org ,登陆后点击右边上角的 submit ,并填入git的项目地址git@github.com:yuansir/toastr-for-laravel5.git 点击 check 就OK了

Laravel Composer Package 开发实战 toastr-for-laravel5 ]( http://website-static.qiniudn.com/wp-content/uploads/2016/01/D9AB1D5A-C1BC-4A01-8A78-D1EDB859822E.png)

Laravel Composer Package 开发实战 toastr-for-laravel5 ]( http://website-static.qiniudn.com/wp-content/uploads/2016/01/705850F3-B2AA-453F-B0DB-6196BE9C0CB0.png)

到此结束,大功告成,这样一个Laravel 的 composer 包就开发完成了。

到此结束,大功告成,这样一个Laravel 的 composer 包就开发完成了。

这个教程的源码和这个包的安装使用方法详见github  https://github.com/yuansir/toastr-for-laravel5

到此结束,大功告成,这样一个Laravel 的 composer 包就开发完成了。

这个教程的源码和这个包的安装使用方法详见github  https://github.com/yuansir/toastr-for-laravel5

如有问题欢迎指正!

原文  https://segmentfault.com/a/1190000005001120
正文到此结束
Loading...