S7
zurück[Translate to English:] Globales Menü aus Datensätzen generiert
08.03.2019
Thema: TYPO3

Generating a global menu from records

For a product overview we had the need to create a menu of the products for the webpage

At first I thought I'd need a plugin for this case which would fetch the product records, and to render the needed fields and push that to the fluid template.

The following scenarios would have been possible:

Including the plugin on every page

Why not?

Well, I would have to always have another column in the TYPO3 backend just for that puropse, in order for the Fluid Template to be able to render the menu on each page.

Adding the plugin with a separate CONTENT-object.

That would be better, I could add the object easily with TypoScript. But the problem still lies in the fact that I would have a to code a complete plugin build with extbase just for a simple menu. Additionaly I couldn't easily manipulate the menu in the Typoscript template.

 

The solution was using the DatabaseQueryProcessor

Now I was looking at the option to fetch the data with the DatabaseQueryProcessor.

That worked quite nicely, i got a result after a few lines already:

 

10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
10 {
   table = tx_sudhaus7product_domain_model_product
   pidInList = 29
   as = prod
}

This processor added to the page-object just after dataProcessing loaded me nicely my elements in my page template.

 

In fluid, this was easy now:

<f:for each="{prod}" as="product">
    <f:link.action
        arguments="{product: '{product.data.uid}'}"
        extensionName="sudhaus7product"
        controller="Product"
        action="show"
    />
</f:for>

Now it got interresting: adding the product category. The processor came to the rescue again, because I can add another dataProcessing instance to each processor:

 

10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
10 {
   table = tx_sudhaus7product_domain_model_product
   pidInList = 29
   as = prod
   dataProcessing {
      10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
      10 {
         if.isTrue.field = category
         pidInList = 29
         table = tx_sudhaus7product_domain_model_category
         selectFields = tx_sudhaus7product_domain_model_product.*
         where.data = field:uid
         where.wrap = tx_sudhaus7product_domain_model_product_category_mm.uid_local=|
         join (
             tx_sudhaus7product_domain_model_product_category_mm on tx_sudhaus7product_domain_model_product_category_mm.uid_foreign=
             tx_sudhaus7product_domain_model_category.uid
         )
         orderBy = tx_sudhaus7product_domain_model_product_category_mm.sorting
         as = category
      }
   }
}

With this I get with each product additionaly its related categories.

 

One could, if needed, of course first fetch the categories and then fetch the products, that depends on the usecase.

Only one thing missing for any real menu: the active flag.

Here I accept the fact that in TYPO3 each call to a product detail page or category page is simply a different GET parameter.

With this knowledge and the fact that the DatabaseQueryProcessor works the same as CONTENT.select in TypoScript, this requires these changes to our code to get the active flag:

 

10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
10 {
   table = tx_sudhaus7product_domain_model_product
   pidInList = 29
   as = prod
   selectFields.stdWrap.cObject = COA
   selectFields.stdWrap.cObject {
      stdWrap.htmlSpecialChars = 1
      10 = TEXT
      10.value = tx_sudhaus7product_domain_model_product.*
      10.wrap = |,
      20 = TEXT
      20.value = 0
      20.override.data = gp:tx_sudhaus7product|product
      20.wrap = wrap = IF(tx_sudhaus7product_domain_model_category.uid=|, 1, 0) as active
   }
   dataProcessing {
      10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
      10 {
         if.isTrue.field = category
         pidInList = 29
         table = tx_sudhaus7product_domain_model_category
         selectFields.stdWrap.cObject = COA
         selectFields.stdWrap.cObject {
            stdWrap.htmlSpecialChars = 1
            10 = TEXT
            10.value = tx_sudhaus7product_domain_model_product.*
            10.wrap = |,
            20 = TEXT
            20.value = 0
            20.override.data = gp:tx_sudhaus7product|category
            20.wrap = IF(tx_sudhaus7product_domain_model_category.uid=|, 1, 0) as active
         }
         where.data = field:uid
         where.wrap = tx_sudhaus7product_domain_model_product_category_mm.uid_local=|
         join (
                     tx_sudhaus7product_domain_model_product_category_mm on tx_sudhaus7product_domain_model_product_category_mm.uid_foreign=
                    tx_sudhaus7product_domain_model_category.uid
         )
         orderBy = tx_sudhaus7product_domain_model_product_category_mm.sorting
         as = category
      }
   }
}

By defining the selectFields as a COA object and a check if the required GET parameter has been set I now get for each product and category an active flag that either says 0 or 1. HtmlSpecialChars helps against any XSS passed through the URL

selectFields.stdWrap.cObject = COA
selectFields.stdWrap.cObject {
   stdWrap.htmlSpecialChars = 1
   10 = TEXT
   10.value = tx_sudhaus7product_domain_model_product.*
   10.wrap = |,
   20 = TEXT
   20.value = 0
   20.override.data = gp:tx_sudhaus7product|product
   20.wrap = wrap = IF(tx_sudhaus7product_domain_model_category.uid=|, 1, 0) as active
}

All in all I think the menu is a good solution this way. The overhead introduced by an extbase plugin was mitigated. The data is fetched directly from the database. The menu can be included and rendered without additional tricks and problems in the template of the page, and changes don't need to be managed in a plugin.

 

Thank to the recursiveness of the dataProcessing pattern one can for example as well fetch product or category images in one swoop and create a tiles-based menu. This is easily extensible.

Ähnliche Beiträge
TYPO3 Extensions aktualisieren
26.02.2019

Help, my TYPO3 extension is too old!

How do you keep your TYPO3 extensions up-to-date?

Everybody who writes and curates TYPO3 extensions over several years will come to the point where the extension is too old for this shiny new version of TYPO3.  

Kommentare