eZ Publish är ett mycket kompetent system för innehållshantering, men ibland kan man behöva gå förbi alla praktiska funktioner som finns. Bland annat kan det vara aktuellt att göra detta när man vill lista en stor mängd data i tabellform, till exempel en medlemslista. Vi hade ett projekt där kunden ville att ungefär 900 medlemmar skulle visas samtidigt i en lista, samt på en Googlekarta, vilket gjorde att det inte blev riktigt optimalt att använda de befintliga funktionerna i eZ Publish, det gick helt enkelt för långsamt. För att lösa problemet byggde jag en modul med en custom fetch som tog hand om det hela istället för de inbyggda fetch-funktionerna. Hur man bygger en egen modul finns väl dokumenterat och det är inget jag tänker beskriva nu, däremot fanns det väldigt lite information (i princip obefintlig) om hur man hämtar ut information direkt ur databasen. Genom att studera databasen och med hjälp av lite reverse enginering kom jag fram till följande.
Om man utgår från tabellen ezcontentobject_tree
som representerar nodträdet så kan man köra en sql-fråga för att få fram alla barn till en viss nod.
SELECT et.contentobject_id id
FROM ezcontentobject_tree et
WHERE et.parent_node_id = 2
Satsen ovan ger följande resultat.
+------+
| id |
+------+
| 58 |
| 59 |
| 76 |
| 122 |
+------+
Alltså, en lista på de objekt-id’n som finns direkt under noden med id 2.
Information om varje objekt lagras i tabellen ezcontentobject_attribute, därför gör man en JOIN för att få ut även denna information. Satsen blir då så här.
SELECT et.contentobject_id id,
en.data_text namn
FROM ezcontentobject_tree et
LEFT JOIN ezcontentobject_attribute en
ON et.contentobject_id = en.contentobject_id
AND et.contentobject_version = en.version
AND en.contentclassattribute_id = 361
WHERE et.parent_node_id = 97
AND et.contentobject_is_published = 1
AND et.is_hidden = 0
AND et.is_invisible = 0
Här hämtas alltså information från tabellen ezcontentobject_attribute med contentclassattribut_id lika med 361, vilket är objektets namn i detta fall. Detta id hittar man i administrationsgränssnittet under Setup->Classes och sedan den klass objektet är en instans av. Se bilden nedan.
Jag har i satsen ovan lagt till tre villkor i slutet som ser till att man bara får träffar på noder som är publicerade och synliga på sajten.
Resultatet blir.
+------+-----------------------------+
| id | namn |
+------+-----------------------------+
| 398 | COOP OBS! LILLESTRØM |
| 399 | COOP OBS! LØREN |
| 400 | COOP OBS! MARIERO |
| 401 | COOP OBS! MORENEN |
| 402 | COOP OBS! NORD AVD. HARSTAD |
+------+-----------------------------+
För varje attribut man vill hämta ut måste man alltså göra en extra JOIN enligt ovan.
Om man vill hämta attribut av typen ezurl måste man göra två extra JOINs eftersom själva urlen sparas i tabellen ezurl
och korskopplas i tabellen ezurl_object_link
. Det man måste lägga till är alltså.
LEFT JOIN ezcontentobject_attribute eu
ON et.contentobject_id = eu.contentobject_id
AND et.contentobject_version = eu.version
AND eu.contentclassattribute_id = 367
LEFT JOIN ezurl_object_link eol
ON eu.id = eol.contentobject_attribute_id
AND eu.version = eol.contentobject_attribute_version
LEFT JOIN ezurl eurl
ON eol.url_id = eurl.id
Den kompletta sql-frågan blev så här.
SELECT et.contentobject_id id,
en.data_text name,
etel.data_text tele,
efa.data_text fax,
pnr.data_text postnr,
por.data_text postort,
em.data_text email,
eurl.url url
FROM ezcontentobject_tree et
LEFT JOIN ezcontentobject_attribute en
ON et.contentobject_id = en.contentobject_id
AND et.contentobject_version = en.version
AND en.contentclassattribute_id = 361
LEFT JOIN ezcontentobject_attribute etel
ON et.contentobject_id = etel.contentobject_id
AND et.contentobject_version = etel.version
AND etel.contentclassattribute_id = 362
LEFT JOIN ezcontentobject_attribute efa
ON et.contentobject_id = efa.contentobject_id
AND et.contentobject_version = efa.version
AND efa.contentclassattribute_id = 363
LEFT JOIN ezcontentobject_attribute pnr
ON et.contentobject_id = pnr.contentobject_id
AND et.contentobject_version = pnr.version
AND pnr.contentclassattribute_id = 364
LEFT JOIN ezcontentobject_attribute por
ON et.contentobject_id = por.contentobject_id
AND et.contentobject_version = por.version
AND por.contentclassattribute_id = 365
LEFT JOIN ezcontentobject_attribute em
ON et.contentobject_id = em.contentobject_id
AND et.contentobject_version = em.version
AND em.contentclassattribute_id = 366
LEFT JOIN ezcontentobject_attribute eu
ON et.contentobject_id = eu.contentobject_id
AND et.contentobject_version = eu.version
AND eu.contentclassattribute_id = 367
LEFT JOIN ezurl_object_link eol
ON eu.id = eol.contentobject_attribute_id
AND eu.version = eol.contentobject_attribute_version
LEFT JOIN ezurl eurl
ON eol.url_id = eurl.id
WHERE et.parent_node_id = 97
AND et.contentobject_is_published = 1
AND et.is_hidden = 0
AND et.is_invisible = 0
Resultatet av frågan blir.
+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+
| id | name | tele | fax | postnr | postort | email | url |
+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+
| 398 | COOP OBS! LILLESTRØM | 63 80 55 00 | 63 81 38 30 | 2000 | LILLESTRØM | xxxxx.xxxxx@obs.coop.no | NULL |
| 399 | COOP OBS! LØREN | 22 65 50 65 | 22 64 57 17 | 0513 | OSLO | xxx.xxx.xxx.xxx@obs.coop.no | NULL |
| 400 | COOP OBS! MARIERO | 51 82 50 50 | 51 82 50 51 | 4095 | STAVANGER | xxxx.xxxxxxx@obs.coop.no | NULL |
| 401 | COOP OBS! MORENEN | 69 84 65 00 | 69 84 65 51 | 1859 | SLITU | xxxxxx.xxxxxxx@obs.coop.no | NULL |
| 402 | COOP OBS! NORD AVD. HARSTAD | 77 02 89 00 | 77 02 89 01 | 9406 | HARSTAD | xxxxxx.xxxxxx.x@nord.coop.no | NULL |
+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+
Den här datan använde vi sedan för att bygga en lista över medlemmarna. Vi valde dessutom att generera html-koden direkt i modulen eftersom vi fortfarande inte var helt nöjda med prestandan när vi använde de befintliga template-funktionerna.
Resultatet kan du se här: http://elektronikkbransjen.no/Medlem/Medlemsoversikt
All utdata från sql-satserna ovan är förkortade, den vekliga utdatan var mer än 900 rader.
Epost-adresserna i utdatan ovan är modifierade på grund av sekretess.