Fi1osof 30 июня 2013 0 0
Опять пишу большой топик в ответ на чужой вопрос.
Топик раскрывает некоторые преимущества работы с xPDO и написал одну хитрость для не посвященных. Но в целом топик оформлен ужасно и не является исчерпывающей мануалой, потому заходите на свой страх и риск, и не пишите сообщений типа «фуууу...».
Так что же дает xPDO лично мне?
1) Сравним эти 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:-)
0 комментариев
Авторизуйтесь или зарегистрируйтесь (можно через соцсети ), чтобы оставлять комментарии.