🐞 Falsche URL bei Überage von Twig an JS mit seoUrl

Hallo,

ich will gern die SEO URL meines Produktes an ein JS Plugin weitergeben. Im Grunde ja nicht so schwierig, dachte ich :smiley:

Das ganze wollte ich ähnlich wie in der Doku beschrieben ist, machen. Also als Json im data-options Attribut übergeben. Dazu erstelle ich im Twig ein Objekt

    {% set options = {
        url: seoUrl('frontend.detail.page', { productId: product.id })
    } %}

soweit sogut, dass funktioniert auch. Wenn ich das dumpe dann erhalte ich, wie ich es erwarte:

{{ dump(options) }}
array:1 [▼
  "url" => "http://localhost:9998/Haupt-Product"
]

Um das ganze zu übertragen muss das ganze noch mit json_encode umgewandelt werden. Aber nun sieht das ganze so hier aus

{{ dump(options|json_encode) }}
"{"url":"http://localhost:9998/\/detail\/f895e22ba1e446508d3c956c684c20ce"}"

Wie kann ich die seoUrl an mein Plugin übertragen?

Ausehen sollte es so:

{% set options = {
    url: seoUrl('frontend.detail.page', { productId: product.id })
} %}

{% block page_product_detail_content %}
    {{ parent() }}

    <template data-example-plugin data-example-plugin-options='{{ options|json_encode }}'></template>
{% endblock %}

Das Beispiel hab ich aus der offizellen Doku von Shopware

Wird ganz normal in die options Variable geschrieben!

example.plugin.js

import Plugin from 'src/plugin-system/plugin.class';

export default class ExamplePlugin extends Plugin {
    static options = {
        url: null
    };

    ...
}

main.js

import ExamlePlugin from './example.plugin';

window.PluginManager.register('Example', ExamplePlugin , '[data-example-plugin]');

if (module.hot) {
    module.hot.accept();
}

@Moorleiche Jup genau danke, genau so wird das gemacht, dass stimmt. Nur ist das keine Lösung für mein oben beschriebenes Problem, denn wenn ich im JS nun die URL aufrufen will, zb. mit

 init() {
        console.log(this.options.url)       
  }

kommt dummerweise
http://localhost:9998/detail/f895e22ba1e446508d3c956c684c20ce
raus.

Ich brauche aber die SEO Url, ich würde gern die
http://localhost:9998/Haupt-Product

Ich hatte auf das JS verzichtet, da ich vermutete das hier im Entwicklerforum dump auch akzeptiert wird

Existiert für das Produkt denn eine SEO URL? Eventuell müsstest du zuerst die Indizes neu bauen?

@abdullah ja, diese wird auch ausgegeben nur, komischerweise, sobald ich das Objekt mit json_encode Umwandle kommt auf einmal die andere Shopware interne URL

   {% set options = {
        url: seoUrl('frontend.detail.page', { productId: product.id })
    } %}
{{ dump(options) }}
{{ dump(options|json_encode) }

Ausgabe:

array:1 [▼
  "url" => "http://localhost:9998/Haupt-Product"
]
"{"url":"http://localhost:9998/\/detail\/f895e22ba1e446508d3c956c684c20ce"}"

Interessantes Verhalten. Für mich macht es aber kein Sinn, warum ein json_encode die nicht SEO URL erzeugt.

Eventuell wird das durch den Watcher verursacht?

Aber am Ende sollte beim URL Aufruf automatisch durch den Controller die SEO URL aufgerufen werden.

Interessantes Verhalten. Für mich macht es aber kein Sinn, warum ein json_encode die nicht SEO URL erzeugt.

Es macht überhaupt keinen Sinn :smiley:.

Eventuell wird das durch den Watcher verursacht?

Hab ich getestet… Leider ist es nicht nur im Watcher :frowning:

Aber am Ende sollte beim URL Aufruf automatisch durch den Controller die SEO URL aufgerufen werden.

Blöderweise soll das, was ich machen will für Social Media sein und ich würde schon gern die richtige URL nach außen kommunizieren, auch wenn der Controller die „kryptische“ Url auflösen kann.

So muss ich wohl einen Workaround machen … das es am json_encode scheitert, hätte ich nicht gedacht :smiley:

Der Workaround würde jetzt so aussehen, würde zwar lieber über das options Objekt die Info übergeben, aber so geht es auch.

Im Twig:

    ...
    {% set productUrl = seoUrl('frontend.detail.page', { productId: product.id }) %}

    {% set options = {
        url: productUrl
    } %}


    <div class="share-dropdown" 
         data-product-share-button 
         data-url="{{ productUrl }}"
         data-product-share-button-options='{{ options|json_encode }}'>
     ...

Im JS:

    ...
    init() {

        console.log(this.options)
        console.log(this.el.dataset.url)
    }
    ...

Ausgabe:

{url: 'http://localhost:9998//detail/f895e22ba1e446508d3c956c684c20ce', title: null, text: null}
text: null
title: null
url: "http://monsterzeug.ddev.site:9998//detail/f895e22ba1e446508d3c956c684c20ce"
[[Prototype]]: Object

product-share-button.js?3382:14 http://localhost:9998/Haupt-Product

Falls jemand weiß, wie man es korrekt macht oder eine bessere Lösung hat, dann sehr gern :slight_smile:

Das liegt daran, weil die SEO Urls im Template erst ersetzt werden, nachdem das gesamte Template gerendert wurde. Sonst hätte man viele Datenbankabfragen bei jedem Produkt. json_encode() maskiert aber die Slashes und deshalb kann die RAW Url nicht mehr im Template gefunden und ersetzt werden.

1 Like

Ahh okay… danke für die Aufklärung @Moorleiche

Dann ist wohl meine Lösung, wie ich das Problem umgehe, doch nicht so verkehrt. Trotzdem für mehr Ideen bin ich Dankbar

Hallo @olli.k, zwar schon ein paar Tage her, aber ich habe mir beholfen, in dem ich dem json_encode die Option übergebe, die Slashes nicht zu maskieren. Vll hilft Dir das ja auch weiter, dann werden die SEO Urls ausgegeben.

|json_encode(constant('JSON_UNESCAPED_SLASHES'))