开源-LaravelPlus-基于-Laravel-魔改为方便实际业务使用-开发中

目的为了减少重复 CURD 和新项目的配置麻烦等问题,(就是为了骗星星:LaravelPlus )如: 现有的 infyomlabs/laravel-generator CODE 生成工具虽然好用,但是不太喜欢样式和代码结构。有些本地,测试,线上的配置需要频繁改动的需要。多个项目构建引入包,配置扩展等重复性操作介绍LaravelPlus 基于 Laravel 增加部分软件包初始安装和进行业务使用功能改动,来创建一个开箱即用的应用 版本基础当前版本基于 PHPLaravel(影响不大,降低版本理论可以)>=7.1.3>=5.8项目使用说明下载项目// 1. github (推荐)$ git clone https://github.com/ElapseAnnals/LaravelPlus.git $ git checkout v5.8.0 // 切换至当前最新稳定版本// 或// 2. composer$ composer create-project elapse-annals/laravel-plus$ mv laravel-plus LaravelPlus#### 复制项目 // 1.在当前目录运行自动复制脚本 (推荐)$ php LaravelPlus/create YourProject// 或 // 2.在当前目录手动复制项目至自身项目$ cd LaravelPlus$ rm composer.lock$ rsync -av --exclude . --exclude .. --exclude .git/ --exclude vendor/ --exclude .github/ LaravelPlus/* YourProject // 为消除对称 */ $ cd YourProject$ rm composer.lock .env .travis$ cp .env.example .env 初始化$ cd YourProject // 进入 YourProject 项目中$ composer install // 更新软件包 (请先已安装 composer )$ php artisan key:generate // 更新 key$ php artisan vendor:publish // 发布扩展包的资源$ php artisan migrate // 迁移$ php artisan storage:link // 图片资源软连接映射【非必须】Tips: ...

June 9, 2019 · 2 min · jiezi

Laravel关联模型中过滤结果为空的结果集(has和with区别)

首先看代码:$userCoupons = UserCoupons::with([‘coupon’ => function($query) use($groupId){ return $query->select(‘id’, ‘group_id’, ‘cover’, ‘group_number’, ‘group_cover’)->where([ ‘group_id’ => $groupId, ]);}])// 更多查询省略…数据结构是三张表用户优惠券表(user_coupons)、优惠券表(coupons),商家表(corps),组优惠券表(group_coupons) (为了方便查看,后两项已去除)这里我本意想用模型关联查出用户优惠券中属于给定组gourpId的所有数据(如果为空该条数据就不返回)。但有些结果不是我想要的: array(20) { [“id”]=> int(6) [“user_id”]=> int(1) [“corp_id”]=> int(1) [“coupon_id”]=> int(4) [“obtain_time”]=> int(1539739569) [“receive_time”]=> int(1539739569) [“status”]=> int(1) [“expires_time”]=> int(1540603569) [“is_selling”]=> int(0) [“from_id”]=> int(0) [“sell_type”]=> int(0) [“sell_time”]=> int(0) [“sell_user_id”]=> int(0) [“is_compose”]=> int(0) [“group_cover”]=> string(0) "" [“is_delete”]=> int(0) [“score”]=> int(100) [“created_at”]=> NULL [“updated_at”]=> NULL [“coupon”]=> NULL // 注意返回了coupons为空的数据 }记录中有的coupon有记录,有的为空。想想也是,with只是用sql的in()实现的所谓预加载。无论怎样主user_coupons的数据都是会列出的。它会有两条sql查询,第一条查主数据,第二条查关联,这里第二条sql如下:select id, group_id, cover, group_number, group_cover from youquan_coupons where youquan_coupons.id in (1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14) and (group_id = 1) and youquan_coupons.deleted_at is null如果第二条为空,主记录的关联字段就是NULL。后来看到了Laravel关联的模型的has()方法,has()是基于存在的关联查询,下面我们用whereHas()(一样作用,只是更高级,方便写条件)这里我们思想是把判断有没有优惠券数据也放在第一次查询逻辑中,所以才能实现筛选空记录。加上whereHas()后的代码如下 $userCoupons = UserCoupons::whereHas(‘coupon’, function($query) use($groupId){ return $query->select(‘id’, ‘group_id’, ‘cover’, ‘group_number’, ‘group_cover’)->where([ ‘group_id’ => $groupId, ]); })->with([‘coupon’ => function($query) use($groupId){ return $query->select(‘id’, ‘group_id’, ‘cover’, ‘group_number’, ‘group_cover’); }])-> // …看下最终的SQL:select * from youquan_user_coupons where exists (select id, group_id, cover, group_number, group_cover from youquan_coupons where youquan_user_coupons.coupon_id = youquan_coupons.id and (group_ids = 1) and youquan_coupons.deleted_at is null) and (status = 1 and user_id = 1)这里实际上是用exists()筛选存在的记录。然后走下一步的with()查询,因为此时都筛选一遍了,所以with可以去掉条件。显然区分这两个的作用很重要,尤其是在列表中,不用特意去筛选为空的数据,而且好做分页。本文最早发布在 Rootrl’s blog ...

