Créez des requêtes imbriquées complexes contenant plusieurs champs et pages et renvoyez un tableau qui peut être analysé en JSON. Ceci est très utile pour récupérer des données pour SPA et PWA.
Vous pouvez utiliser le module pour transformer une page ProcessWire ou un PageArray – même RepeaterMatrixPageArrays – en un tableau ou un JSON. Les requêtes peuvent être imbriquées et contenir des fermetures comme fonctions de rappel. Certains types de champs sont transformés automatiquement, comme Pageimages ou MapMarker.
Consultez la page des versions et abonnez-vous aux mises à jour.
Il est recommandé d'installer via l'administrateur ProcessWire " Modules " > " Site " > " Ajouter un nouveau " > " Ajouter un module à partir du répertoire " en utilisant le nom de classe PageQueryBoss
.
Téléchargez les fichiers depuis Github ou le référentiel ProcessWire : https://modules.processwire.com/modules/page-query-builder/
Il existe deux méthodes principales :
$page->pageQueryJson($query);
$page->pageQueryArray($query);
La requête peut contenir des paires clé et valeur, ou uniquement des clés. Il peut être imbriqué et contenir des fermetures pour les valeurs dynamiques. Pour illustrer un court exemple :
// simple query:
$query = [
'height',
'floors',
];
$pages->find('template=skyscraper')->pageQueryJson($query);
Les requêtes peuvent être imbriquées, contenir des noms de pages, des noms de modèles ou contenir des fonctions et des sélecteurs ProcessWire :
// simple query:
$query = [
'height',
'floors',
'images', // < some fileds contain default sub-queries to return data
'files' => [ // but you can also overrdide these defaults:
'filename'
'ext',
'url',
],
// Assuming there are child pages with the architec template, or a
// field name with a page relation to architects
'architect' => [ // sub-query
'name',
'email'
],
// queries can contain closure functions
'querytime' => function($parent){
return "Query for $parent->title was built ".time();
}
];
$pages->find('template=skyscraper')->pageQueryJson($query);
Un seul nom de champ ; height
ou floors
ou architects
Le module peut gérer les champs suivants :
Un nom de modèle ; skyscraper
ou city
Nom d'une page enfant (page.child.name=pagename) ; my-page-name
Un sélecteur ProcessWire ; template=building, floors>=25
Un nouveau nom pour l'index renvoyé passé par un délimiteur #
:
// the field skyscraper will be renamed to "building":
$query = ["skyscraper`#building`"]
N'importe laquelle des clés ci-dessus (1-5) avec un nouveau tableau de sous-requêtes imbriqué :
$query = [
'skyscraper' => [
'height',
'floors'
],
'architect' => [
'title',
'email'
],
]
Une clé nommée et une fonction de fermeture pour traiter et renvoyer une requête. La fermeture obtient l'objet parent comme argument :
$query = [
'architecs' => function($parent)
{
$architects = $parent->find('template=architect');
return $architects->arrayQuery(['name', 'email']);
// or return $architects->explode('name, email');
}
]
$query = [
'title',
'subtitle',
// naming the key invitation
'template=Invitation, limit=1#invitation' => [
'title',
'subtitle',
'body',
],
// returns global speakers and local ones...
'speakers' => function($page){
$speakers = $page->speaker_relation;
$speakers = $speakers->prepend(wire('pages')->find('template=Speaker, global=1, sort=-id'));
// build a query of the speakers with
return $speakers->arrayQuery([
'title#name', // rename title field to name
'subtitle#ministry', // rename subtitle field to ministry
'links' => [
'linklabel#label', // rename linklabel field to minlabelistry
'link'
],
]);
},
// Child Pages with template=Program
'Program' => [
'title',
'summary',
'start' => function($parent){ // calculate the startdate from timetables
return $parent->children->first->date;
},
'end' => function($parent){ // calculate the endate from timetables
return $parent->children->last->date;
},
'Timetable' => [
'date', // date
'timetable#entry'=> [
'time#start', // time
'time_until#end', // time
'subtitle#description', // entry title
],
],
],
// ProcessWire selector, selecting children > name result "location"
'template=Location, limit=1#location' => [
'title#city', // summary title field to city
'body',
'country',
'venue',
'summary#address', // rename summary field to address
'link#tickets', // rename ticket link
'map', // Mapmarker field, automatically transformed
'images',
'infos#categories' => [ // repeater matrix! > rename to categories
'title#name', // rename title field to name
'entries' => [ // nested repeater matrix!
'title',
'body'
]
],
],
];
if ($input->urlSegment1 === 'json') {
header('Content-type: application/json');
echo $page->pageQueryJson($query);
exit();
}
Les paramètres des modules sont publics. Ils peuvent être directement modifiés, par exemple :
$modules->get('PageQueryBoss')->debug = true;
$modules->get('PageQueryBoss')->defaults = []; // reset all defaults
Certains types de champs ou modèles sont livrés avec des sélecteurs par défaut, comme Pageimages, etc. Voici les requêtes par défaut :
// Access and modify default queries: $modules->get('PageQueryBoss')->defaults['queries'] = …
public $defaults = [
'queries' => [
'Pageimage' => [
'basename',
'url',
'httpUrl',
'description',
'ext',
'focus',
],
'Pageimages' => [
'basename',
'url',
'httpUrl',
'description',
'ext',
'focus',
],
'Pagefile' => [
'basename',
'url',
'httpUrl',
'description',
'ext',
'filesize',
'filesizeStr',
'hash',
],
'Pagefiles' => [
'basename',
'url',
'httpUrl',
'description',
'ext',
'filesize',
'filesizeStr',
'hash',
],
'MapMarker' => [
'lat',
'lng',
'zoom',
'address',
],
'User' => [
'name',
'email',
],
],
];
Ces valeurs par défaut ne seront utilisées que s'il n'y a pas de sous-requête imbriquée pour le type respectif. Si vous interrogez un champ avec des données complexes et ne fournissez pas de sous-requête, il sera transformé en conséquence :
$page->pageQueryArry(['images']);
// returns something like this
'images' => [
'basename',
'url',
'httpUrl',
'description',
'ext',
'focus'=> [
'top',
'left',
'zoom',
'default',
'str',
]
];
Vous pouvez toujours fournir votre propre sous-requête, afin que les valeurs par défaut ne soient pas utilisées :
$page->pageQueryArry([
'images' => [
'filename',
'description'
],
]);
Vous pouvez également remplacer les valeurs par défaut, par exemple
$modules->get('PageQueryBoss')->defaults['queries']['Pageimages'] = [
'basename',
'url',
'description',
];
L'index des éléments imbriqués peut être ajusté. Cela se fait également avec les valeurs par défaut. Il y a 3 possibilités :
Il s'agit du paramètre par défaut. Si vous avez un champ qui contient des sous-éléments, le nom sera la clé dans les résultats :
// example
$pagesByName = [
'page-1-name' => [
'title' => "Page one title",
'name' => 'page-1-name',
],
'page-2-name' => [
'title' => "Page two title",
'name' => 'page-2-name',
]
]
Si un objet est répertorié dans $defaults['index-id'], l'identifiant sera la clé dans les résultats. Actuellement, aucun élément n'est répertorié par défaut pour l'index basé sur l'identifiant :
$modules->get('PageQueryBoss')->defaults['index-id']['Page'];
// example
$pagesById = [
123 => [
'title' => "Page one title",
'name' => 123,
],
124 => [
'title' => "Page two title",
'name' => 124,
]
]
Par défaut, quelques champs sont automatiquement transformés pour contenir des index numérotés :
// objects or template names that should use numerical indexes for children instead of names
$defaults['index-n'] => [
'skyscraper', // template name
'Pageimage',
'Pagefile',
'RepeaterMatrixPage',
];
// example
$images = [
0 => [
'filename' => "image1.jpg",
],
1 => [
'filename' => "image2.jpg",
]
]
Astuce : lorsque vous supprimez la clé Pageimage
de $defaults['index-n'], l'index sera à nouveau basé sur le nom.
Voici quelques fonctions de fermeture d'aide que vous voudrez peut-être utiliser ou qui pourraient vous aider comme point de départ pour la vôtre (faites-moi savoir si vous avez la vôtre) :
$query = ['languages' => function($page){
$ar = [];
$l=0;
foreach (wire('languages') as $language) {
// build the json url with segment 1
$ar[$l]['url']= $page->localHttpUrl($language).wire('input')->urlSegment1;
$ar[$l]['name'] = $language->name == 'default' ? 'en' : $language->name;
$ar[$l]['title'] = $language->getLanguageValue($language, 'title');
$ar[$l]['active'] = $language->id == wire('user')->language->id;
$l++;
}
return $ar;
}];
À l'aide du module ContinentsAndCountries, vous pouvez extraire le code ISO et les noms des pays :
$query = ['country' => function($page){
$c = wire('modules')->get('ContinentsAndCountries')->findBy('countries', array('name', 'iso', 'code'),['code' =>$page->country]);
return count($c) ? (array) $c[count($c)-1] : null;
}];
À l'aide d'un RepeaterMatrix, vous pouvez créer une chaîne de modèle pour votre interface. Ceci est utile pour les boutons, les étiquettes, etc. Le code suivant utilise un répéteur avec les strings
de nom a une key
et un champ body
, le tableau renvoyé contient le champ key
comme, vous devinez, les clés et le champ body
comme valeurs :
// build custom translations
$query = ['strings' => function($page){
return array_column($page->get('strings')->each(['key', 'body']), 'body', 'key');
}];
En utilisant la configuration suivante, vous pouvez gérer le multilingue et renvoyer votre langue par défaut si la langue demandée n'existe pas. L'url est composée comme ceci : page/path/{language}/{content-type}
par exemple : api/icf/zurich/conference/2019/de/json
// get contenttype and language (or default language if not exists)
$lang = wire('languages')->get($input->urlSegment1);
if(!$lang instanceof Nullpage){
$user->language = $lang;
} else {
$lang = $user->language;
}
// contenttype segment 2 or 1 if language not present
$contenttype = $input->urlSegment2 ? $input->urlSegment2 : $input->urlSegment1;
if ($contenttype === 'json') {
header('Content-type: application/json');
echo $page->pageQueryJson($query);
exit();
}
Le module respecte wire('config')->debug. Il s'intègre à TracyDebug. Vous pouvez le remplacer comme ceci :
// turns on debug output no mather what:
$modules->get('PageQueryBoss')->debug = true;
Rendre les valeurs par défaut configurables via Backend. Comment cela pourrait-il être fait avec style avec les requêtes par défaut ?
Voir le fichier LICENSE inclus pour le texte complet de la licence.
© noelboss.com