Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Mój pierwszy framework, kilka problemów.
Forum PHP.pl > Forum > PHP > Object-oriented programming
pajaa1981
Witam, wczoraj starałem się stworzyć swój pierwszy framework w PHP, lecz napotkałem kilka problemów. Z racji, że nie jestem profesjonalistą proszę o wyrozumiałość. Od razu chcę zaznaczyć, że jeśli ktoś chce napisać posta w stylu: "wyjdź z tym i idź się ucz symfony/cakephp" to proszę, aby się nie fatygował bo po prostu to zignoruje. Chce budować aplikacje na własnym silniku, który bardzo dobrze znam i mogę go dowolne rozbudować itp. Poza tym mam też inne powody, których nie będę tutaj opisywał. Chce po prostu używać swojego i tyle.

Zrobiłem go na takiej zasadzie:

struktura folderów i plików:

  1. .htaccess
  2. index.php
  3.  
  4. [folder]conf
  5.  
  6. [folder]system:
  7. Dispatcher.php
  8. _init.php
  9. Model.php
  10. Database.php
  11. Autoloader.php
  12.  
  13. [folder]lib:
  14. debugClass.php
  15.  
  16. [folder]controllers:
  17. [folder]index:
  18. Controller.php
  19.  
  20. [folder]cache




Plik .htaccess - zadanie kierowania wszelkiego ruchu do index.php:

  1. RewriteEngine On
  2.  
  3. # Przekierowanie całego ruchu do index.php
  4. RewriteRule (.*) index.php [L]



Plik index.php - załączenie frameworka z innego katalogu:
  1. <?php
  2.  
  3. // Uruchamienie aplikacji
  4. require_once('system/_init.php');
  5.  
  6. // Wyłączanie parsera
  7. exit();



system/_init.php - główny plik frameworku:

  1. <?php
  2.  
  3. // Definicje
  4. define('INC_PATH', realpath(dirname(dirname(__FILE__))).'/');
  5.  
  6. // Autoloader
  7. require(INC_PATH.'system/Autoloader.php');
  8.  
  9. // Debug
  10. $debug = new Debug;
  11.  
  12. // Załaczanie niezbędnych plików
  13. $debug->drequire(INC_PATH.'system/Dispatcher.php');
  14. $debug->drequire(INC_PATH.'system/Model.php');
  15. $debug->drequire(INC_PATH.'system/Database.php');
  16.  
  17. // Uruchamianie
  18. $dispatcher = new Dispatcher;
  19. $dispatcher->_init();



system/Dispatcher.php - przetwarza ścieżkę wpisaną przez usera:

  1. <?php
  2.  
  3.  
  4. class Dispatcher
  5. {
  6.  
  7. private $_strUrlParameters;
  8. private $_arrUrlParameters;
  9. private $_index = FALSE;
  10.  
  11. public function __construct()
  12. {
  13. if (isset($_SERVER['PATH_INFO']))
  14. {
  15. $strUrlParameters = $_SERVER['PATH_INFO'];
  16. $this->_strUrlParameters = substr($strUrlParameters, 1);
  17. }
  18. else
  19. {
  20. $strUrlParameters = $_SERVER['REQUEST_URI'];
  21. $this->_strUrlParameters = substr($strUrlParameters, 1);
  22. }
  23. }
  24.  
  25. public function _init()
  26. {
  27. $this->_parsePath();
  28. $strControllerName = $this->_getControllerName();
  29. $strControllerFile = INC_PATH.'controllers/'.$this->_getControllerName().'/Controller.php';
  30. if(file_exists($strControllerFile))
  31. {
  32. require_once($strControllerFile);
  33. $strControllerClasName = $this->_getControllerName().'Controller';
  34. $objController = new $strControllerClasName($this->_getParametersForController());
  35. $NumOfTrans = count($this->transfer);
  36. $objController->_init();
  37. }
  38. elseif ($this->index == FALSE)
  39. {
  40. require_once(INC_PATH.'controllers/index/Controller.php');
  41. $objController = new indexController($this->_getParametersForController());
  42. $objController->_init();
  43. }
  44. }
  45.  
  46. private function _parsePath()
  47. {
  48. $arrParameters = explode('/', $this->_strUrlParameters);
  49. if($arrParameters[count($arrParameters) - 1] == '')
  50. array_pop($arrParameters);
  51. $this->_arrUrlParameters = $arrParameters;
  52. }
  53.  
  54. private function _getControllerName()
  55. {
  56. $strControllerName = $this->_arrUrlParameters[0];
  57. if(strlen($strControllerName))
  58. return $strControllerName;
  59. elseif ($this->index == FALSE)
  60. {
  61. $this->index = TRUE;
  62. require_once(INC_PATH.'controllers/index/Controller.php');
  63. $objController = new indexController($this->_getParametersForController());
  64. $objController->_init();
  65. }
  66. }
  67.  
  68. private function _getParametersForController()
  69. {
  70. $intNumOfPathParameters = count($this->_arrUrlParameters);
  71. $arrPrametersForController = array();
  72. for($i = 1; $i < $intNumOfPathParameters; $i++)
  73. $arrPrametersForController[] = $this->_arrUrlParameters[$i];
  74. return $arrPrametersForController;
  75. }
  76.  
  77. }



