Lage sider fra database

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

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]
[/PHP]

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");

}[/PHP]

2 Likes

Ikke hyr inn Orkla til lage koden din: https://www.webforumet.no/forum/lover-regler-og-normer/22998-blir-nektet-publisere-oppskrift-p-seigmenn.html
Da vil ikke seigmennsiden vises i det hele tatt.

Ellers, takk til adeneo som er en uutømmelig kilde til smart koding.

Takk for tips adeneo :slight_smile:

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.

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.

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();

} [/PHP]

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

Jeg tror du missforstår meg :wink: Kontrolleren er fin den, men innholdet bør genereres live, og ikke avhenge av at en fil allerede har innhold.

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

}[/PHP]

Dette virker som en veldig treg måte å gjøre det på. Dessuten er den lite fleksibel.

/seigmann.php kan hente fra tabellen med tittel (celle) “seigmann”. id-en trenger man ikke til annet enn å sortere, slette eller endre. Ikke til å hente.