Bakke Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 (endret) Holder på å lage et lite CMS, som skal kunne endre innholdet på sider jeg lager (dvs legge til sider, ta vekk sider og endre innholdet på dem). Med tanke på utbygging av dette systemet i fremtiden, så vil jeg lage det 100% OOP. Har dessverre litt begrenset kunnskap om OOP, men ser på dette som et læringsprosjekt. Jeg vil selvfølgelig skille logikk og presentasjon, så jeg har skrevet min egen lille template-klasse. Det jeg lurer på er hvordan jeg skal implementere resten av klassene mine i denne template-motoren, slik at de kan brukes i sider som blir hentet inn av templaten. F.eks både meny og innhold på siden skal bestå av egne filer, som skal settes sammen med template-filen av template-motoren. Disse sidene trenger begge tilgang til database-klassen min, men jeg vil helst slippe å lage et nytt objekt av denne klassen i hver av filene. Er det mulig at alt innhold på siden, som blir generert av template-klassen, får tilgang til de andre nødvendige klassene mine, kun ved å lage objekter av dem en gang? lib/template.php <?php class template { public $output; function __construct($templateFile = 'template.html') { require_once('lib/error_object.php'); if(file_exists($templateFile)) { $this->output = file_get_contents($templateFile); } else { $this->error[] = new error_object('Template file not found.'); } } function parseTemplate($tags = array()) { if(count($tags) > 0) { foreach($tags as $tag=>$data) { if(file_exists($data)) { $data = $this->parseFile($data); } $this->output = str_replace('#' . $tag . '#', $data, $this->output); } } else { $this->error[] = new error_object('No tags were provided for replacement in template file.'); } } function parseFile($file) { ob_start(); if(!require_once($file)) { $this->error[] = new error_object('Could not put file content into template - file not found.'); } $content = ob_get_contents(); ob_end_clean(); return $content; } function display() { return $this->output; } } ?> index.php <?php require_once('lib/template.php'); $template = new template(); $tags = array('page'=>'test', 'menu'=>'menu.php', 'content'=>'content.php'); $template->parseTemplate($tags); echo $template->display(); ?> Slik som her, må jeg lage et objekt av database-klassen inni både menu.php og content.php? Hva vil være den mest pratiske løsningen? Takker for svar Endret 20. januar 2010 av Bakke Lenke til kommentar
medlem-68510 Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 (endret) Ta følgende eksempel: <?php $foo = new bar; include('cake.php'); Om cake.php skal ha tilgang til $foo må du bruke global $foo; i cake.php. Endret 20. januar 2010 av Jckf Lenke til kommentar
Jonas Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 (endret) Om cake.php skal ha tilgang til $foo må du bruke [..] Dette stemmer ikke helt. Faktisk ikke i det hele tatt, i nyeste versjon. Men nok om det. Trådstarter - det virker som du blander to måter å lage templates på; en hvor man bruker PHP filer og henter ut det genererte innholdet via output buffering, samt den andre hvor man lager sin egen syntaks, som i ditt tilfellet er #whatever#. Å blande disse er fullstendig unødvendig og kan føre til utrolig mye rart. F.eks. kan brukergenerert innhold blir tolket som tags. La meg vise det hvordan jeg (nesten) pleier å gjøre det. <?php class Presenter { public function GetFromTemplate ( $data, $template ) { extract ( $data ); ob_start (); require ( $template ); return ob_get_clean (); } } ?> Index-filen kan typisk se noe lignende som følger. <?php $includes = array_map ( function ( $file ) { return pathinfo ( $file, PATHINFO_FILENAME ); }, glob ( '/includes/*.php' ) ); if ( array_key_exists ( 'page', $_GET ) && array_key_exists ( $_GET['page'], $includes ) ) $page = $_GET['page']; else $page = 'home'; $presenter = new Presenter (); echo $presenter -> GetFromTemplate ( array ( 'page_title' => 'My Site!', 'page' => $page, ), '/templates/index.php' ); ?> .. og hvor template-filen kanskje ser slik ut. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title><?= $page_title; ?></title> </head> <body> <?php require ( '/templates/' . $page . '.php' ); ?> </body> </html> Endret 20. januar 2010 av Jonas Lenke til kommentar
medlem-68510 Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 (endret) Du glemmer noe her. Hva om jeg sender en request ala ?page=../index.php ? EDIT: Oops. Glem det =) Skjønte sikkerhetssjekken din nå. Endret 20. januar 2010 av Jckf Lenke til kommentar
Jonas Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 (endret) Kødder du nå med meg nå? Hadde sikkerhet vært topic, så hadde jeg kanskje brydd meg et sekkund om det, men siden det ikke er det, så gjør jeg ikke det. Det skal samtidig nevnes at da hadde det ikke skjedd noe som helst. Ta en kikk på koden en gang til. Edit: Copy that.. Endret 20. januar 2010 av Jonas Lenke til kommentar
Bakke Skrevet 20. januar 2010 Forfatter Del Skrevet 20. januar 2010 (endret) Takk for hjelpen. Skrev om template-motoren slik som du viste, Jonas Jeg har nå puttet <?php require($config) ?> helt på toppen av template-filen min. Config-filen inneholder en __autoload funksjon og laster inn alle de nødvendige klassene som websiden vil trenge. Er dette en grei løsning, eller burde jeg aktivere klassene en annen plass? Endret 20. januar 2010 av Bakke Lenke til kommentar
Jonas Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 (endret) Tja.. Du kommer garantert til å trenge flere funksjoner i template-ene dine, så jeg ville f.eks. laget en mappe med alle og inkludert de i presenter-klassen. <?php class Presenter { public function GetFromTemplate ( $data, $template ) { $functions = glob ( '/presenters/functions/function.*.php' ); foreach ( $functions as $function ) require_once ( $function ); extract ( $data ); ob_start (); require ( $template ); return ob_get_clean (); } } ?> Endret 20. januar 2010 av Jonas Lenke til kommentar
medlem-68510 Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 (endret) Off topic, rettet mot Jonas: Når man bruker include() eller lignende funksjoner inne i en class, blir da funksjonene i filen man includer del av classen? I så fall, kan man erstatte funksjoner på noe samme vis som en class som extender en annen kan? EDIT: Til trådstarter: Jeg ville ikke plasser annet enn konfigurasjonsvariabler i konfigurasjonsfilen. Endret 20. januar 2010 av Jckf Lenke til kommentar
Jonas Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 Nei, slik er det ikke. En funksjon er bare en funksjon, uansett hvor den er definert. Den er samtidig tilgjengelig uansett hvor den er definert. Derfor er det viktig at man i en slik klasse bruker require_once og ikke require. Følgende eksempel vil f.eks. printe ut «z0mg». <?php class Foo { public function __construct () { function Bar () { echo 'z0mg'; } } } $myObject = new Foo (); Bar (); ?> Lenke til kommentar
medlem-68510 Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 (endret) Leit. Har prøvd å lage et mer dynamisk system for class extension, men så langt har det kun blitt objekter med underobjekter som har en ref til parent-objektet for å kunne bruke sine "brødre og søstre". Idé? EDIT: Eksempel: class pappa { public $navn; function nytt_barn($navn,$objekt) { $this->$navn = $objekt; $this->$navn->parent = &$this; } } class unge { function sutre() { echo 'Buhu og wahwah, ' . $this->parent->navn . '!'; } } $pappa = new pappa(); $pappa->navn = 'Hans'; $pappa->nytt_barn('kjetil',new unge()); $pappa->kjetil->sutre(); Endret 20. januar 2010 av Jckf Lenke til kommentar
Jonas Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 Far og barn er egentlig ikke noen god analog til klasser og arv. Hva er det du ønsker å bruke dette til? Kanskje det finnes andre og bedre fremgangsmåter. Lenke til kommentar
medlem-68510 Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 Klaska bare sammen et eksempel i farten. Jeg ønsker å skrive en klasse som inneholder et sett funksjoner, men jeg ønsker også å kunne erstatte disse med andre funksjoner. F.eks. for å implementere et annet brukersystem i en CMS-klasse. Lenke til kommentar
Alex Moran Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 En familie representert ved objekter (med inheritance og composition) <?php class Person { protected $name; protected $children = array(); protected $parent; public function __construct($name) { $this->name = $name; } public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } public function addChild(Person $child) { $child->setParent($this); $this->children[$child->getName()] = $child; } public function getChildren() { return $this->children; } public function setParent(Person $parent) { $this->parent = $parent; } public function getParent() { return $this->parent; } public function __toString() { return $this->name; } } // A little boy IS a person class LittleBoy extends Person { public function whine() { return 'buhuhuhuhu'; } } // A little girl IS also a person class LittleGirl extends Person { public function whine() { return 'meeeeeee'; } } $dad = new Person('Nils'); // a person HAS a child $dad->addChild(new LittleBoy('Thomas')); $dad->addChild(new LittleGirl('Blair')); $children = $dad->getChildren(); echo $children['Thomas']->getParent()->getName(); foreach ($children as $child) { echo $child->whine(); } Lenke til kommentar
Jonas Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 (endret) Klaska bare sammen et eksempel i farten. Jeg ønsker å skrive en klasse som inneholder et sett funksjoner, men jeg ønsker også å kunne erstatte disse med andre funksjoner. F.eks. for å implementere et annet brukersystem i en CMS-klasse. Isåfall er det ikke verre enn å opprette en ny klasse som arver fra CMS-klassen din og skrive over metoden ved å enkelt og greit lage en ny med samme navn. Endret 20. januar 2010 av Jonas Lenke til kommentar
medlem-68510 Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 Det var slik jeg gjorde det først, men hva om jeg vil extende CMS-classen min med flere enn én annen class? Lenke til kommentar
Jonas Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 Klasser kan arve fra klasser som arver fra klasser som arver ... osv. Det er dog rimelig statisk og det virker som du ønsker det dynamisk. Jeg tipper du har et CMS og forskjellige applikasjoner som skal modifisere virkemåte eller output på noe vis. Ofte brukes et observer-pattern til slikt. Du skal ikke se bort ifra at det allerede er implementert i CMSet du benytter deg av. https://www.diskusjon.no/index.php?showtopi...8&hl=plugin http://en.wikipedia.org/wiki/Observer_pattern Lenke til kommentar
Bakke Skrevet 20. januar 2010 Forfatter Del Skrevet 20. januar 2010 Jeg tenkte på å gjøre alle klassene tilgjengelige for siden som blir hentet inn i templaten, ikke bare funksjoner, men det fungerte jo på noe lunde samme viset. Løsningen ble slik lib/template.php class template { public function getFromTemplate($tags, $template='templates/index.php') { // Check that the autoload function is not already declared if(!function_exists('__autoload')) { // Autoload a class when requested function __autoload($class) { require_once('lib/' . $class . '.php'); } // Initiate classes $db = new db(); // Connect to database $db->connect(); } // Load the page extract($tags); ob_start(); require($template); return ob_get_clean(); // Disconnect from database $db->disconnect(); } } Lenke til kommentar
Jonas Skrevet 20. januar 2010 Del Skrevet 20. januar 2010 Å gjøre database-klassen tilgjengelig fra templates strider på en måte litt i mot hele prinsippet med å separere logikk og presentasjon, men.. Lenke til kommentar
Bakke Skrevet 20. januar 2010 Forfatter Del Skrevet 20. januar 2010 Å gjøre database-klassen tilgjengelig fra templates strider på en måte litt i mot hele prinsippet med å separere logikk og presentasjon, men.. Så jeg bør heller koble til databasen i index.php? Men kan jeg gjøre resten av klessene tilgjengelige fra templaten? Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå