shadoll/lantana

Library for jStorage

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

README

Latest Stable Version pipeline status coverage report License

Library for jStorage

Install

composer require shadoll/lantana

ChangeLog:

Версия (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 добавлен метод (возвращает родную модель JS интерфейса BeMainGuardModel):
    /**
     * @return BeMainGuardModel
     * */
    public function getJSModel();
    

При необходимости добавления новых функций - опишите их в файле src/Extensions/Guard/guardFunctions.php, прежде ознакомтесь с небольшими рекомендациями в header.

Версия (1.2.2)

НОВОЕ:

10.09.2019

  1. Дополнительные данные Lantana\Core\Exceptions\LantanaException из метода getData(): mixed возвращает обект интерфейса Lantana\Core\Contracts\BeAdditional или null если данных нету. В данный момент реализовано для обработки при запросе storeall, updateall, deleteall, возвращаются соответственно Lantana\Core\Exceptions\Additionals\Models\StoreAllData, Lantana\Core\Exceptions\Additionals\Models\UpdateAllData, Lantana\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. Добавлен метод __toString() и __isset в базовую модель Model,
  5. Добавленны методы для Relations (трейт 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) (protected)
  6. Класс Lantana\Core\Request\Request при запросе вместо form_params использует json,
  7. Добавлен пакет Lantana\Extensions\Guard:
    • модели которые используются в Guard должны реализовать интерфейс Lantana\Extensions\Guard\Contracts\BeMainGuardModel (в данный момент это касается только JSSharedCustomersServices, JSSharedApikeys, JSSharedPeriods, JSSharedAmocrm),

Core

Class Model (abstract)

Методы:

  1. Публичные (Работа с моделью):

    • save() - Сохранение модели (создание, обновление) (return bool):

       // store
       $shared = new JSSharedCustomersServices();
       $shared->field = 'value';
       $shared->save();
       // update
       $shared = JSSharedCustomersServices::find('uuid');
       $shared->field = 'value';
       $shared->save();
      
    • delete() - Удаление модели (return bool):

       $shared = JSSharedCustomersServices::find('uuid');
       $shared->delete();
      
    • get() (alias all()) - Получение коллекции моделей (return Lantana\Extensions\Collection\Collection):

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

      Метод all() помимо обычного вызова так же имеет статический вызов (в примере показано).

    • find('uuid') (alias 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 = []) - Метод конструктора запросов для выборки определенных полей модели(ей) (return T extends Lantana\Model):

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

      Метод select($fields = []) помимо обычного вызова так же имеет статический вызов (в примере показано).

    • where($field, $value) (alias findByFieldValue($field, $value)) - Метод конструктора запросов для добавления условий выборки (фильтра) (return 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) - Метод конструктора запросов для добавления условий связаных сущностей один к одному (return 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) - Метод конструктора запросов для добавления условий связаных сущностей один к многим (return 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 то что первым параметром передается строковое представление названия класса модели которую нужно привязать) (return 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 то что первым параметром передается строковое представление названия класса модели которую нужно привязать) (return 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) - Метод получения связаных сущностей один к многим (расширяемый в конкретном классе модели) (особенность метода в том что он лениво загружает и отдает данные, т.е. если связаная коллекция существеут вернет ее, если не существует - загрузит с сервера и вернет) (return \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) - Метод получения связаных сущностей один к одному (расширяемый в конкретном классе модели) (особенность метода в том что он лениво загружает и отдает данные, т.е. если связаная сущность существеут вернет ее, если не существует - загрузит с сервера и вернет) (return T extends Lantana\Model):

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

      Примеры методов hasMany и belongsTo можно посмотреть в классах Lantana\Models\{JSSharedCustomersServices, JSSharedApikeys, JSSharedAmocrm, JSSharedPeriods}

Class \Lantana\Extensions\Collection\Collection

Методы:

Методов очень много см. Illuminate\Support\Collection;

Работа с сервисом \Lantana\Extensions\Guard\GuardService

Для простого внедрения сервиса в фреймворки laravel и Lumen:

  1. Зарегистрировать Lantana\Extensions\Guard\Lara\Providers\ServiceProvider в приложении (Laravel -> config/app.php в секции providers добавить Lantana\Extensions\Guard\Lara\Providers\ServiceProvider::class,) (Lumen -> bootstrap/app.php добавить $app->register(Lantana\Extensions\Guard\Lara\Providers\ServiceProvider::class);),
  2. Сервис можете инициализировать самому в любом месте приложения или добавить уже существующий Middleware Lantana\Extensions\Guard\Lara\Middlewares\Authenticate который сам загрузит сервис и может загрузить дополнительные данные для вашего приложения (если Lantana\Extensions\Guard\Lara\Middlewares\Authenticate не устраивает можете создать свой посредник наследуя Lantana\Extensions\Guard\Lara\Middlewares\BaseGuard и определить логику в методе isAuth()). Добавление Middleware в приложение - (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_TABLES и APP_CONFIG_MODELS как описано выше.

Версия с коллекцией (1.0.1)

НОВОЕ:

  1. Все модели автоматически серриализуются в JSON (interface JsonSerializable),
  2. Общая логика базовой модели разнесена по трейтам (в пакете Lantana\Core\Helpers).
  3. Классы Data, Request, RequestData, RequestParams вынесены в пакет Lantana\Core\Request.
  4. Создан класс исключений Core\Exceptions\LantanaException.
  5. Обеденил базовые модели Base и Model в общую Model, (модель Model абстрактная в целях безопасности).
  6. удалены методы toArray(), current(), next(), key(), valid(), rewind() (набность в них пропала).
  7. Методы where(), select(), all(), find() так же могут вызываться в статическом контексте (удобно при получении моделей (коллекций) пример JSSharedCustomersServices::all() вернет обект коллекции Lantana\Extensions\Collection\Collection, JSSharedCustomersServices::where('customer_id', '1')->get() вернет коллекцию с условием фильтра) -- условие файл .env должен существовать так как это требует конструктор базовой модели.
  8. Модель обязана реализовать интерфейс Lantana\Extensions\Collection\Contracts\BeCollectionModel чтобы быть в коллекции (пока не очень оправдвно, возможно в целях безопасности).