shadoll/lantana

v3.2.8 2020-07-28 11:53 UTC

README

Latest Stable Version pipeline status coverage report License

jStorage 的库

安装

composer require shadoll/lantana

变更日志

版本 (1.2.4) 全局函数助手

新增

14.09.2019

  1. 在全局作用域中添加了2个函数助手,以便更容易访问服务。文件 src/Extensions/Guard/guardFunctions.php 通过 composer 连接(如果库已经集成,可能需要更新自动加载文件 composer dump-autoload
    • lGuard() - 返回当前上下文 \Lantana\Extensions\Guard\GuardService(在调用函数之前,服务必须已经加载,下面将说明),类似于 \Lantana\Extensions\Guard\GuardService::context()
    • lCustomer() - 返回模型绑定助手 \Lantana\Models\JSSharedCustomersServices 和接口对象 \Lantana\Extensions\Guard\Contracts\BeSharedCustomerServices 目前这是 \Lantana\Extensions\Guard\Models\SharedCustomerServices(服务 \Lantana\Extensions\Guard\GuardService 必须已加载)。
  2. 在接口 \Lantana\Extensions\Guard\Contracts\BeGuard 中添加了一个方法(返回接口 BeMainGuardModel 的原生模型 JS
    /**
     * @return BeMainGuardModel
     * */
    public function getJSModel();
    

如果需要添加新的功能,请在文件 src/Extensions/Guard/guardFunctions.php 中描述它们,在此之前请阅读 header 中的简要说明。

版本 (1.2.2)

新增

10.09.2019

  1. 从方法 getData(): mixedLantana\Core\Exceptions\LantanaException 中返回额外的数据,返回接口对象 Lantana\Core\Contracts\BeAdditionalnull 如果没有数据。目前实现用于处理请求 storeallupdatealldeleteall,分别返回 Lantana\Core\Exceptions\Additionals\Models\StoreAllDataLantana\Core\Exceptions\Additionals\Models\UpdateAllDataLantana\Core\Exceptions\Additionals\Models\DestroyAllData,我们可以从中获取相应的数据集合。

      $collect = JSSharedCustomersServices::all();
    
      $newCollectDestroy = $collect->filter(function ($item) {
          return $item->code == 'almond';
      });
    
      // получения дополнительных данных во время исключения
      try {
          $newCollectDestroy->destroy();
      } catch (\Lantana\Core\Exceptions\LantanaException $exception) {
          /**
           * @var Lantana\Core\Exceptions\Additionals\Models\DestroyAllData $destroyAllData
           */
          $destroyAllData = $exception->getData();
    
          echo $destroyAllData->deleted->toJson();
    
          $destroyAllData->skipped->each(function ($item) {
              // any action
          });
    
          $destroyAllData->not_found->isEmpty();
      }
    

09.09.2019

  1. 添加了克隆模型的功能
     $modelClone = clone $modelOriginal;
    
  2. 将方法 toArray() 返回到基本模型
  3. Lantana\Core\Exceptions\LantanaException 中添加了2个新方法 setData($data)getData(): mixed 以在异常期间获取额外数据(例如在大量创建、更新、删除模型时 - 当键 $strict=true 时,可以查看哪些模型与 JStorage 有冲突),
  4. 添加了用于与集合进行批量操作的方法

    • 在基本模型 Lantana\Model
      • static store(Lantana\Extensions\Collection\Collection $collection, bool $strict = true): Lantana\Extensions\Collection\Collection,
      • static update(Lantana\Extensions\Collection\Collection $collection, bool $strict = true): Lantana\Extensions\Collection\Collection,
      • static destroy(Lantana\Extensions\Collection\Collection $collection, bool $strict = true): Lantana\Extensions\Collection\Collection,
    • 在集合类 Lantana\Extensions\Collection\Collection
      • store(bool $strict = true): Lantana\Extensions\Collection\Collection,
      • update(bool $strict = true): Lantana\Extensions\Collection\Collection,
      • destroy(bool $strict = true): Lantana\Extensions\Collection\Collection,
     $collect = JSSharedCustomersServices::all();
    
     $newCollectStore = $collect->map(function ($item) {
         return clone $item;
     });
    
     $newCollectUpdate = $collect->map(function ($item) {
         $item->code = 'any-code';
         return $item;
     });
    
     $newCollectDestroy = $collect->filter(function ($item) {
         return $item->code == 'almond';
     });
    
     // Массовое создание
     // используя статический метод модели
     // (обязательно модель должна быть того же класса что и модели внутри коллекции)
     JSSharedCustomersServices::store($newCollectStore);
     // или создание напрямую из коллекции
     $newCollectStore->store();
    
     // вторым параметром можно передать ключ при котором будет
     // применено нестрогие условия создания моделей
     // Если ключ будет true - JStrorage не создаст ниодную модель в базе
     // если хотья бы одна не удовлетворит правилам массового сохранения
     // В результате ошибки будет брошено исключение. В методе `getData()` `LantanaException`
     // можно посмотреть список моделей которые могли бы быть сохранены и список отброшеных моделей
     // Если ключ будет false - JStrorage создаст модели которые валидны для создания
     //
     // Все эти условия так же относятся и к массовом обновлении и массовом удалении моделей
     JSSharedCustomersServices::store($newCollectStore, false); // по умолчанию true
     $newCollectStore->store(false); // по умолчанию true
    
     // Массовое обновление
     // используя статический метод модели
     // (обязательно модель должна быть того же класса что и модели внутри коллекции)
     JSSharedCustomersServices::update($newCollectUpdate);
     // или обновление напрямую из коллекции
     $newCollectUpdate->update();
    
     // Массовое удаление
     // используя статический метод модели
     // (обязательно модель должна быть того же класса что и модели внутри коллекции)
     JSSharedCustomersServices::destroy($newCollectDestroy);
     // или удаление напрямую из коллекции
     $newCollectDestroy->destroy();
    
     // получения дополнительных данных во время исключения
     try {
         $newCollectDestroy->destroy();
     } catch (\Lantana\Core\Exceptions\LantanaException $exception) {
         print_r($exception->getData());
     }
    
  5. 优化了抛出异常的机制(所有异常都在库外处理)。

07.09.2019

  1. 所有在 版本 (1.0.1) 中列出的内容,
  2. 改进了创建带有嵌套模型和/或模型集合的集合的机制(特例 Lantana\Core\Helpers\CollectHelper),
  3. 删除了基本模型的方法 getFromEmbedded()(因为 _embedded 将自动存储模型或模型集合,见本版本第 2 点),
  4. 在基本模型 Model 中添加了方法 __toString()__isset
  5. 添加了用于关系的辅助方法(特例 Lantana\Core\Helpers\RelationsHelper
    • withModel(string $model, string $foreign = null) (public)
    • belongsToModel(string $model, string $local_key = null) (public)
    • hasMany(string $class, string $local_key = null) (protected)
    • belongsTo(string $class, string $foreign = null) (受保护的)
  6. Lantana\Core\Request\Request 在请求中,而不是使用 form_params,使用 json,
  7. 添加了包 Lantana\Extensions\Guard
    • 在 Guard 中使用的模型应该实现接口 Lantana\Extensions\Guard\Contracts\BeMainGuardModel(目前这仅适用于 JSSharedCustomersServicesJSSharedApikeysJSSharedPeriodsJSSharedAmocrm),

Core

模型类 (抽象)

方法

  1. 公共的(与模型交互)

    • save() - 保存模型(创建或更新)(返回 bool)

       // store
       $shared = new JSSharedCustomersServices();
       $shared->field = 'value';
       $shared->save();
       // update
       $shared = JSSharedCustomersServices::find('uuid');
       $shared->field = 'value';
       $shared->save();
      
    • delete() - 删除模型 (返回 bool)

       $shared = JSSharedCustomersServices::find('uuid');
       $shared->delete();
      
    • get() (同义词 all()) - 获取模型集合 (返回 Lantana\Extensions\Collection\Collection)

       $shared = new JSSharedCustomersServices::where('field', 'value')->get();
       $sharedAll = JSSharedCustomersServices::all();
      

      方法 all() 除了普通调用外,还有静态调用(示例中显示)。

    • find('uuid') (同义词 findByUUID('uuid')) - 根据UUID获取模型 (return T extends Lantana\Model)

       // не очень красиво но возможность есть и так получить модель
       $shared1 = new JSSharedCustomersServices();
       $shared1->findByUUID('uuid');
       // так элегантнее
       $shared2 = JSSharedCustomersServices::find('uuid');
      

      方法 find('uuid') 除了普通调用外,还有静态调用(示例中显示)。

    • first()last() - 获取第一个或最后一个模型 (return T extends Lantana\Model)

      $shared1 = JSSharedCustomersServices::where('field', 'value')->first();
      $shared2 = JSSharedCustomersServices::where('field', 'value')->last();
      
    • select($fields = []) - 用于选择特定字段的方法(返回 T extends Lantana\Model)

      $sharedModel = JSSharedCustomersServices::select(['field1', 'field2'])->first();
      $sharedCollect = JSSharedCustomersServices::where('field', 'value')->select(['field1', 'field2'])->get();
      

      方法 select($fields = []) 除了普通调用外,还有静态调用(示例中显示)。

    • where($field, $value) (同义词 findByFieldValue($field, $value)) - 用于添加选择条件的方法(返回 T extends Lantana\Model)

      $sharedModel = JSSharedCustomersServices::where('field', 'value')->where('field2', 'value2')->last();
      $sharedCollect = JSSharedCustomersServices::where('field', 'value')->get();
      

      方法 where($field, $value) 除了普通调用外,还有静态调用(示例中显示)。

    • getEntity() - 获取当前实体的字符串表示方法,

    • getBy[实体名称]() - 瓦斯说了(细节忘了),

    • with(string $entity, string $foreign = null) - 用于添加与关联实体 一对一 的条件的方法(返回 T extends Lantana\Model)

      $sharedModel = JSSharedCustomersServices::where('field', 'value')->with('shared-apikeys')->first();
      $sharedCollect = JSSharedCustomersServices::where('field', 'value')->with('shared-apikeys')->with('shared-periods')->get();
      
    • belongs($entity, $local_key = null) - 用于添加与关联实体 一对多 的条件的方法(返回 T extends Lantana\Model)

      $sharedModel = JSSharedCustomersServices::where('field', 'value')->belongs('almond-configs')->first();
      $sharedCollect = JSSharedCustomersServices::where('field', 'value')->belongs('almond-configs')->belongs('other-entity')->get();
      
    • withModel(string $model, string $foreign = null) - 用于添加与关联实体 一对一 的条件的方法(与方法 with 的区别在于第一个参数是传递要绑定模型的字符串表示)(返回 T extends Lantana\Model)

      $sharedModel = JSSharedCustomersServices::where('field', 'value')->withModel('Lantana\Models\JSSharedApikeys')->first();
      $sharedCollect = JSSharedCustomersServices::where('field', 'value')->withModel('Lantana\Models\JSSharedApikeys')->withModel('App\Models\JSOtherClass')->get();
      
    • belongsToModel(string $model, string $local_key = null) - 用于添加与关联实体 一对多 的条件的方法(与方法 belongs 的区别在于第一个参数是传递要绑定模型的字符串表示)(返回 T extends Lantana\Model)

      $sharedModel = JSSharedCustomersServices::where('field', 'value')->belongsToModel('Lantana\Models\JSAlmondConfigs')->first();
      $sharedCollect = JSSharedCustomersServices::where('field', 'value')->belongsToModel('Lantana\Models\JSAlmondConfigs')->belongsToModel('App\Models\JSOtherClass')->get();
      
  2. 受保护的方法(用于功能扩展)

    • hasMany(string $class, string $local_key = null) - 获取与关联实体 一对多 的方法(在特定模型类中可扩展)(该方法的特点是它延迟加载和返回数据,即如果关联的集合存在,则返回它,如果不存在,则从服务器加载并返回)(返回 \Lantana\Extensions\Collection\Collection)

      class JSSharedApikeys extends Model implements BeCollectionModel
      {
      
            public function sharedCustomersServices()
            {
                return $this->hasMany('Lantana\Models\JSSharedCustomersServices');
            }
      }
      
      // гдето в коде
      $sharedCustomersServicesModel = JSSharedApikeys::find('uuid')->sharedCustomersServices();
      
    • belongsTo(string $class, string $foreign = null) - 获取与关联实体 一对一 的方法(在特定模型类中可扩展)(该方法的特点是它延迟加载和返回数据,即如果关联的实体存在,则返回它,如果不存在,则从服务器加载并返回)(返回 T extends Lantana\Model)

      class JSSharedCustomersServices extends Model implements BeCollectionModel
      {
      
            public function sharedApikeys()
            {
                return $this->belongsTo('Lantana\Models\JSSharedApikeys');
            }
      }
      
      // гдето в коде
      $sharedApikeysModel = JSSharedCustomersServices::find('uuid')->sharedApikeys();
      

      有关 hasManybelongsTo 方法的示例,请查看类 Lantana\Models\{JSSharedCustomersServices, JSSharedApikeys, JSSharedAmocrm, JSSharedPeriods}

类 \Lantana\Extensions\Collection\Collection

方法

有很多方法,请参阅 Illuminate\Support\Collection;

处理服务 \Lantana\Extensions\Guard\GuardService

对于简单地将服务集成到 laravel 和 Lumen 框架中

  1. 在应用程序中注册 Lantana\Extensions\Guard\Lara\Providers\ServiceProvider(laravel -> 在 config/app.phpproviders 部分中添加 Lantana\Extensions\Guard\Lara\Providers\ServiceProvider::class,)(Lumen -> 在 bootstrap/app.php 中添加 $app->register(Lantana\Extensions\Guard\Lara\Providers\ServiceProvider::class);),
  2. 您可以在应用程序的任何位置自行初始化此服务,或者添加现有的中间件 Lantana\Extensions\Guard\Lara\Middlewares\Authenticate,该中间件将自动加载服务,并可以为您的应用程序加载额外的数据(如果 Lantana\Extensions\Guard\Lara\Middlewares\Authenticate 不符合要求,您可以创建自己的中间件,通过继承 Lantana\Extensions\Guard\Lara\Middlewares\BaseGuard 并在方法 isAuth() 中定义逻辑)。将中间件添加到应用程序中 - (Laravel -> App\Http\Kernel$middleware 属性用于所有路由或 $routeMiddleware 用于特定路由)

        protected $middleware = [
             \App\Http\Middleware\CheckForMaintenanceMode::class,
             \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
             \App\Http\Middleware\TrimStrings::class,
             \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
             \App\Http\Middleware\TrustProxies::class,
             \Barryvdh\Cors\HandleCors::class,
    
             \Lantana\Extensions\Guard\Lara\Middlewares\Authenticate::class, // <- тут
         ];
    
         protected $routeMiddleware = [
             'auth' => \App\Http\Middleware\Authenticate::class,
             'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
             'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
             'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
             'can' => \Illuminate\Auth\Middleware\Authorize::class,
             'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
             'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
             'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
             'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    
             'guard' => \Lantana\Extensions\Guard\Lara\Middlewares\Authenticate::class, // <- тут
         ];
    

    ) (Lumen -> bootstrap/app.php 中添加)

     // для всех роутов
     $app->middleware([
         \Lantana\Extensions\Guard\Lara\Middlewares\Authenticate::class,
     ]);
    
     // для конкретных роутов
     $app->routeMiddleware([
      'guard' => Lantana\Extensions\Guard\Lara\Middlewares\Authenticate::class,
     ]);
    

    ),

  3. 在控制器构造器、方法或其他方便的地方

     //...
     use Lantana\Extensions\Guard\GuardService;
    
     class ExampleController extends Controller
     {
          private $guardService;
    
          public function __construct(GuardService $guardService)
          {
              $this->guardService = $guardService;
          }
    
          public function index()
          {
              try {
                  $this->guardService
                    ->validApikey('apikey')
                    ->validPeriod()
                    ->validAmocrm();
    
                  // is valid, other actions
                  return 'ok';
              } catch (GuardingException $guardingException) {
                  \Log::error('#FK.SECURITY:: ' . $guardingException->getMessage());
              }
    
              return 'error';
          }
     }
    

在您的应用程序的 .env 文件中,您可以通过属性 APP_CONFIG_TABLES 指定所有要随服务初始化自动加载的实体,通过逗号(不带空格)分隔(例如 APP_CONFIG_TABLES=almond-configs,other-entity)(实体类必须位于 Lantana\Models 目录中)或 APP_CONFIG_MODELS 通过逗号(不带空格)分隔所有实体类名,这些类名也将随服务初始化自动加载(例如 APP_CONFIG_MODELS=Lantana\Models\JSAlmondConfigs,App\XYZ\JSMyModel)(相应模型类可以位于任何位置,只要满足 psr-4 规则即可)(条件 - 实体必须引用 shared-customers-services),您可以通过服务 Lantana\Extensions\Guard\GuardService 获取数据

如上所述,您可以通过 Lantana\Extensions\Guard\Lara\Middlewares\BaseGuard 或不通过它来定义服务的初始化和操作方式。

.env

为了使库更易于使用,可以在 .env 文件中添加环境变量 JSTORAGE_URI(指向 JStorage 服务器)和 JSTORAGE_APIKEY(访问 JStorage 服务器的密钥)(如果使用静态模型上下文,则此条件是强制性的),以及(如有必要)环境变量 APP_CONFIG_TABLESAPP_CONFIG_MODELS,如上所述。

带集合的版本(1.0.1)

新增

  1. 所有模型自动序列化为 JSON(实现接口 JsonSerializable)。
  2. 基础模型的通用逻辑分散在特例(在 Lantana\Core\Helpers 包中)。
  3. DataRequestRequestDataRequestParams 类已移至 Lantana\Core\Request 包。
  4. 创建了异常类 Core\Exceptions\LantanaException
  5. 将基本模型 BaseModel 合并为 ModelModel 模型是抽象的,以保障安全)。
  6. 删除了方法 toArray()current()next()key()valid()rewind()(这些功能已不再需要)。
  7. where()select()all()find() 方法也可以在静态上下文中调用(在获取模型(集合)时很方便,例如 JSSharedCustomersServices::all() 将返回对象集合 Lantana\Extensions\Collection\CollectionJSSharedCustomersServices::where('customer_id', '1')->get() 将返回满足条件过滤器的集合)-- 条件是 .env 文件必须存在,因为这需要基础模型的构造函数。
  8. 模型必须实现接口 Lantana\Extensions\Collection\Contracts\BeCollectionModel 才能在集合中(目前这并不是很有道理,可能是出于安全考虑)。