Skip to content

Data

Одна из центральных философий разработки в runway состоит в том, чтобы избавиться от работы с массивами данных и работать только с объектами.

Работа с массивами

Работа с массивами данных неудобна прежде всего тем, что программисту необходимо точно знать структуру массива. При этом также необходимо контролировать и доступ к "ключам" массива. Если при обращении к элементу массива допущена ошибка - программист может это узнать только в процессе тестирования.

Пример
php
$arData = array(
            'name'=>'test',
            'picture_src'=>'/upload/some-path/image.jpg',
            'description'=>'<b>Some html text</b>',
            'price'=>3000
          );
.....

echo $arData['discription']; //Допущена ошибка в ключе массива

Работа с объектами

"Перевод" массивов данных (В общем случае получаемых из БД) в объекты данных позволяет контролировать обращения к полям сущности

Пример
php
namespace Realweb\Api\Module\Test\Model;
/**
 * Class \Realweb\Api\Module\Test\Model\Entity
 *
 * @method string getName()
 * @method string getPictureSrc()
 * @method string getDescription()
 * @method int getPrice()
 */
class Entity extends \Realweb\Api\Model\Data\Data
{
      public function __construct(array $arData = array())
      {
        $this->_data = $arData;
      }

      public function getData(): array
      {
        return $this->_data;
      }
}
$obEntity = new \Realweb\Api\Module\Test\Model\Entity(array(
            'name'=>'test',
            'picture_src'=>'/upload/some-path/image.jpg',
            'description'=>'<b>Some html text</b>',
            'price'=>3000
          ));
.....

echo $obEntity->getDescription(); //Ошибку допустить невозможно, т.к вызов несуществующего метода вызовет остановку работы приложения

Основной контейнер данных

Основным контейнером данных для всех сущностей realweb.api является класс \Realweb\Api\Model\Data\Data. В конструктор подается массив данных, который впоследствии сформирует поля объекта.

Для доступа к полям объекта имеет встроенные магические методы по названиям полей (ключи массива)

  • get* - получение значения поля, если оно есть
  • set* - установка значения поля (даже если поле не существует изначально - это не вызовет ошибку)
  • has* - проверка на существование поля
  • is* - проверка поля на истину
Пример
php
class Entity extends \Realweb\Api\Model\Data\Data
{
    public function __construct(array $arData = array())
    {
        $this->_data = $arData;
    }
    public function getData(): array
    {
        return $this->_data;
    }

}
$obSomeEntity = new Entity(array(
                            'name'=>'test',
                            'picture_src'=>'/upload/some-path/image.jpg',
                            'description'=>'<b>Some html text</b>',
                            'price'=>3000,
                            'is_product'=>1,
                          ));

$obSomeEntity->getName(); //Получение значения поля name
$obSomeEntity->getTitle(); //Вызовет Exception - такого поля нет
$obSomeEntity->setName('New Name'); //Установка значения поля name
$obSomeEntity->setTitle('New Title'); //Установка значения поля title
$obSomeEntity->getPictureSrc('New Name'); //нижнее подчеркивание превращается в camelCase
$obSomeEntity->hasSubTitle(); //Проверка на наличие поля sub_title
$obSomeEntity->isProduct(); //true/false

Для вывода сущности на фронтенд рекомендуется использовать метод toJson()

Сущность БД

Все сущности, которые хранятся в БД "оборачиваются" в экземпляр класса \Realweb\Api\Model\Data\Entity, который наследуется от \Realweb\Api\Model\Data\Data.

Имеет встроенный метод сохранения в БД. Сохраняются поля, возвращаемые статическим методом getFields класса Базы Данных этой сущности.

Наследуемый класс должен реализовывать метод _getDatabase (Необходимо для сохранения сущности в БД).

Класс имеет ряд часто используемых методов:

  • public static function cleanFromAliases(array &$arData, string $strAlias = "UALIAS_"): void - очищение данных сущностей от алиасов запроса. Полезно, если сущность сохраняется в кеш (меньше полей - меньше размер кеша)
  • public static function getByAlias(array &$arData, string $strAlias): array - получение (и очищение) данных, не относящихся к сущности.
  • public function setRefreshData(bool $bRefresh = true): self - полезно вызвать перед сохранением сущности, если дальнейшая работа с сущностью не планируется и данные в ней уже не нужны
  • public function save(): bool - сохранение сущности в БД (Существующая сущность обновится, новая - добавится)
  • public function delete(): bool - удаление сущности из БД
  • public function isExist(): bool - проверка на существование записи в БД
Пример
php
class Database extends \Realweb\Api\Model\User\Database
{
....
    public static function getQuery(?Pagination $obNav = null): Query
    {
        //В запросе будут содержаться поля другой таблицы
        $obQuery = parent::getQuery()
                    ->setSelect(self::getFields())
                    ->addSelect("PHONE_AUTH.PHONE_NUMBER", "PHONE_NUMBER")
                    ->registerRuntimeField(
                              "SOME_FIELD",
                              (new \Bitrix\Main\ORM\Fields\Relations\Reference(
                              "SOME_FIELD",
                              \Bitrix\Sale\Internals\FuserTable::class,
                              \Bitrix\Main\ORM\Query\Join::on('this.ID', 'ref.USER_ID')
                              ))->configureJoinType(\Bitrix\Main\ORM\Query\Join::TYPE_LEFT),
                    )
                    ->addSelect($strFUserIdField . '.ID', 'F_USER_ID')
                    ->addSelect($strFUserIdField . '.CODE', 'F_USER_CODE')
                    ->addSelect($strFUserIdField . '.DATE_INSERT', 'F_USER_DATE_INSERT')
                    ->addSelect($strFUserIdField . '.*', 'F_USER_')//Получение вообще всех полей с префиксом F_USER_
        ;

        return $obQuery;
    }
}
class Entity extends \Realweb\Api\Model\User\Entity
{
    private ?\Realweb\Api\Module\User\Model\Fuser\Entity $_f_user = null;

    public function setData(?array $arData = null): self
    {
        //Очищаем от лишних данных, если они там есть
        self::cleanFromAliases($arData);

        //В $arData содержатся поля F_USER_ID, F_USER_CODE, F_USER_DATE_INSERT
        $arFuser = self::getByAlias($arData,"F_USER_");

        //Теперь в $arFuser содержатся поля ID, CODE, DATE_INSERT, а в $arData теперь их нет
        $this->fuser = new \Realweb\Api\Module\User\Model\Fuser\Entity($arFuser);

        return parent::setData($arData);
    }
}