Voor degenen die hun websites bouwen met CakePHP, en merken dat een compleet serverpad in de URL staat als ze met de HTMLHelper of via de Router links laten maken, heb ik hier een mogelijke oplossing. Ik moet er wel gelijk even bij vermelden dat ik deze bug heb geconstateerd in CakePHP versie 1.2.3.8166, en niet heb gekeken of het in de meest recente versie nog steeds geldt. Mocht je die versie gebruiken, en is het niet mogelijk te upgraden, probeer dan dit.
Het komt weleens voor dat hosts, zeker in een shared hosting omgeving, symbolic links gebruiken in de DOCUMENT_ROOT, of in andere superglobals. Dat houdt in, dat bijvoorbeeld echo $_SERVER['DOCUMENT_ROOT']; iets teruggeeft als /var/www/example.com
, terwijl de site in werkelijkheid staat in /usr/domains/example.com/htdocs
. De map /var/www/example.com
is een symbolic link naar /usr/domains/example.com/htdocs
.
In zo’n geval komt het soms voor dat CakePHP bij het genereren van URLs het verkeerde pad als basis-url neemt, waardoor je in je html-code dit hebt staan: <a href="/var/www/example.com/pagina">Pagina</a>. De site werkt verder wel, de goede pagina’s worden ook geladen, maar het staat zo lelijk in je adresbalk.
Gelukkig is het heel simpel op te lossen. De basis-url die gebruikt wordt, wordt bepaald in /cake/dispatcher.php.
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | function baseUrl() { $dir = $webroot = null; $config = Configure::read('App'); extract($config); if (!$base) { $base = $this->base; } if ($base !== false) { $this->webroot = $base . '/'; return $this->base = $base; } if (!$baseUrl) { $replace = array('<', '>', '*', '\'', '"'); $base = str_replace($replace, '', dirname(env('PHP_SELF'))); if ($webroot === 'webroot' && $webroot === basename($base)) { $base = dirname($base); } if ($dir === 'app' && $dir === basename($base)) { $base = dirname($base); } if ($base === DS || $base === '.') { $base = ''; } $this->webroot = $base .'/'; return $base; } $file = null; if ($baseUrl) { $file = '/' . basename($baseUrl); $base = dirname($baseUrl); if ($base === DS || $base === '.') { $base = ''; } $this->webroot = $base .'/'; if (strpos($this->webroot, $dir) === false) { $this->webroot .= $dir . '/' ; } if (strpos($this->webroot, $webroot) === false) { $this->webroot .= $webroot . '/'; } return $base . $file; } return false; } |
Het gaat fout bij het volgende stuk:
347 348 349 | if (!$baseUrl) { $replace = array('<', '>', '*', '\'', '"'); $base = str_replace($replace, '', dirname(env('PHP_SELF'))); |
Op de server waarbij dit fout ging, bevatte env(‘PHP_SELF’) een symbolic link. De oplossing was heel simpel:
347 348 349 | if (!$baseUrl) { $replace = array('<', '>', '*', '\'', '"'); $base = str_replace($replace, '', dirname(realpath(env('PHP_SELF')))); |
PHP heeft een ingebouwde functie realpath() die symbolic links volgt, en het echte pad teruggeeft. Na deze kleine aanpassing in de Dispatcher werkt alles weer zoals het hoort.
Recente reacties