[Silverstripe 2.4]: Как получить записи, содержащие столбцы из отношения "один ко многим"?
Есть два класса объектов данных "A" и "B", имеющие отношение "один ко многим". Я хочу получить данные, содержащие столбцы из родительского и дочернего объекта данных. Как этого добиться в ORM или SQL-запросе Silverstripe.
Пример: Dataobject "A" имеет два события, и первое событие содержит одну информацию о дате (дата начала и окончания). Второе событие содержит информацию о двух датах (дата начала и окончания).
Я хочу запросить базу данных, чтобы получить информацию, содержащую столбцы как из "A", так и из "B", и она должна показывать 3 строки в качестве результата. один из "A" и два из "B".
Я использую Silverstripe 2.4. Фильм может иметь несколько дат для показа. Объект данных фильма имеет отношение один-ко-многим с объектом данных MovieDate. Я хочу получить все столбцы из фильма, повторяя каждую запись MovieDate, связанную с ним. Это означает, что если у фильма есть две даты, то я хочу получить две записи
Title Desc StartDate EndDate
----- ---- --------- -------
Matrix AAA 2012-09-20 2012-09-20
Matrix AAA 2012-09-29 2012-09-29
Вот код для вашего рассмотрения
<?php
class Movie extends DataObject
{
public static $db = array(
'Title' => 'Varchar',
'Desc' => 'Text',
);
public static $defaults = array(
'RedirectionType' => 'Internal',
);
public static $has_one = array(
'Image' => 'Image',
'Parent' => 'Page',
"LinkTo" => "SiteTree"
);
public static $has_many = array(
'MovieDates' => 'MovieDate'
);
static $summary_fields = array(
'Title' => 'Movie Title',
'Desc' => 'Movie Description'
);
function getRequirementsForPopup() {
Requirements::customCSS("
.iframe_wrap {
top: 35%;
}
");
}
public function getCMSFields()
{
$fields = new FieldSet(new TabSet('Root', $tab1 = new Tab('Main')));
$fields->addFieldsToTab('Root.Main', new TextField('Title', 'Movie Title'));
$fields->addFieldsToTab('Root.Main', new TextareaField('Desc', 'Movie Description'));
$tablefield = new DataObjectManager(
$this,
'MovieDates',
'MovieDate',
array('MovieStartDate' => 'Movie Start', 'MovieEndDate' => 'Movie End')
);
$tablefield->setPopupWidth(900);
$tablefield->setAddTitle("Movie Date/Time");
$fields->addFieldsToTab('Root.Main', $tablefield);
$fields->addFieldsToTab('Root.Main', new LiteralField("Space", "</br></br></br></br></br>") );
return $fields;
}
}
<?php
class MovieDate extends DataObject{
static $db = array(
'MovieStartDate' => 'Datetime',
'MovieEndDate' => 'Datetime',
);
static $has_one = array(
'Movie' => 'Movie'
);
function getCMSFields(){
$fields = new FieldSet();
$movieStartDate = new DateField('MovieStartDate', 'Movie Start');
$movieStartDate->setConfig('showcalendar', true);
$fields->push($movieStartDate);
$movieEndDate = new DateField('MovieEndDate', 'Movie End');
$movieEndDate->setConfig('showcalendar', true);
$fields->push($movieEndDate);
$space = new LiteralField("Space", "</br></br></br></br></br>");
$fields->push($space);
return $fields;
}
}
2 ответа
Я думаю, что вы ищете "левое соединение". к сожалению, silverstripe не имеет средств для извлечения данных из объединенной таблицы с использованием встроенных запросов ORM (см. http://doc.silverstripe.org/framework/en/2.4/topics/datamodel)
поэтому вам нужно выполнить простой SQL-запрос здесь:
$query = "
SELECT `Movie`.*, `MovieDate`.*
FROM `Movie`
LEFT JOIN `MovieDate` ON `Movie`.`ID` = `MovieDate`.`MovieID`
ORDER BY `Movie`.`Title`
";
$records = DB::query($query);
Вы можете перебрать $records
сейчас использую foreach
:
foreach($records as $record) {
print_r($record);
}
также смотрите эту ветку форума для получения дополнительной информации: http://www.silverstripe.org/general-questions/show/12745
Вы можете создать DataObjectSet
который содержит результат отдельного DataObject::get()
звонки.
$a = DataObject::get(...);
$b = DataObject::get(...);
$all = new DataObjectSet();
$all->merge($a);
$all->merge($b);
$all->sort('date','desc');
Код не проверен, но, надеюсь, вы поняли идею. Ссылка на документы DataObjectSet, чтобы увидеть полный API.
Изменить: Предполагается, что вы используете SilverStripe 2.x - см. Обновленную документацию по модели данных 3.0 для использования с SS 3.0, в частности, DataObject::get()
звонки.