WEDOS je jedním z největších českých poskytovatelů webhostingu a tak by se dalo říct, že zprovoznit Laravel na sdílený hosting nebude žádný problém. Nicméně to tak lehké není, protože při spuštění stránek můžete narazit na několik problémů, které nasazení zkomplikují.

V tomto článku najdete na co můžete při nasazení čisté instalace Laravelu narazit a jak to s několika úpravami obejít.

Edit: článek byl aktualizován pro Laravel 5.6

Mod_negotiation

Mod_negotiation je modulu Apache, který je zodpovědný za výběr dokumentu, který nejlépe vyhovuje klientových možnostem. Možností jak tuto funkci vypnout je vytvořit .htaccess a do něj vložit následující řádek s ```php Options -Multiviews ```

Laravel po čerstvé instalaci ve složce /public obsahuje .htaccess právě s těmito řádky, konkrétně

<IfModule mod_negotiation.c>
    Options -MultiViews
</IfModule>

Bohužel Wedos mod_negotiation neumožňuje vypnout a tak je tedy jedinou možností tyto řádky z .htaccess prostě vymazat a smířit se s tím.

Parse error

Když narazíte na problém s načtením frameworku tak jako první doporučuji mrknout na FTP do adresáře `storage/logs`  a v něm do souboru `laravel.log` . Často zde najdete zalogovaný error, který vám může pomoct dále k řešení.

Pokud v něm narazíte na chybu tohohle typu:

production.ERROR: Parse error: syntax error, unexpected '?', expecting 
variable (T_VARIABLE) {"exception":"[object] (Symfony\\Component\\Debug
\\Exception\\FatalThrowableError(code: 0): Parse error: syntax error, 
unexpected '?', expecting variable (T_VARIABLE) at /data/web/virtuals/123456/virtual/www/domains/vendor/symfony/routing/Route.php:53)  .....

Pak máte špatně nastavenou verzi PHP ve Wedosu.  Znak ?  na řádku 53 je nový nulový typ fungující od PHP 7.1 a Laravel 5.6 již vyžaduje tuto verzi. PHP verze je ve Wedosu defaultně nastavená na 7.0, takže je potřeba aby jste přes webovou administraci ve Wedosu u svého webhostingu změnili verzi na 7.1. Poté by jste již měli vidět chybovou hlášku (případně narazit na jiný zde popsaný problém) "Whoops, looks like something went wrong.", čímž se posouváme dále k rozjetí stránky.

Aplikační klíč

Po instalaci Laravelu je potřeba vygenerovat náhodný řetězec, který zajišťuje, že uživatelské sessions a jiné nešifrované data budou v bezpečí. Pro její vygenerování je potřeba spustit příkaz `php artisan key:generate`. Ten je potřeba nejlépe vygenerovat ještě před nasazením do produkce, případě pokud jste Laravel nainstalovali přes Composer, máte klíč již náhodně vygenerován. Občas se může stát, že při vymazání cache se klíč vymaže i ze souboru bootstrap/cache/compiled.php, což je víceméně nakešované nastavení. Je tak potřeba se do něj podívat a ujistit, že se zde klíč opravdu nachází. Tento klíč by měl být totožný s klíčem v souboru .env. V případě, že vám klíče nesedí, nejčastěji uvidíte chybovou hlášku "The only supported ciphers are AES-128-CBC and AES-256-CBC".

Artisan a SSH

