Skip to content

Laravel 插件包开发

准备工作

这里要求你对 composer 的包封装有所了解, 本文仅仅对封装 laravel 包进行说明

  • 需要阅读并弄清楚 composer 包的封装方式, 参考 怎样创建 PSR-4 的 Php 包
  • 必须对 laravel版本且有一定的基础,了解服务提供者/门面概念

包初始化以及创建

详细文档查看 怎样创建 PSR-4 的 Php 包

新建文件夹

在新建的 laravel 项目中建立如下目录:

packages/toastr/src

packages 目录和 app 目录同级。我们开发包的代码都放在这个 src 目录中,toastr 作为包的名称可以自定义其命名

设定命名空间

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

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

Laravel 配置相关

创建服务提供者Service Provider

php artisan make:provider ToastrServiceProvider

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

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

创建配置文件

新建 packages/toastr/src/config/toastr.php 来保存 toastr.js 的 options

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

创建自定义类

新建Toastr类,来实现toastr 的info,success,error,warning的相关实现,代码还是很简单的

php
<?php 

namespace Duoli\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 = [];
		}
}

创建视图文件

新建 packages/toastr/src/views/toastr.blade.php 视图文件:

html
<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>

创建门面Facade

建立 Facade, 新建 packages/toastr/src/Facades/Toastr.php 就是引入了 toastr 插件,输出我们render 方法中的 $javascript

php
<?php 

namespace Duoli\Toastr\Facades;
use Illuminate\Support\Facades\Facade;
class Toastr extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'toastr';
    }
}

修改服务提供者

php
<?php 
namespace Duoli\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目录中渲染,所以我们上面用

php
return view('Toastr::toastr', compact(‘javascript’));

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

本地测试

修改 config/app.php 添加服务提供者如下:

'aliases' => [
    ......
    'Toastr' => Duoli\Toastr\Facades\Toastr::class,
],

创建测试控制器

$ php artisan make:controller TestController
php
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use Toastr;
class HomeController extends Controller
{
    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        Toastr::error('你好啊','标题');
         dd(session('toastr:notifications'));
        return view('home');
    }
}

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

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

如下:

json
{
    "name": "duoli/toastr.js",
    "description": "toastr.js for laravel",
    "authors": [
        {
            "name": "Duoli",
            "email": "i@wulicode.com"
        }
    ],
    "require": {},
    "autoload": {
        "psr-4": {
            "Duoli\\Toastr\\": "src/"
        }
    }
}

发布到 git 并发布到 packagist 上

使用 git 发布到 github, 然后在 packagist 上增加这个包即可就OK

使用

安装使用

在发布到公有包的情况下可以使用, 如果想要发布到私有包可以查看 使用 packeton 来管理私有包

composer require duoli/toastr.js

Demo视图

html
<!DOCTYPE html>
<html>
<head>
    <title>Laravel</title>
</head>
<body>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
{!! Toastr::render() !!}
</body>
</html>

参考

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


说明

创建时间: 2023-01-15 00:30:00 , 最后编辑于 2023-12-06 19:33:00