承接 honeystone/context 相关项目开发

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

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

honeystone/context

最新稳定版本:2.0.0

Composer 安装命令:

composer require honeystone/context

包简介

Application context manager for Laravel.

README 文档

README

Static Badge GitHub License Latest Version on Packagist Packagist Dependency Version Packagist Dependency Version Static Badge

Important

Rename Incoming: honeystone/contexthoneystone/tenancy

Given the introduction of Laravel's own context package and the inevitable confusion around the name, we will soon be renaming this package to better reflect its purpose and avoid confusion.

We developed honeystone/context for managing the application context in multi-tenant applications. It provides a simple, fluent API for intializing, extending and switching contexts using 'context resolvers'. In addition, contexts are automagically available in queued jobs and can be used to scope Eloquent models.

This package was developed several years ago for our own multi-tenant applications. We've recently decided to release it in the hope it will be useful to the wider Laravel community. We're open to contributions, feedback and constructive criticism.

Getting started

Start by reading the short blog post that demonstrates how to use this package in multi-tenant application.

Support us

Support Us

We are committed to delivering high-quality open source packages maintained by the team at Honeystone. If you would like to support our efforts, simply use our packages, recommend them and contribute.

If you need any help with your project, or require any custom development, please get in touch.

Installation

composer require honeystone/context

Usage

A typical use-case would be to declare and initialize the context in your middleware. You can then access the context data like this:

$team = context('team');
$project = context('project');

Defining the context

Contexts need to be defined before they can be resolved:

context()->define()
    ->require('team', Team::class)
    ->require('project', Project::class);

These context definitions are 'required', so if they cannot be resolved a CouldNotResolveRequiredContextException will be thrown. For undefined contexts, a UndefinedContextException will be thrown.

You can also define 'accepted', but not 'required' contexts:

context()->define()
    ->accept('team', Team::class)
    ->accept('project', Project::class);

Or accept / require based on the existence of another context:

context()->define()
    ->require('team', Team::class)
    ->requireWhenProvided('team', 'project', Project::class); //Or acceptWhenProvided

Initializing the context

To initialize the context, you'll need to provide a resolver:

context()->initialize(new MyResolver());

Here's an example resolver class:

<?php

declare(strict_types=1);

namespace App\Context\Resolvers;

use Honeystone\Context\ContextResolver;

class MyResolver extends ContextResolver
{
    public function __construct(
        private ?Team = null,
        private ?Project = null,
    ) {}

    public function resolveTeam(): Team
    {
        //your resolution logic

        return $this->team;
    }

    public function resolveProject(): Project
    {
        //your resolution logic

        return $this->project;
    }

    public static function deserialize(array $data): static
    {
        //you must also declare a deserialization method,
        //to reinstate the serialised data

        return new static($team, $project);
    }
}

You can customize serialization logic like this:

class MyResolver extends ContextResolver
{
    //...

    public function serializeTeam(Team $team): int
    {
        return $team->id;
    }
}

You can validate the integrity of a resolved context like this:

class MyResolver extends ContextResolver
{
    //...

    public function checkProject(
        DefinesContext $definition,
        Project $project,
        array $resolved,
    ): bool {
        return $project->id === $resolved['team']->project_id;
    }
}

You can also reinitialize or deinitialize the current context:

context()->reinitialize(new AnotherResolver());

context()->deinitialize();

Extending the context

The current context can be extended using another resolver:

context()->define()->accept('site', Site::class);

context()->extend(new AnotherResolver());

Temporarily switching the context

Using a closure:

context()->initialize(new MyResolver());

context()->temporarilyInitialize(new AnotherResolver())
    ->run(function () {
        //do something
    });

Using the start and end methods:

context()->initialize(new MyResolver());

$tmpContext = context()->temporarilyInitialize(new AnotherResolver());

$tmpContext->start();

//do something

$tmpContext->end();

Events and receivers

The Honeystone\Context\Events\ContextChanged event is dispatched whenever the context is changed.

You can also specify receivers to be notified when individual context values are set:

context()->receive('team', new MyReceiver());

Here's an example receiver:

<?php

declare(strict_types=1);

namespace App\Context\Receivers;

use Honeystone\Context\Contracts\ReceivesContext;

class TeamReceiver implements ReceivesContext
{
    public function receiveContext(string $name, ?object $context): void
    {
        //process received context
    }
}

Scoping models using the context

You can use the current context to scope your Eloquent models.

Here's an example:

<?php

declare(strict_types=1);

namespace App\Models;

use Honeystone\Context\Models\Concerns\BelongsToContext;
use Illuminate\Database\Eloquent\Model;

class Project extends Model
{
    use BelongsToContext;

    protected static array $context = ['team'];

    //optionally specify context aliases
    protected static array $context = ['team' => 'my_team'];

    //optionally configure a context foreign key
    protected function getTeamContextForeignKey(Team $team): string
    {
        return 'my_team_id'; //the default is generated like this
    }

    //optionally configure a context owner id
    protected function getTeamContextOwnerId(Team $team): int
    {
        return $context->id; //defaults to the id prop
    }

    //optionally configure the relationship name
    protected function getTeamContextRelationName(Team $team): string
    {
        return 'my_team'; //the default is generated like this
    }
}

Known issues

  • Tests could do with improvement

Laravel's "context"

When this solution was created, Laravel context did not exist. The function name collision is unfortunate, but not really a problem. You'll just need to make sure you import the function.

use function Honeystone\Context\context;

Whilst the name will invite comparison, these packages are solving different problems. Laravel context is a generic global data store. This package is specifically for resolving context objects with more complex logic and using them to scope the application, for example in a multi-tenancy application.

Changelog

A list of changes can be found in the CHANGELOG.md file.

License

MIT © George Palmer, Honeystone Consulting Ltd

honeystone/context 适用场景与选型建议

honeystone/context 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 16 次下载、GitHub Stars 达 41, 最近一次更新时间为 2024 年 07 月 20 日, 在 PHP 生态内属于活跃度较高的组件。

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

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

围绕 honeystone/context 我们能提供哪些服务?
定制开发 / 二次开发

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

  • 总下载量: 16
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 41
  • 点击次数: 15
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 41
  • Watchers: 3
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-07-20