Webcity.pl


  Własna wyszukiwarka ...

  System wejścia w PHP

  Kompilacja PHP w sys...

  5 niezbędnych czynni...

  Język marketingu

 

 02.02.06 - [new] E-video - artykuł

 30.01.06 - [update] Artykuł o sesjach

 18.12.05 - [update] PDO - artykuł

 19.08.05 - [new+upd] Aktualizacja materia...

 26.04.05 - [update] Nowy artykuł



  Pomocy WML
[php]Sesje nie działają, ...
[actionscript 2.0] [flash...
Problem z talicami w php
[ocena] llll.pl darmowe a...
Kamera na stronie interne...
Kamera na stronie interne...
[xml] Jak wyciągnąć dane
Wizualizacja w JS - POMOC
Web Developer - stała / f...

... i wiele innych wątków na forum ›

Partnerzy
› allRSS.info - katalog zasobów RSS
› iloveflyer.org - webdesign
› webserv.pl - serverpack
› skryptoteka.pl - mnóstwo skryptów
› vel.pl - hosting
› TelePraca.net - pracuj swobodnie
› PHP Solutions - magazyn PHP
› HELION - wydawnictwo informatyczne

Ksišżka dnia

CityMag
Wpisz swój e-mail, aby zaprenumerować nasz Magazyn, który zawiera najnowsze informacje ze świata i najciekawsze teksty.
 

Szukasz czegoś?
Nasza wyszukiwarka znajdzie wszystko, czego szukasz.
 

Szukanie zawansowane


  Reklama
  Redakcja
  Hosting
  Kanał

© WebCity.pl Team
 
 
  Forum Forum
Kursy Kursy
Porady Porady
Recenzje Recenzje
Newsy Newsy
Katalog stron WWW Katalog
Skrypty PHP Skrypty
Download Oferty i praca
Artykuły:
 Teoria
 Praktyka
 Promocja
 Inne
 

 Webcity.pl |

Piszemy Engine cz. 3

Autor: Zyx
   W trzeciej części mam zamiar zająć się stworzeniem właściwego jądra naszego silnika. Jego zadanie jest bardzo proste: zainicjować wszystko, uruchomić stronę, wyświetlić kod w przeglądarce. Całość będzie zawarta w klasie "z_engine", od której stworzymy obiekt $zengine.
   Do pełni szczęścia brakuje nam jednak jednego interfejsu - config, odpowiedzialnego za obsługę konfiguracji znajdującej się w bazie. Dlatego nim zajmiemy się najpierw. Utwórz więc bazę danych "z-engine" i wgraj do niej poniższy kod SQL:

CREATE TABLE config (
   config_name varchar(255) NOT NULL default '',
   config_value varchar(255) NOT NULL default ''
) TYPE=MyISAM;

INSERT INTO config VALUES ('SITE_NAME', 'Z-Engine');
INSERT INTO config VALUES ('SITE_ADDRESS', 'http://www.webcity.pl');
INSERT INTO config VALUES ('DATE_FORMAT', 'd.m.Y H:i');
INSERT INTO config VALUES ('ARROW', '->');
INSERT INTO config VALUES ('SEPARATOR', ' ::');

Tabela ma bardzo prostą budowę, wzorowaną na tablicach asocjacyjnych w PHP, dzięki czemu po załadowaniu będzie można ją przechowywać właśnie w takiej postaci.
   Stwórz także nowy plik: "config.php" w katalogu "engine" i wklep do niego następujący kod:

<?php
   class config extends obj{
      var $vars;

      function load(){
         $r = mysql_query("SELECT * FROM config");
         while($rows = mysql_fetch_row($r)){
            $this -> vars[$rows[0]] = $rows[1];
         }
         return 1;
      }

      function add_value($name, $value){
         mysql_query("INSERT INTO config VALUES('".$name."', '".$value."')");
      }

      function delete_value($name){
         mysql_query("DELETE FROM config WHERE config_name = '$name'");
      }

      function update_value($name, $value){
         mysql_query("UPDATE config SET config_value='".$value."' WHERE config_name = '$name'");
      }

   }
?>

Kod raczej nie wymaga analizy. Do pełni szczęścia brakuje nam jednej małej rzeczy - konfiguracji połączenia z bazą. W katalogu "db" umieszczę więc plik "db.php", a w nim:

<?php

   $this -> dbhost = 'localhost';
   $this -> dbuser = 'root';
   $this -> dbpass = '';
   $this -> dbname = 'z-engine';

?>

Z czystym sumieniem możemy teraz zabrać się za samo jądro. Będzie ono posiadało zbiór pól odpowiadający poszczególnym interfejsom. Znajdą się więc tam pola "config", w którym będzie interfejs konfiguracji, "input" dla wejścia, "timer" dla zegara itp. Dodatkowo umieścimy zbiór metod do zarządzania takimi elementami strony, jak tytuł, czy pasek nawigacyjny, oraz takich, które będą inicjowały bardziej złożone interfejsy, np. "template" dla informacji o używanym layoucie (następny odcinek). Jądro będzie rozbudowywane w miarę kolejnych odcinków, dlatego radzę zostawić tam miejsce na nowe metody. A oto jego zaczątek (plik z-engine.php):

<?php

   class z_engine extends obj{
      var $prefix;
      
      var $timer;
      var $input;
      var $config;
      var $page;
      var $template;
      
      var $dbhost;
      var $dbuser;
      var $dbpass;
      var $dbname;

Konstruktor na samym początku uruchomi zegar, potem system obsługi błędów i komunikatów. W następnej kolejności realizowane będzie połączenie z bazą danych, a dopiero później pozostałych interfejsów:

      function z_engine(){
         $this -> timer = new timer;
         $this -> timer -> start_timer();
         
         $this -> error = new error;
         
         if(file_exists('db/db.php')){
            $this -> prefix = '';
         }else{
            $this -> prefix = '../';
         }
         
         require($this -> prefix.'db/db.php');
         mysql_connect($this->dbhost, $this->dbuser, $this->dbpass) or
            $this -> error -> general_error('Nie mogę nawiązać połączenia z bazą!');
         mysql_select_db($this->dbname) or
            $this -> error -> general_error('Nie znalazłem bazy danych!');
            
         $this -> config = new config;
         $this -> config -> load();
         
         $this -> input = new input;
         $this -> input -> load_input_variables();
      }

Wstawimy też funkcję "date()", która ułatwi formatowanie daty zgodnie z wzorcem podanym w bazie - ominiemy więc konieczność wklepywania całego ciągu do odpowiedniej dyrektywy konfiguracyjnej. Jeśli nie podamy koniecznego parametru, sformatowana zostanie aktualna data:

      function date($t = 0){
         if($t == 0){
            return date($this -> config -> vars['DATE_FORMAT']);
         }
         return date($this -> config -> vars['DATE_FORMAT'], $t);
      }

Ostatnie trzy metody ustawiać będą kluczowe elementy layoutu: tytuł, pasek nawigacji i dodatkowych linków strony:

      function set_page_title($title){
         global $tpl;
         $tpl -> assign_block('PAGE_TITLE', $title.' - '.$this -> config -> vars['SITE_NAME']);
      }
      
      function set_navigation_bar($list){
         global $tpl;
         $tpl -> assign_block('NAVIG_BAR', '<a href="'.$this->config->vars['SITE_ADDRESS'].'">'.$this->config->vars['SITE_NAME'].'</a> '.
            $this->config->vars['ARROW']. implode($this->config->vars['ARROW'], $list));
      }
      
      function set_additional_links($list){
         global $tpl;
         $tpl -> assign_block('ADDITIONAL_LINKS', implode($this->config->vars['SEPARATOR'], $list));
      }
   
   }

Po czym nastąpi inicjacja systemu szablonów i samego jądra:

   $zengine = new z_engine;
   $tpl = new Template($zengine -> prefix.'templates');

?>

Na tym w zasadzie odcinek powinien się skończyć, ale zdecydowałem się opowiedzieć jeszcze o praktycznym użyciu systemu szablonów z PE 2. Oto i swoisty mikroporadnik:

<!-- VAR title "TPL DEMO 1" -->

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>{@title}</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">
</head>

<body>
   Hello World, pracujesz na PHP {PHP_VERSION}.
</body>
</html>

Oto plik '1.tpl', obok którego umieszczamy odpowiadający mu plik przetwarzający:

<?php

   require('../engine/basic.php');
   require('../engine/templates.php');
   
   $tpl = new Template('./');
   $tpl -> set_filename('uchwyt', '1.tpl');
   
   $tpl -> assign_block('PHP_VERSION', phpversion());
   
   $tpl -> parse('uchwyt');
   echo $tpl -> compiled;

?>

Teraz analiza: najpierw musimy ustawić katalog, w którym znajdują się pliki TPL. Możemy to zrobić bezpośrednio za pomocą konstruktora, lub używając jednej z metod: set_root(). Następnym krokiem jest ustawienie uchwytów dla pliku, który chcemy przetwarzać. Uchwyt jest jakby nazwą zastępczą dla pliku i jego używa się w dyrektywie INCLUDE, oraz w metodzie parse(). Za pomocą metody assign_block() ustalamy, jaką wartość ma mieć blok "PHP_VERSION".
   Przypatrz się także plikowi TPL - na samym jego początku zainicjowałem zmienną 'title' o wartości 'TPL DEMO 1'. Później możemy jej używać zarówno przy blokach, jak i w instrukcjach warunkowych, poprzedzając jej nazwę znakiem małpy.

   Oto kod TPL do przykładu drugiego. Aby go obsłużyć, po prostu zmień nazwę używanego pliku w podanym wyżej kodzie PHP:

<!-- VAR title "TPL DEMO 2" -->

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>{@title}</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">
</head>

<body>
   <!-- IF PHP_VERSION eq "4.3.2" -->
   <b>Brawo, używasz tego samego PHP, co ja :).</b>
   <!-- ELSE -->
   <i>Używasz PHP {PHP_VERSION}.</i>
   <!-- ENDIF -->
