codez Posted July 30, 2010 Report Share Posted July 30, 2010 (edited) Neliela pamācība par to, kā izveidot vienkāršu smuko urļu routing sistēmu, bez MVC freimworka un OOP. Sākam ar .htaccess faila izveidi: .htaccess Options +FollowSymlinks RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !^(.+)\.(css|js|jpg|gif|png|ico)$ RewriteRule ^(.*) index.php [QSA,L] Šis .htaccess fails redirektos visus requestus, kuri nav uz .css, .js, ..., failiem, uz index.php. Tātad index.php būs visu php pieprasījumu ieejas punkts. Izveidojam failu index.php: index.php <?php $p=explode('/',$_SERVER['REQUEST_URI']); if ($p[1]=='') {$p[1]='index';} if (file_exists($m=$p[1].'.ctrl')) { ob_start(); require $m; $content = ob_get_contents(); ob_end_clean(); } else { $content = 'page not found'; } include 'layout.php'; index.php ar komentāriem <?php //nolasa pieprasīto adresi un ar explode sadalā daļās. //Piemeram, adrese /article/100-Hello/4, izveidos $p masīvu ['','article','100-Hello','4'] //Tātad izvēlētā lapa atradīsies masīva 1. elementā. $p=explode('/',$_SERVER['REQUEST_URI']); //pārbauda, ja nu gadījumā tiek pieprasīta pamatlapa ar uri '/' tad $p[1] būs '', tāpēc piešķiram viņam 'index'. if ($p[1]=='') {$p[1]='index';} //pārbaudam vai fails, kurā tālāk glabāsies katra no sadaļām, eksistē. Tie būs, piemēram, faili:index.ctrl, user.ctr, login.ctrl if (file_exists($m=$p[1].'.ctrl')) { //ja eksistē, tad palaižam failu un tā uzģenerēto saturu nevis izvadam uzreiz ārā, bet saglabājam mainīgajā $content ob_start(); require $m; $content = ob_get_contents(); ob_end_clean(); } else { //ja neeksistē, tad ierakstām kontentā vienkārši, ka lapa nav atrasta. $content = 'page not found'; } //šijā pozīcijā mums ir uzģenerēts katras lapas mainīgais saturs, izsaucam layout.php, kurš izvadīs visu lapas saturu, ievietojot tur $content include 'layout.php'; Kopumā šis index.php nodrošina, ka ja tiks izsaukta saite /modulis/param1/param2/, tad tiks izsaukt modulis.ctrl fails un tā uzģenērētais saturs ievietots layout.php failā. Atliek tikai uzrakstīt sev vēlamo layout.php un vēlamos .ctrl failus layout.php <div>Header</div> <?php echo $content; ?> <div>Footer</div> index.ctrl <b>Jūs esat nonācis sākumlapā</b> user.ctrl Sveiki, es esmu <?php echo $p[2]; ?>. lietotājs. tagad varat pamēģināt izsaukt /user/123 saiti. Tālāk katras jaunas lapas izveidošanai atliek tikai izveidot jaunu .ctrl failu, kurā uzreiz var rakstīt attiecīgajai sadaļai atbilstošo kodu. Edited July 30, 2010 by codez Quote Link to comment Share on other sites More sharing options...
codez Posted July 30, 2010 Author Report Share Posted July 30, 2010 (edited) Nedaudz uzlabota versija. .htaccess failu atstājam to pašu: index.php: <?php function load($_name,$_data=array()){ extract($_data); ob_start(); require $_name; $c = ob_get_contents(); ob_end_clean(); return $c; } $p=explode('/',$_SERVER['REQUEST_URI']); if ($p[1]=='') {$p[1]='index';} if (file_exists($m=$p[1].'.ctrl')) { $content = include $m; } else { $content = 'page not found'; } include 'layout.php'; Šijā index.php atšķirībā no pirmā .ctrl faili netiek ielādēti kā tepleiti, bet tiek gaidīts, ka tie atgreizīs savu uzģenerēto saturu. Tagad .ctrl fails izskatīsies šādi: user.ctrl <?php $data=array( 'id'=>(int)@$p[2], 'name'=>'Jonh' //šo nolasa no db, piemēram. ); return load('user.tpl',$data); Katram .ctrl failam ar return jāatgriež savs uzģenerētais saturs. Šijā gadījumā to daru ar load funkciju ielādējot user.ctrl atbilstošu templeitu user.tpl Load funkcijai pirmais paramters ir templeita fails, otrais ir masīvas ar parametriem, kurus nodot templeitam. user.tpl Lietotāja id:<?php echo $id; ?><br /> Lietotāja vārds:<?php echo $name; ?> Šāda pieeja ļauj katras lapas PHP kodu, atdalīt atsevišķā failā no teplate koda. Tagad, katras jaunas lapas izveidei, jāizveido .ctrl un .tpl fails un .ctrl failā ar retrun load('kautkas.tpl'); jāatgriež uzģenerētais templeits. Tagad šis jau būtībā ir tāds vienkārš MVC, kurā realizēta V un C daļa. Edited July 30, 2010 by codez Quote Link to comment Share on other sites More sharing options...
Kemito Posted August 10, 2010 Report Share Posted August 10, 2010 Sveiki, patestēju, un pats iemēģināju visu! Diagnoze man ir diezgan smaga, pats esmu iesācējs, tāpēc ir tā, ka ar šādām lietām ir jāsāk darboties KAUTKAD vismaz. Izmantojot pirmo veidu, bez tā teiktā uzlabojuma, viss iziet laukā kā tam jābūt tā teikt. HEADRIS CONTENT FOOTER Bet atverot, kādu URL, šajā gadījumā pieminēto /user vai /user/123 Reālā veidā man viņš viņu neatver, bet ja ievada kautko citu, pasaka - Šāda lapa neeksistē. Viss kā nākas. Ja uztaisa ctrl failu lol atverot /lol atkal tas pats, kas ar user! Otro veidu izmantojot manuprāt aizgāja sliktāk ( MAN ). Sākuma lapā CONTENT HEADER 1 FOOTER Atverot "Šāda lapa neeksistē" viss ir bumbā, un atkal tā pati kļūda ar šiem CTRL failiem! Tā tad mans .htaccess un pārējie faili ir sekojoši šeit: HTACCESS Options +FollowSymlinks RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !^(.+)\.(css|js|jpg|gif|png|ico)$ RewriteRule ^(.*) index.php [QSA,L] INDEX <?php $p=explode('/',$_SERVER['REQUEST_URI']); if ($p[1]=='') {$p[1]='index';} if (file_exists($m=$p[1].'.ctrl')) { ob_start(); require $m; $content = ob_get_contents(); ob_end_clean(); } else { $content = 'page not found'; } include 'layout.php'; ?> LAYOUT <div>Header</div> <?php echo $content; ?> <div>Footer</div> index.ctrl <b>Jus esat nonacis sakumlapa</b> USER CTRL Sveiki, es esmu <?php echo $p[2]; ?>. lietotajs. PIedevām atverot - /index viss itkā ir okey :P Quote Link to comment Share on other sites More sharing options...
codez Posted August 10, 2010 Author Report Share Posted August 10, 2010 (edited) Otrajā variantā tiek izmantots principā jau MVC paterns, tāpēc kontrolerim (.ctrl failos) ir nevis jāsatur html kods, bet gan jāatgriež tas. Kontrolerī šijā gadījumā ir paredzēts apstrādāt pieprasījumu: nolasīt datus no modeļiem, padot tos templeitam, utt. Kā redzams index.php (2.variantā) tād no kontrolera tā ģenerētais saturs tiek saņemts šādi: $content = include $m; tas nozīmē, ka kontrolerim saturs ir jāatgriež šādi: return 'kaut kas'; Bet tā kā mēs gribam saturu rakstīt smukā html formātā, tad to mēs daram .tpl failā, kuru kontroleris tad arī ielādē un tā uzģenerēto saturu atgriež. Bet ielādes procesā kontroleris par parametru nodot datus, kurus templeits izmanto html koda ģenerēšanai. Tāpēc 2. variantā (kurš aprakstīts komentārā #2) kontrolerim (.ctrl failam) jāizskatās šādi: <?php $data=array( 'id'=>(int)@$p[2], 'name'=>'Jonh' //šo nolasa no db, piemēram. ); return load('user.tpl',$data); kur $data ir masīvs ar mainīgajiem, kurus gribam nodot templeitam. kamēr templeitam (.tpl failam) šādi: Padotais parametrs id: <?php echo $id; ?> Padotais parametrs name: <?php echo $name; ?> templeitā tiek izmantoti ar $data nodotie mainīgie. Ja masīvā $data ir elementi a,b,c - $data=array('a'=>1,'b'=>'hi','c'=>777); tad .tpl failā būs pieejami mainīgie $a,$b,$c ar šādām vērtībām. 2. variants ir nedaudz labāks par 1. jo tajā tad teiksim viss PHP kods tiek atdalīts no templeita. .ctrl failā mēs veicam dažādas pārbaudes, ielādējam vajadzīgos failus, utt. Bet beigās uzģenerētos datus padodam .tpl failam satura uzģenerēšanai un ar return atgriežam index.php failam. Mēs pat varam no viena kontrolera izvēlēties dažādu .tpl failu ielādi. Piemēram, ja lietotājs nav ielogojies, varam atgriezt viņam, ka lapai nav iespējams piekļūt, bet lai dāžadi templeiti nebūtu jāliek vienā failā un tad ar case vai if izvēlās, kuru tekstu izvadīt, mēs kontrolerī jau nosakām, kuru tpl failu atgreizt. <?php if (lietotajs_ielogojies()){ $data=ieladejam_leitotaja_datus(); return load('secretpage.tpl',$data); } else { return load('accessdenied.tpl'); } Tas mums ļauj arī izvairīties no headers already sent kļūdām, jo kontrolera izpildes laikā vēl nekāda izvade nav notikus, tāpēc varam rakstīt, piemēram, ja lietotājs nav ielogojies, redirektojam viņu uz login lapu, savadāk lādējam vajadzīgo templeitu. <?php if (lietotajs_ielogojies()){ $data=ieladejam_leitotaja_datus(); return load('secretpage.tpl',$data); } else { Header('location:/login'); exit; } Tātad #2 komentāra variantā: - kontrolerī (.ctrl failā) ir PHP kods - aplikācijas loģika - templeitā (.tpl failā) ir HTML templeits ar atsevieškiem PHP koda fragmentiem, kuri tiek izmantoti mainīgo izvadei, vai teiksim kādai cikliskai koda ģenerācijai. Edited August 10, 2010 by codez Quote Link to comment Share on other sites More sharing options...
codez Posted August 10, 2010 Author Report Share Posted August 10, 2010 (edited) Kemito, ja tev tomēr neiet pirmais variants, tad pārbaudi vai tev rewrite modulis apacī ir ieslēgts. Ja izmanto wamp, tad menu, tad ir pie Apache->apache modules-> rewrite_module Ja pliku apache, tad httpd.conf failā pie Loadmodule rewrite_module jānoņem komentārs - # zīmē. Jāpārstartē apacis. P.S. Nokopēju kodus tieši no komentāra un saliku failos - viss strādā kā vajag. Pārbaudi vai tev visi faili ir ar mazajiem burtiem. Edited August 10, 2010 by codez Quote Link to comment Share on other sites More sharing options...
Леший Posted August 10, 2010 Report Share Posted August 10, 2010 Ja izmanto wamp, tad menu, tad ir pie Apache->apache modules-> rewrite_module Ja pliku apache, tad httpd.conf failā pie Loadmodule rewrite_module jānoņem komentārs - # zīmē. Ja džekam ir kāda Debian-like distra ar apache2, tad moduļu ir jāenablo ar a2enmod komandu šellā. Quote Link to comment Share on other sites More sharing options...
Kemito Posted August 10, 2010 Report Share Posted August 10, 2010 Bet tā arī neizskaidroji, kapēc man mistiskajā veidā neatrod tādu URL, ja ir izveidots ctrl fails, bet index atrod, kā arī, ar otro veidu mistiski parādās 1nieks!, un virs header parādās saturs! Quote Link to comment Share on other sites More sharing options...
codez Posted August 10, 2010 Author Report Share Posted August 10, 2010 Kemito, man pārkopējot kodus no tava komentārā, viss strādā kā vajag. Iespējams vaina ir kur citur. Piemēram, kāda ir pilnā adrese uz kuru tu testē? http://localhost/user/123 vai http://localhost/tests1/user/123 Otrajā gadījumā viņš mēģinās meklēt tests1.ctrl failu, kura protams nebūs. Pameklē vēl kas varētu ne tā būt. Pamēģini padebugot - ko tev izvada šādi?: <?php $p=explode('/',$_SERVER['REQUEST_URI']); print_r($p); echo '<br />'; if ($p[1]=='') {$p[1]='index';} print_r($p); echo '<br />'; if (file_exists($m=$p[1].'.ctrl')) { print_r($m); echo '<br />'; ob_start(); require $m; $content = ob_get_contents(); ob_end_clean(); } else { $content = 'page not found'; } include 'layout.php'; Quote Link to comment Share on other sites More sharing options...
shurix Posted August 27, 2010 Report Share Posted August 27, 2010 Kā pārveidot htaccess, lai varētu atvērt dažas izņēmumu mapes, piemēram localhost/forums ? Quote Link to comment Share on other sites More sharing options...
Maaren Posted August 28, 2010 Report Share Posted August 28, 2010 (edited) Kā pārveidot htaccess, lai varētu atvērt dažas izņēmumu mapes, piemēram localhost/forums ? RewriteEngine On RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L] php_flag magic_quotes_gpc off php_flag register_globals off Es izmantoju šādu variantu, tiesa gan, nav manis rakstīts.. Bet deļ kam divreiz izgudrot divriteni. Edited August 28, 2010 by Maaren Quote Link to comment Share on other sites More sharing options...
xcwcx Posted August 29, 2010 Report Share Posted August 29, 2010 Mazliet offtopiks, bet kāpēc jālieto kaut kas tik nepareizs kā (int)@$p[2] ? Divkāršs type castings un @ - sucks. $data = array( 'id' => (isset($p[2]) && is_int($p[2])) ? $p[2] : '', ); Palabojiet, ja kļūdos. Quote Link to comment Share on other sites More sharing options...
codez Posted August 29, 2010 Author Report Share Posted August 29, 2010 Mazliet offtopiks, bet kāpēc jālieto kaut kas tik nepareizs kā (int)@$p[2] ? Divkāršs type castings un @ - sucks. 1)Tāpēc, ka tas ir acīmredzami īsāk: 'id' => (isset($p[2]) && is_int($p[2])) ? $p[2] : '' 'id' => (int)@$p[2] un viennozīmīgi ir vieglāk uztverams un tas strādā. 2)Tāpēc, ka cenšoties izdarīt tipa "pareizāk", kā tu centies, var pielaist kaudzi kļūdu, kā to izdarīji tu, jo $p[2] pēc explode vienmēr būs string tipa mainīgais un tavs nosacījums vienmēr būs false un izteiksme atgriezīs ''. Vai palaboju? P.S. Maaren .htaccess fails iepriekš'īsti nederēs, jo ļaus pa taisno piekļūt .ctrl un .tpl failiem. Quote Link to comment Share on other sites More sharing options...
rATRIJS Posted August 29, 2010 Report Share Posted August 29, 2010 Īsti negribas piekrist pa to, ka vieglāk saprast. Vēl viens iemesls varētu būt ātrums. Rezultāti un manas sistēmas: Short: 3.8734s Long: 0.8649s Ar kodu: <?php function test_long($p) { return isset($p[0]) ? (int) $p[0] : 0; } function test_short($p) { return (int) @$p[0]; } class Timer { private $t; public function __construct() { $this->t = microtime(true); } public function __toString() { return round(microtime(true) - $this->t, 4) . 's'; } } $p = array(); $t = new Timer(); for($i = 0; $i < 1000000; $i++) { test_short($p); } echo "Short: $t"; echo '<br /><br />'; $t = new Timer(); for($i = 0; $i < 1000000; $i++) { test_long($p); } echo "Long: $t"; ?> Lai vai kā - katrs dara kā ērtāk. Quote Link to comment Share on other sites More sharing options...
codez Posted August 29, 2010 Author Report Share Posted August 29, 2010 (edited) ratrij, 1)Par to vieglāk saprasts, atkarīgs no tavām zināšanām, kuras veidojas no ikdienas pieredzes. Ja tu protams tādus neizmanto, tad saprast grūtāk, bet, ja zini abu variantu darbības mehānismus, tas īsāko izlasīt ir ātrāk. 2) Patestē klašu metožu izsaukšanu objektu instancēm pret funkcijas izsaukšanu. Varbūt teiksi, ka tas ir vērā ņemams iemesls kapēc vairs nelietot OOP? Class: 2.9369s Function: 1.783s OMG, OOP is evil. 3)Kāpēc tu testē gadījumu, kurš pareizas aplikācijas darbība izpildīsies zem 1% gadījumu? Patestē šo ar varaintu, kad masīva elements ir definēts - test_long(array($p)); . Starpība vairs nebūs tik liela. Short: 2.5447s Long: 1.5923s Ja godīgi, es uzskatu, ka PHP skriptam griežoties pie nedefinēta mainīgā vajadzētu atgriez NULL, nevis saukt warning-us. Bet tā kā PHP nav tā kā es vēlētos, tad es to simulēju visērtākajā veidā, attiecīgi, @$p[0]; Edited August 29, 2010 by codez Quote Link to comment Share on other sites More sharing options...
xcwcx Posted August 29, 2010 Report Share Posted August 29, 2010 @codez, atvaino - ielaidu kļūdu - is_int vietā biju domājis is_numeric. Jebkurā gadījumā uzskatu, ka tavs piemērs ir nedaudz čž, vienkārši centos palabot konkrēto vietu. Un tas, ka kods ir nedaudz īsāks, uzreiz nenozīmē, ka tas ir arī vieglāk lasāms un pareizāks. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.