system/Model.php - plik pusty, jeszcze nic tam nie wrzuciłem.

system/Database.php - sterownik bazy danych.

  1. <?php
  2.  
  3. DEFINE('CACHE_DIR', 'cache/');
  4.  
  5. class Database {
  6. public $server;
  7. public $answer;
  8. var $rows;
  9. var $queries = 0;
  10. var $cache_state = 0;
  11. var $cache_file;
  12. var $cache_buffer;
  13. var $cache_ptr;
  14. public function CONNECT ($HOST,$USER,$PASSWORD,$DATABASE) {
  15. $this->server = @mysql_connect ($HOST,$USER,$PASSWORD) OR die ('dbClass.php ERROR: '.mysql_error());
  16. $selectDatabase = @mysql_select_db ($DATABASE, $this->server) OR die ('dbClass.php ERROR: '.mysql_error());
  17. }
  18. public function POLISH_CHARACTERS () {
  19. @mysql_query("SET NAMES utf8");
  20. }
  21. public function SELECT ($query) {
  22. $answer = @mysql_query($query);
  23. $array = @mysql_fetch_assoc($answer);
  24. return $this->answer = $array;
  25. }
  26. public function VAILD ($query) {
  27. $answer = @mysql_query($query);
  28. $qty = @mysql_num_rows($answer);
  29. if ($qty >= 1) $return = TRUE;
  30. else $return = FALSE;
  31. return $this->answer = $return;
  32. }
  33. public function QUERY ($query) {
  34. $answer = @mysql_query($query);
  35. return $this->answer = $answer;
  36. }
  37. public function VAILD_QUERY ($query) {
  38. $answer = @mysql_query($query);
  39. $qty = @mysql_num_rows($answer);
  40. if ($qty >= 1) $return = @mysql_fetch_assoc($answer);
  41. else $return = FALSE;
  42. return $this->answer = $return;
  43. }
  44. public function sql_cache($handle = 0) {
  45. if(is_string($handle)) {
  46. if(file_exists(CACHE_DIR.'sql_cache-'.$handle.'.cache')) {
  47. $this->cache_state = 1;
  48. $this->cache_ptr = 0;
  49. $this->cache_buffer = unserialize(file_get_contents(CACHE_DIR.'sql_cache-'.$handle.'.cache'));
  50. }
  51. else {
  52. $this->cache_state = 2;
  53. $this->cache_buffer = array();
  54. $this->cache_file = CACHE_DIR.'sql_cache-'.$handle.'.cache';
  55. }
  56. }
  57. else {
  58. if($this->cache_state == 2) {
  59. file_put_contents($this->cache_file, serialize($this->cache_buffer));
  60. }
  61. $this->cache_state = 0;
  62. }
  63. }
  64. function sql_cache_remove($handle) {
  65. if(file_exists(CACHE_DIR.'sql_cache-'.$handle.'.cache')) {
  66. unlink(CACHE_DIR.'sql_cache-'.$handle.'.cache');
  67. }
  68. }
  69. function cache_query($query) {
  70. if($this->cache_state != 1) {
  71. $this->result = mysql_query($query);
  72. return 1;
  73. }
  74. }
  75. function sql_fetch_array() {
  76. if($this->cache_state == 1) {
  77. if(!isset($this->cache_buffer[$this->cache_ptr])) {
  78. return 0;
  79. }
  80. $this->rows = $this->cache_buffer[$this->cache_ptr];
  81. $this->cache_ptr++;
  82. return 1;
  83. }
  84. else {
  85. if($this->rows = mysql_fetch_assoc($this->result)) {
  86. if($this->cache_state == 2) {
  87. $this->cache_buffer[] = $this->rows;
  88. }
  89. return 1;
  90. }
  91. }
  92. return 0;
  93. }
  94. function sql_fetch_row() {
  95. if($this->cache_state == 1) {
  96. if(!isset($this->cache_buffer[$this->cache_ptr])) {
  97. return 0;
  98. }
  99. $this->rows = $this->cache_buffer[$this->cache_ptr];
  100. $this->cache_ptr++;
  101. return 1;
  102. }
  103. else {
  104. if($this->rows = mysql_fetch_row($this->result)) {
  105. if($this->cache_state == 2) {
  106. $this->cache_buffer[] = $this->rows;
  107. }
  108. return 1;
  109. }
  110. }
  111. return 0;
  112. }
  113. }
  114.  
  115. ?>



