Ik loop een beetje vast met op welk moment ik een Cookie moet zetten voor een geselecteerde taal (drie talige website) met het gebruik van AltoRouter. De situatie is momenteel als volgt. In mijn controller file heb ik momenteel het volgende:

$lang  = filter_input(INPUT_GET, 'lang');
$route = filter_input(INPUT_GET, 'route');

if ( !$lang ) {
    if ( isset($_COOKIE["language"]) ) {
        $lang = $_COOKIE["language"];
    } else {
        $lang = 'nl';
    }
    header("Location: /$lang/$route");
}

Met andere woorden als $_Cookie{"language"] bestaat (nl, en, de) dan dient de uitgangs- taal (bij een tweede bezoek) de waarde van het Cookie te zijn (www.website.com/de/ of een van de andere twee), bestaat het Cookie nog niet zet de taal dan op Nederlands (www.website.com/nl/).

In de navigatie wil ik graag een taal dropdown hebben waar de Cookie taal de link voor de dropdown is:

<?php if (!isset($_COOKIE["lang"]) || isset($_COOKIE["lang"]) && $_COOKIE["lang"] == 'nl' ): ?>
<li class="nav-item dropdown">
	<a id"languageDropdown" class="nav-link dropdown-toggle" href="#" data-toggle="dropdown">
		<img src="/images/flaggs/nl.png">&nbsp;&nbsp;Nederlands
	</a>
	<div class="dropdown-menu" aria-labelledby="languageDropdown">
		<a href="/en<?php echo $current_route?>" class="dropdown-item">
			<img src="/images/flaggs/uk.png">&nbsp;&nbsp;English
		</a>
		<a href="/de<?php echo $current_route?>" class="dropdown-item">
			<img src="/images/flaggs/de.png">&nbsp;&nbsp;Deutsch
		</a>		
	</div>
</li>
<?php elseif(isset($_COOKIE["lang"]) && $_COOKIE["lang"] == 'en'): ?>	
	// Zelfde als boven met Engels als uitgangs taal	
<?php elseif(isset($_COOKIE["lang"]) && $_COOKIE["lang"] == 'de'): ?>
	// Zelfde als boven met Duits als uitgangs taal
<?php endif; ?>


Ik kom er alleen niet uit op welk moment en waar ik het best het Cookie kan zetten. Zit me nu al een uur of wat rot te tobben. Iedere hulp zou ik zeer op prijs stellen.





[size=xsmall]Toevoeging op 30/09/2018 18:11:46:[/size]

Ik heb dit op de volgende wijze opgelost:

$lang  = filter_input(INPUT_GET, 'lang');
$route = filter_input(INPUT_GET, 'route');

if ( !$lang ) {
    if ( isset($_COOKIE["language"]) ) {
        $lang = $_COOKIE["language"];
    } else {
        $lang = 'nl';
    }
    header("Location: /$lang/$route");
} else {
    $lang = (string)$lang; 
    setcookie( 'language', $lang, time() + 60*60*24*365, '/' );	
}

En dat werkt prima. Het enige probleem dat ik nu nog ondervind is de content voor de dropdown niet wijzigd, althans niet met gebruik van de header("Location") Als iemand bijvoorbeeld Engels kies veranderd de waarde van het Cookie naar en maar de nederlandse vlag met bijbehorende tekst blijven staan.

<img src="/images/flaggs/nl.png">&nbsp;&nbsp;Nederlands

Als ik daarna de pagina handmatig ververs veranderd de content wel naar de engelse versie:

<img src="/images/flaggs/uk.png">&nbsp;&nbsp;English

Hoe zou ik dit kunnen oplossen? Alvast bedankt
@Thomas. Hartelijk bedankt voor je reactie

Thomas van den Heuvel op 30/09/2018 21:11:02

In je controller, voordat je een header verstuurt?

Wat bedoel je precies met het bovenstaande?
Thomas van den Heuvel op 30/09/2018 21:11:02

Achter zo'n header moet trouwens nog steeds een exit-statement, want het instellen van een Location header transporteert je niet direct naar de nieuwe locatie (interne link).

Bedankt voor je opmerkzaamheid. Ik heb het meteen aangepast!

Thomas van den Heuvel op 30/09/2018 21:11:02

En dan moet je wellicht nog rekening houden met dat geneuzel dat de gebruiker expliciet moet instemmen met het gebruik van cookies om je site fatsoenlijk te laten werken.

Wanneer dit op een andere/betere manier opgelost zou kunnen worden, sta ik open voor iedere suggestie. Hoe zou jij dit dan aanpaggen
je bent bekend met het MVC-pattern?
@- Ariën - Ik ben bekent met het MVC-pattern en weet dus ook wat de Controller is, maar mijn vraag is wat ik in de Controller moet doen voordat ik de header verstuur.
Het lijkt me dat je het wat "centraler" zou moeten regelen Donald. Je zou niet in elke functie van je controller jezelf moeten bezighouden met welke taal er nu gebruikt moet worden. Ik heb geen idee welk framework je gebruikt en al zou ik dat hebben dan ben ik er wellicht niet bekend mee dus ik probeer je de goede richting in te duwen.

Stel dat de taal niet bekend is. Je moet dan een taal als standaard taal nemen en deze opslaan in
a) een variabele ergens in je applicatie en op zo een manier dat je er overal gemakkelijk bij kunt komen. (Je gebruikt elders in je applicatie niet meer rechtstreeks je $_COOKIE['language'] maar gebruikt een eigen variabele, bijvoorbeeld $language). en
b) moet je een COOKIE meesturen in de header van je response, dus de "pagina" die je terug gaat sturen naar de browser.