Laravel využívá především příkazové řádky, především pak Artisan, který práci s frameworkem velmi zjednodušuje. U sdíleného hostingu na Wedosu narazíte ale na problém, jak provést některé příkazy i bez Artisana, především pak při vymazání cache. Jako možnost namísto CLI lze využít fasády Artisan a její metody call(). Jako příklad můžeme uvést: ```php // Vymazat cache fasády Route::get('/clear-cache', function() { Artisan::call('cache:clear'); });

// Znovu přegenerovat class loader Route::get('/optimize', function() { Artisan::call('optimize'); });

// Vymazat cache cest Route::get('/route-cache', function() { Artisan::call('route:cache'); });

// Vymazat cache pohledu Route::get('/view-clear', function() { Artisan::call('view:clear'); });

// Vymazat cache configu Route::get('/config-cache', function() { Artisan::call('config:cache'); });


Tuto variantu lze použít, ale doporučuji ji po potřebě opět smazat, nechceme přece aby nám kdokoliv mohl mazat cache.

<h2>putenv()</h2>
S největší pravděpodobností (pokud již Wedos neuvolnil možnost upravit `disable_functions` v `php.ini` , v psaní tohoto článku ale ještě ne) dostanete chybu:
```php
ErrorException thrown with message "putenv() has been disabled for security reasons"

Bohužel jsem nenašel žádné vhodné řešení jak to obejít. Nejjednodušší možnost je opět bohužel zakomentovat řádky, které tuto chybu způsobují. Pravděpodobně se bude jednat o soubor a řádek vendor/symfony/console/Application.php:110  a vendor/symfony/console/Application.php:843 . Stačí zakomentovat vše kde se vyskytuje funkce putenv() . V případě potřeby není nutné řádky zakomentovat, ale vložit podmínku aby se funkce zavolala jen pokud existuje, např.:

if (function_exists('putenv')) {
    putenv('LINES='.$this->terminal->getHeight());
}

Všeobecný problém

Nejčastěji při rozjetí Laravelu na Wedosu narazíte na problém, že není možné využít artisan a díky tomu není možné přegenerovat cache s configy a routami. Hlavně je tedy problém se souborem `bootstrap/cache/config.php` . Když se do něj podíváte, je nutné, aby všechny cesty byly správně nastaveny (pomocí route pro zavolání artisanu), např. ```php 'view' => array ( 'paths' => array ( 0 => '/data/web/virtuals/123456/virtual/www/domains/resources/views', ), 'compiled' => '/data/web/virtuals/123456/virtual/www/domains/storage/framework/views', ), ```

a aby byl vyplněn vygenerovaný klíč, shodný s klíčem v .env:

'key' => 'base64:nejakyKlic',

Další problémy

Na další problém jsem již nenarazil, ve starších verzích Laravel ale můžete ještě narazit na podobné problémy:

escapeshellarg()

Při escapování využívá Laravel funkci escapeshellarg(), která ale není na Wedosu z bezpečnostního hlediska povolena. Místo toho si můžeme vytvořit vlastní escapeshellarg, který escapuje všechny uvozovky v daném stringu a obalí je dalšími uvozovkami ```php $input = str_replace('\'', '\\\'', $input); return '\''.$input.'\''; ```

Tyto řádky pak nahradíme namísto funkce escapeshellarg() v souboru vendor/symfony/process/ProcessUtils.php v metodě escapeArgument($argument).

Přesměrování do public

Wedos má defaultně nastaveno v kořenovém adresáři v .htaccess toto: ```php # cele domeny (aliasy) RewriteCond %{REQUEST_URI} !^domains/public/ RewriteCond %{REQUEST_URI} !^/domains/public/ RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$ RewriteCond %{DOCUMENT_ROOT}/domains/public/%2 -d RewriteRule (.*) domains/public/%2/$1 [DPI] ```

Tudíž by se mělo vše načíst automaticky. Nicméně pokud by bylo potřeba zde je postup pro přesměrování.

Po instalaci frameworku nenajdeme v kořenovém adresáři žádný index.php, kterým bychom Laravel nastartovali. Spouštěcí soubor se totiž nachází až ve složce public. Abychom vytvořili jednoduché přesměrování, využijeme nový .htaccess v kořenovém adresáři s obsahem:

RewriteEngine on
RewriteCond %{REQUEST_URI} !^public
RewriteRule ^(.*)$ public/$1 [L]