有没有关于Service层使用的详细介绍

有没有关于在laravel中Service层使用的详细介绍

例如:
什么时候使用Service层
Service层如何划分,模块?功能?控制器?
Service层如何返回,抛出异常?返回数组?返回布尔值?
控制层是不是什么都不写直接调用Service层,所有判断、数据、通知都放入Service层?
……

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 20
laradocs

星期二引用你的主题写篇博文,记得来捧场噢:smile:

2年前 评论
臭鼬 (楼主) 2年前
laradocs (作者) 2年前
  • 站在抽象的最高点,程序是 数据逻辑 的结合体,由 业务 串联到一起。
  • Service 层 如其名,做具体实现,服务于具体业务。
  • 入参、出参 在于 你 或 你团队规范。
  • 它是一种思想,需要理解它的定位:服务于具体业务,明白这一点,就不会纠结何划分。

拿 Laravel 来说吧,如果我新开一个项目,那么我会:

  • 建一个 目录,统一入参。
  • 建一个 目录,统一出参。
  • 建一个 目录,统一各种数据资源(model,api...),返回格式为出参所定义的。
  • 建一个目录,服务层,入参只能是 由入参目录定义的为,出参也是。
  • 其它的目录,按Larvel 默认的来。

那么一个正常的运行流程是:

  • 控制器获得请求数据,转换成 入参 格式,调用服务层。
  • 服务层处理逻辑, 数据调用 数据资源层,处理完毕,返回 出参 格式。
  • 控制器拿到出参,做对控制即可。

没错,这样做,产生的代码或目录会多一些,但好处就太多了。

2年前 评论
臭鼬 (楼主) 2年前
臭鼬 (楼主) 2年前

有的人喜欢命名一个logic,有的人喜欢service,主要用来处理逻辑,控制层只做参数和验证,其实写哪里都行,看你们公司的要求

2年前 评论
臭鼬 (楼主) 2年前

service

public function login(array $post) { $val = Validator::make($post, [ 'admin_name' => 'required', 'admin_password' => 'required', ], [ 'admin_name.required' => '用户名不能为空', 'admin_password.required' => '密码不能为空' ]);

    $this->validateErrors($val);

    $admin = $this->model->where('admin_name', $post['admin_name'])->first();
    if (empty($admin) || $admin->admin_is_del == 1) {
        throw new \Exception('用户名不存在');
    }
    if ($admin->admin_password != md5($post['admin_password'])) {
        throw new \Exception('密码错误');
    }
    if ($admin->village_id != 0) {
        $village = VillageList::where('id', $admin->village_id)->first();
        // 1 为true
        if ($village->village_is_del) {
            throw new \Exception('用户名不存在');
        }
    }
    if ($admin->admin_status == 0) {
        throw new \Exception('账号已禁用');
    }
    if ($admin->expire_at > time()) {
        return $admin->admin_token;
    }
    $salt = md5(mt_rand(0, 999) . uniqid());
    $token = md5($salt . $post['admin_name'] . $salt);
    $admin->expire_at = time() + 60 * 60 * 3 * 24;
    $admin->admin_token = $token;
    $admin->save();
    return $admin->admin_token;
}
2年前 评论
臭鼬 (楼主) 2年前

controller:

public function login(Request $request) { try { $token = $this->service->login($request->post()); } catch (\Exception $e) { return $this->fail($e->getMessage()); } return $this->success(['data' => '登录成功', 'token' => $token]); }

2年前 评论
臭鼬 (楼主) 2年前
臭鼬 (楼主) 2年前

看你自己 正常控制器可以配合验证使用 一般只用于校验参数 逻辑判断可以写在service

2年前 评论

硬性目录要求

file

开发相关规范说明

  • model 声明数据表,字段类型,数据表关联关系
  • dal 声明模型查询字段,进行基础查询
  • logic 嵌套 try catch 接管 dal 的返回值
  • logic 开事务,进行多表操作
2年前 评论
臭鼬 (楼主) 2年前

dal 是数据访问层(Data Access Layer)的英文缩写;具体到项目里面,其实是只有查询数据库的功能,外部 API 调用并没有封装进去。具体的代码是一些通用方法的实现,子类可以重写。

dal 结构 file

logic 结构

file

logic 第一个作用就是 try catch 只在这一层写, dal 层是不写的,举个例子:

   #dal
    public function getAllList($params = [], $use_status = null, $condition = [])
    {
        $query = $this->model->field($this->listField);
        $with = $condition['with'] ?? [];
        $search_field = $condition['search_field'] ?? $this->setAllSearchField();
        $this->orderBy = $condition['order'] ?? $this->orderBy;
        $where = $this->formatWhere($search_field, $params);
        if (null !== $use_status) {
            $where[] = ['use_status', '=', $use_status];
        } else {
            $where[] = ['use_status', '=', 1];
        }

        return $query->where($where)->order($this->orderBy)->with($with)->cache($this->cacheTime)->select();
    }
    # logic 
   public function getAllList($params = [], $use_status = null, $condition = [])
    {
        try {
            $arr = $this->dal->getAllList($params, $use_status, $condition);

            return $this->resultType($arr);
        } catch (\Exception $e) {
            $this->setTraceLog($e);
        } catch (\Error $e) {
            $this->setTraceLog($e);
        }

        return [];
    }

第二个就是 dal 实现了一般的通用单表操作,logic 就是多表的操作,例子:

    public function saveBook($data, $param)
    {
        try {
            Db::startTrans();
            $book_id = Db::table('book_info')->insertGetId($this->appendAddAttr($data));
            if (!empty($param['tag'])) {
                $tags = array_map(function ($item) use ($book_id) {
                    return $this->appendAddAttr([
                        'tag_id' => $item,
                        'book_id' => $book_id,
                    ]);
                }, $param['tag']);
                Db::table('book_tag_bind')->insertAll($tags);
            }
            Db::commit();

            return ['code' => 1, 'txt' => '操作成功'];
        } catch (\Throwable $e) {
            Db::rollback();
            $this->setTraceLog($e, [$data, $param]);
        }

        return ['code' => -1, 'txt' => '操作失败'];
    }

大概就是这样吧,没什么很精彩的代码 :joy:

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!