Короче есть класс и его метод должен иметь очень разную реализацию в зависимости от состояния экземпляра. Был бы это тикль там бы все решилось тупо динамической построчной сборкой функции. А как это по человечески реализовать на php чтобы оно еще и быстро работало?
Писать кучу реализаций и абстрактный класс не вариант, потому что реализаций реально много (в конечном счете за сотню зашкалит).
Решил попробовать сделать через замыкания (раньше не пробовал на пыхе): http://pastebin.com/cLbzjQf3
Ъ - там нечто вроде:
class SCIBlockElementHD {
protected static $_method;
protected static $_db_res;
protected static $_GetElements;
protected $_DeployPictures;
protected $_DeployLinks;
protected $_DeployFiles;
function __construct(
# какие-то параметры
) {
$this->_method = $Method;
$arSelect = $arSelectFields;
if ($arSelectProps) {
foreach ($arSelectProps as $prop) {
$arSelect[] = 'PROPERTY_'.$prop;
}
}
$this->_db_res = CIBlockElement::GetList($arOrder, $arFilter, false, $arNav, $arSelect);
# constucte closure
if ($Method == 'P') {
$this->_GetElements = function ($db_res, $DeployPictures, $DeployLinks, $DeployFiles) {
while($arElement = $db_res->GetNext()) {
$arElement = $DeployPictures($arElement);
$arElement = $DeployLinks($arElement);
$arElement = $DeployFiles($arElement);
$arElements[] = $arElement;
}
return $arElements;
};
} elseif ($Method == 'F') {
# какой-то код похожий на предыдущий
} else { # S
# какой-то код похожий на предыдущий
}
# пустые замыкания
$this->_DeployPictures = function ($element) {return $element;};
$this->_DeployLinks = function ($element) {return $element;};
$this->_DeployFiles = function ($element) {return $element;};
return $this;
}
#
# метод перегрузки замкания (для "настройки" экземпляра)
public function DeployPictures() {
$this->_DeployPictures = function ($element) {
if(isset($element['PREVIEW_PICTURE'])) {
$element['PREVIEW_PICTURE'] = (0 < $element['PREVIEW_PICTURE'] ? CFile::GetFileArray($element['PREVIEW_PICTURE']) : false);
}
if(isset($element['DETAIL_PICTURE'])) {
$element['DETAIL_PICTURE'] = (0 < $element['DETAIL_PICTURE'] ? CFile::GetFileArray($element['DETAIL_PICTURE']) : false);
}
return $element;
};
}
#
# Целевой метод
public function GetElements() {
$clsrElements = $this->_GetElements;
$DeployPictures = $this->_DeployPictures;
$DeployLinks = $this->_DeployLinks;
$DeployFiles = $this->_DeployFiles;
return $clsrElements($this->_db_res, $DeployPictures, $DeployLinks, $DeployFiles);
}
#
}
#
Смысл примерно такой - объект должен получить из базы некоторые данные одним из способов, а потом получить/или не получить некоторые зависимые наборы данных, разными способами в зависимости от того каким из способов были выдернуты первичные данные.
Но это выглядит как говно. Хотя работает относительно шустро.
Можно это как-то сделать менее говённо?