PHP-Variablen in JavaScript verfügbar machen

Quell-ID: GitHub Discussion #9

Use Case

Daten aus der REDAXO-Datenbank oder aus AddOns wie “Globale Einstellungen” sollen in externen JavaScript-Dateien verfügbar sein.

Verwendete AddOns

  • REDAXO Core
  • Globale Einstellungen (optional)

Zielbeschreibung

PHP-Variablen sollen sicher an JavaScript übergeben werden, damit sie in Frontend-Scripts verwendet werden können.

Lösung

Im PHP-Template oder Modul werden die Daten als JSON ausgegeben, bevor das JavaScript geladen wird:

<?php
$sql = rex_sql::factory();
$sql->setQuery('SELECT * FROM rex_global_settings');
$global_settings = $sql->getArray();
$global_settings = array_filter($global_settings[0]);
?>

<script type="text/javascript">
    let rex_global_settings = <?= json_encode($global_settings) ?>;
</script>

<!-- Danach das JavaScript laden -->
<script src="/assets/theme/main.js"></script>

Im JavaScript kann dann auf die Daten zugegriffen werden:

// In main.js
console.log(rex_global_settings.key);

Besserer Ansatz

Mit Sicherheit und Struktur

<?php
// Daten aufbereiten und filtern
$jsConfig = [
    'apiEndpoint' => rex_url::frontend(),
    'language' => rex_clang::getCurrentId(),
    'settings' => [
        'googleMapsKey' => rex_config::get('project', 'google_maps_key', ''),
        'contactEmail' => rex_config::get('project', 'contact_email', ''),
    ],
];

// Sensible Daten entfernen
unset($jsConfig['settings']['password']);
?>

<script type="application/json" id="rex-config">
<?= json_encode($jsConfig, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) ?>
</script>
// In JavaScript sicher parsen
const configElement = document.getElementById('rex-config');
const REX_CONFIG = configElement ? JSON.parse(configElement.textContent) : {};

// Verwendung
if (REX_CONFIG.settings?.googleMapsKey) {
    initGoogleMaps(REX_CONFIG.settings.googleMapsKey);
}

Als data-Attribute

Für einzelne Werte können auch data-Attribute verwendet werden:

<body 
    data-api-url="<?= rex_escape(rex_url::frontend()) ?>"
    data-clang="<?= rex_clang::getCurrentId() ?>"
>
const apiUrl = document.body.dataset.apiUrl;
const clangId = parseInt(document.body.dataset.clang);

In Fragment auslagern

// Fragment: fragments/js_config.php
<?php
/** @var rex_fragment $this */
$config = $this->getVar('config', []);
?>
<script type="application/json" id="rex-config">
<?= json_encode($config, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) ?>
</script>
// Im Template
$fragment = new rex_fragment();
$fragment->setVar('config', $myConfig);
echo $fragment->parse('js_config.php');

Sicherheitshinweise

  1. Niemals sensible Daten (Passwörter, API-Secrets) an JavaScript übergeben
  2. json_encode() mit Escape-Flags verwenden
  3. Daten vor der Ausgabe filtern und validieren