Yii2: Работа с внешним API как с локальной БД.

- Запросы к апи через интерфейс Query, $model->findOne() - легко!

- Вывод стандартных Grid-ов и других виджетов с данными из АПИ.

- Использование связей (relations) c моделями БД.

1

О проекте uniple.ru

Площадка для организации совместных закупок.

Более 1000 поставчиков.

От 1000 до 500 000 товаров у поставщика.

Апи в роли шард-кроллера

Архитектура проекта: 50% данных из апи

На проекте

  • Пользователи
  • Настройка магазина
  • Заказы

В Апи :

  • Поставщики
  • Товары

2

Окружение

Требования

  • Проект на Yii2 php 7.0 PostgreSql
  • Основная часть данных поступает от внешнего АПИ
  • Работать с данными из базы и из АПИ через одни интерфейсы
  • Использовать виджеты Yii для отображения данных полученных из апи
  • Иметь возможность расширять модели

3

Что необходимо переопределить:

4

  • \yii\db\ActiveRecord
  • \yii\db\Query
  • \yii\db\QueryBuilder

Api Adapter

Возьмем за основу

  • yii\httpclient\Client

  • сделать запрос
  • проверить код ответа
  • вернуть данные

5

Пишем свой QueryBuilder

6

Реализуем методы:

  • buildAndCondition
  • buildNotCondition
  • buildBetweenCondition
  • buildInCondition
  • buildSubqueryInCondition
  • buildLikeCondition
  • $patchs

Пишем свой Query

Реализуем методы:

  • all
  • one
  • count
  • exist
  • createModels

Обязательные переменные:

  • $className
  • $miltiple
  • Implement \yii\db\QueryInterface.
  • use \yii\db\QueryTrait

7

Пример метода all()

public function __construct($className)

{

$this->modelClass = $className;

}

public function all($db = null)

{

$result = Api::request((new QueryBuilder())->build($this, $this->class));

$items = $this->createModels($result);

return $items;

}

8

Пишем свой ActiveRecord

  • find
  • findAll
  • findOne
  • load
  • getAttributes
  • setAttributes
  • hasAttribute
  • toArray
  • primaryKey
  • Также, для возможности реализовать связи добавим:
  • hasOne
  • hasMany

9

Примеры методов

public static function find()

{

return \Yii::createObject(ApiQuery::class, [static::class]);

}

public static function findAll($conditions = [])

{

return static::find()->where($conditions)->all();

}

10

Связи через магический __get

....

if ($value instanceof ApiQuery) {

if ($value->multiple) {

return $this->$name = $value->all();

} else {

return $this->$name = $value->one();

}

}

...

11

Пример фабрики

public static function fabric($data)

{

$class = static::class;

$model = new $class();

foreach ($model::$replaceFields as $fieldName => $apiName) {

if (array_key_exists($apiName, $data)) {

$data[$fieldName] = $data[$apiName];

unset($data[$apiName]);

}

}

$model->setAttributes($data);

return $model;

}

12

Заключение

Мы используем те же методы при All и One при работе как с БД так и с АПИ

Используем все вижеты

Архитектура MVC

13

Presentation_shablone.pptx - Google Slides