详解Laravel服务容器的优势

概述

laravel服务容器就像一个高度自动化的工厂,你需要的东西,定制好模型,使用特定接口来制造。

因为使用了服务容器,laravel中大部分对象实例化的方式是这样的:

$obj1 = $container->make('class1', 'class2');

$obj2 = $container->make('class3', 'class4');

但是在没有使用服务容器的情况下,以下这种方式同样可以做到:

$obj1 = new class1(new class2());

$obj2 = new class3(new class4());

使用服务容器的优势

下面我们通过一些具体例子来分析下它的优势:

例一、发送邮件

我们把发送邮件的功能封装成一个类,需要使用的时候,实例化并调用发送方法。

以下是不使用laravel服务容器常见的方式:

/**

 *发送邮件服务类

 */

class EmailService{
    public function send(){
        //todo 发送邮件方法
    }
}
//如果任何地方要发邮件我们就复制下面这两行代码

$emailService = new EmailService();

$emailService->send();

使用了laravel服务容器以后:

$this->app->bind('emailService', function ($app) {
    return new EmailService();
});
//如果任何地方要发邮件我们就复制下面这两行代码
$emailService = app('emailService');
$emailService->send();

这使得我们的代码更加简洁了,并且由于有了中间层,灵活性提高了(解耦),那么无论是测试(在测试时我们可以伪造类替换EmailService类)还是优化EmailService类,都变得更加方便。

//只需要改这一个地方
$this->app->bind('emailService', function ($app) {
    return new SupperEmailService();
});

其他调用的部分我们完全不用动,如果我们没有这个绑定操作,那么不得不在每个使用邮件服务的地方做更改。

//使用到EamilSerice类的每个地方都要更改
$emailService = new SupperEmailService();
$emailService->send();

例二、实现单例模式

还是上面的例子,出于性能的考虑,你需要SupperEamilService类实现单例模式,于是在不使用laravel服务容器的情况下,你将SupperEmailService类更改如下:

class SupperEamilService{
    //创建静态私有的变量保存该类对象
    static private $instance;
    //防止直接创建对象
    private function __construct(){

    }
    //防止克隆对象
    private function __clone(){

    }
    static public function getInstance(){
        //判断$instance是否是Uni的对象
        //没有则创建
        if (!self::$instance instanceof self) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    //发送邮件方法
    public function send(){

    }

}

除此之外,由于现在SupperEamilService类构造函数为私有,无法通过new关键字来实例化对象,所以在每个实例化SupperEmailService类的地方都要改成这样:

$emailService=SupperEmailService::getInstance();
$emailService->send();

laravel服务容器天生支持单例,下面是laravel的实现方式:

//只需要把bind改成singleton
$this->app->singleton('emailService', function ($app) {
    return new SupperEmailService();
});

要实现单例甚至只需要改一行代码,把原来的bind方法改成singleton ,通过容器取出来的便是单例,真是太方便了。

例三、旅行者去旅行

这个例子假设一个旅行者去西藏旅行,可以做火车(train)或者走路(leg)去。

不使用laravel服务容器:

<?php
interface TrafficTool{
    public function go();
}
class Train implements TrafficTool{
    public function go(){
        echo "train....";
    }

}
class Leg implements TrafficTool{
    public function go(){
        echo "leg..";
    }
}
class Traveller{
    /**
    * @var Leg|null|Train
    * 旅行工具
    */
    protected $_trafficTool;
    public function __construct(TrafficTool $trafficTool){
        $this->_trafficTool = $trafficTool;
    }
    public function visitTibet() {
        $this->_trafficTool->go();
    }

}

当旅行者要坐火车去旅行通常我们这样写:

<?php
$train = new Train();
$tra = new Traveller($train);
$tra->visitTibet();

事实上这种写法已经非常不错了,因为对于旅行工具的依赖已经通过接口的方式转移到外部了。但是使用new来实例化对象的时候还是会产生依赖.比如上面trafficTool),这说明我们要创建一个Traveller之前必须得有一个$trafficTool,即Traveller依赖于trafficTool.当使用new来实例化Traveller的时候,Traveller和trafficTool之间就产生了耦合.这样,这两个组件就没办法分开了。

现在我们来看看使用laravel服务容器是怎么实现的:

在服务容器中绑定类

