Outils pour utilisateurs

Outils du site


Panneau latéral

ref:docs:requetes_de_documents

Requêtes de documents

Change fournit une API orientée Objet permettant d'interroger la base de données des documents.

Les principes en sont relativement simples :

  • Créer un objet requête (ou Query), en général depuis le service du document que l'on cible (méthode createQuery())
  • Lui ajouter des Restrictions (méthode add())
  • Appeler la méthode find() qui retourne les documents satisfaisant l'ensemble des restrictions

Ainsi, pour obtenir les pages publiées d'un site donné, ou pourra procéder comme suit :

// a website_persistentdocument_website object is retrieved by some way ...
$website = ...;
// Get the Query object
$query = website_PageService::getInstance()->createQuery();
// Add some restrictions
$query->add(Restrictions::published())
  ->add(Restrictions::descendentOf($website->getId()));
// Execute the Query
$pages = $query->find();
 
// find() returns an array of website_persistentdocument_page
foreach ($pages as $page)
{
  assert('$page instanceof website_persistentdocument_page');
  assert('$page->isPublished()');
  assert('f_util_StringUtils::beginsWith(LinkHelper::getUrl($page), $website->getUrl()."/")');
  echo $page->getLabel()."\n";
}

L'objet Query

L'objet Query (de nom complet f_persistentdocument_criteria_Query) peut être obtenu depuis :

  1. La méthode f_persistentdocument_PersistentProvider::createQuery($model, $includeChildren = true)
    • Le premier argument $model est le type de document ciblé, par exemple modules_website/page
    • Le deuxième argument $includeChildren signifie récupérer ou non les documents d'un sous type de $model. Par défaut les documents du type et des sous-types sont récupérés
  2. Le raccourci createQuery() ou createStrictQuery() sur le service du document ciblé.
    • createQuery() sur mymodule_mydocService équivaut à PersistentProvider::createQuery('modules_mymodule/mydoc')
    • createStrictQuery() sur mymodule_mydocService équivaut à PersistentProvider::createQuery('modules_mymodule/mydoc', false)

Query::add()

La méthode add() permet d'ajouter des Restrictions à la requête. add() retourne l'objet Query. Les ajouts de restrictions peuvent être chaînées :

$query->add($restriction1)->add($restriction2);

Query::find()

La méthode find() retourne un tableau de documents du type spécifié. Si aucun document ne satisfait les restrictions, find() retourne un tableau vide.

$query = website_PageService::getInstance()->createQuery();
$pages = $query->find();
 
assert('is_array($pages)');
foreach ($pages as $page)
{
  assert('$page instanceof website_persistentdocument_page');
}

Query::findUnique()

La méthode findUnique() est un raccourci pour find() : si les restrictions spécifiée font que find() retourne au plus un élément, findUnique() retourne ce document ou null :

$query = website_WebsiteService::getInstance()->createQuery();
$query->add(Restrictions::eq("url", "http://www.rbschange.fr"));
$website = $query->findUnique();
 
if ($website !== null)
{
   assert('$website->getUrl() == "http://www.rbschange.fr"');
}

Attention à ne pas utiliser findUnique() pour des requêtes pouvant ramener plus d'un document : utiliser plutôt les fonctions de pagination.

Les restrictions

La classe Restrictions fournit un ensemble de filtres applicables à un objet Query, sous la forme de méthodes statiques. Les filtres peuvent porter sur des propriétés, des relations d'arbres, des tags.

Restrictions sur les propriétés

Sont disponibles les filtres suivants :

Egalités, inclusions

eq()

La restriction eq() (EQuals) est l'équivalent de l'opérateur ==.

Exemple : les documents dont le libellé vaut exactement “This is the label

$query->add(Restrictions:eq("label", "This is the label"));
 
foreach ($query->find() as $doc)
{
  assert('$doc->getLabel() == "This is the label"');
}

eq() s'applique également sur les propriétés document.

