Хороший вопрос. Прежде всего, обратите внимание, что я считаю, что расширенному сервису метаданных в ILIAS не хватает хорошего readme-файла, который бы четко обозначал, каким образом интерфейс предлагает такие задачи, как ваша. Некоторое время назад мне также пришлось столкнуться с этим сервисом и столкнуться с похожими проблемами. Надеюсь, ваш вопрос поможет немного лучше документировать это, и я сам с нетерпением жду других предложений, зная, что мое тоже не очень хорошо. Если у вас есть какие-либо ресурсы, мы будем очень благодарны за продвижение введения хорошего readme для сервисов, а также за продвижение сервисов к использованию шаблона репозитория с понятным интерфейсом.
На ваш вопрос о том, что можно улучшить: в строках кода я вижу три основных проблемы:
Шаг 1 Давайте начнем с первого. Обратите внимание, что мне не удалось решить эту проблему без введения нового (новый запрос). Плохо знаю. Я надеюсь, что есть лучшее решение, я не нашел его после быстрого исследования. Вы сохраняете идентификатор, так как заголовок поля не является надежно уникальным, верно? Это правильно, однако, вы можете подумать о сохранении триплета field_title, record_title и (возможно) области видимости. Обратите внимание, что вам, возможно, не нужен объем, поскольку вы хотите использовать его глобально. Функция, возвращающая вас, и массив, содержащий field_id и record_id, может выглядеть так:
function getFieldAndRecordIdByFieldTitles($field_title, $record_title, $scope_title){
$query = "select field.field_id,field.record_id from adv_mdf_definition as field
INNER JOIN adv_md_record as record ON record.record_id = field.record_id
INNER JOIN adv_md_record_scope as scope ON scope.record_id = field.record_id
INNER JOIN object_reference as ref ON scope.ref_id = ref.ref_id
INNER JOIN object_data as scope_data ON ref.obj_id = scope_data.obj_id
WHERE field.title='$field_title' AND record.title='$record_title' AND scope_data.title = '$scope_title'";
$set = $this->dic()->database()->query($query);
if($row = $this->dic()->database()->fetchAssoc($set))
{
return array_values($row);
}
}
Тогда получите ваши значения так:
list($field_id,$record_id) = getFieldAndRecordIdByFieldTitles("my_field", "my_record", "my_scope");
Обратите внимание, что я знаю, что я представляю новый запрос здесь. Извините, это было лучшее, что я мог придумать. Я уверен, что там вы найдете лучшее решение, если ваше исследование немного, дайте нам знать, если успешно. Тем не менее, мы удалим один на следующем шаге.
Шаг 2 Используйте недокументированный сервис, чтобы получить выгоду от предварительных метаданных. Поскольку теперь у вас есть идентификатор записи и идентификатор поля, вы можете сделать это следующим образом:
$record_values = new ilAdvancedMDValues($record_id, $obj_id);
$record_values->read();
$ADTGroup = $ilAdvancedMDValues->getADTGroup();
$ADT = $ilADTGroup->getElement($field_id);
$value = $ADT->getText();
/**if you have text, others are possible, such as:
switch (true) {
case ($ADT instanceof ilADTText):
break;
case ($ADT instanceof ilADTDate):
$value = $ADT->getDate();
break;
case ($ADT instanceof ilADTExternalLink):
$... = $ADT->getUrl();
$... = $ADT->getTitle();
break;
case ($ADT instanceof ilADTInternalLink):
$... = $ADT->setTargetRefId($value);
}
**/
Обратите внимание, что ADT также не имеют документов. Возможно, есть лучший способ извлечь из этого пользу.
Шаг 3 Оберните ваши статические и новые в некоторую инъекционную зависимость. Я обычно использую раздутый образец конструктора, чтобы сделать это. Выглядит так:
public function __construct(InjectedSettings $mySettings = null)
{
if (!$mySettings) //Case in the default scenario
{
$this->mySettings = new InjectedSettings();
} else //used e.g. for unit tests, where you can stuff the constructor with a mock
{
$this->mySettings = $mySettings;
}
$this->mySettings->doSometing();
}
Обратите внимание, что это не настоящая деп. впрыск, все еще вы все еще используете новый, но я думаю, что очень работоспособное решение использовать dep. инъекция, по крайней мере, для контекста теста в ilias
Это помогает? Я надеюсь, что будут другие (лучшие ответы также).
Я ожидаю, что то, что Вы видите, является решением безопасности - путем ограничения возвращенной информации, они не предоставляют информацию злонамеренным сторонам.
Предположите, что Вы - Cyril Cracker, пытаясь ворваться в веб-сайт.
Сценарий № 1: Вы пытаетесь ввести имя пользователя "Администратор" с паролем "Пароль", и система говорит Вам остановку. Единственная информация, которую Вы имеете, - то, что Администратор/Пароль не является допустимой комбинацией.
Сценарий № 2: Вы пытаетесь ввести имя пользователя "Администратор" с паролем "Пароль", и система говорит Вам, что никакой пользователь тем именем не известен. Можно продолжать пробовать различные имена пользователей, пока Вы не находите тот, который известен.
Сценарий № 3: Вы пытаетесь ввести имя пользователя "Администратор" с паролем "Пароль", и система говорит Вам, что не пароль является неверным. Внезапно, Вы знаете, что "Администратор" является действительным пользователем. Вы изучили что-то полезное, и все, что необходимо продолжать предполагать, пароль.
Сценарий № 4: Вы пытаетесь ввести имя пользователя "Администратор" с паролем "Пароль", и система говорит Вам, что учетная запись заблокирована. Теперь, Вы знаете допустимое имя пользователя и пароль, и что учетная запись заблокирована. Можно возвратиться позже и попробовать еще раз.
Системы, которые выдают секрет о том, что допустимо, и что не, известны как болтливые системы, и их считают небезопасными на серьезном основании, поскольку их легче взломать.
Надежда это полезно.