</body>
</html>

Zastosowaliśmy tutaj instrukcję warunkową, która wyświetla tekst "Brawo, używasz tego samego PHP, co ja :)", jeśli pracujesz na PHP 4.3.2. W przeciwnym wypadku po prostu wyświetla używaną wersję. Jeżeli zachciałoby nam się robić bardziej złożony warunek, mamy do dyspozycji inne operatory, a także dyrektywę <!-- ELSEIF -->, którą także można użyć.

   Następny przykład zademonstruje dołączanie plików TPL za pomocą dyrektywy <!-- INCLUDE -->. Będą nam do tego celu potrzebne dwa pliki: właściwy, oraz dołączany. Zacznijmy od właściwego (3.tpl):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>TPL DEMO 3</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">
</head>

<body>
   <b>TPL DEMO 3</b>
   <!-- INCLUDE body -->
   <b>Koniec TPL demo 3</b>
</body>
</html>

Teraz ten, który będziemy dołączać (3_inc.tpl):

   <!-- IF PHP_VERSION eq "4.3.2" -->
   <b>Brawo, używasz tego samego PHP, co ja :).</b>
   <!-- ELSE -->
   <i>Używasz PHP {PHP_VERSION}.</i>
   <!-- ENDIF -->

Aby obsłużyć te szablony, potrzebny nam będzie taki plik PHP:

