Lage sider fra database

kongen

kongemedlem
Hvis jeg i en database har oppskrift på seigmenn og kremtopper. Seigmenn har id1 og kremtopper har id2. Jeg ønsker at når noen taster inn domene.no/seigmann.php så skal oppskriften på seigmann komme opp, men filen seigmann.php eksisterer ikke, men skal bli dynamisk laget fra databasen. Hvordan gjøres dette?

Jeg vil ikke ha urlene slik: domene.no/oppskrift.php?id=1
Jeg vil ha: domene.no/seigmann.php
 

adeneo

Medlem
Uffda, nå ble det plutselig litt mer komplisert!

Skal du svare på requests som ikke går til filer må du ha en eller annen slags kontroller.
Du må begynne med å videresende alle forespørsler som ikke matcher en fysisk fil eller mappe til kontrolleren, og det gjøres normalt i Apache, med .htaccess

PHP:
RewriteEngine On

# Disable rewriting for existing files or directories
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# redirect all other requests to controller.php
RewriteRule ^.*$ controller.php [PT,L]

Nå har vi videresendt alt til controller.php, så da må sjekke URL'en i den filen og vise det rette innholdet.

PHP:
session_start();
$url = explode('/', trim($_SERVER['REQUEST_URI'], '/'));

switch($url[0]) {
    case '': //startside

        include("menu.php");
        include("sites/start.php");

    break;
    case 's%C3%B8k': //søk
        $query = isset($url[1]) ? $url[1] : "";
		    
        include("menu.php");
        include("sites/search.php");

    break;
    case 'seigmann.php':

        include("menu.php");
        include("sites/seigmann.php");

    break;
    default:
        include("404.php");
}
 

kongen

kongemedlem
Takk for tips adeneo :)

Kanskje jeg også burde legge inn noe serverside caching for å "permanent" lagre de nye sidene slik at databaseserveren kan få seg et 5-minutt.

@Tonny, uff da, jeg glemte Orkla. Da får jeg lage oppskrift på seige damer istedet. Pyntet med melis-sikkel i munnen.
 

spikre

peterhamre.no
Denne koden forutsetter at seigmann.php-fila faktisk eksisterer. Det gjør den jo ikke. Jeg ville heller ha tillatt URL-en som alias, men kjørt alle forespørsler mot oppskrift.php. I oppskrift.php bruker du en php_self til å hente data rett fra databasen og servere et "live generert resultat". Hvis kodeordet ikke gir treff, kan du redirecte til en 404-side.
Med denne metoden er det også veldig enkelt å lage sitemaps, eller gjøre globale endringer.
 

adeneo

Medlem
Denne koden forutsetter at seigmann.php-fila faktisk eksisterer.

Ehm, nei! Det vil si den gjør jo forsåvidt det ettersom jeg har lagt til en include til en seigmann.php fil i en annen mappe, men kontrolleren forutsetter ingenting, den fanger opp en hver URL som ikke går til en fysisk fil eller mappe.

Grunnen til at man ikke ønsker å fange opp filer som eksisterer er selvfølgelig at det blir et helvete med statiske ressurser som bilder, css og js filer, slik at de leveres direkte utenom kontrolleren.

Det er jo et så enkelt eksempel som mulig på hvordan en kontroller virker, uten å bruke store klasser. Ønsker man å gå videre og se på MVC og mer avanserte ting er det bare å lese kildekoden til Laravel, Symfony, Fuel eller lignende, de bruker alle det samme prinsippet, men i mer kompliserte klasser. Selv Wordpress bruker det samme prinsippet i sin kontroller.

Man videresender altså alt utenom statiske ressurser i .htaccess, slik at uansett hvilken URL som skrives inn, forutsatt at det ikke er til en eksisterende fil, så ender man opp i controller.php, og i controller.php fanger man opp det man ønsker, og sender 404 for resten.
Den enkleste måten å fange opp forskjellige adresser på er å sjekke URL'en og bruke en switch, hva man gjør i den switched er fritt valg, jeg bare skrev et kjapt eksempel, her er et annet

PHP:
$url = explode('/', trim($_SERVER['REQUEST_URI'], '/')); 

switch($url[0]) { 
    case '': //startside 

        echo "startsiden";

    break; 
    case 'side1': // http://www.minside.no/side1/

        echo "side1";

    break; 
    case 'side2': // http://www.minside.no/side2/

        switch($url[1]) {
            
            case 'info': //  http://www.minside.no/side2/info/

                echo "side2 - info";

            break;
            
        }
    break; 

    default: // alt annet
        header('HTTP/1.0 404 Not Found');
        echo "<h1>404 Not Found</h1>";
        echo "The page that you have requested could not be found.";
        exit();
}

og slik lager man verdens enkleste kontroller, og det finnes flere sider på nettet hvor man kan se litt andre versjoner av samme prinsipp

Simple PHP Front Controller | TechnoTaste
PHP Tutorials Examples Model View Controller MVC
PHP Master | An Introduction to the Front Controller Pattern, Part 1
Building a PHP Front Controller - O'Reilly Media
 
Sist redigert:

adeneo

Medlem
Det kan jeg være enig, det er gjerne der litt mer kompliserte klasser kommer inn, og henting fra databasen, feilmeldinger osv.

Enkelt eksempel ut i fra spørsmålet, fortsatt med en switch da jeg ikke gidder å skrive en klasse for håndtering av URL'en

PHP:
$url = explode('/', trim($_SERVER['REQUEST_URI'], '/'));  

class DB {
    public function __construct() {
       // sett opp database
       $this->db = $database;
       $this->table = 'oppskrifter';
    }

    public function hent_oppskrift( $id ) {
        $this->db->query("SELECT * FROM ".$this->table." WHERE id=".$id);
    }
}

$db = new DB();

switch($url[0]) {  
    case '': //startside  

        echo "startsiden"; 

    break;  
    case 'seigmenn.php':

        echo $db->hent_oppskrift( 'id1' );

    break;  
    case 'kremtopper':

        echo $db->hent_oppskrift( 'id2' );

    break;
    default:
        // 404
}
 
Topp