Als de taal wel bekend is (Je hebt een cookie meegestuurd gekregen in de REQUEST) dan stel je eveneens de taal in een variabele ergens in je applicatie. Het verschil is echter dat het nu de voorkeurstaal van de gebruiker is in plaats van de default-taal die jij zelf ingesteld hebt. Er hoeft nu geen nieuw cookie verstuurd te worden want de gebruiker heeft die al. (ga er van uit dat je hem een lange geldigheidsduur geeft).

Vervolgens kun je overal dus bijvoorbeeld in je controller, je menu-builder en in je view de $language variabele raadplegen. Dit betekend dus ook dat je bij voorkeur deze variabele al geïnitialiseerd hebt voordat je controller wordt geraadpleegd of misschien uiterlijk in de constructor van je baseController class.

Indien bovenstaande niet duidelijk is laat dan even weten hoe je controller class er uit ziet en of deze van een base class extended wordt.
Gebruik je een bestaand framework? Vaak hebben deze de beschikking over 'auto loaders', en daar zou dit prima in passen.
Frank Nietbelangrijk op 01/10/2018 13:12:33

Het lijkt me dat je het wat "centraler" zou moeten regelen Donald. Je zou niet in elke functie van je controller jezelf moeten bezighouden met welke taal er nu gebruikt moet worden. Ik heb geen idee welk framework je gebruikt en al zou ik dat hebben dan ben ik er wellicht niet bekend mee dus ik probeer je de goede richting in te duwen.

@Frank Nietbelangrijk. Lang niet gehoord. Het is geen bestaand Framewerk, maar een samengesteld. Het taal gebeuren vind niet echt plaats in elke functie van een Controller. Ik heb een file (Bootstrap.php) wat ik include in index.php. In dit document worden zaken zoals autoloader, PATH en routes gedefinieerd Voor de goede orde. Dit is wat er dit document staat:


error_reporting(E_ALL);
ini_set('display_errors', 1);

define('APP_PATH', realpath(__DIR__.'/../'));

session_start();

$lang  = filter_input(INPUT_GET, 'lang');
$route = filter_input(INPUT_GET, 'route');

if ( !$lang ) {
    if ( isset($_COOKIE["language"]) ) {
        $lang = $_COOKIE["language"];
    } else {
        $lang = 'nl';
    }
    header("Location: /$lang/$route");
	exit;
} else {
    $lang = (string)$lang; 
    setcookie( 'language', $lang, time() + 60*60*24*365, '/' );	
}

require_once 'autoloader.php';
require_once APP_PATH . '/lib/password.php';
require_once APP_PATH . '/lib/i18n.class.php';
require_once APP_PATH . '/lib/AltoRouter.php';

Config::setDirectory(APP_PATH.'/config'); 
View::setDirectory(APP_PATH.'/templates');

$router = new Router();
$router->dispatch('/'.$route);

Daarnaast heb ik een main Controller waarin zaken zoals de navigatie geregeld worden. Ik heb werkelijk geen idee wat in dit geval de beste aanpak zou kunnen zijn

[size=xsmall]Toevoeging op 01/10/2018 13:35:22:[/size]

@- Ariën - Dit staat niet in elke Controller. Dit staat alleen in het document wat ik in index.php include:

require_once('../private/includes/bootstrap.php');
- Ariën - op 01/10/2018 13:42:03

Een auto-loader zou dan makkelijker zijn. Dan hoef je eigenlijk niet steeds meer alles zelf te includeren ;-)

http://php.net/manual/en/language.oop5.autoload.php

Je Language-systeem kan je ook dan tot een Language-class verpakken.


@- Ariën - Ik gebruik een auto-loader zoals ik in mijn antwoord aan @Frank reeds aangaf. Dit is mijn auto-loader:

function auto_loader($file)
{
    $file = APP_PATH . '/includes/classes/' . str_replace('_', '/', $file) . '.php';
    if (file_exists($file)) {
        require_once $file;
    } 
}
    
spl_autoload_register('auto_loader');

De netste oplossing lijkt mij een class te schrijven die bepaald en bijhoudt welke taal er gebruikt moet worden.

<?php

class LanguageManager
{
private static $defaultLanguage = 'nl'; // of haal deze uit de configuratie

private static $language;

public static function init()
{
/* checken of we een cookie hebben ontvangen */
if ( isset($_COOKIE["language"]) ) {
self::$language = $_COOKIE["language"];

/* anders dan maken we een taal nederlands en schrijven we een cookie weg */
} else {
self::setLanguage(self::$defaultLanguage);
}
}

public static function getLanguage()
{
return self::$language;
}

public static function setLanguage($language)
{
self::$language = $language;
setcookie( 'language', self::$language, time() + 60*60*24*365, '/' );
}

}

/* ergens in je applicatie voordat je met je controllerfuncties aan de gang gaat: */
LanguageManager::init();

/* Een andere taal instellen kan maar moet wel voordat je enige output verstuurd met: */
// LanguageManager::setLanguage('de'); // (bijvoorbeeld als een gebruiker dit kiest in een dropdown)

/* welke taal moeten we hebben? */
echo LanguageManager::getLanguage();
?>

Reageren