system/Autoloader.php - ładuje biblioteki z folderu:

  1. <?php
  2.  
  3. function __autoload ($classname)
  4. {
  5. require_once(INC_PATH.'lib/'.$classname.'Class.php');
  6. }




lib/debugClass.php - liczy jak długo parseruje się dana klasa:


  1. <?php
  2.  
  3. function getMicrotime()
  4. {
  5. list($usec, $sec) = explode(" ", microtime());
  6. return ((float)$usec + (float)$sec);
  7. }
  8.  
  9. class Debug
  10. {
  11.  
  12. private $requireArray = array();
  13.  
  14. public function drequire($dir)
  15. {
  16. $this->requireArray[$dir] = getMicrotime();
  17. require_once($dir);
  18. $this->requireArray[$dir] = getMicrotime()-$this->requireArray[$dir];
  19. }
  20.  
  21. public function RequireTime ()
  22. {
  23. return $this->requireArray;
  24. }
  25.  
  26. }
  27.  



contollers/index/Controller.php - plik kontrolera index:

  1. <?php
  2.  
  3. class indexController
  4. {
  5.  
  6. var $var;
  7.  
  8. function __CONSTRUCT ($var)
  9. {
  10. $this->var = $var[0];
  11. echo $this->test;
  12. }
  13.  
  14. public function _init()
  15. {
  16. if ($this->var == "test")
  17. echo "<b>Wszystko działa poprawnie!</b>";
  18. elseif ($this->var == "debug")
  19. {
  20. echo '<pre>';
  21. print_r($debug->RequireTime());
  22. echo '</pre>';
  23. }
  24. else
  25. echo "<b>Hello world!</b>";
  26. }
  27.  
  28. }



Prosiłbym o rady takie, które odpowiedzą mi na pewne pytania:
- Czy dobrze zbudowałem cały framework? Coś powinienem zmienić?
- Mam taki problem, że gdy chce np. wykonać akcje localhost/index/debug to dostaje błąd, że $debug nie jest obiektem. Wiem o tym, ale jak stworze go na nowo, to nie będzie miał już tej tablicy z danymi. Jak to rozmwiać?
- Inne uwagi według własnego uznania mile widziane.
Crozin
Cytat
Czy dobrze zbudowałem cały framework? Coś powinienem zmienić?
Fatalnie. Kompletny brak elastyczności, używanie przestarzałych mechanizmów, maskowanie błędów, kompletnie nielogiczny kod ("Debug" odpowiada za wczytywanie plików, wtf?), jakieś śmieci typu getMicrotime() - przyjrzyj się dokładniej funkcji microtime, nie przestrzegasz konwencji nazewnictwa, korzystasz z przestrzeni globalnej (jak rozpoczynasz teraz pisanie czegoś to PHP5.3 powinno być bazową platformą).

Pisanie własnego frameworka jest uzasadnione chyba tylko w dwóch przypadkach:
1. Gdy piszesz go w celu edukacyjnym.
2. Gdy istniejące rozwiązania po prostu nie sprawdzą się w danym projekcie.
I nie pisz o tym, że chcesz znać go dogłębnie, bo przestudiowanie źródeł istniejących projektów jest o wiele szybsze niż tworzenia wszystkiego od podstaw. I kto Ci broni rozbudowywać istniejące projekty?

