CodeIgniter 404 Page Not Found: причини и решения (с примери с код)

CodeIgniter 404 Page Not Found: причини и решения (с примери с код)

TL;DR

Грешката CodeIgniter 404 Page Not Found почти винаги е проблем с маршрутизацията на уеб сървъра, а не бъг в кода ви.

Бърз тест: ако yoursite.com/index.php/controller се зарежда, но yoursite.com/controller връща 404, слоят за пренаписване е счупен. Четирите обичайни причини и решения: поправете .htaccess файла, включете mod_rewrite в Apache, задайте правилния базов URL и подравнете дефинициите на маршрутите с имената на контролерите (на Linux главните и малките букви имат значение). При Nginx изобщо няма .htaccess; заявките се насочват с директивата try_files.

Приложението ви на CodeIgniter работи без проблем на лаптопа. Качвате го на лайв сървър, отваряте началната страница и изглежда, че всичко е наред. Но когато кликнете на някой линк и екранът изписва „404 Page Not Found“. Нито един от маршрутите ви не се достига и това е проблем.

Грешката CodeIgniter 404 Page Not Found почти винаги опира до това как уеб сървърът предава заявките към фреймуърка, а не до дефект в контролерите. Четири възможни причини стоят зад огромното мнозинство от случаите: липсващ или счупен файл .htaccess, изключен mod_rewrite, неправилен базов URL и дефиниции на маршрути, които не съвпадат с контролерите.

Ето как да разпознаете кой от тях в “виновникът” и какво точно да поправите – както за CodeIgniter 3, така и за CodeIgniter 4.

Какво причинява грешка CodeIgniter 404 Page Not Found?

404 в CodeIgniter означава едно от две неща: рутерът е получил заявка, която не съвпадна с контролер и метод, или заявката изобщо не е стигнала до рутера. Четири основни причини покриват почти всеки случай:

CodeIgniter 404 Page Not Found: причини и решения (с примери с код), Какво причинява грешка CodeIgniter 404 Page Not Found?
  • Липсващ или счупен .htaccess. Фреймуъркът така и не получава заявката, защото Apache няма правило за пренаписване, което да я насочи през index.php.
  • mod_rewrite не е включен. Apache игнорира правилата ви за rewrite, защото модулът е изключен или AllowOverride блокира файла .htaccess.
  • Неправилен базов URL. Фреймуъркът строи грешни линкове и не може да ги върне към правилния контролер.
  • Грешни дефиниции на маршрути. URL адресът не сочи към нито един контролер и метод, затова пренасочването отива към 404.

30-секунден тест ви казва кой проблем да разследвате. Отворете сайта с index.php в пътя, например yoursite.com/index.php/products.

CodeIgniter 404 Page Not Found: причини и решения (с примери с код), Какво причинява грешка CodeIgniter 404 Page Not Found? 2

Ако това работи, но yoursite.com/products връща 404, проблемът е в слоя за пренаписване: .htaccess или mod_rewrite (решения 1 и 2). Ако нито един от двата URL адреса не работи, проблемът е в конфигурацията или маршрутизацията: базов URL или дефиниции на маршрути (решения 3 и 4).

Решение 1: Добавете или поправете файла .htaccess

CodeIgniter насочва всяка заявка през един front controller – index.php. Файлът .htaccess казва на Apache да праща чисти URL адреси като /products/42 към този front controller, вместо да търси реален файл или папка с име products. Няма правило за rewrite – няма и маршрутизация.

В CodeIgniter 4 файлът .htaccess е в директорията public/ и идва заедно с фреймуърка. В CodeIgniter 3 мястото му е в корена на проекта. Ако липсва, е повреден или е презаписан при деплой, пресъздайте го с този минимален и надежден набор от правила:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]

Двете условия казват едно и също на човешки език: ако заявката не е нито реален файл, нито реална директория, предайте я на index.php. Точно това трябва на front controller-а на един фреймуърк.

CodeIgniter 4 идва с по-дълъг public/.htaccess с допълнителна обработка. Ако сте го изтрили или оплескали, върнете оригинала от чиста инсталация на фреймуърка, вместо да го съкращавате на око.

Решение 2: Включете mod_rewrite в Apache

Ако yoursite.com/index.php/products работи, а yoursite.com/products хвърля 404, Apache не прилага правилата ви за rewrite. Две неща го причиняват: модулът mod_rewrite е изключен или Apache е настроен да игнорира файловете .htaccess.

На сървър, който контролирате, включете модула и рестартирайте Apache:

sudo a2enmod rewrite
sudo systemctl restart apache2