<?php
namespace App\Providers;
use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider{
    public function register(){
        //在服务容器中绑定类
        $this->app->bind( 'TrafficTool', 'Train');
        $this->app->bind('Traveller', 'Traveller');
    }
}

实例化对象

<?php
// 实例化对象
$tra = app()->make('Traveller');
$tra->visitTibet();

当我们使用服务容器获取旅行类的对象时,容器会自动注入对象所需要的参数。而在此之前我只需要绑定特定的类就可以了,这样做才体现了真正的自动化,而且使得旅行类和旅行工具类完全解耦了。当我们需要更改旅行方式的时候,我们就只需要更改绑定就可以了。

总结

上面举了几个简单的例子,如果能完全理解和掌握laravel服务容器,实际开发中它会给你提供更多的便利。当然它也不是完美无缺的,总之实际使用中扬长避短才是关键。

以上就是详解Laravel服务容器的优势的详细内容,更多关于Laravel服务容器的优势的资料请关注我们其它相关文章!

(0)

相关推荐

  • Laravel中Kafka的使用详解

    本文并没有kafka的安装教程,本文是针对已经安装kafka及其配置好kafka的php拓展并且使用laravel框架进行开发项目,配置一个可供laravel框架使用的生产及消费者类. 以下代码修改自本站的YII框架关于kafka类的代码,经过测试使用在本人的项目中,可正常运行,larvael版本:5.6 代码放置larvael框架位置:app/Tools/Kafka.php <?php namespace App\Tools; use Illuminate\Config\Repository;

  • 详解Laravel服务容器的绑定与解析

    前言   老实说,第一次老大让我看laravel框架手册的那天早上,我是很绝望的,因为真的没接触过,对我这种渣渣来说,laravel的入门门槛确实有点高了,但还是得硬着头皮看下去(虽然到现在我还有很多没看懂,也没用过).   后面慢慢根据公司项目的代码对laravel也慢慢熟悉起来了,但还是停留在一些表面的功能,例如依赖注入,ORM操作,用户认证这些和我项目业务逻辑相关的操作,然后对于一些架构基础的,例如服务提供器,服务容器,中间件,Redis等这些一开始就要设置好的东西,我倒是没实际操作过(因

  • Laravel的加密解密与哈希实例讲解

    一.加密解密 当你的应用程序中需要用到加密和解密的地方时可以使用Laravel自带的加密解密工具. Laravel 的加密机制使用的是 OpenSSL 所提供的 AES-256 和 AES-128 加密.强烈建议你使用 Laravel 内建的加密工具,而不是用其它的加密算法.所有 Laravel 加密之后的结果都会使用消息认证码 (MAC) 签名,使其底层值不能在加密后再次修改. 相应的配置文件 config/app.php 首先生成 APP_KEY php artisan key:genera

  • laravel ajax curd 搜索登录判断功能的实现

    今天来说说关于laravel的各种操作 混杂了一点ajax先来个添加表单 有些英文的$没法打出来用中文代替 登录数据我和列表展示混在一起了,千万不要和我犯一样的错误. <form action="insert" method="post" enctype="multipart/form-data"> @csrf <div style="width: 600px;height: auto;margin: 20px aut

  • Laravel服务容器绑定的几种方法总结

    绑定基础 几乎所有的服务容器绑定都是在 服务提供者 中完成. 在目录结构如下图 注:如果一个类没有基于任何接口那么就没有必要将其绑定到容器.容器并不需要被告知如何构建对象,因为它会使用 PHP 的反射服务自动解析出具体的对象. 简单的绑定 在一个服务提供者中,可以通过 $this->app 变量访问容器,然后使用 bind 方法注册一个绑定,该方法需要两个参数,第一个参数是我们想要注册的类名或接口名称,第二个参数是返回类的实例的闭包: $this->app->bind('HelpSpot

  • laravel使用redis队列实例讲解

    1.队列配置文件是config/queue.php(这里我默认配置即可): 2. 创建迁移表(failed-table .jobs.migrations) php artisan queue:table php artisan queue:failed-table php artisan migrate ps:出现下面错误,修改对应表名即可 ps:出现下面红色错误,修改如下图string(字段,长度(随便填)) 3.创建任务 1)生成任务类: 通常,所有的任务类都保存在 app/Jobs 目录.

  • 详解如何实现Laravel的服务容器的方法示例

    1. 容器的本质 服务容器本身就是一个数组,键名就是服务名,值就是服务. 服务可以是一个原始值,也可以是一个对象,可以说是任意数据. 服务名可以是自定义名,也可以是对象的类名,也可以是接口名. // 服务容器 $container = [ // 原始值 'text' => '这是一个字符串', // 自定义服务名 'customName' => new StdClass(), // 使用类名作为服务名 'StdClass' => new StdClass(), // 使用接口名作为服务名

  • 详解Laravel服务容器的优势

    概述 laravel服务容器就像一个高度自动化的工厂,你需要的东西,定制好模型,使用特定接口来制造. 因为使用了服务容器,laravel中大部分对象实例化的方式是这样的: $obj1 = $container->make('class1', 'class2'); $obj2 = $container->make('class3', 'class4'); 但是在没有使用服务容器的情况下,以下这种方式同样可以做到: $obj1 = new class1(new class2()); $obj2 =

  • 详解Laravel框架的依赖注入功能

    概述 任何时候,你在一个控制器类中请求一个依赖,这个服务容器负责: 1.自动地在构造函数中检测依赖关系 2.如果需要构建这个依赖关系 3.通过构造函数创建对象形成依赖关系 来看一个非常简单的例子. <?php namespace App\Http\Controllers; use App\User; use App\Repositories\UserRepository; use App\Http\Controllers\Controller; class UserController exte

  • 详解JavaScript状态容器Redux

    目录 一.Why Redux 二.Redux Data flow 三.Three Principles(三大原则) 四.Redux源码解析 4.1.index.js 4.2.createStore.js 4.3.combineReducers.js 4.4.bindActionCreators.js 4.5.compose.js 4.6.applyMiddleware.js 五.从零开始实现一个简单的Redux 六.Redux Devtools 七.总结 一.Why Redux 在说为什么用 R

  • 详解微服务架构及其演进史

    目录 1 传统单体系统介绍 1.1 单体系统的问题 1.2 单体系统的优点 1.3 单体服务到微服务的发展过程 2 关于微服务 2.1 单一职责 2.2 轻量级通信 2.3 独立性 2.4 进程隔离 2.5 混合技术栈和混合部署方式 2.6 简化治理 2.7 安全可靠,可维护. 3 微服务演进史 3.1 第一阶:简单服务通信模块 3.2 第二阶:原始通信时代 3.3 第三阶:TCP时代 3.4 第四阶:第一代微服务(Spring Cloud/RPC) 3.5 第五阶:第二代微服务 3.6 第六阶

  • 详解Docker修改容器端口映射的方法

    直接解决方法 具体可参考Stack Overflow链接 docker运行时存在守护程序,所以我们需要停止docker内运行的容器和docker服务.具体可参考官网给出的守护程序解释 docker stop 容器id //CentOS下停止docker服务(Ubuntu类似) sudo systemctl stop docker 使用以下命令找到已创建容器的hostconfig.json和config.v2.json配置文件. find / -name hostconfig.json //或co

  • 详解docker nginx 容器启动挂载到本地

    首先nginx容器内部的结构: 进入容器: docker exec -it b511b6049f57 bash 查看容器的结构目录:其实每一个容器就相当于一个独立的系统. root@b511b6049f57:/# ls bin dev home lib64 mnt proc run srv tmp var boot etc lib media opt root sbin sys usr nginx的结构目录在容器中: 日志位置:/var/log/nginx/ 配置文件位置:/etc/nginx/

  • 详解Laravel制作API接口

    需要注意的是:API有它的具体用途,我们应该清楚它是干啥的.访问API的时候应该输入什么.访问过API过后应该得到什么. 在开始设计API时,我们应该注意这8点.后续的开发计划就围绕着这个进行了. 1.Restful设计原则 2.API的命名 3.API的安全性 4.API返回数据 5.图片的处理 6.返回的提示信息 7.在线API测试文档 8.在app启动时,调用一个初始化API获取必要的信息 用laravel开发API 就在我上愁着要不要从零开始学习的时候,找到了这个插件dingo/api那

  • 详解SpringCloud服务认证(JWT)

     - JWT JWT(JSON Web Token), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景.JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密. - JWT与其它的区别 通常情况下,把API直接暴露出去是风险很大的,不说别的

随机推荐