定制 longman/laravel-lodash 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

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

longman/laravel-lodash

Composer 安装命令:

composer require longman/laravel-lodash

包简介

Add more functional to Laravel

README 文档

README

Build Status Code Coverage Code Quality Latest Stable Version Total Downloads Downloads Month License

This package adds lot of useful functionality to the Laravel >=13.0 project.

Compatibility

Since version 11, the package major version matches the Laravel framework major version (lodash 13 targets Laravel 13, lodash 12 targets Laravel 12, and so on).

laravel-lodash Laravel framework PHP
^13.0 ^13.0 ^8.4
^12.0 ^12.0 ^8.4
^11.0 ^11.0 ^8.2
^9.0 ^10.0 ^8.1
^4.0 < 8.0 varies
^1.0 < 5.8 varies

If your application is still on an older Laravel major, install the matching previous tag of laravel-lodash.

Table of Contents

Installation

Install this package through Composer.

Run a command in your command line:

composer require longman/laravel-lodash

Add LodashServiceProvider to your service providers list in the app.php

'providers' => [
    . . .
    /*
     * Package Service Providers...
     */
    Longman\LaravelLodash\ServiceProvider::class,
    . . .
],

Copy the package config and translations to your application with the publish command:

php artisan vendor:publish --provider="Longman\LaravelLodash\LodashServiceProvider"

Usage

General

Enable Debug Mode depending on visitor's IP Address

Add Longman\LaravelLodash\Debug\DebugServiceProvider::class in to config/app.php and specify debug IP's in your config/lodash.php config file:

    . . .
    'debug' => [
        'ips' => [ // IP list for enabling debug mode
            //'127.0.0.1',
        ],
    ],
    . . .

Add created_by, updated_by and deleted_by to the eloquent models

Sometimes we need to know who created, updated or deleted entry in the database.

For this just add Longman\LaravelLodash\Eloquent\UserIdentities trait to your model and also update migration file adding necessary columns:

    $table->unsignedInteger('created_by')->nullable();
    $table->unsignedInteger('updated_by')->nullable();
    $table->unsignedInteger('deleted_by')->nullable();

Use UUID in the Eloquent Models

For this just add Longman\LaravelLodash\Eloquent\UuidAsPrimary trait to your model and also update related migration file:

    $table->uuid('id')->primary();

Also there is possible to specify uuid version via defining uuidVersion property in the model class.

Eager loading of limited many to many relations via subquery or union

Eager load many to many relations with limit via subquery or union. For using this feature, add Longman\LaravelLodash\Eloquent\ManyToManyPreload trait to the models. After that you can use methods limitPerGroupViaUnion() and limitPerGroupViaSubQuery(). For example you want to select users and 3 related user photos per user.

    $items = (new User)->with([
        'photos' => function (BelongsToMany $builder) {
            // Select via union. There you should pass pivot table fields array
            $builder->limitPerGroupViaUnion(3, ['user_id', 'photo_id']);
            // or
            // Select via subquery
            $builder->limitPerGroupViaSubQuery(3);
        }, 'other.relation1', 'other.relation2'
    ]);
    $items = $items->get();

Now each user model have 3 photos model selected via one query. You can specify additional where clauses or order by fields before the group method call.

Redis using igbinary

Igbinary is a drop in replacement for the standard php serializer. Igbinary stores php data structures in compact binary form. Savings are significant when using Redis or similar memory based storages for serialized data. Via Igbinary repetitive strings are stored only once. Collections of Eloquent objects benefit significantly from this.

By default Laravel does not provide an option to enable igbinary serializer for PhpRedis connection and you have to use LaravelLodash implementation for this.

First of all, make sure you enabled PhpRedis driver by this guide https://laravel.com/docs/5.5/redis#phpredis

After that include Cache and Redis service providers in the app.php before your App providers:

    . . .
    Longman\LaravelLodash\Cache\CacheServiceProvider::class,
    Longman\LaravelLodash\Redis\RedisServiceProvider::class,
    . . .

You can remove Laravel's Cache and Redis service providers from the config, because LaravelLodash providers are extended from them and therefore implements entire functional.

Now you can specify the serializer in your database.php under config folder:

Also, you can specify other options like scan or etc. See https://github.com/phpredis/phpredis#setoption

