Query - uniqcle/Bitrix GitHub Wiki

IWasBornInBarnaul84!

Модели

Модель Books
namespace Models;

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\ORM\Data\DataManager;
use Bitrix\Main\ORM\Fields\DateField;
use Bitrix\Main\ORM\Fields\IntegerField;
use Bitrix\Main\ORM\Fields\StringField;
use Bitrix\Main\ORM\Fields\TextField;
use Bitrix\Main\ORM\Fields\Validators\LengthValidator;

// также добавили пространства имен
use Bitrix\Main\ORM\Fields\Validator\Base,
	Bitrix\Main\ORM\Fields\Validators\RegExpValidator,
	Bitrix\Main\ORM\Fields\Relations\Reference,
	Bitrix\Main\ORM\Fields\Relations\OneToMany,
	Bitrix\Main\ORM\Fields\Relations\ManyToMany,
	Bitrix\Main\Entity\Query\Join;

use Models\WikiprofileTable as Wikiprofile;
use Models\PublisherTable as Publisher;
use Models\AuthorTable as Author;

/**
 * Class BookTable
 * @package Models
 **/

class BookTable extends DataManager
{
	/**
	 * Returns DB table name for entity.
	 *
	 * @return string
	 */
	public static function getTableName()
	{
		return 'books';
	}

	/**
	 * Returns entity map definition.
	 *
	 * @return array
	 */
	public static function getMap()
	{
		return [
			new IntegerField(
				'id',
				[
					'primary' => true,
					'autocomplete' => true,
					'title' => Loc::getMessage('_ENTITY_ID_FIELD'),
				]
			),
			new StringField(
				'name',
				[
					'validation' => [__CLASS__, 'validateName'],
					'title' => Loc::getMessage('_ENTITY_NAME_FIELD'),
				]
			),
			new TextField(
				'text',
				[
					'title' => Loc::getMessage('_ENTITY_TEXT_FIELD'),
				]
			),
			new DateField(
				'publish_date',
				[
					'title' => Loc::getMessage('_ENTITY_PUBLISH_DATE_FIELD'),
				]
			),
			new StringField(
				'ISBN',
				[
					'validation' => [__CLASS__, 'validateIsbn'],
					'title' => Loc::getMessage('_ENTITY_ISBN_FIELD'),
				]
			),
			new IntegerField(
				'author_id',
				[
					'title' => Loc::getMessage('_ENTITY_AUTHOR_ID_FIELD'),
				]
			),
			new IntegerField(
				'publisher_id',
				[
					'title' => Loc::getMessage('_ENTITY_PUBLISHER_ID_FIELD'),
				]
			),
			new IntegerField(
				'wikiprofile_id',
				[
					'title' => Loc::getMessage('_ENTITY_WIKIPROFILE_ID_FIELD'),
				]
			),
// один к одному
(new Reference('WIKIPROFILE',
	Wikiprofile::class,
	 Join::on('this.wikiprofile_id', 'ref.id')))
	->configureJoinType('inner'),

// один ко многим. Одна книга, много издателей
(new Reference('PUBLISHER',
	Publisher::class,
	 Join::on('this.publisher_id', 'ref.id')))
	->configureJoinType('inner'),

// один ко многим
(new ManyToMany('AUTHORS', Author::class))
	->configureTableName('book_author')

	->configureLocalPrimary('id', 'book_id')
	->configureLocalReference('BOOKS')

	->configureRemotePrimary('id', 'author_id')
	->configureRemoteReference('AUTHORS'),
		];
	}

	/**
	 * Returns validators for name field.
	 *
	 * @return array
	 */
	public static function validateName()
	{
		return [
			new LengthValidator(3, 50),
		];
	}


	/**
	 * Returns validators for ISBN field.
	 *
	 * @return array
	 */
	public static function validateIsbn()
	{
		return
			array(function($value) {
				$clean = str_replace('-', '', $value);
				if (preg_match('/[\d-]{13,}/', $clean))
				{
					return true;
				}
				else
				{
					return 'Код ISBN должен содержать 13 цифр.';
				}
			});
	}
}
Модель Clients
namespace Models;

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\ORM\Data\DataManager;
use Bitrix\Main\ORM\Fields\IntegerField;
use Bitrix\Main\ORM\Fields\StringField;
use Bitrix\Main\ORM\Fields\Validators\LengthValidator;

use Bitrix\Main\ORM\Fields\Validators\RegExpValidator,
	Bitrix\Main\ORM\Fields\Relations\Reference,
	Bitrix\Main\ORM\Fields\Relations\OneToMany,
	Bitrix\Main\Entity\Query\Join;

/**
 * Class ClientsTable
 **/

class HospitalClientsTable extends DataManager
{
	/**
	 * Returns DB table name for entity.
	 *
	 * @return string
	 */
	public static function getTableName()
	{
		return 'hospital_clients';
	}

