保姆级教程:Laravel中添加Service

9 篇文章 0 订阅

前提

已经成功安装PHP 8.2 和 Laravel 10.x,并且可以正常启动使用。

为什么要用Service

理由很简单,在Laravel中其实各种逻辑的实现都是Service,可以这么说Service才是真正干活的。

如何创建Service

一般来说对Service会有这么几个需求

  • 可以用不同的实现去替换同种Service,而不需要大改代码
  • 希望能在几乎任何地方可以呼叫到Service,而不需要复杂的代码引用
  • 暂时用不到的Service不需要初始化
  • 代码里引入一个Service可以自动加载和初始化

常规Service要创建4个Class

  • Service Class
  • Service Provider Class
  • Contract Class
  • Facade Class

这儿用一个简单的样例来说明,比如我们需要一个从免费图片网站里拉取图片的服务,假设现在使用 unsplash,这是一个常用的免费图片网站,注册后可以直接申请一个api key,做个demo完全没问题。

那么先建好4个空的Class

  •  app/Contract/PullImageContract.php
<?php

namespace App\Contracts;

interface PullImageContract
{

    /**
     * 搜索关键字,返回第一个结果的url
     * @return string 图片url
     */
    public function pullImageByKeyword(string $keyword): string;

}
  • app/Services/PullImageService.php
<?php

namespace App\Services;

use App\Contracts\PullImageContract;

class PullImageService implements PullImageContract{

    public static function make(): PullImageContract{
        return new PullImageService();
    }

    public function pullImageByKeyword(string $keyword): string{
        return "";
    }

}
  • app/Providers/PullImageServiceProvider.php
<?php

namespace App\Providers;

use App\Contracts\PullImageContract;
use App\Services\PullImageService;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;

class PullImageServiceProvider extends ServiceProvider implements DeferrableProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        //
        $this->app->singleton(PullImageContract::class, static function (): PullImageContract {
            return PullImageService::make();
        });

        $this->app->alias(PullImageContract::class, 'pullimage');
        $this->app->alias(PullImageContract::class, PullImageService::class);
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        //
    }
}
  • app/Facades/PullImage.php
<?php

declare(strict_types=1);

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

/**
 */
final class PullImage extends Facade
{
    /**
     * Get the registered name of the component.
     */
    protected static function getFacadeAccessor(): string
    {
        return 'pullimage';
    }
}

看上去有点繁琐,其实都是有需求才建立的。解释一下为什么要建立这4个class。

  • app/Contract/PullImageContract.php: 就是一个interface,意思是规定好一个内部接口,这个服务将会有什么具体实现的功能,每个功能是输入和输出是什么,约定好具体的输入和输出,这样可以借助IDE的功能来检查是否有错误。在这个例子里只有一个功能 pullImageByKeyword ,输入是一个string类型的keyword,返回一个 string类型的 url,可以在注释里多说明详细内容。
  • app/Services/PullImageService.php: 就是实现了PullImageContract的具体class
  • app/Providers/PullImageServiceProvider.php : 提供了符合PullImageContract规范的服务,目前只是简单地在register里提供了一个单例类,boot暂时不需要初始化什么。
    • $this->app->singleton 是设计模式里的单例模式,就是保证只创建一个实体
    • DeferrableProvider 意味着延迟加载,当用到的时候才会加载,可以节省资源

  • app/Facades/PullImage.php: 可以看成一个快捷存取方式,在Laravel大部分使用场景里都可以用 PullImage::pullImageByKeyword 直接调用服务

安装和启动Service

只要简单地设定在 config/app.php,剩下的就让laravel自行完成。

  • 自动载入Provider : 在 providers 里加上一行 App\Providers\PullImageServiceProvider::class,
  • 别名:在 aliases 里加上一行 'PullImage'=> App\Facades\PullImage::class,

不需要去掉原来的内容,只要加上就行了

    'providers' => ServiceProvider::defaultProviders()->merge([
        App\Providers\PullImageServiceProvider::class,
    ])->toArray(),

    'aliases' => Facade::defaultAliases()->merge([
        'PullImage'=> App\Facades\PullImage::class,
    ])->toArray(),

使用服务

一般有两种方式使用服务

  • 让Laravel 自动注入,在command/controller等地方可以直接写一个参数就可以自动注入,就是这么简单。之所以用 Contract 就是因为PullImageServiceProvider的register里做了绑定,所以laravel知道对应这个Contract 如何找到Service
    public function handle(PullImageContract $pullImageContract)
    {
        $url=$pullImageContract->pullImageByKeyword("...");
    }
  • 使用Facade快捷调用,基本上laravel内都可以这样使用,在PullImage这个Facade里定义了一个名字 "pullimage",这个名字也是在 PullImageServiceProvider的register里设定了别名,所以也可以顺利找到Service
use App\Facades\PullImage;


$url=PullImage::pullImageByKeyword("....");

更新具体内容

完成以上所有工作后,以后只要更新两个类 PullImageContract 和 PullImageService ,PullImageContract 负责接口定义,PullImageService则是真正的实现代码

总结

  • 创建4个Class
  • 在 config/app.php 里设定
  • 用自动注入和Facade调用服务
  • 更新代码主要在 Contract 和 Service
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值