2017-10-18 6 views
1

J'essaye de faire un select all pour obtenir trois colonnes à partir d'une seule table, puis simplement utiliser le résultat sous forme de tableau. Sans le coût d'une boucle.Silverstripe 3.5 - Comment faire une requête pour des colonnes spécifiques et retourner un tableau

J'ai essayé en utilisant la méthode ORM:

DataObject::get('City')->sort('Name ASC')->toNestedArray(); 

Cela me donne un tableau parfaitement. Mais je ne peux pas voir un moyen de ne retourner que les colonnes que je veux. Il retourne toutes les colonnes. C'est un problème parce que je suis en train de coder ce tableau et le paquet est 3 fois plus grand que nécessaire.

donc j'ai essayé cela en utilisant SQLQuery à la place:

DB::query('SELECT "ID","Name","ParentID" FROM "City"'); 

Maintenant, cela me permet de sélectionner les trois champs, mais pour autant que je sache, il n'y a pas de méthode pour renvoyer cette requête sous la forme d'un tableau comme toNestedArray()

Recherché haut et bas mais rien ne convient. Des idées?

Editer: J'aurais dû mentionner que j'ai essayé setQueriedColumns() désolé. Cela ne semble pas être destiné à ce que je fais ici.

$cities = AspireCity::get()->sort(['Name' => 'ASC'])->setQueriedColumns(['ID', 'Name']); 
Debug::dump($cities->toNestedArray()); 

Sorties:

Array 
(
    [0] => Array 
     (
      [ClassName] => City 
      [LastEdited] => 2017-09-26 11:14:16 
      [Name] => Acacia Bay 
      [ID] => 70 
      [RecordClassName] => City 
      [Created] => 
      [ParentID] => 9 
     ) 

    [1] => Array 
     (
      [ClassName] => City 
      [LastEdited] => 2017-09-26 11:14:16 
      [Name] => Ahaura 
      [ID] => 71 
      [RecordClassName] => City 
      [Created] => 
      [ParentID] => 9 
     ) 
+0

Caisse http://api.silverstripe.org/fr/3.1/class-DataList.html # _setQueriedColumns –

+0

Merci. J'ai essayé mais ça ne semble pas fonctionner comme prévu. Voir le modifier à ma question pour plus de détails. Peut-être toNestedArray() l'ignore? – Aaryn

+1

Je suis assez sûr que lorsque vous utilisez l'ORM, les champs du système dataobject sont toujours affichés. Ce sont ClassName, LastEdited, ID, Created. 'setQueriedColumns' vous permet ensuite de choisir les champs que vous avez ajoutés à votre modèle DataObject. Si vous voulez seulement les champs ID, Name, ParentID, vous devrez utiliser les requêtes sql comme vous l'avez fait dans votre réponse ci-dessous. –

Répondre

0

J'ai donc décidé qu'il s'agissait d'un cas de dépendance excessive vis-à-vis des méthodes d'assistance SS existantes. Alors que toNestedArray() est très pratique, mon objectif était de penser principalement que je pouvais éviter une boucle en l'utilisant. Quand en réalité, la méthode est bien sûr une boucle. Donc, ma préoccupation est sans fondement.

L'objectif le plus important était de réduire l'ensemble de données au moment de la requête. Donc, la solution se concentre simplement là-dessus.

// Inject the default country/city/suburb data as vars so they can be easily filtered. 
$location['countries'] = DB::query('SELECT "ID","Description" FROM "Country" ORDER BY "ID" ASC'); 
$location['cities'] = DB::query('SELECT "ID","Name","ParentID" FROM "City" ORDER BY "Name" ASC'); 
$location['suburbs'] = DB::query('SELECT "ID","Name","ParentID" FROM "Suburb" ORDER BY "Name" ASC'); 

$masterLocationArray = []; 
foreach($location as $key => $data) { 
    $locationArray = []; 
    foreach($data as $item) { 
     $locationArray[] = $item; 
    } 
    $masterLocationArray[$key] = $locationArray; 
} 

// $masterLocationArray is our filtered, tidy array. Do stuff with it 
+0

Je vous suggère d'utiliser 'SQLSelect' sur les requêtes DB brutes. Cela assurera la compatibilité avec les différents RDBM et réduira le risque d'attaques par injection. – bummzack

+0

Excellente idée. Merci. – Aaryn

2

Selon le API Docs, setQueriedColumns() est votre ami:

De votre question, je suppose que le DataObject vous voulez interroger est appelé City, donc nous avons besoin que cela extraire toutes les villes de la base de données:

City::get(); 

Ceci renvoie un DataList et interroge la base de données lorsque vous en avez besoin. Jusqu'à présent, votre base de données ne sait rien de ce que vous voulez. Alors affinons-le, triez-le par "Name" ASC. J'aime la syntaxe de tableau beaucoup plus, à mon humble avis, il est plus facile à lire, et si vous devez trier contre une deuxième rangée, il suffit d'ajouter au tableau:

City::get() 
    ->sort(['Name' => 'ASC']); 

Maintenant que vous vouliez, pour certaines raisons, juste quelques colonnes arrière. Comme je ne sais pas quelle base de données champs votre City DataObject a, je suppose que vous voulez juste « Nom » et « ZIP »:

City::get() 
    ->sort(['Name' => 'ASC']) 
    ->setQueriedColumns(['Name', 'ZIP']); 

Cela limite les colonnes et vous pouvez requêtés ajouter toNestedArray() pour obtenir les données sur que un tableau pur vintage. Cela peut être utile pour transmettre les données à une API, mais il est peut-être préférable de laisser les objets et d'utiliser la logique spécifique à City dans votre code.

+0

Désolé j'aurais dû mentionner que j'ai regardé setQueriedCoumns. Je pensais que ce n'était pas pertinent. Ne semble pas servir à cette fin $ cities = City :: get() -> sort (['Name' => 'ASC']) -> setQueriedColumns (['ID', 'Nom']); Debug :: dump ($ cities-> toNestedArray()); Génère tous les champs de la table – Aaryn

+0

vous pouvez voir la requête générée en ajoutant '-> sql()' à la liste de données. Ma conjecture est, qu'il réduit d'abord la requête, mais quand votre course 'toNestedArray()' laster, il récupère les autres colonnes. – wmk

+0

Na J'ai effectivement testé une boucle sur la liste sans utiliser toNestedArray(), Tous les champs étaient là. Vous ne savez pas pourquoi setQueriedColumns ne semble pas faire ce qu'il dit. Dans mon cas, ce n'est pas le cas. – Aaryn