Exemple : les rubriques dont la page d'index est une page donnée

// $page is an instance of website_persistentdocument_page
$page = ...;
$query = website_TopicService::getInstance()->createQuery()
   ->add(Restrictions:eq("indexPage", $page));
 
foreach ($query->find() as $topic)
{
  assert('$topic->getIndexPage()->getId() == $page->getId()');
}
ieq()

La restriction ieq() (EQuals Ignore case) est l'équivalent de l'opérateur ==, en ignorant les différences de casse des caractères.

Exemple : les documents dont le libellé vaut “This is the label”, quelque soit la casse des caractères.

// $query1 and $query2 do the same
$query1 = $myService->createQuery();
$query1->add(Restrictions:eq("label", "this is the label"));
 
$query2 = $myService->createQuery();
$query2->add(Restrictions:eq("label", "ThiS IS tHe lAbEL"));
ne()

La restriction ne() (Not Equals) est l'équivalent de l'opérateur !=

Exemple : les documents dont le libellé est différent de “not this label

$query->add(Restrictions:ne("label", "not this label"));
 
foreach ($query->find() as $doc)
{
  assert('$doc->getLabel() != "not this label"');
}
in()

La restriction in() est l'équivalent de l'opérateur SQL du même nom.

Exemple : les documents dont le libellé est “aaa” ou “bbb” ou “ccc”