Poza tym niezależnie jaki będzie Twój powód dla stworzenia swojego rozwiązania trzeba najpierw porządnie poznać kilka innych projektów tego typu, zobaczyć jak działają, przekonać się jakie są ich mocne i słabe strony (by nie powielić tych samych błędów u siebie).

Na chwile obecną to co prezentujesz nie nadaje się kompletnie do niczego.
pajaa1981
W takim razie co proponujesz? Dodam, że chodzi mi o framework, który nie będzie posiadał zbędnych funkcji. Potrzebuje czegoś pod tworzenie gier przeglądarkowych. Kupiłem książkę "Symfony aplikacje internetowe w praktyce", ale ta książka wydaje się przestarzała - Symfony od tego czasu się zmieniło i korzysta z Doctrine, a tam jest wszystko oparte o Propel. Jeśli znasz jakiś framework z którym poradzi sobie początkująca osoba taka jak ja, to bardzo proszę Cię o pomoc.
Crozin
Po pierwsze nie cytuj całych wypowiedzi, a już w szczególności gdy w dyskusji jest tylko jedna odpowiedź.

Cytat
Dodam, że chodzi mi o framework, który nie będzie posiadał zbędnych funkcji.
Co z tego, że będzie miał zbędne funkcje? Nie potrzebujesz czegoś to nie używasz tego, ewentualnie w przypadku jakiś większych "dodatków" (np. pluginy) nie ładujesz ich.
Cytat
Symfony od tego czasu się zmieniło i korzysta z Doctrine
Symfony może co najwyżej wykorzystywać Doctrine, ale nic nie stoi na przeszkodzie byś korzystał z Propela czy innego ORM-a. Możesz nawet nie korzystać z żadnego.
Cytat
Jeśli znasz jakiś framework z którym poradzi sobie początkująca osoba taka jak ja, to bardzo proszę Cię o pomoc.
Nie ma czegoś takiego jak FW dla osoby początkującej. Z wartych uwagi są właściwie tylko Symfony i ZendFramework (powinieneś się już brać za wersję drugą w obu przypadkach). Jest jeszcze kilka innych mniej znanych projektów na które można by zwrócić uwagę (np. Yii), ale te dwa dominują.
melkorm
Cytat
Z wartych uwagi są właściwie tylko Symfony i ZendFramework (powinieneś się już brać za wersję drugą w obu przypadkach).


Zend'a 2.0 długo jeszcze nie będzie widać, więc radzę wziąć się za 1.11.1, która jest ostatnią wersją z linii 1.X .

Edit: Oczywiście że 1.11.1 biggrin.gif
Damonsson
1.9.1? Ostatnio ściągałem 1.11.1, chyba, że coś mnie się przewidziało worriedsmiley.gif
Daimos
Crozin ma dużo racji, a dodatkowo tak tylko z ciekawości...
Cytat
RewriteRule (.*) index.php [L]

Jak chcesz załączyć pliki graficzne, style i javascript?
pgrzelka
małe odejście od tematu:

Cytat(melkorm @ 16.01.2011, 19:23:19 ) *
Zend'a 2.0 długo jeszcze nie będzie widać

zf 2 jest już dostępny, fakt że nie jest to wersja stabilna ale lepiej coś pisać w wersji 2 ponieważ upgrate z 1.x do 2.x będzie praktycznie niemożliwy
melkorm
Cytat
zf 2 jest już dostępny


Jest to raczej wersja mało edukacyjna bo żaden z głównych komponentów Zend'a (routing, modulara application, session, form i wiele innych) nie zostały przepisane i nie są jeszcze dostępne więc nauka tej wersji jest bezcelowa na tą chwilę, wersja która została wydana bodajże wprowadziła Namespaces i nie wiele więcej.
Crozin
OK, zejdźcie z tematu ZF2 - trochę się z nim pośpieszyłem.
Zyx
  1. function __autoload ($classname)
  2. {
  3. require_once(INC_PATH.'lib/'.$classname.'Class.php');
  4. }


Co to jest? W tym momencie zablokowałeś sobie możliwość wykorzystania większości zewnętrznych bibliotek. Musisz się poduczyć najpierw samego PHP, ponieważ na razie wykorzystujesz jakiś mechanizm, a ani nie wiesz ani, jak powinien być używany, ani nawet jak właściwie działa. O poprawnym ładowaniu klas możesz poczytać np. tutaj:

http://pl.wikibooks.org/wiki/PHP/Automatyczne_ładowanie
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.