<?php

   require('../engine/basic.php');
   require('../engine/templates.php');
   
   $tpl = new Template('./');
   $tpl -> set_filename('body', '3_inc.tpl');
   $tpl -> set_filename('uchwyt', '3.tpl');
   
   $tpl -> assign_block('PHP_VERSION', phpversion());
   
   $tpl -> parse('uchwyt');
   echo $tpl -> compiled;

?>

Zauważ, iż dyrektywa INCLUDE także korzysta z uchwytu pliku, tak więc plik PHP musi go ustawić. Pozwala to robić różne ciekawe sztuczki, takie jak w przykładzie. Mamy plik z nagłówkiem i stopką, wewnątrz którego jest dyrektywa <!-- INCLUDE body -->. Teraz w zależności od zawartości strony, do uchwytu "body" możemy przypisać np. plik "news.tpl", "articles.tpl" itd. i właśnie ta zawartość będzie tam wstawiona.

   Ostatni przykład zademonstruje, czym tak naprawdę są te #$%#%$% sekcje, oraz jak się ich używa :). Oto plik TPL (4.tpl):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Zmienne ?rodowiskowe w PHP</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">
</head>

<body>
<b>Lista zmiennych ?rodowiskowych w PHP</b>
<ul>
<!-- BEGIN zmienna -->
   <!-- IF zmienna.NAZWA neq "REMOTE_ADDR" -->
   <li><b>{zmienna.NAZWA}</b> - {zmienna.WARTOSC}</li>
   <!-- ENDIF -->
<!-- END zmienna -->
</ul>

</body>
</html>

Mamy tu utworzoną sekcję o nazwie "zmienna". Kod w niej zawarty zostanie wykonany tyle razy, ile wprowadzimy do niej dane.

<?php

   require('../engine/basic.php');
   require('../engine/templates.php');
   
   $tpl = new Template('./');
   $tpl -> set_filename('uchwyt', '4.tpl');
   
   foreach($_SERVER as $nazwa => $wartosc){
      $tpl -> assign_section_blocks('zmienna',
            array(
               'NAZWA' => $nazwa,
               'WARTOSC' => $wartosc
            ));
   }
   
   $tpl -> parse('uchwyt');
   echo $tpl -> compiled;

?>

Kod ten odczytuje całą zawartość tablicy $_SERVER i wprowadza ją do sekcji właśnie przez wywołanie metody "assign_section_blocks()". Tak więc ile razy wywołamy ją z adresem naszej sekcji (w tym przypadku "zmienna"), tyle razykod w tej sekcji zostanie wykonany, z tym, iż za każdym razem trafią do niego inne dane. W pliku TPL widać dodatkowo, jak łączymy adresy bloków w sekcjach z instrukcją warunkową - napisałem proste wyrażenie, które blokuje wyświetlenie danych, gdy nazwa zmiennej równa się "REMOTE_ADDR".
   Pamiętaj, iż sekcje można zagnieżdżać w sobie nawzajem. Do takiej zagnieżdżonej sekcji odwołujemy się w taki sposób: "sekcja_nadrzedna.sekcja_podrzedna", a do jej bloków: "sekcja_nadrzedna.sekcja_podrzedna.BLOK".

   To już tyle w tej części. Opisałem dla Ciebie budowę jądra engine'u, oraz w przystępny sposób wyjaśniłem działanie systemu szablonów. W następnym odcinku zajmiemy się obsługą layoutów, oraz poszczególnych stron. Napiszemy także szkielet pliku index.php.

Powrót