$query->add(Restrictions:in("label", array("aaa", "bbb", "ccc"));
notin()

notin() est la négation de in().

Exemple : les documents dont le libellé n'est ni “aaa” ni “bbb” ni “ccc”.

$query->add(Restrictions:notin("label", array("aaa", "bbb", "ccc"));
isNull()

isNull() est l'équivalent du 'IS NULL' SQL. Il est applicable aux propriétés scalaires uniquement.

Exemple : les pages publiées qui n'ont pas d'habillage directement associé

$query = website_PageService::getInstance()->createQuery()
  ->add(Restrictions::published())
  ->add(Restrictions::isNull("skin"));
isNotNull()

isNotNull() est l'inverse de isNull().

isEmpty()

Pour les propriétés scalaires, isEmpty() signifie est NULL ou est vide (chaîne vide).

Pour les propriétés documents, isEmpty() signifie aucun document associé.

Exemple : les rubriques qui n'ont pas de gabarit de page directement associé

$query = website_TopicService::getInstance()->createQuery();
$query->add(Restrictions::isEmpty("allowedpagetemplate"));
isNotEmpty()

isNotEmpty() est l'inverse de isEmpty().

published()

Requêter les documents publiés est chose fréquente. Le raccourci published() permet l'obtention des documents dont le statut de publication est “PUBLICATED” :

Exemple : les pages publiées

// $query1 and $query2 do the same:
$query1 = website_PageService::getInstance()->createQuery()
  ->add(Restrictions::published());
 
$query2 = website_PageService::getInstance()->createQuery()
  ->add(Restrictions::eq("publicationstatus", "PUBLICATED"));
eqProperty()

eqProperty (EQuals Property) permet de tester l'égalité entre deux propriétés du même document

$query->add(Restrictions::eqProperty("someProperty", "otherProperty"));
 
foreach ($query->find() as $doc)
{
   assert('$doc->getSomeProperty() == $doc->getOtherProperty()');
}
neProperty()

neProperty (Not Equals Property) permet de tester que deux propriétés d'un document sont différentes

$query->add(Restrictions::neProperty("someProperty", "otherProperty"));
 
foreach ($query->find() as $doc)
{
   assert('$doc->getSomeProperty() != $doc->getOtherProperty()');
}

Inégalités

lt()

La restriction lt() (Less Than) est l'équivalent de l'opérateur <

Exemple : les documents dont l'identifiant est strictement inférieur à 100

$query->add(Restrictions:lt("id", 100));
le()

La restriction le() (Less than or Equals) est l'équivalent de l'opérateur

Exemple : les documents dont l'identifiant est inférieur ou égal 100

$query->add(Restrictions:le("id", 100));
gt()

La restriction gt() (Great Than) est l'équivalent de l'opérateur >

Exemple : les documents dont l'identifiant est strictement supérieur à 100

$query->add(Restrictions:gt("id", 100));
ge()

La restriction ge() (Great than or Equals) est l'équivalent de l'opérateur >=

Exemple : les documents dont l'identifiant est supérieur ou égal à 100

$query->add(Restrictions:ge("id", 100));
between()

La restriction between() est un raccourci pour exprimer la restriction entre a et b où a est inclus et b exclu.

Exemple : les documents dont l'identifiant est compris entre 50 et 100

// $query1 and $query2 do the same
$query1 = $myService->createQuery();
$query1->add(Restrictions:between("id", 50, 100));
 
$query2 = $myService->createQuery();
$query2->add(Restrictions:ge("id", 50)->add(Restrictions:lt("id", 100));
geProperty()

geProperty (Great than or Equals Property) permet d'appliquer l'opérateur >= sur deux propriétés d'un document

$query->add(Restrictions::geProperty("someProperty", "otherProperty"));
 
foreach ($query->find() as $doc)
{
   assert('$doc->getSomeProperty() >= $doc->getOtherProperty()');
}
gtProperty()

gtProperty (Great Than Property) permet d'appliquer l'opérateur > sur deux propriétés d'un document

$query->add(Restrictions::gtProperty("someProperty", "otherProperty"));
 
foreach ($query->find() as $doc)
{
   assert('$doc->getSomeProperty() > $doc->getOtherProperty()');
}
leProperty()

leProperty (Less than or Equals Property) permet d'appliquer l'opérateur sur deux propriétés d'un document

$query->add(Restrictions::leProperty("someProperty", "otherProperty"));
 
foreach ($query->find() as $doc)
{
   assert('$doc->getSomeProperty() <= $doc->getOtherProperty()');
}
ltProperty()

leProperty (Less Than or Equals Property) permet d'appliquer l'opérateur < sur deux propriétés d'un document

$query->add(Restrictions::ltProperty("someProperty", "otherProperty"));
 
foreach ($query->find() as $doc)
{
   assert('$doc->getSomeProperty() < $doc->getOtherProperty()');
}

Egalités partielles

like()

like() est l'équivalent de l'opérateur SQL like.

Exemple : les documents dont le libellé contient “change”.

$query1->add(Restrictions::like('label', 'change'));
foreach ($query1->find() as $doc)
{
  assert('f_util_StringUtils::contains($doc->getLabel(), 'change')');
}
 
// $query1 and $query2 do the same : MatchMode::ANYWHERE() is default "MatchMode"
$query2->add(Restrictions::like('label', 'change', MatchMode::ANYWHERE()));
...

Exemple : les documents dont le libellé commence par “change”.

$query->add(Restrictions::like('label', 'change', MatchMode::START()));
foreach ($query->find() as $doc)
{
  assert('f_util_StringUtils::beginsWith($doc->getLabel(), 'change')');
}

Exemple : les documents dont le libellé termine par “change”.

$query->add(Restrictions::like('label', 'change', MatchMode::END()));
foreach ($query->find() as $doc)
{
  assert('f_util_StringUtils::endsWith($doc->getLabel(), 'change')');
}
ilike()

ilike() se comporte comme like(), en ignorant la casse des caractères.

beginsWith()

beginsWith($propName, $value) est un raccourci pour like($propName, $value, MatchMode::START())

ibeginsWith()

ibeginsWith($propName, $value) est un raccourci pour ilike($propName, $value, MatchMode::START())

endsWith()

endsWith($propName, $value) est un raccourci pour like($propName, $value, MatchMode::END())

iendsWith()

iendsWith($propName, $value) est un raccourci pour ilike($propName, $value, MatchMode::END())

Restrictions sur les tags

Pour les étiquettes sont disponibles les restrictions hasTag() et isTagged().

hasTag()

La restriction hasTag() permet l'obtention des documents qui ont été étiquetés avec un certain tag.

Exemple : la page 1) étiquetée contextual_website_website_blog_post-detail :

$query = website_PageService::getInstance()->createQuery();
$query->add(Restrictions::descendentOf($websiteId));
$query->add(Restrictions::hasTag("contextual_website_website_blog_post-detail"));
 
$detailPage = $query->findUnique();
if ($detailPage !== null)
{
  $tagService = TagService::getInstance();
  assert('tagService->hasTag($detailPage, "contextual_website_website_blog_post-detail")');
}

isTagged()

La restriction isTagged() permet l'obtention des documents qui ont été étiquetés avec au moins un tag.

Exemple :

$query->add(Restrictions::isTagged());
 
$docs = $query->find();
foreach ($docs as $doc)
{
  assert('f_util_ArrayUtils::isNotEmpty(tagService->getTags($doc))');
}

Restrictions sur les arbres

Pour les arbres sont disponibles les restrictions suivantes :

parentOf()

parentOf() permet l'obtention du parent d'un document donné :

// $page is a website_persistentdocument_page
$query->add(Restrictions::parentOf($page->getId()));
 
$topicOrWebsite = $query->findUnique();

ancestorOf()

ancestorOf() permet l'obtention des ancêtres d'un document donné :

// $page is a website_persistentdocument_page
$query->add(Restrictions::parentOf($page->getId()));
 
$topicsOrWebsite = $query->find();
foreach ($topicsOrWebsite as $topicOrWebsite)
{
  // ...
}

childOf()

childOf() permet l'obtention des fils d'un document donné.

Exemples : pages directement placées sous une rubrique

$query = website_PageService::getInstance()->createQuery();
// $topic is a website_persistentdocument_topic
$query->add(Restrictions::parentOf($topic->getId()));
 
$topicsOrPages = $query->find();
foreach ($topicsOrPages as $topicOrPage)
{
  // ...
}

descendentOf()

descendentOf() permet l'obtention des descendants d'un document donné.

Exemple : ensemble des pages d'un site donné

$query = website_PageService::getInstance()->createQuery();
// $website is a website_persistentdocument_website
$query->add(Restrictions::descendentOf($website->getId()));
 
$topicsOrPages = $query->find();
foreach ($topicsOrPages as $topicOrPage)
{
  // ...
}

siblingOf()

siblingOf() permet l'obtention des frères d'un document donné.

Exemple : ensemble des pages situées dans la même rubrique que la page courante

// $page is a website_persistentdocument_page
$query = website_PageService::getInstance()->createQuery();
$query->add(Restrictions::siblingOf($page->getId()));
 
$pages = $query->find();
foreach ($pages as $page)
{
  // ...
}

nextSiblingOf()

nextSiblingOf() permet l'obtention des frères “droite” d'un document donné.

Exemple : ensemble des pages situées dans la même rubrique que la page courante, situées “après” selon l'ordre du plan du site

// $page is a website_persistentdocument_page
$query = website_PageService::getInstance()->createQuery();
$query->add(Restrictions::nextSiblingOf($page->getId()));
 
$pages = $query->find();
foreach ($pages as $page)
{
  // ...
}

previousSiblingOf()

previousSiblingOf() permet l'obtention des frères “gauche” d'un document donné.

Exemple : ensemble des pages situées dans la même rubrique que la page courante, situées “avant” selon l'ordre du plan du site

// $page is a website_persistentdocument_page
$query = website_PageService::getInstance()->createQuery();
$query->add(Restrictions::previousSiblingOf($page->getId()));
 
$pages = $query->find();
foreach ($pages as $page)
{
  // ...
}

Gestion de l'opérateur logique OU

Restrictions::orExp() permet la gestion de l'opérateur logique OU. Les arguments sont un nombre variable de Restrictions.

Exemple : ensemble des pages publiées qui utilisent le gabarit webfactory/tplOne ou le gabarit webfactory/tplTwo 2)

$query = website_PageService::getInstance()->createQuery()
  ->add(Restrictions::published())
  ->add(Restrictions::orExp(Restrictions::eq("template", "webfactory/tplOne"), Restrictions::eq("template", "webfactory/tplTwo")));

Appliquer des restrictions à des "sous-documents"

Hormis quelques exceptions comme eq() ou isEmpty(), filtrer sur les propriétés Document n'est pas possible directement par simple application de restrictions.

Pour filtrer sur une des propriétés d'un document contenu stocké dans une propriété document il faut utiliser la méthode createCriteria() sur l'objet Query.

createCriteria() retourne un objet, Criteria 3), semblable à Query, qui permet l'ajout de restrictions qui porteront sur le ou les “sous-document”. Conceptuellement, on peut assimiler cet objet à une sous requête. Du point de vue SQL, l'opération se traduira par une jointure avec la table du type de la propriété.

