Laravel лойиҳасини биринчи марта оддий хостингга юклаган дастурчиларнинг кўпчилиги бир хил ҳолатга дуч келади: барча файллар сайтнинг асосий каталогига кўчирилади, браузерда эса саҳифа ўрнига файллар рўйхати, 403 хатоси ёки бўш ойна чиқади. Сабаби оддий: Laravel сайтнинг фақат битта қисмини, яъни public папкасини интернетга очиқ кўришни кутади. Қолган ҳамма нарса, жумладан созламалар, кутубхоналар ва махфий калитлар, веб-сервер етиб бора олмайдиган жойда туриши керак. Ушбу мақолада бу талаб нимага кераклигини ва уни оддий хостингда қандай бажариш мумкинлигини босқичма-босқич тушунтирамиз.
Нега Laravel фақат public папкани очиқ кўришни хоҳлайди
Laravel лойиҳасининг илдизида app, config, routes, vendor, storage каби папкалар ва .env файли жойлашган. Айнан .env файлида маълумотлар базасининг пароли, APP_KEY шифрлаш калити, почта серверининг логин-пароли ва тўлов тизимларининг махфий калитлари сақланади. Сайтга келадиган барча сўровлар эса public/index.php орқали кириб, фреймворк томонидан қайта ишланади. Агар бутун лойиҳани сайтнинг илдиз каталогига ташлаб қўйсангиз, веб-сервер .env файлини оддий матн сифатида бериб юбориши мумкин, бу эса базангиз ва калитларингизнинг тўлиқ ошкор бўлиши демакдир. Шунинг учун мақсад битта: домен очилганда сервер тўғридан-тўғри public папкага қараши керак.
Мисол учун, Тошкентдаги кичик китоб дўкони ўзининг misol.uz сайтини Laravel'да ёздирган дейлик. Дастурчи лойиҳани ZIP архив қилиб, ISPmanager файл менежери орқали www/misol.uz папкасига очиб қўйди. Сайт очилмади, шошилиб қилинган тузатиш натижасида эса misol.uz/.env манзили браузерда пароллар билан кўринадиган бўлиб қолди. Қуйидаги усуллар айнан шундай вазиятнинг олдини олади.
1-усул: ҳужжат илдизини public папкага йўналтириш
Энг тоза ва тавсия этиладиган ечим доменнинг ҳужжат илдизини (document root) ўзгартиришдир. ISPmanager панелида WWW-домен созламаларини очсангиз, сайтнинг илдиз каталоги кўрсатилган майдонни топасиз; панел версиясига қараб бу майдон номи бироз фарқ қилиши мумкин. Одатда у /var/www/login/data/www/misol.uz кўринишида бўлади, сиз эса охирига /public қўшиб сақлайсиз. Шундан кейин лойиҳа файллари аввалгидек битта папкада туради, лекин интернетдан фақат public ичидаги нарсаларга мурожаат қилиш мумкин бўлади.
Бу усулнинг афзаллиги шундаки, Laravel ўзи кутган тузилмада ишлайди ва ҳеч қандай йўлни қўлда таҳрирлаш керак эмас. php artisan storage:link яратадиган символик ҳавола, Vite йиғган build файллари ва public/.htaccess ичидаги қайта ёзиш қоидалари одатдагидек ишлайди. Агар панелда бу майдон сизга очиқ бўлмаса, sayt.uz кабинетидан техник ёрдамга тикет ёзиб, ҳужжат илдизини ўзгартириб беришни сўрашингиз мумкин.
2-усул: илдиздаги .htaccess орқали public папкага қайта йўналтириш
Баъзи ҳолларда ҳужжат илдизини ўзгартириш имкони бўлмайди, масалан, бир нечта лойиҳа битта каталогни бўлишганда. Шунда лойиҳа илдизига алоҳида .htaccess файли қўйилиб, барча сўровлар ички тарзда public папкага узатилади. Браузер манзилида /public кўринмайди, чунки бу ташқи йўналтириш эмас, Apache ичидаги қайта ёзишдир.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
# Qo'shimcha himoya: maxfiy fayllarni to'g'ridan-to'g'ri bermaslik
<FilesMatch "^(\.env.*|composer\.(json|lock)|artisan)$">
Require all denied
</FilesMatch>
Бу усул ишлайди, аммо у биринчи усулчалик ишончли эмас. Агар кимдир кейинчалик .htaccess файлини ўчириб юборса ёки сервер созламаси ўзгарса, бутун лойиҳа яна очиқ қолади. Шунинг учун FilesMatch блоки қўшимча суғурта сифатида қўйилган. Уни жойлагандан сўнг албатта https://misol.uz/.env манзилини очиб кўринг: 403 ёки 404 хатоси чиқиши керак, файл мазмуни эса ҳеч қачон кўринмаслиги лозим.
3-усул: ядрони веб-каталогдан ташқарига чиқариш
Учинчи йўл энг кўп қўл меҳнати талаб қилади, лекин ҳужжат илдизига умуман тегиб бўлмайдиган хостингларда фойдали. Бунда Laravel'нинг асосий қисми уй каталогидаги алоҳида папкага, масалан laravel-app га жойланади, public ичидаги файллар эса www/misol.uz га кўчирилади. Кейин index.php ичидаги йўллар янги жойлашувга мослаб таҳрирланади. Laravel 11 учун файл тахминан қуйидагича бўлади:
<?php
use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true));
if (file_exists($maintenance = __DIR__.'/../../laravel-app/storage/framework/maintenance.php')) {
require $maintenance;
}
require __DIR__.'/../../laravel-app/vendor/autoload.php';
$app = require_once __DIR__.'/../../laravel-app/bootstrap/app.php';
$app->usePublicPath(__DIR__);
$app->handleRequest(Request::capture());
usePublicPath қатори муҳим: усиз public_path() функцияси эски жойни кўрсатади ва юкланган расмлар ёки Vite манифести топилмайди. Эски версияларда index.php тузилиши бироз бошқача, шунинг учун ўз версиянгиздаги асл файлни асос қилиб олинг ва фақат йўлларни ўзгартиринг. Бу усулда storage ҳаволасини ҳам қайта яратиш керак бўлади, чунки у энди www/misol.uz/storage дан laravel-app/storage/app/public га ишора қилиши лозим.
Vendor, PHP версияси ва .env созламалари
Кўп оддий хостингларда SSH ёки Composer бўлмайди, шунинг учун vendor папкасини ўз компьютерингизда тайёрлаб юклаш қулай. Буни ишлаб чиқариш режимига мос қилиб бажаринг, яъни тест кутубхоналарини қўшмасдан ва автоюкловчини оптималлаштириб:
composer install --no-dev --optimize-autoloader
npm run build
Хостингдаги PHP версияси composer.json талаб қилган версиядан паст бўлмаслиги керак, акс ҳолда сайт биринчи сўровдаёқ хато беради. ISPmanager панелида домен учун PHP версиясини танлаш мумкин; Laravel 11 камида PHP 8.2 талаб қилади. .env файлида эса қуйидаги қийматларни текширинг:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://misol.uz
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=login_shop
DB_USERNAME=login_shop
DB_PASSWORD=kuchli-parol
APP_DEBUG=false айниқса муҳим. Агар у true бўлиб қолса, исталган хато саҳифасида файл йўллари, сўров параметрлари ва баъзан муҳит ўзгарувчилари кўриниб қолади.
Рухсатлар, кеш ва якуний текширув
Laravel storage ва bootstrap/cache папкаларига ёзиш имконига эга бўлиши шарт, акс ҳолда лог, сессия ва компиляция қилинган шаблонлар сақланмайди. Одатда папкалар учун 755, файллар учун 644 рухсати етарли, чунки хостингда PHP сизнинг фойдаланувчингиз номидан ишлайди; 777 қўйиш шарт эмас ва хавфли. SSH мавжуд бўлса, жойлашдан кейин кешларни янгилаб қўйинг:
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
Шуни ёдда тутингки, config:cache дан кейин env() функцияси фақат config файллари ичида ишлайди, контроллер ёки шаблонда тўғридан-тўғри чақирилса, null қайтаради. Охирида учта нарсани текширинг: бош саҳифа очиляптими, /.env манзили ёпиқми ва расмлар ҳамда CSS файллари тўғри юкланяптими.