	/**
	 * Returns entity map definition.
	 *
	 * @return array
	 */
	public static function getMap()
	{
		return [
			new IntegerField(
				'id',
				[
					'primary' => true,
					'autocomplete' => true,
					'title' => Loc::getMessage('CLIENTS_ENTITY_ID_FIELD'),
				]
			),
			new StringField(
				'first_name',
				[
					'validation' => function()
					{
						return[
							new LengthValidator(null, 50),
						];
					},
					'title' => Loc::getMessage('CLIENTS_ENTITY_FIRST_NAME_FIELD'),
				]
			),
			new StringField(
				'last_name',
				[
					'validation' => function()
					{
						return[
							new LengthValidator(null, 50),
						];
					},
					'title' => Loc::getMessage('CLIENTS_ENTITY_LAST_NAME_FIELD'),
				]
			),
			new IntegerField(
				'age',
				[
					'title' => Loc::getMessage('CLIENTS_ENTITY_AGE_FIELD'),
				]
			),
			new IntegerField(
				'doctor_id',
				[
					'title' => Loc::getMessage('CLIENTS_ENTITY_DOCTOR_ID_FIELD'),
				]
			),
			new IntegerField(
				'procedure_id',
				[
					'title' => Loc::getMessage('CLIENTS_ENTITY_PROCEDURE_ID_FIELD'),
				]
			),
			new IntegerField(
				'contact_id',
				[
					'title' => Loc::getMessage('CLIENTS_ENTITY_CONTACT_ID_FIELD'),
				]
			),

			// виртуальное поле CONTACT которое получает запись из таблицы контактов
			// где ID равен значению contact_id таблицы hospital_clients
			(new Reference('CONTACT', \Bitrix\CRM\ContactTable::class,
				Join::on('this.contact_id', 'ref.ID')))
				->configureJoinType('inner'),
		];
	}
}
use Bitrix\Main\Entity\Query;
use Bitrix\Main\Type;
use Models\BookTable as Books;
use Models\HospitalClientsTable as Clients;

// объект query
// запрос к кастомной таблице BookTable
$query = new Query(Books::getEntity()); // передаем объект сущности Books
$query->setSelect([
        'id', 'name', 'publish_date', 'text', 'ISBN'
]);
$query->setFilter([
	'=id' => 1
]);
$result = $query->exec();

while($row = $result->fetch()){
	debug($row);  // возвращает массив
}

Получение коллекции

// объект query
// связь OneToMany указано на стороне класса модели Books в поле PUBLISHER
// коллекция книг
$query = new Query(Books::getEntity());
$query->setSelect([
	'id', 'name', 'publish_date', 'publisher_id', 'PUBLISHER'
]);
$result = $query->exec();
$collection = $result->fetchCollection();

foreach($collection as $key => $book){
	debug($book->getName());
	debug($book->getPublishDate());
	debug($book->getPublisher()->getName());
}

Связь в модели

// один ко многим. Одна книга, много издателей
(new Reference('PUBLISHER',
	Publisher::class,
	 Join::on('this.publisher_id', 'ref.id')))
	->configureJoinType('inner'),

Получение коллекции

// объект query
// получаем коллекцию
$query = new Query(Clients::getEntity());
$query->setSelect([
	'id', 'first_name', 'contact_id', 'CONTACT.*'
]);
$result = $query->exec();
$collection = $result -> fetchCollection();

foreach($collection as $key => $record){
	debug($record->getFirstName());
	debug($record->getContactId());
	debug($record->getContact()->getPost());
	debug($record->getContact()->getCompanyId());
}

Обратить внимание на связь в модели

// обратить внимание, есть связь в модели
// виртуальное поле CONTACT которое получает запись из таблицы контактов
// где ID равен значению contact_id таблицы hospital_clients
(new Reference('CONTACT', \Bitrix\CRM\ContactTable::class,
	Join::on('this.contact_id', 'ref.ID')))
	->configureJoinType('inner')

Объект query с виртуальным полем в запросе

// Объект query
// Связь непосредственно в запросе.
$query = new Query(Books::getEntity());

$query->registerRuntimeField(
	'PUBLISHER',
	[
		// тип - сущность ElementTable
		'data_type' => 'Models\PublisherTable',
		'reference' => ['=this.publisher_id' => 'ref.id'],
		'join_type' => 'INNER'
	]
);

$query->setSelect([
	'id', 'name', 'publish_date', 'publisher_id', 'PUBLISHER.name'
]);

$result = $query -> exec();

while($row = $result -> fetch()){
	debug($row);
}

registerRuntimeField аналог new Reference() в модели

(new Reference('PUBLISHER',
	Publisher::class,
	 Join::on('this.publisher_id', 'ref.id')))
	->configureJoinType('inner'),
⚠️ **GitHub.com Fallback** ⚠️