Ainsi, pour obtenir les rubriques dont la page d'index a un libellé contenant “Change”, on pourra procéder comme suit 4) :

$query = website_TopicService::getInstance()->createQuery();
// website_persistentdocument_topic has a mono-valued property "indexPage" that stores a website_persistentdocument_page document
$criteria = $query->createCriteria('indexPage');
$criteria->add(Restrictions::like("label", "Change"));
 
foreach ($query->find() as $topic)
{
  assert('f_util_StringUtils::contains($topic->getIndexPage()->getLabel(), "Change")');
}

Les Criteria peuvent être cumulés. On pourra reprendre l'exemple précédent en demandant en plus que l'habillage de la page d'index aie un libellé contenant lui aussi “Change” :

$query = website_TopicService::getInstance()->createQuery();
 
$pageCriteria = $query->createCriteria('indexPage');
$pageCriteria->add(Restrictions::like("label", "Change"));
 
// website_persistentdocument_page has a mono-valued property "skin" that stores a skin_persistentdocument_skin document
$skinCriteria = $pageCriteria->createCriteria('skin');
$skinCriteria->add(Restrictions::like("label", "Change"));
 
foreach ($query->find() as $topic)
{
  assert('f_util_StringUtils::contains($topic->getIndexPage()->getLabel(), "Change")');
  assert('f_util_StringUtils::contains($topic->getIndexPage()->getSkin()->getLabel(), "Change")');
}

