Есть ли в PHP ORM позволяющая забирать из базы данные со сложной структурой?

Поясню что я имею в виду.
Допустим есть таблица с объявлениями. У каждого объявления есть связанные с ним данные:
1) Теги
1.1) Категория тега
2) Номера телефонов
3) Изображения
4) Автор

Структура примерно такая


5a865985762ed002990257.png

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for advert
-- ----------------------------
DROP TABLE IF EXISTS `advert`;
CREATE TABLE `advert` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `author_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `author_id` (`author_id`),
  CONSTRAINT `advert_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for author
-- ----------------------------
DROP TABLE IF EXISTS `author`;
CREATE TABLE `author` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `login` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for category
-- ----------------------------
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for image
-- ----------------------------
DROP TABLE IF EXISTS `image`;
CREATE TABLE `image` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `advert_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `advert_id` (`advert_id`),
  CONSTRAINT `image_ibfk_1` FOREIGN KEY (`advert_id`) REFERENCES `advert` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for link_advert_phone
-- ----------------------------
DROP TABLE IF EXISTS `link_advert_phone`;
CREATE TABLE `link_advert_phone` (
  `phone_id` int(10) unsigned NOT NULL,
  `advert_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`advert_id`,`phone_id`),
  KEY `phone_id` (`phone_id`),
  CONSTRAINT `link_advert_phone_ibfk_1` FOREIGN KEY (`phone_id`) REFERENCES `phone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `link_advert_phone_ibfk_2` FOREIGN KEY (`advert_id`) REFERENCES `advert` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for link_advert_tag
-- ----------------------------
DROP TABLE IF EXISTS `link_advert_tag`;
CREATE TABLE `link_advert_tag` (
  `tag_id` int(10) unsigned NOT NULL,
  `advert_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`tag_id`,`advert_id`),
  KEY `advert_id` (`advert_id`),
  CONSTRAINT `link_advert_tag_ibfk_1` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `link_advert_tag_ibfk_2` FOREIGN KEY (`advert_id`) REFERENCES `advert` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for phone
-- ----------------------------
DROP TABLE IF EXISTS `phone`;
CREATE TABLE `phone` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `value` varchar(16) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for tag
-- ----------------------------
DROP TABLE IF EXISTS `tag`;
CREATE TABLE `tag` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `category_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `category_id` (`category_id`),
  CONSTRAINT `tag_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS=1;



Необходимо вытащить все связанные с объявлениями данные.
База весит примерно 4Гб. Сейчас всё это дело вытягивает самопис который строит запрос основываясь на структуре базы. Происходит это примерно так:
$result = $db->getTable('advert')
	->select()
	->limit(180)
	->offset(0)
	->cache(5)
	->link('author')
	->link('image')
	->link('link_advert_phone.phone')
	->link('link_advert_tag.tag.category')
	->query()
;


В результате получаем такой массив:
$result = [
	[
		'id' => 1,
		'title' => '....',
		'author_id' => 1,
		'author_id.author.id' => [
			'id' => 1,
			'login' => 'user name',
		],
		'id.image.advert_id' => [
			[
				'id' => 1,
				'advert_id' => 1,
			],
			[
				'id' => 2,
				'advert_id' => 1,
			],
			// ....
		],
		'id.link_advert_phone.advert_id' => [
			[
				'advert_id' => 1,
				'phone_id' => 1,
				'phone_id.phone.id' => [
					'id' => 1,
					'value' => '+996......',
				]
			],
			// ....
		],
		'id.link_advert_tag.advert_id' => [
			[
				'advert_id' => 1,
				'tag_id' => 1,
				'tag_id.tag.id' => [
					'id' => 1,
					'name' => 'Тег',
					'category_id' => 1,
					'category_id.category.id' => [
						'id' => 1,
						'name' => 'Категоряия',
					]
				]
			],
			// ....
		],
	],
	// ...
];


Самопис при необходимости строит временные таблицы с ключами и составляет сложные запросы вытягивающие вот такие структуры произвольной вложенности. Плюс можно писать условия к вложенным таблицам которые будут влиять на результат. Писать такие запросы в ручную можно но очень проблематично и сложно. Сейчас в планах переписать весь сайт и хотелось бы этот самопис заменить сторонним решением. Пробовал doctrine, он увеличивает время с 200 мс примерно до 3-х секунд, плюс сложность написания запросов возрастает на порядок.
  • Вопрос задан
  • 666 просмотров
Пригласить эксперта
Ответы на вопрос 2
dmitriylanets
@dmitriylanets
веб-разработчик
Isolution666
@Isolution666
Full-Stack Developer
Попробуйте фреймворк Yii2 - там есть ORM. Готовые модели, работающие через функции, всё просто, прописываете в контроллере, что хотите видеть во вьюшке через экшен, и готово! Выводит информацию любой сложности. Я до сих пор не жалею, что выбрал этот фреймворк. Он гибкий, способен реализовывать много разных задач. Под Yii2 написано много разных решений с обработкой данных. Сэкономите время на разработку. Отпадут подобные вопросы. Есть много уроков на youtube, если знаете php, MySQL, sql, то без труда всё настроите, установите и упакуете. В коробке есть базовые решения, можно бесплатно добавлять разработки сторонних разработчиков. И не только.

А ещё количество таблиц можно сократить php.net/manual/ru/function.implode.php
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы