Опять пишу большой топик в ответ на чужой вопрос.
Топик раскрывает некоторые преимущества работы с xPDO и написал одну хитрость для не посвященных. Но в целом топик оформлен ужасно и не является исчерпывающей мануалой, потому заходите на свой страх и риск, и не пишите сообщений типа «фуууу...».
Так что же дает xPDO лично мне?
Сравним эти 2 запроса: $sql = array( select => "a., ah.description, ah.conditions, ah.features, ah.action_end, ah.full_price, ah.discount, ah.sale_price, ah.cost_discount, adrs.name as firmname, (select act.cat_cat_id from ".self::$tables['actions_categories']." as act where act.action_action_id = a.action_id limit 1) as cat_id, (select cat.name from ".self::$tables['actions_categories']." as act join ".self::$tables['categories']." as cat on cat.cat_id = act.cat_cat_id where act.action_action_id = a.action_id limit 1) as category, c.pagetitle, c.longtitle, c.id, c.uri, cp.id as partnerDocID, cp.uri as partnerDocUri, cp.published as parentIsPublished, cp.deleted as parentIsDeleted, cp.hidemenu as parentIsHideMenu, ai.value as action_image, pi.value as partner_logo, (select count() from ".self::$tables['user_cupon']." as uc where uc.action_action_id = a.action_id) as bought, metro.station as metro",
from => self::$tables['actions']." as a
join ".self::$tables['actions_history']." ah ON ah.action_action_id = a.action_id and
ah.actstat_actstat_id = 5
and now() between ah.start_date and ah.end_date AND NOW() < ah.action_end
join ".self::$tables['actions_status']." as as
on as
.actstat_id = ah.actstat_actstat_id
join ".self::$tables['partners']." as p on p.partner_id = a.partner_partner_id
join ".self::$tables['partners_history']." as ph on ph.partner_partner_id = p.partner_id
and now() between ph.start_date and ph.end_date
join ".self::$tables['partners_statuses']." as ps on ps.partstatus_id = ph.partstatus_partstatus_id".
" join ".self::$tables['catalog_content']." as cc on cc.action_action_id = a.action_id
join ".self::$tables['catalog_content']." as ccp on ccp.partner_partner_id = p.partner_id
join ".self::$tables['site_content']." as c on cc.cont_cont_id = c.id
and c.published = 1 and c.hidemenu = 0 and c.deleted = 0
join ".self::$tables['tv_values']." as ai on ai.contentid = c.id
and ai.tmplvarid = ".self::$TVs['actionImg']."
left join (select aa.action_action_id, adh.name from ".self::$tables['addresses']." as ca
join ".self::$tables['addresses_history']."
as adh on adh.adrs_adrs_id = ca.adrs_id and adh.adrstat_adrstat_id = 1
and now() between adh.start_date and adh.end_date
join ".self::$tables['actions_addresses']." as aa on ca.adrs_id = aa.adrs_adrs_id and aa.status = 1
and now() between aa.start_date and aa.end_date
where adh.city in (". implode(",", $cities). ")
{$adrs_where}
group by aa.action_action_id
) as adrs on adrs.action_action_id = a.action_id
left join ".self::$tables['site_content']." as cp on ccp.cont_cont_id = cp.id
left join ".self::$tables['tv_values']." as pi on pi.contentid = cp.id
and pi.tmplvarid = ".self::$TVs['partnerLogo']."
left join (
SELECT caa.action_action_id, if(cm.complex_name is not null && cm.complex_name != '',
cm.complex_name, cm.station) as station
FROM modx_catalog_actions_addresses as caa
join modx_catalog_metro_relations as cmr on cmr.adrs_adrs_id = caa.adrs_adrs_id
join modx_catalog_metro as cm on cm.metro_id = cmr.metro_metro_id
where now() between caa.start_date and caa.end_date
group by 1
) as metro on metro.action_action_id = a.action_id
". ($not_sended == true ? " left join modx_catalog_actions_sended as asn
on
asn
.action_action_id = a.action_id ": "")."
where `as`.status = 'Активна'
and ps.status = 'Активный'
and (adrs.action_action_id is not null OR ah.all_cities = '1')
{$where}
order by c.publishedon desc",
limit => self::$limit,
offset => self::$offset
); и // Получаем города, которые используются для этого хоста $cities = self::get_host_cities(); $where = array( 'now() between ah.start_date and ah.end_date', 'ah.actstat_actstat_id' => 5, 'NOW() < ah.action_end', 'now() between ph.start_date and ph.end_date', 'ph.partstatus_partstatus_id' => 2, 'c.published' => 1, 'c.hidemenu' => 0, 'c.deleted' => 0, 'ai.tmplvarid' => self::$TVs['actionImg'], 'now() between aa.start_date and aa.end_date', 'aa.status' => 1, 'now() between adh.start_date and adh.end_date', );
$q = self::$modx->newQuery('Actions');
$q->select(array( 'Actions.*', 'ah.description', 'ah.conditions', 'ah.features', 'ah.action_end', 'ah.full_price', 'ah.discount', 'ah.sale_price', 'ah.cost_discount', 'adh.name as firmname', 'c.pagetitle', 'c.longtitle', 'c.id', 'c.uri', 'cp.id as partnerDocID', 'cp.uri as partnerDocUri', 'cp.published as parentIsPublished', 'cp.deleted as parentIsDeleted', 'cp.hidemenu as parentIsHideMenu', 'ai.value as action_image', 'pi.value as partner_logo', "if(cm.complex_name is not null && cm.complex_name != '', cm.complex_name, cm.station) as metro" ));
$q->innerJoin('ActionsHistory', 'ah', 'ah.action_action_id = Actions.action_id'); $q->innerJoin('Partners', 'p', 'p.partner_id = Actions.partner_partner_id'); $q->innerJoin('PartnersHistory', 'ph', 'ph.partner_partner_id = p.partner_id'); $q->innerJoin('Content', 'cc', 'cc.action_action_id = Actions.action_id'); $q->innerJoin('Content', 'ccp', 'ccp.partner_partner_id = p.partner_id'); $q->innerJoin('modResource', 'c', 'cc.cont_cont_id = c.id'); $q->innerJoin('modResource', 'cp', 'ccp.cont_cont_id = cp.id'); $q->innerJoin('modTemplateVarResource', 'ai', 'ai.contentid = c.id'); $q->innerJoin('ActionsAddresses', 'aa', 'aa.action_action_id = Actions.action_id'); $q->innerJoin('AddressesHistory', 'adh', 'adh.adrs_adrs_id = aa.adrs_adrs_id'); $q->leftJoin('MetroRelations', 'cmr', 'cmr.adrs_adrs_id = aa.adrs_adrs_id'); $q->leftJoin('Metro', 'cm', 'cm.metro_id = cmr.metro_metro_id');
$q->leftJoin('modTemplateVarResource', 'pi', 'pi.contentid = cp.id AND pi.tmplvarid = '.self::$TVs['partnerLogo']);
if($not_sended == true){ $q->leftJoin('ActionsSended', 'asn', 'asn.action_action_id = Actions.action_id'); $where['asn.actsnd_id'] = NULL; }
$q->where($where);
$q->andCondition( "(adh.city IN (".implode(",", $cities).") OR ah.all_cities = '1')" );
if($not_sended == false){ self::$rows = self::$modx->getCount('Actions', $q); $q->limit(self::$limit, self::$offset); }
// Подсчитываем кол-во строк
$q->groupby('Actions.action_id'); $q->sortby('c.publishedon', 'DESC');
if(!$q->prepare()){ return false; }
if(!$q->stmt->execute()){ return false; }
$result__ = $q->stmt->fetchAll(PDO::FETCH_ASSOC); Да, каждый пример — это один запрос и да, иногда нужны и такие большие запросы. Так вот, как считаешь, какой легче будет сопровождать и дорабатывать? Лично я отвечу: второй запрос (который на xPDO) сопровождать в разы легче. 2. Если у тебя таблица изменилась, тебе не надо лазить по всему проекту и искать, во всех ли у тебя запросах прописаны все необходимые колонки… 3. Простейшая для xPDO операция: $object = $modx->getObject('object', $where); $object->fromArray($data); $object->save(); На чистой связке PHP+Mysql это как бе гемор, так как надо проверить какие данные есть в массиве $data, какие колонки могут этому соответствовать, а какие нет, какие типы данных и какие преобразования могут понадобиться… Дофига гемора. Это маленькая часть из преимуществ. Далее. SELECT * FROM atable WHERE id=$parent AND id>(MIN+((MAX-MIN)/COUNT)*offset LIMIT numrows Это вообще не проблема. Подробней читаем здесь. А конкретно по поводу WHERE id=$parent AND id>(MIN+((MAX-MIN)/COUNT)*offset: надо правильно массив условий собирать. $where = array( 'id' => $parent, 'id > (MIN+((MAX-MIN)/COUNT)*offset' ) Не 'id:>' =>, а именно так, как я написал, потому что иначе xPDO запрос соберет так, как будто '(MIN+((MAX-MIN)/COUNT)*offset' — это название колонки. Но все же одно ограничение действительно есть, которое я встречал. На xPDO нельзя собрать запроса типа UNION ALL. Но это так редко используется… И под конец компенсация за мой наезд: твоя проблема в том, что ты не видишь SQL? $q = $modx->newQuery($class); $q->select($select); $q->where($where); $q->prepere(); <strong>print $q->toSQL();</strong> И вот тебе чистый SQL:-)