Restreindre la liaison à un sous-type

Le deuxième argument de createCriteria() permet de restreindre la liaison à un sous-type du type déclaré par la liaison.

Exemple : le document modules_website/page est étendu par le document modules_website/pagereference. La propriété indexPage des rubriques, de type modules_website/page peut donc contenir des instances directes de modules_website/page ou de type modules_website/pagereference.

Pour obtenir les rubriques dont la page d'index est une modules_website/pagereference dont le libellé contient “Change”, on pourra écrire :

$query = website_TopicService::getInstance();
$indexCriteria = $query->createCriteria("indexPage", "modules_website/pagereference");
$indexCriteria->add(Restrictions::like("label", "Change"));
 
foreach ($query->find() as $topic)
{
  assert('$topic->getIndexPage() instanceof website_persistentdocument_pagereference');
  assert('f_util_StringUtils::contains($topic->getIndexPage()->getLabel(), "Change")');
}

Raccourci syntaxique pour les Criteria simples

Lorsque l'objet Criteria ne contient qu'une seule restriction, vous pouvez utiliser le raccourci syntaxique “notation pointée”.

Reprenant l'exemple des rubriques dont le libellé de la page d'index contient “Change” :

$query = website_TopicService::getInstance()->createQuery();
$query->add(Restrictions::like("indexPage.label", "Change"));

Attention à ne pas cumuler ces raccourcis sur la même propriété Document : vous multiplieriez les jointures inutilement.