Рестартът на Apache за кратко прекъсва всеки сайт на машината, затова го правете във възможно най-спокоен период откъм трафик.

Включването на модула е само половината работа. Apache трябва и да чете .htaccess презаписите в уеб корена. Във виртуалния хост или в блока Directory задайте AllowOverride All:

<Directory /var/www/yoursite/public>
    AllowOverride All
    Require all granted
</Directory>

При AllowOverride None (често срещан по подразбиране) Apache мълчаливо игнорира всеки .htaccess файл и никакви правилни правила за rewrite няма да помогнат.

На споделен хостинг mod_rewrite обикновено вече е включен. Ако не е и нямате достъп до конфигурацията на Apache, трябва ви доставчик или хостинг план, който ви дава този контрол.

Решение 3: Задайте правилния базов URL

Грешният базов URL не винаги дава 404 на началната страница, но чупи всеки генериран линк, всяко действие по форма и всеки път към ресурс. После това излиза като 404 в момента, в който посетителят кликне нататък. Винаги завършвайте стойността с наклонена черта в края.

В CodeIgniter 3 редактирайте application/config/config.php:

$config[‘base_url’] = ‘https://example.com/’;
$config[‘index_page’] = “;

Задаването на index_page като празен низ е това, което ви позволява да махнете index.php от URL адресите, след като пренаписването вече работи.

В CodeIgniter 4 базовият URL е в app/Config/App.php:

public string $baseURL = ‘https://example.com/’;
public string $indexPage = “;

По-добра практика в CodeIgniter 4 е да го задавате по среда във файла .env, за да държите стойностите за конкретната среда извън контрола на версиите:

app.baseURL = ‘https://example.com/’

Решение 4: Поправете дефинициите на маршрутите

Ако URL адресът стига до фреймуърка, но пак връща 404, рутерът не може да го върже към контролер и метод. Това е основата на повечето доклади за CodeIgniter routing 404.

В CodeIgniter 4 маршрутите са в app/Config/Routes.php и се дефинират изрично:

$routes->get(‘/’, ‘Home::index’);
$routes->get(‘products’, ‘Products::index’);
$routes->get(‘products/(:num)’, ‘Products::show/$1’);

В CodeIgniter 3 файлът е application/config/routes.php:

$route[‘default_controller’] = ‘welcome’;
$route[‘products/(:num)’] = ‘catalog/product_lookup_by_id/$1’;

Две неща причиняват повечето от тези 404-ки.

  • Чувствителност към главни и малки букви. Това е най-честата причина едно CodeIgniter приложение да работи локално и да дава 404 на живия сървър. Windows и macOS третират имената на файловете като нечувствителни към регистъра; повечето Linux сървъри не го правят. Ако файлът на контролера е app/Controllers/Products.php, класът трябва да е Products и маршрутът трябва да го сочи като Products, не products. Несъответствие, което лаптопът ви прощава, но на лайв сайт ще се превърне в 404.
  • Автоматичната маршрутизация е изключена по подразбиране в CodeIgniter 4. По-старият CodeIgniter автоматично свързваше URL адреси към контролери и методи без дефиниции на маршрути. Съвременният CodeIgniter 4 изключва това поведение по подразбиране. Ако сте приели, че фреймуъркът сам ще намери Products::show, дефинирайте маршрута изрично или включете auto-routing.

CodeIgniter 404 при Apache срещу Nginx

Всичко казано дотук приема, че уеб сървърът ви е Apache. В момента, в който приложението тръгне на Nginx, правилата се сменят и точно тук много от copy/paste съдържанието се проваля.

Nginx изобщо не чете .htaccess файлове. Може да пуснете перфектен CodeIgniter .htaccess върху Nginx сървър и той няма да направи абсолютно нищо, защото Nginx няма еквивалент на per-directory override файлове. Логиката за пренаписване трябва да живее в server block-а.

CodeIgniter 404 Page Not Found: причини и решения (с примери с код), CodeIgniter 404 при Apache срещу Nginx

Ето конфигурация за Nginx, която работи добре с CodeIgniter. Тя праща всяка заявка, която не е реален файл, към index.php – това е Nginx еквивалентът на правилото от .htaccess в решение 1:

server {
    listen 80;
    server_name example.com;
    root /var/www/example.com/public;
    index index.php;
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
    error_page 404 /index.php;
}

Редът с try_files върши тежката работа. Проверява за файла, после за директорията, после пада към front controller-а със запазен query string.

ВАЖНО: Версията на FPM и пътят до сокета се различават на различните сървъри. Бъдете сигурни, че въвеждате правилната версия; може да се консултирате с екипа за техническа поддръжка на хоста, за да я потвърдите.

