承接 railken/eloquent-mapper 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

railken/eloquent-mapper

Composer 安装命令:

composer require railken/eloquent-mapper

包简介

README 文档

README

Actions Status

A laravel package that use the full power of relations to create automatic joins and perform advanced filtering.

Given for e.g. two models Office and Employee, you can transform a string like this "employees.name ct 'Mario Rossi' or employees.name ct 'Giacomo'" into a sql query like this

select offices.* 
from `offices` 
left join `employees` as `employees` on `employees`.`office_id` = `offices`.`id`
where (`employees`.`name` like ? or `employees`.`name` like ?)

Functions:

Requirements

PHP 8.1 and laravel 8

Installation

You can install it via Composer by typing the following command:

composer require railken/eloquent-mapper

Usage

In order to use this library you need a map.

Create a new class wherever you want like the following example

app/Map.php

namespace App;

use Railken\EloquentMapper\Map as BaseMap;

class Map extends BaseMap
{
    /**
     * Return an array of all models you want to map
     *
     * @return array
     */
    public function models(): array
    {
        /** return [
            \App\Models\User::class
        ]; **/
    }
}

The method models must return a list of all models. You can even add models that are in your vendor folder, regardless of the logic you use, you only have to return an array.

Railken\EloquentMapper\Map also has the mapping of relations and attributes based on the model, if you wish you can ovveride that functionality and write your own. Check source

These methods are invoked only when you call the command artisan mapper:generate (see below) and the result will be cached in a file placed in bootstrap/cache/map.php.

This means you can perform whatever logic you want to retrieve all models (e.g. scanning files), so don't worry about caching.

Important: In order to be detected, all relations must return the type Illuminate\Database\Eloquent\Relations\Relation like this:

namespace App;

use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Foo extends Model
{   
    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function bar(): BelongsTo
    {
        return $this->belongsTo(Bar::class);
    }
}

Now it's time to register this class in any provider to override the default one.

app/Providers/AppServiceProvider.php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Map;
use Railken\EloquentMapper\Contracts\Map as MapContract;

class AppServiceProvider extends ServiceProvider
{
    /**
     * @inherit
     */
    public function register()
    {
        $this->app->bind(MapContract::class, Map::class);
    }
}

Artisan

There is only one command, and it's artisan mapper:generate. This command will remap and recache so keep in mind that you have to execute it whanever you change your code models .

If you use models that are in your vendor folder, you could add this in your composer.json to reload everytime the libreries are updated.

{
   "scripts": {
        "post-autoload-dump": [
            "@php artisan mapper:generate"
        ]
    }
}

Filtering

Sow how the filtering actually works?

use Railken\EloquentMapper\Scopes\FilterScope;
use Railken\EloquentMapper\With\WithCollection;
use Railken\EloquentMapper\With\WithItem;
use App\Models\Foo;

$foo = new Foo;
$query = $foo->newQuery();
$filter = "created_at >= 2019";

$scope = new FilterScope;
$scope->apply($query, $filter, new WithCollection([
    new WithItem('bar')
]));

And that's it! $query is now filtered, if Foo has any relationships you can use the dot notation and the filter will automatically perform the join. For e.g. if Foo has a relationship called tags and you want to retrieve all Foo with the tag name myCustomTag simply use tag.name = 'myCustomTag'.

Here's the full syntax

The third parameter is the eager loading option. You can of course use the dot notation as well and add subquery. For istance the following example rapresent a list of all authors that contains the name Mario and returns all of theirs books that have a tag.name called sci-fi.

use Railken\EloquentMapper\Scopes\FilterScope;
use Railken\EloquentMapper\With\WithCollection;
use Railken\EloquentMapper\With\WithItem;
use Railken\EloquentMapper\Tests\Models\Author;

$author = new Author;
$query = $author->newQuery();
$filter = "name ct 'Mario'";
$scope = new FilterScope;

$scope->apply($query, $filter, new WithCollection([
    new WithItem('books', 'tag.name eq "sci-fi"')
]));

Joiner

This is an internal class used by the FilterScope to join the necessary relations before performing the filtering, but you can use it indipendently. see tests

Example - Setup

Let's continue with a real example, first the setup. We will use two models: Office and Employee

app/Models/Office.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Office extends Model
{   
    /** 
     * @var array
     */
    public $fillable = [
        'name',
        'description'
    ];

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function employees(): HasMany
    {
        return $this->hasMany(Employee::class);
    }
}

app/Models/Employee.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\Office;

class Employee extends Model
{   
    /**
     * @var array
     */
    public $fillable = [
        'name',
        'description',
        'office_id'
    ];

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function office(): BelongsTo
    {
        return $this->belongsTo(Office::class);
    }
}

app/Map.php

namespace App;

use Railken\EloquentMapper\Map as BaseMap;

class Map extends BaseMap
{
    /**
     * Return an array of all models you want to map
     *
     * @return array
     */
    public function models(): array
    {
        return [
            \App\Models\Employee::class,
            \App\Models\Office::class
        ];
    }
}

Example - Usage

Retrieve all offices that have employees with name Mario Rossi or Giacomo

use App\Models\Office;
use Railken\EloquentMapper\Scopes\FilterScope;

$office = new Office;

$query = $office->newQuery();
$filter = "employees.name ct 'Mario Rossi' or employees.name ct 'Giacomo'"

$scope = new FilterScope();
$scope->apply($query, $filter);

echo $query->toSql();

Result:

select offices.* 
from `offices` 
left join `employees` as `employees` on `employees`.`office_id` = `offices`.`id`
where (`employees`.`name` like ? or `employees`.`name` like ?)

railken/eloquent-mapper 适用场景与选型建议

railken/eloquent-mapper 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 27.44k 次下载、GitHub Stars 达 7, 最近一次更新时间为 2019 年 03 月 14 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「eloquent-mapper」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 railken/eloquent-mapper 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 railken/eloquent-mapper 我们能提供哪些服务?
定制开发 / 二次开发

基于 railken/eloquent-mapper 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 27.44k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 7
  • 点击次数: 1
  • 依赖项目数: 7
  • 推荐数: 0

GitHub 信息

  • Stars: 7
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2019-03-14