Rajouter la restriction sur le libellé du skin ne doit pas se faire de la manière suivante (même si cela fonctionne), car on fait une jointure de trop sur la table d'indexPage :

// This works but is not effective because you make two joins on indexPage's table
$query = website_TopicService::getInstance()->createQuery();
$query->add(Restrictions::like("indexPage.label", "Change"));
$query->add(Restrictions::like("indexPage.skin.label", "Change"));

On préférera l'implémentation suivante :

$query = website_TopicService::getInstance()->createQuery();
$pageCriteria = $query->createCriteria("indexPage");
$pageCriteria->add(Restrictions::like("label", "Change"));
$pageCriteria->add(Restrictions::like("skin.label", "Change"));

Simuler l'existence d'une propriété document

Liaison par identifiant

Certains documents sont liés à d'autres documents d'une relation “faible”. C'est le cas de l'objet commentaire (modules_comment/comment) qui ne stocke que l'identifiant du document commenté, dans la propriété targetId. Query::createPropertyCriteria() permet de créer des Criteria sur ces propriétés.

Exemple : les commentaires portant sur des produits dont le libellé contient “Change”

$query = comment_CommentService::getInstance()->createQuery();
$productCriteria = $query->createPropertyCriteria("targetId", "modules_catalog/product");
$productCriteria->add(Restrictions::like("label", "Change"));
 
foreach ($query->find() as $comment)
{
  $product = DocumentHelper::getDocumentInstance($comment->getTargetId());
  assert('$product instanceof catalog_persistentdocument_product');
  assert('f_util_StringUtils::contains($product->getLabel(), "Change")');
}

La relation peut être interrogée dans le sens inverse.

Exemple : les produits qui ont été noté au moins une fois plus de 4 ; ici targetId est définie sur le criteria et non sur la requête de base :

$query = catalog_ProductService::getInstance()->createQuery();
$commentCriteria = $query->createPropertyCriteria("targetId", "modules_comment/comment");
$commentCriteria->add(Restrictions::gt("rating", 4));

Propriétés inverses

Lorsqu'une propriété Document a été déclarée inverse, RBS Change simule l'existence de la propriété sur le document cible.

Exemple : le produit “compilé” catalog/compiledproduct a une propriété inverse product, de type modules_catalog/product. Ceci a pour effet de simuler l'existence de la propriété compiledproduct de type modules_catalog/compiledproduct sur le document modules_catalog/product.

Pour obtenir les commentaires portant sur des produits dont le prix par défaut (ou prix “boutique”) est au moins de 20 euros dans un site donné, on peut donc écrire :

$websiteId = ...;
$query = comment_CommentService::getInstance()->createQuery();
$productCriteria = $query->createPropertyCriteria("targetId", "modules_catalog/product");
$productCriteria->createCriteria("compiledproduct")
  ->add(Restrictions::ge("price", 20))
  ->add(Restrictions::eq("websiteId", $websiteId));
 
foreach ($query->find() as $comment)
{
  $product = DocumentHelper::getDocumentInstance($comment->getTargetId());
  assert('$product instanceof catalog_persistentdocument_product');
  assert('f_util_StringUtils::contains($product->getLabel(), "Change")');
}

Jointures "ouvertes"

Il est parfois nécessaire d'avoir des documents dont certaines propriétés de type document satisfont certains critères soit sont non définies. En SQL on ferait un “left join”, avec RBS Change, on crée un “leftCriteria”.

Ainsi, pour obtenir les clients n'ayant jamais commandé ou dont les commandes ont été annulées :

$query = customer_CustomerService::getInstance()->createQuery();
$subQuery = $query->createLeftCriteria("order")
  ->add(Restrictions::eq("orderStatus", order_OrderService::CANCELED));

Note : dans cet exemple, la propriété order de customer est de plus simulée du fait de la propriété inverse “customer” de order.

Projections