October 18, 2018 · 1 min · jiezi

Laravel源码解析之Model

前言提前预祝猿人们国庆快乐,吃好、喝好、玩好,我会在电视上看着你们。根据单一责任开发原则来讲,在laravel的开发过程中每个表都应建立一个model对外服务和调用。类似于这样namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model{ protected $table = ‘users’;}解析Laravel的数据操作分两种DB facadeEloquent ORM它们除了有各自的特色外,基本的数据操作都是通过 Illuminate\Database\Query\Builder 调用方法去完成整个SQL。你也可以帮Builder这个类作为整个SQL操作的基类。这个类涵盖了以下的操作方法(部分展示)方法 public function select($columns = [’*’]) public function selectSub($query, $as) public function selectRaw($expression, array $bindings = []) public function fromSub($query, $as) public function fromRaw($expression, $bindings = []) public function addSelect($column) public function distinct() public function from($table) public function join($table, $first, $operator = null, $second = null, $type = ‘inner’, $where = false) public function joinWhere($table, $first, $operator, $second, $type = ‘inner’) public function joinSub($query, $as, $first, $operator = null, $second = null, $type = ‘inner’, $where = false) public function leftJoin($table, $first, $operator = null, $second = null) public function where($column, $operator = null, $value = null, $boolean = ‘and’) public function orWhere($column, $operator = null, $value = null) public function whereRaw($sql, $bindings = [], $boolean = ‘and’) public function whereIn($column, $values, $boolean = ‘and’, $not = false) public function orWhereIn($column, $values) 可见有很多方法在中国laravel站或者官方文档上都没有体现,所以说就算要精通一款框架,不去看它的源码也是不行的。这个文件在你项目目录中的 vendor/laravel/framework/src/Illuminate/Database/Query 下,你可以自行去查看。DB facade正常情况下你可能会这样写一个操作DB::table(‘user’)->get();这个操作首先经过laravel的门面指向文件,不过它并不在 app.php 中,而是通过内核直接加载,它在Illuminate\Foundation\Application -> registerCoreContainerAliases()被注册。门面直接调用 Illuminate\Database\DatabaseManager 类。public function registerCoreContainerAliases(){ foreach ([ … ’encrypter’ => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class], ‘db’ => [\Illuminate\Database\DatabaseManager::class], ‘db.connection’ => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class], ’events’ => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class], ‘files’ => [\Illuminate\Filesystem\Filesystem::class], …. )} Illuminate\Database\DatabaseManager 内并没有太多的代码,大多都是处理数据库链接。当你使用 DB::table()时,会通过public function __call($method, $parameters){ return $this->connection()->$method(…$parameters);}转发,调用的是 Illuminate\Database\Connection ,用户处理 table() 方法,随后会通过 table() 方法指向 Illuminate\Database\Query 类,开头我们讲过这个类了,这里就不多说了,随后就是各种sql的拼接->执行sql->结束战斗Eloquent ORMEloquent ORM 与DB facade 类似,首先每个 Eloquent ORM 都需要继承父类 Illuminate\Database\Eloquent\Model 你大概会这样写User::find(1)父类是不存在这个方法的,它会通过public static function __callStatic($method, $parameters){ return (new static)->$method(…$parameters);}去转发请求调用。同理User::get()则是通过public function __call($method, $parameters){ if (in_array($method, [‘increment’, ‘decrement’])) { return $this->$method(…$parameters); } return $this->newQuery()->$method(…$parameters);}去调用,这个方法最终以 new Builder() 而告终,public function newEloquentBuilder($query){ return new Builder($query);}最后我们到了 Illuminate\Database\Eloquent\Builder 文件下,这个类中涵盖了ORM的基本操作,例如find , findOrFail 等等。如果你在代码用到了get方法,抱歉,这里没有,它依旧会通过__call 方法将你的请求转发到 Illuminate\Database\Query\Builder 类中$this->query->{$method}(…$parameters);至此就完成了整个数据操作。致谢感谢你看到这里,希望本篇文章可以帮助到你,谢谢 ...

September 30, 2018 · 2 min · jiezi