Ето как се сравняват двата уеб сървъра за приложение на CodeIgniter:

АспектApacheNginx
.htaccessЧете се по директорияНикога не се чете
Правилата за rewrite са в.htaccess или vhostСамо в server block
Чисти URL адреси чрезmod_rewrite + RewriteRuleдиректива try_files
Промяната изисква рестартНе (за .htaccess)Да (презареждане на Nginx)
Сочи къмКорена на проекта или public/public/ като root

Има и междинен случай, който си струва да се знае, защото точно така работят много управлявани платформи. Когато Nginx стои пред Apache като reverse proxy, Apache все още може да чете .htaccess. Вашият CodeIgniter .htaccess работи, въпреки че Nginx е сървърът към външния свят. Когато знаете коя от тези три схеми ползвате, знаете и къде точно да сложите поправката.

Къде се вписва хостинг средата ви

Всяко решение по-горе приема по подразбиране, че можете да редактирате .htaccess, да включвате и изключвате mod_rewrite, да насочите document root към папката public/ на CodeIgniter и да изберете версия на PHP. На заключен споделен хостинг често имате много ограничен достъп и петминутна поправка се превръща в тикет към поддръжката.

Този контрол прави разликата между среда, която ви работи, и среда, която ви спира.

При управлявания хостинг на NS1 стекът работи с Nginx като reverse proxy пред Apache, така че Apache отзад чете директно вашия CodeIgniter .htaccess. Правилото за rewrite от решение 1 работи, без да го превеждате в Nginx server block.

Още две неща, които конкретно предотвратяват CodeIgniter 404, се управляват в SPanel, контролния панел на NS1. Може да насочите document root направо към директорията public/, точно откъдето CodeIgniter 4 очаква уеб сървърът да сервира и да зададете версия на PHP по директория, вместо да сте вързани към една версия за целия сървър. Ако предпочитате да не управлявате сами слоя на уеб сървъра, напълно управляван VPS оставя тази конфигурация в ръцете на екип, който го е правил хиляди пъти, и пак ви дава root достъп, когато ви потрябва.

Заключение

Грешката CodeIgniter 404 Page Not Found рядко е проблем в кода и почти винаги е проблем с маршрутизацията, затова започнете с теста с index.php и оставете това да ви посочи правилното решение. Настройте слоя на уеб сървъра веднъж в среда, която контролирате, и тези грешки престават да бъдат ритуал при всеки деплой.

Често задавани въпроси

В: Как да оправя грешка 404 Page Not Found в CodeIgniter 4?

О: Започнете с теста с index.php: заредете маршрут с /index.php/ в пътя. Ако това работи, а чистият URL не, възстановете файла public/.htaccess и потвърдете, че mod_rewrite е включен с AllowOverride All. Ако нито един URL не работи, проверете дали базовият URL е зададен правилно в app/Config/App.php или .env и дали маршрутът в app/Config/Routes.php съвпада с точното име и капитализация на класа на контролера.

В: Защо сайтът ми на CodeIgniter работи с index.php, но не и без него?

О: Слоят за пренаписване не е активен. Самият фреймуърк е наред, но Apache не насочва чистите URL адреси към index.php. Това означава, че или mod_rewrite е изключен, файлът .htaccess липсва, или AllowOverride е зададен на None и Apache игнорира файла. Когато оправите слоя за пренаписване, index.php изчезва от URL адресите.

В: Защо маршрутизацията на CodeIgniter връща 404 на лайв сървър, но не и локално?

О: Почти винаги е чувствителността към главни и малки букви. Локалната файлова система на Windows или macOS третира products.php и Products.php като един и същ файл, а Linux сървърът не го прави. Уверете се, че името на файла на контролера, името на класа и референцията в маршрута ползват еднаква капитализация.

В: Различава ли се решението за CodeIgniter 404 при Nginx?

О: Да. Nginx никога не чете .htaccess, така че правилата за rewrite на Apache там не правят нищо. При Nginx насочвате заявките чрез директивата try_files $uri $uri/ /index.php$is_args$args; вътре в server block-а и сочите root към директорията public/ на CodeIgniter.

Борислав Тонев

Автор

Борислав е копирайтър с набито око за детайла и увлечение по информационните технологии, което датира от детството му. През годините, той е писал за огромно разнообразие от най-различни теми, но признава, че най-вълнуващото предизвикателство за него е да разбере как работи модерният онлайн свят и да предаде знанията си на читателите.

Напишете коментар

Задължително поле*