Lorsque que l'on sait que seules certaines propriétés des documents résultats vont au final être utilisées, on peut économiser le chargement des documents en effectuant des projections. La méthode Query::find() retourne alors un tableau dont les éléments sont des tableaux associatifs donnant accès aux valeurs des propriétés choisies.

Pour effectuer des projections, on utilise la méthode setProjection() de l'objet Query.

Ainsi, pour n'obtenir que l'identifiant et le libellé des documents satisfaisant la requête :

$query->setProjection(Projections::property("id"), Projections::property("label"));
foreach ($query->find() as $row)
{
  echo $row["id"]." ".$row["label"]."\n";
}

Lorsque la propriété en question est un document, le tableau contient le ou les documents en question :

$query = website_TopicService::getInstance()->createQuery();
$query->setProjection(Projections::property("id"), Projections::property("label"), Projections::property("indexPage"));
foreach ($query->find() as $row)
{
  $indexPage = $row["indexPage"];
  echo $row["id"]." ".$row["label"].", index : ".$indexPage->getLabel()."\n";
}

Raccourci findColumn()

Lorsqu'on ne s'intéresse qu'à une des propriétés, on peut utiliser le raccourci Query::findcolumn() qui permet d'obtenir un tableau contenant directement les valeurs de la propriété.

Ainsi, pour obtenir la liste des identifiants des documents satisfaisant la requête, on pourra procéder comme suit :

$query->setProjection(Projections::property("id"));
foreach ($query->findColumn("id") as $id)
{
  echo $id."\n";
}

Projections::rowCount()

Projections::rowCount() permet le compte des documents

Exemple : compter le nombre de pages publiées, tous sites confondus

$query = website_PageService::getInstance()->createQuery()->add(Restrictions::published());
$query->setProjection(Projections::rowCount());
$result = $query->find();
echo "There are ".$result[0]["rowcount"]." published pages\n";

Projections::groupProperty()

Projections::groupProperty() permet de grouper les lignes de résultat selon la valeur d'une propriété donnée.

Exemple : répartition de la propriété “template” sur l'ensemble des pages publiées

Le code suivant :

$query = website_PageService::getInstance()->createQuery();
$query->add(Restrictions::published());
$query->setProjection(Projections::groupProperty('template'), Projections::rowCount());
 
var_export($query->find());

Donne un résultat du type (où X est le nombre de pages utilisant le gabarit webfactory/tplOne et Y le nombre de pages utilisant webfactory/tplTwo):

array (
  0 => 
  array (
    'template' => 'webfactory/tplOne',
    'rowcount' => X,
  ),
  1 => 
  array (
    'template' => 'webfactory/tplTwo',
    'rowcount' => Y,
  ),
  ...
  )

Appliquer une fonction sur une propriété

La classe Projections fournit un certain nombre d'opérations applicables à des propriété numériques :

  • Projections::min() : valeur minimale d'une propriété
  • Projections::max() : valeur maximale d'une propriété
  • Projections::avg() : valeur moyenne d'une propriété
  • Projections::sum() : somme des valeurs d'une propriété

Leur signature est la même : Projections::<opName>($propName, $as = <opName>) où :

  • $propName est le nom de la propriété à laquelle appliquer la fonction
  • $as est le nom de la clef utilisée pour stocker la valeur retournée. Par défaut $as vaut le nom de l'opération.

Exemple : prix “boutique” moyen des produits d'un rayon donné

$websiteId = ...;
$shelfId = ...;
 
$query = catalog_CompiledproductService::getInstance()->createQuery();
$query->add(Restrictions::eq("websiteId", $websiteId));
$query->add(Restrictions::eq("shelfId", $shelfId));
$query->setProjection(Projections::avg("price", "averagePrice"));
$result = $query->findUnique();
 
echo "Average price is ".$result["averagePrice"]."\n";

Filtrer sur résultat d'une fonction

