#php #zend-framework #orm #relationships
#php #zend-framework #orm #отношения
Вопрос:
Мне нужен PHP ORM для хорошей работы с отношениями. Пожалуйста, рассмотрите приведенный ниже код в Zend:
$persons = new Persons();
$person = $persons->find(5)->current();
echo 'Name: '.$person->fullname;
$phones = $person->findDependentRowset('Phones');
foreach($phones as $phone)
echo 'Phone: '.$phone->phonenumber;
Или код ниже в xPDO:
$person = $xpdo->getObject('Persons', 5);
echo 'Name: '.$person->get('fullname');
$phones = $person->getMany('Phones');
foreach($phones as $phone)
echo 'Phone: '.$phone->get('phonenumber');
в обоих сценариях ORMs выполняет два запроса, как показано ниже:
SELECT * FROM persons WHERE id=5;
SELECT * FROM phones WHERE person=5;
Это означает один запрос для основного объекта и один запрос для каждого отношения, но мне нужно использовать ОДИН запрос для основного объекта и его отношений!
xPDO может сделать это, как показано ниже:
$person = $xpdo->getObjectGraph('Persons', '{"Phones":{}}', 5);
echo 'Name: '.$person->get('fullname');
foreach($person->Phones as $phone)
echo 'Phone: '.$phone->get('phonenumber');
который выполняет этот запрос:
SELECT * FROM persons
LEFT JOIN phones ON phones.person=persons.id
WHERE persons.id=5
Это здорово, но невозможно установить поля для получения из таблиц!
это означает, что в этом случае xPDO использует «SELECT * «, поэтому, если я получу объект и его 4 отношения, я получу все поля всех этих таблиц!
Итак, мне нужен ORM для выполнения запроса ниже, например, выше:
SELECT persons.fullname , phones.phonenumber FROM persons
LEFT JOIN phones ON phones.person=persons.id
WHERE persons.id=5
Doctrine может сделать это через DQL, но я думаю, что Doctrine не подходит для личных проектов. Есть ли какой-либо PHP ORM для этого?
Спасибо AHHP
Комментарии:
1. Что не так с Doctrine? Вы можете настроить свои объекты для выполнения отдельных запросов с объединениями, используя «нетерпеливую выборку». См . doctrine-project.org/docs/orm/2.0/en/reference /. … Кроме того,
Zend_Db_Table
это не ORM. В лучшем случае это реализация шаблона table-data-gateway2. Спасибо, Фил. Doctorine тяжелый для небольших проектов! Не могли бы вы дать мне образец для моего примера? Как это сделать с (вне) DQL?
3. Я понятия не имею, что означает «тяжелый для небольших проектов». Это инструмент, вы его используете. Если вам нужен ORM в вашем проекте, Doctrine будет моим первым выбором. Также см. раздел Быстрая загрузка . Вы, по сути, добавляете
fetch="EAGER"
к своему сопоставлению ассоциаций. Кроме того, это Doctrine , а не Doctorine .
Ответ №1:
xPDO может это сделать. Вам просто нужно настроить свое мышление и свой запрос.
Помните, что ObjectGraph использует имя класса объекта, где как отношения в графе используются в графике и запросе.
$criteria = $this->xpdo->newQuery('prefixClient');
if (!empty($limit))
$criteria->limit($limit);
$criteria->where(array('Child.planid' => $this->getPrimaryKey(),
'Child.active' => true,
'GrandChild.someAttribute' => true,
'GreatGrandChild.someOtherAttribute' => true,
'suspended' => false
));
$out = $this->xpdo->getCollectionGraph('prefixClient', '{"Child":{"GrandChild":{"GreatGrandChild":{}}}}', $criteria);
Вы устанавливаете WHERE для любого аспекта отношения, включая текущий объект, как показано в строке suspended => false .
Моя книга может немного помочь вам в создании вашей схемы и отношений. Объекты всегда должны быть единственными в номенклатуре, тогда как их отношения могут быть множественными (1: M) или единственными (1: 1).
Ответ №2:
О боже,
Я ем этот корм для собак около 2 месяцев, и мне это нравится. RED BEAN.
Вложенные компоненты, которые являются их словами для того, чтобы один объект был свойством другого.
http://www.redbeanphp.com/manual/nested_bean
Весь файл довольно маленький. Работает с SQL. Я использую его в масштабном проекте, и мне нравится, как быстро я могу все сделать.
Джон.
Комментарии:
1. RedBean полон потрясающего соуса.
Ответ №3:
Существует несколько способов, которыми Gacela может обрабатывать автоматическую выборку связанной информации:
1) Отношения наследования
В примере, подобном следующему:
CREATE TABLE wizards (
wizardId INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
fname VARCHAR(255) NOT NULL,
lname VARCHAR(255) NOT NULL,
ROLE ENUM('teacher', 'student') NULL,
addressId INT UNSIGNED NULL,
CONSTRAINT fk_address_wizard
FOREIGN KEY (addressId)
REFERENCES addresses(addressId)
ON DELETE SET NULL
) ENGINE = Innodb;
CREATE TABLE students (
wizardId INT UNSIGNED NOT NULL PRIMARY KEY,
houseId INT UNSIGNED NOT NULL,
isDAMembmer BOOL NOT NULL DEFAULT 0,
CONSTRAINT fk_wizard_student
FOREIGN KEY (wizardId)
REFERENCES wizards(wizardId)
ON DELETE CASCADE,
CONSTRAINT fk_house_students
FOREIGN KEY (houseId)
REFERENCES houses(houseId)
ON DELETE RESTRICT
) ENGINE = Innodb;
students
Таблица имеет тот же первичный ключ, wizards
что и таблица, и из-за определения отношения внешнего ключа Gacela обнаружит, что students
наследует
все поля wizards
.
2) Зависимые отношения
Вероятно, это ближе к тому, что вы ищете:
CREATE TABLE addresses (
addressId INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
locationName VARCHAR(255) NOT NULL
) ENGINE = Innodb;
CREATE TABLE wizards (
wizardId INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
fname VARCHAR(255) NOT NULL,
lname VARCHAR(255) NOT NULL,
ROLE ENUM('teacher', 'student') NULL,
addressId INT UNSIGNED NULL,
CONSTRAINT fk_address_wizard
FOREIGN KEY (addressId)
REFERENCES addresses(addressId)
ON DELETE SET NULL
) ENGINE = Innodb;
Однако этот пример все еще немного отличается от вашего примера, потому что AddressID находится в wizards
таблице, что создает отношение belongsTo, а не hasMany,
что и отражает ваш пример.
В Gacela доступен третий вариант, однако я бы сначала посоветовал вам подумать о том, что, хотя часто предпочтительнее быстро извлекать данные, всегда быстрая выборка, а не отложенная загрузка данных, имеет реальные последствия для производительности. Именно по этой причине Gacela (и, в основном, любой другой Data Mapper или ORM) по умолчанию не извлекает данные из отношений hasMany. Тем не менее, вы могли бы написать что-то вроде следующего:
class Mapper extends GacelaMapper
{
public function find($id)
{
$query = $this->_source()->query();
$query->from('persons', array('fullName'))
->join('phones', 'phones.person=persons.id', array('phonenumber'), 'left')
->where('persons.id = :id', array(':id' => $id);
$data = $this->_source->query($query);
return $this->_load($data);
}
}
Комментарии:
1. Спасибо Ноа. Последний способ хорош, но нужно хорошо знать коды Gacela, что занимает некоторое время, но может помочь мне разработать его для моих целей.