Redis client side sharding

PhpRedis extension along with native Redis Cluster, also supports client-side sharding. This feature is very useful, when you want distribute your data between multiple servers, but do not want use native Redis Cluster.

Its not implemented in the Laravel by default. We tried to fix this 😄

Config example:

    . . .
    'redis' => [
        'client' => 'phpredis',
        
        'clusters' => [
            'options' => [
                'lazy_connect'      => true,
                'connect_timeout'   => 1,
                'read_timeout'      => 3,
                'password'          => env('REDIS_PASSWORD', null),
                'database'          => env('REDIS_DATABASE', 0),
                'prefix'            => env('REDIS_PREFIX'),
                'serializer'        => Redis::SERIALIZER_IGBINARY,
                'compression'       => Redis::COMPRESSION_ZSTD,
                'compression_level' => Redis::COMPRESSION_ZSTD_DEFAULT,
            ],

            'default' => [
                [
                    'host' => env('REDIS_SHARD1_HOST', '127.0.0.1'),
                    'port' => env('REDIS_SHARD1_PORT', 6379),
                ],
                [
                    'host' => env('REDIS_SHARD2_HOST', '127.0.0.2'),
                    'port' => env('REDIS_SHARD2_PORT', 6379),
                ],
                . . .
            ],
        ],
    ],
    . . .

AWS SQS Fifo Queue

Laravel by default does not supports AWS FIFO queues and this package fixes it.

You have to add QueueServiceProvider service provider in the app.php before your App providers:

    . . .
    Longman\LaravelLodash\Queue\QueueServiceProvider::class,
    . . .

You can remove Laravel's Queue service provider from the config, because LaravelLodash provider are extended from that and therefore implements entire functional.

Now you can add the new connection in the queue.php under config folder:

    . . .
    'sqs_fifo' => [
        'driver'  => 'sqs.fifo',
        'version' => 'latest',
        'key'     => env('AWS_ACCESS_KEY_ID'),
        'secret'  => env('AWS_SECRET_ACCESS_KEY'),
        'prefix'  => env('AWS_SQS_URL'),
        'queue'   => env('AWS_SQS_DEFAULT_QUEUE'),
        'region'  => env('AWS_DEFAULT_REGION'),
        'options' => [
            'type'      => 'fifo', // fifo, normal
            'polling'   => 'long', // long, short
            'wait_time' => 20,
        ],
    ],
    . . .

Elasticsearch Integration

First of all you have to install official elasticsearch php sdk:

composer require elasticsearch/elasticsearch

After add ElasticsearchServiceProvider service provider in the app.php before your App providers:

    . . .
    Longman\LaravelLodash\Elasticsearch\ElasticsearchServiceProvider::class,
    . . .

Now you can add the configuration in the services.php under config folder:

    . . .
    'elasticsearch' => [
        'enabled'          => env('ELASTICSEARCH_ENABLED', false),
        'log_channel'      => ['daily'],
        'hosts'            => [
            [
                'host' => env('ELASTICSEARCH_HOST', 'localhost'),
                'port' => env('ELASTICSEARCH_PORT', 9200),
            ],
        ],
        'connectionParams' => [
            'client' => [
                'timeout'         => env('ELASTICSEARCH_TIMEOUT', 3),
                'connect_timeout' => env('ELASTICSEARCH_TIMEOUT', 3),
            ],
        ],
    ],
    . . .

You can use Elasticsearch integration via

    $elasticsearch_manager = app(ElasticsearchManagerContract::class);
    
    // Call wrapped methods
    $elasticsearch_manager->createIndex('some-index');
    
    // Or get native client and access their methods
    $client = $elasticsearch_manager->getClient();
    $client->indices()->create($params);

Also you can perform search via searchable query object. Just create class and implement ElasticsearchQueryContract and you can pass object to performSearch method

    $elasticsearch_manager = app(ElasticsearchManagerContract::class);
    $results = $elasticsearch_manager->performSearch($query); 

Check if installed packages are in sync with composer.lock

For development purposes, it is recommended to check if vendor folder is in sync with composer.lock file.

For this, in composer.json you have to add script ComposerScripts::createPackageHash:

    . . .
    "post-autoload-dump": [
        "Longman\\LaravelLodash\\Composer\\ComposerScripts::createPackageHash",
        . . .
    ],
    . . .

And in the AppServiceProvider::boot add these lines:

    . . .
    if (config('app.debug')) {
        $checker = new ComposerChecker(base_path());
        $checker->checkHash();
    }
    . . .

Helper Functions

Function Description
p(...$values): void Add debug messages to the debugbar
get_db_query(): ?string Get last executed database query
get_db_queries(): ?array Get all executed database queries

Extended Classes

For this fuctional you should add Longman\LaravelLodash\LodashServiceProvider::class in the config/app.php file.

There is an extended classes via Laravel's builtin macros functionality

Request class

Method Description
getInt(string $name, int $default = 0): int Return request field value as a integer
getBool(string $name, bool $default = false): bool Return request field value as a boolean
getFloat(string $name, float $default = 0): float Return request field value as a float
getString(string $name, string $default = ''): string Return request field value as a string

Artisan Commands

For this fuctional you should add Longman\LaravelLodash\LodashServiceProvider::class in the config/app.php file.

Command Description
php artisan clear-all Clear entire cache and all cached routes, views, etc.
php artisan db:clear Drop all tables from database. Options:
--database= : The database connection to use.
--force : Force the operation to run when in production.
--pretend : Dump the SQL queries that would be run.
php artisan db:dump Dump database to sql file using mysqldump CLI utility. Options:
--database= : The database connection to use.
--path= : Folder path for store database dump files.
php artisan db:restore {file} Restore database from sql file using mysqldump CLI utility. Options:
--database= : The database connection to use.
--force : Force the operation to run when in production
php artisan log:clear Clear log files from storage/logs recursively. Options:
--force : Force the operation to run when in production.
php artisan user:add {email} {password?} Create a new user. Options:
--guard= : The guard to use.
php artisan user:password {email} {password?} Update/reset user password. Options:
--guard= : The guard to use.

Middleware List

XssSecurity

Sets XSS Security headers. Can be configured excluded URI-s, etc in the config/lodash.php .

SimpleBasicAuth

Add simple basic auth to a route.

In the config/auth.php you have to add:

    . . .
    'simple' => [
        'enabled'  => env('SIMPLE_AUTH_ENABLED', true),
        'user'     => env('SIMPLE_AUTH_USER', 'user'),
        'password' => env('SIMPLE_AUTH_PASS', 'secret'),
    ],
    . . .

Blade Directives

For this functional you should add Longman\LaravelLodash\LodashServiceProvider::class in the config/app.php file.

Directive Description
@datetime($date); Display relative time. Example:
$date = Carbon\Carbon::now();
@datetime($date);
@plural($count, $word) Pluralization helper. Example:
@plural(count($posts), 'post')
Produces '1 post' or '2 posts', depending on how many items in $posts there are

Misc

SelfDiagnosis Checks

For using this checks, you have to install the package: laravel-self-diagnosis

Available Disk Space Check

...
\Longman\LaravelLodash\SelfDiagnosis\Checks\AvailableDiskSpace::class => [
    'paths' => [
        '/' => '100G', // At least 100G should be available for the path "/"
        '/var/www' => '5G',
    ],
],
...

Filesystem Disks Are Available

...
\Longman\LaravelLodash\SelfDiagnosis\Checks\FilesystemsAreAvailable::class => [
    'disks' => [
        'local',
        's3',
    ],
],
...

Elasticsearch Health Check

...
\Longman\LaravelLodash\SelfDiagnosis\Checks\ElasticsearchCanBeAccessed::class => [
    'client' => ElasticSearchClient::class,
],
...

Php Ini Options Check

...
\Longman\LaravelLodash\SelfDiagnosis\Checks\PhpIniOptions::class => [
    'options' => [
        'upload_max_filesize' => '>=128M',
        'post_max_size'       => '>=128M',
        'memory_limit'        => '>=128M',
        'max_input_vars'      => '>=10000',
        'file_uploads'        => '1',
        'disable_functions'   => '',
    ],
],
...

Php Ini Options Check

...
\Longman\LaravelLodash\SelfDiagnosis\Checks\RedisCanBeAccessed::class => [
    'default_connection' => true,
    'connections'        => ['sessions'],
],
...

Servers Are Pingable Check