La classe HavingRestrictions fournit des restrictions applicables au résultat d'une fonction sur une propriété :

  • HavingRestrictions::between() : entre deux valeurs, bornes haute exclues si setStrict() est invoquée
  • HavingRestrictions::eq() : égale à une valeur
  • HavingRestrictions::ge() : supérieur ou égal à une valeur
  • HavingRestrictions::gt() : supérieur strictement à une valeur
  • HavingRestrictions::in() : élément d'un ensemble de valeurs
  • HavingRestrictions::notin() : n'est pas élément d'un ensemble de valeurs
  • HavingRestrictions::le() : inférieur ou égal à une valeur
  • HavingRestrictions::lt() : inférieur strictement à une valeur
  • HavingRestrictions::ne() : différent d'une valeur

Exemple : les clients dont les commandes payées ont en moyenne un montant total hors taxes supérieur ou égal à 20 euros

$query = customer_CustomerService::getInstance()->createQuery();
$orderQuery = $query->createCriteria('order');
$orderQuery->setProjection(Projections::avg("totalAmountWithoutTax", "averageOrder"));
$orderQuery->createCriteria('bill')
           ->add(Restrictions::published())
           ->add(Restrictions::eq('status', order_BillService::SUCCESS));
$query->having(HavingRestrictions::ge("averageOrder", 20));

Tri

Ordonner la requête se fait en utilisant la méthode Query::addOrder() qui accepte un objet Order, que l'on obtient depuis les méthodes statiques :

  • Order::asc(“propName”) : tri croissant sur la propriété “propName”
  • Order::desc(“propName”) : tri décroissant sur la propriété “propName”

Exemple : tri croissant selon le libellé

$query->addOrder(Order::asc('label'))

Les tris peuvent être cumulés, en faisant plusieurs appels à Query::addOrder.

Exemple : tri croissant selon le libellé puis tri décroissant selon l'auteur :

$query->addOrder(Order::asc('label'))
  ->addOrder(Order::desc('author'));

Un appel à Order::ignoreCase() rend le tri insensible à la casse des caractères. Vous pouvez également utiliser les raccourcis Order::iasc() et Order::idesc().

Exemple : tri croissant selon le libellé puis tri décroissant insensible à la casse selon l'auteur :

// $query1 and $query2 have the same order
$query1->addOrder(Order::asc('label'))
  ->addOrder(Order::desc('author')->ignoreCase());
 
$query2->addOrder(Order::asc('label'))
  ->addOrder(Order::idesc('author'));

Trier sur une propriété d'un sous-document nécessite qu'un Criteria aie été crée.

Exemple : tri croissant de rubriques selon le libellé de leur page d'index

$query = website_TopicService::getInstance()->createQuery();
$indexCriteria = $query->createCriteria("indexPage");
$query->addOrder(Order::asc("indexPage.label"));
foreach ($query->find() as $topic)
{
  echo $topic->getIndexPage()->getLabel()." : ".$topic->getLabel()."\n";
}

Pagination

Limiter le nombre de résultats

Pour limiter le nombre de résultats retournés, on utilise la méthode Query::setMaxResults().

Exemple : retourner au plus 10 documents

$query->setMaxResults(10);
assert('count($query->find()) <= 10');

Paginer un résultat

Pour paginer un résultat, on combine Query::setMaxResults() et Query::setFirstResult() :

Exemple : résultats 41 à 50 (inclus)

$query->setFirstResult(40)->setMaxResults(10);

N.B : l'index du premier résultat est 0.

1)
le tag étant ici contextuel au document website, il y a au maximum un descendant d'un site étiqueté “contextual_website_website_blog_post-detail”
2)
cet exemple peut aussi être implémenté avec in()
3)
de nom complet f_persistentdocument_criteria_Criteria
4)
l'objet topic déclarant une propriété indexPage de type modules_website/page
ref/docs/requetes_de_documents.txt · Dernière modification: 2017/01/19 14:54 (modification externe)