Home > Enterprise >  Every URL is showing me "/" (index) with Heroku
Every URL is showing me "/" (index) with Heroku

Time:02-28

I just finished my first MVC project with PHP and MySQL. I created a router that allows me to when I visit an URL, call a function that render the expected file.

I'm doing it with lampp's PHP and MySQL, but not using Apache, otherwise I'm using the php server (php -S localhost:3000 -t public/). There, my project works perfectly well, and the routing is working like normal.

Well, I deployed it on Heroku but the problem is that my routing just doesn't work; every time I try to go (clicking a button or just typing it on the searchbar) to, for example, /about-us it just render "/" (index) again.

Here's my index.php (here I have all of my urls and call the functions that render everything)

<?php 

require_once __DIR__ . '/../includes/app.php';

use MVC\Router;
use Controllers\PropiedadController;
use Controllers\VendedorController;
use Controllers\PaginasController;
use Controllers\BlogController;
use Controllers\AuthController;

$router = new Router();


$router->get('/admin', [PropiedadController::class, 'index']);

$router->get('/propiedades/crear', [PropiedadController::class, 'crear']);
$router->post('/propiedades/crear', [PropiedadController::class, 'crear']);
$router->get('/propiedades/actualizar', [PropiedadController::class, 'actualizar']);
$router->post('/propiedades/actualizar', [PropiedadController::class, 'actualizar']);
$router->post('/propiedades/eliminar', [PropiedadController::class, 'eliminar']);

$router->get('/vendedores/crear', [VendedorController::class, 'crear']);
$router->post('/vendedores/crear', [VendedorController::class, 'crear']);
$router->get('/vendedores/actualizar', [VendedorController::class, 'actualizar']);
$router->post('/vendedores/actualizar', [VendedorController::class, 'actualizar']);
$router->post('/vendedores/eliminar', [VendedorController::class, 'eliminar']);

$router->get('/blog/crear', [BlogController::class, 'crear']);
$router->post('/blog/crear', [BlogController::class, 'crear']);
$router->get('/blog/actualizar', [BlogController::class, 'actualizar']);
$router->post('/blog/actualizar', [BlogController::class, 'actualizar']);
$router->post('/blog/eliminaradminpropiedades', [BlogController::class, 'eliminar']);

$router->get('/', [PaginasController::class, 'index']);
$router->get('/nosotros', [PaginasController::class, 'nosotros']);
$router->get('/anuncios', [PaginasController::class, 'propiedades']);
$router->get('/anuncio', [PaginasController::class, 'propiedad']);
$router->get('/blog', [PaginasController::class, 'blog']);
$router->get('/entrada', [PaginasController::class, 'entrada']);
$router->get('/contacto', [PaginasController::class, 'contacto']);
$router->post('/contacto', [PaginasController::class, 'contacto']);

//Login

$router->get('/login', [AuthController::class, 'login']);
$router->post('/login', [AuthController::class, 'login']);
$router->get('/logout', [AuthController::class, 'logout']);

$router->comprobarRutas();

Here's my router.php

<?php 

namespace MVC;

class Router {

    public $rutasGET = [];
    public $rutasPOST = [];

    public function get($url, $fn) {
        $this->rutasGET[$url] = $fn;
    }

    public function post($url, $fn) {
        $this->rutasPOST[$url] = $fn;
    }

    public function comprobarRutas() {

        session_start();
        $auth = $_SESSION['login'] ?? null;

        //Arreglo de rutas protegidas
        $rutas_protegidas = ['/admin', '/propiedades/crear', '/propiedades/actualizar', '/propiedades/eliminar', '/vendedores/crear', '/vendedores/actualizar', '/vendedores/eliminar/', '/blog/crear', '/blog/actualizar', '/blog/eliminar'];


        $urlActual = $_SERVER['PATH_INFO'] ?? '/';
        $metodo = $_SERVER['REQUEST_METHOD'];

        if($metodo === 'GET') {
            $fn = $this->rutasGET[$urlActual] ?? NULL;
        } else {
            $fn = $this->rutasPOST[$urlActual] ?? NULL;
        }

        if(in_array($urlActual, $rutas_protegidas) && !$auth) {
            header('Location: /');
        }

        if($fn) {
            call_user_func($fn, $this);
        } else {
            echoPre('ERROR 404');
        }

   
    }

    public function render($view, $datos = []) {
        
        foreach($datos as $key => $value) {
            $$key = $value;
        }

        ob_start();
        include __DIR__ . "/view/$view.php";
        $contenido = ob_get_clean();
        include __DIR__ . "/view/layout.php";
    }

}

Here's my .htaccess

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]

Here's my Procfile

web: vendor/bin/heroku-php-apache2 public/

CodePudding user response:

So, the problem was that in my router.php I was looking for $_SERVER['PATH_INFO'] and that wasn't able on the Heroku's web (mine). So, what I did is change the following:

$urlActual = $_SERVER['PATH_INFO'] ?? '/'; to $urlActual = $_SERVER['REDIRECT_URL'] ?? '/';

Problem solved!

PATH_INFO was throwing "/" because it doesn't exist in $_SERVER and that's because I was constantly redirected to the index page.

CodePudding user response:

$urlActual = $_SERVER['PATH_INFO'] ?? '/';
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]

Your router.php is expecting the requested URL to be passed as path-info, but your .htaccess file is not doing this. To pass the URL as path-info then change the RewriteRule directive to read:

RewriteRule (.*) index.php/$1 [L]

$1 is a backreference that contains the URL-path (less the slash prefix) captured from the RewriteRule pattern.

(The QSA flag is not required here.)

  • Related