...
\Longman\LaravelLodash\SelfDiagnosis\Checks\ServersArePingable::class => [
    'servers' => [
        [
            'host'    => config('app.url'),
            'port'    => 80,
            'timeout' => 1,
        ],
        [
            'host'    => 'sqs.eu-west-1.amazonaws.com',
            'port'    => 443,
            'timeout' => 3,
        ],
        [
            'host'    => 'www.googleapis.com',
            'port'    => 443,
            'timeout' => 3,
        ],
    ],
],
...

Horizon is running

...
\Longman\LaravelLodash\SelfDiagnosis\Checks\HorizonIsRunning::class,
...

Testing Helpers

The Longman\LaravelLodash\Testing\Response class extends Laravel's TestResponse with assertions for JSON envelopes of the shape {status, message, data, meta}. Wire it into your base test case by overriding createTestResponse():

use Longman\LaravelLodash\Testing\Response;

protected function createTestResponse($response, $request)
{
    return Response::fromBaseResponse($response, $request);
}

Register your application's envelope shapes once (for example in the base test case's setUp()):

Response::setSuccessResponseStructure(['status', 'message', 'data']);
Response::setErrorResponseStructure(['status', 'message']);

Structure assertions validate data as a single item or as a collection. Collection assertions validate every row and fail with readable messages when data is missing, empty, or not a list. With exact: true any missing or unexpected extra key inside data (and inside meta.pagination when pager or cursor meta is included) fails the test, while envelope keys outside those subtrees stay loosely checked:

$response->assertJsonDataItemStructure(['id', 'type', 'attributes' => ['name']], exact: true);
$response->assertJsonDataCollectionStructure($structure, includePagerMeta: true, exact: true);

Reusable structures live in a DataStructuresProvider subclass, one static property per structure:

use Longman\LaravelLodash\Testing\DataStructuresProvider;

class AppStructures extends DataStructuresProvider
{
    protected static array $userStructure = ['id', 'type', 'attributes' => ['name']];
    protected static array $roleStructure = ['id', 'type', 'attributes' => ['title']];
}

$structure = AppStructures::getUserStructure(['roles[]']);

Relation includes accept dots for linear chains and nested arrays for branching. Each segment is name or name[] (collection), optionally followed by :StructureName when the structure name differs from the relation key. Overlapping declarations merge, regardless of order:

AppStructures::getUserStructure([
    'program:AdminProgram' => [
        'faculty:AdminFaculty',
        'department:AdminDepartment',
    ],
    'roles[]',
    'roles[].admins[].item',
]);

The legacy '[roles]' wrapper syntax is not supported; declarations like it throw an InvalidArgumentException with a migration hint (write 'roles[]' instead).

The combined resource assertions tie a response to the exact records it should contain. Register the provider once, then a single call checks the structure (exact by default), the wire type (defaults to the structure name, override with type:), and the record identity. Expected ids derive from (string) $model->getKey(), or getUidString() for UUID-primary models:

Response::setDataStructuresProvider(AppStructures::class);

$response->assertJsonDataResource('User', $user, relations: ['roles[]']);

$response->assertJsonDataResources('User', $users);                  // exactly these ids, any order
$response->assertJsonDataResources('User', $users, ordered: true);   // and in this sequence
$response->assertJsonDataResources('User', []);                      // proves the response is empty

On paginated endpoints the id comparison covers the current page. Resources with conditional fields can opt out of exactness with exact: false.

TODO

write more tests and add more features

Troubleshooting

If you like living on the edge, please report any bugs you find on the laravel-lodash issues page.

Contributing

Pull requests are welcome. See CONTRIBUTING.md for information.

License

Please see the LICENSE included in this repository for a full copy of the MIT license, which this project is licensed under.

Credits

Full credit list in Contributors

longman/laravel-lodash 适用场景与选型建议

longman/laravel-lodash 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 96.89k 次下载、GitHub Stars 达 97, 最近一次更新时间为 2017 年 10 月 07 日, 在 PHP 生态内属于活跃度较高的组件。

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

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

围绕 longman/laravel-lodash 我们能提供哪些服务?
定制开发 / 二次开发

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

  • 总下载量: 96.89k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 97
  • 点击次数: 38
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 97
  • Watchers: 4
  • Forks: 11
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2017-10-07