Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: metody magiczne i odczyt z pliku settings.ini
Forum PHP.pl > Forum > PHP > Object-oriented programming
Black-Berry
Skoro po kilku konsultacjach doszedłem do wniosku, że jednak nie warto stosować tablicy $GLOBALS do przechowywania ustawień witryny zaczałem pisać klasę settings czarodziej.gif Wygląda ona mniej więcej tak:

  1. <?php
  2. class settings //ta klasa wchodzi w skłąd klasy głównej jako singleton
  3. {
  4. private static $instance = null;
  5. private $tablica=array( "db_name"=>"test" ); //tablica przechowywująca zmienne 
  6.  
  7. public function get_instance() //funkcja do przekazania instancji - singleton
  8. {
  9. $class = __CLASS__;
  10. return self::$instance == null ? self::$instance = new $class : self::$instance;
  11. }
  12.  
  13. function __get( $name ) //magiczna metoda do pobierania zmiennych
  14. { 
  15. return strtolower( $this->tablica[$name] );
  16. }
  17. }
  18. ?>


Chciałbym teraz wczytać do tablicy '$tablica' zmienne z pliku 'settings.ini' który wyglądał będzie tak:
Kod
db_name = nazwa_bazy
db_host = nazwa_hosta
itd...

Pierwsze pytanie:
-- Czy istnieje jakaś fajna funkcja która wczyta za mnie zmienne z pliku .ini? Może ktoś ma i mógłby mi wkleić? (znalazłem już dlatego pytanie jest nieważne - funkcja $ini = parse_ini_file('file.ini'); )
-- Chciałbym jednak zapytać czy uważacie że to dobry (albo zły) sposób na napisanie takiej klasy. Pytam bo nie chce juz tego poprawiać więcej wstydnis.gif

Drugie pytanie dotyczy posta którego nie mogę teraz odnaleźć ale pisało w nim, że:
Cytat
(..)metody magiczne zaciemniają kod(..)

-- Czy powinienem unikać metody magicznej? Muszę przyznać, że w tym wypadku znacznie poprawiłaby ona czytelność kodu.
nowotny
Cytat(Black-Berry @ 20.02.2008, 12:38:47 ) *
-- Czy istnieje jakaś fajna funkcja która wczyta za mnie zmienne z pliku .ini? Może ktoś ma i mógłby mi wkleić?

Masz bana na manuala...?
parse_ini_file" title="Zobacz w manualu PHP" target="_manual
Black-Berry
Sory pospieszyłem się z tym pytaniem ale chodzi mi teraz o bardziej ogólne pytanie o opinię na temat tego sposobu.
mike
Lepiej zrobisz jak odziedziczysz po ArrayObject. Dostaniesz gratis funkcję ArrayObject::offsetGet(), dzięki której wszystko zrobisz bardziej elastycznie i bardziej elegancko.

Co to jest klasa main_object i dlaczego po niej dziedziczą wszystkie inne?
Black-Berry
racja @mike. Klasa settings nie musi dziedziczyć po żadnej. (Mój bład) Klasa "settings" wchodzi w skłąd klasy "main_object" jako singleton. Po main_object dziedziczą wszystkie inne klasy dzięki temu mamy główny węzeł dla całego systemu.
mike
Cytat(Black-Berry @ 20.02.2008, 13:04:22 ) *
Po main_object dziedziczą wszystkie inne klasy dzięki temu mamy główny węzeł dla całego systemu.
Coooooo? Wyrzuć to do kosza. Natychmiast!
Splatch’s devblog :: Singleton
Antywzorzec projektowy
Black-Berry
o matko znowu od nowa... a było juz tak pięknie worriedsmiley.gif
mike
Noc chyba, że źle zrozumiałem.
Jeśli u Ciebie każda klasa (lub większość) jest singletonem to ja na zawał padnę tongue.gif
Black-Berry
Na zawał to o mało ja nie padam teraz worriedsmiley.gif Bo co ja zrobię bez singletona.

Nie wszystkie. W zasadzie tylko kilka. Jest tak:

--main_object // klasa główna po której dziedziczą inne
---- db_driver() // singleton
---- settings() // to tez miałem nadzieję zrobić jako singleton
---- db_functions // konkretne zapytania do bazy opakowane w funkcje tez jako singleton

nowy obiekt tworzę tak:
class news extends main_object

Co ja zrobię bez singletona? sadsmiley02.gif globals zle, $GLOBALS też zle i teraz singleton też jest be. Proszę pomocy! Co ja mam zrobić?
Cysiaczek
1. Nie wpadać w panikę
2. Zainwestować w książkę
3. Ukorzyć się przed wielkim OOP ;p
Black-Berry
Cytat(Cysiaczek @ 20.02.2008, 13:45:16 ) *
1. Nie wpadać w panikę
2. Zainwestować w książkę
3. Ukorzyć się przed wielkim OOP ;p

dzieki za radę ale jakoś nie czuję się mądrzejszy po niej dry.gif
Cysiaczek
No co? ;p Pierwsze 2 punkty są zupełnie na poważnie. W moim odczuciu wpadasz w panikę i miotasz się, bo chcesz wszystko od razu mieć naj. Tak się nie da, bo konsekwencje odczujesz dopiero, gdy zaczniesz tego używać. Pomyśl o tym jak o żywym organiźmie. Mózg sam nic nie robi, tylko wydaje polecenia za pośrednictwem połączeń nerwowych. Tak samo od nich odbiera sygnały. Każdy singleton to jak połączenie oddzielnym kanałem nerwowym, który omija wszystkie inne i cholera wie, jakie informacje tam idą.
Black-Berry
Mi tylko chodzi o to żebym mógł w klasach stosować proste odwołanie do settings. Singleton dobrze sie do tego nadawał:

  1. <?php
  2. $this->settings()->db_host;
  3. ?>


a co do mojej potzreby "idealności" to naprawde zależy mi na ostatecznym rozwiązaniu. Już nie mam siły tego przepisywać co pół roku. Muszę jeszcze napisać newslettery, file_menagera, sondę i mase innych a nie mogę wyjść z jądra systemu. sadsmiley02.gif
Sedziwoj
Wiesz jaki kod piszemy jest zależne od tego co umiemy, jak ktoś się ciągle rozwija to będzie ciągle zmieniał to co kiedyś napisał.

Co do settings i singletona, to przecież i tak w konkretnym miejscu pobierasz te dane i tam też je możesz przekazać do innych obiektów które je potrzebują, że to są startowe informacje tylko raz musisz je przekazać, więc na prawdę używanie singletona jest w tym przypadku niepotrzebne.

Bo chyba masz w jednym miejscu wczytywanie konfiguracji? Bo jak będzie rozrzucona to będzie właśnie problem z tym "a gdzie to ja tego używam", dlatego singleton jest antywzorcem.
Black-Berry
@Sedziwoj Trochę nie radzę sobie z tym zadaniem. Mógłbyś mi doradzić?

  1. <?php
  2. abstract class main_object
  3. {
  4. /* settings getting instance */
  5. public function settings(){ 
  6. return edc_settings::get_instance(); 
  7. }
  8.  
  9. /* db_driver getting instance */
  10. public function db_driver(){ 
  11. return mysql_db_driver::get_instance();
  12. }
  13. }
  14.  
  15. class edc_settings
  16. {
  17. private static $instance = null;
  18. public $settings = array();
  19.  
  20. public function __construct(){
  21. $this->settings=parse_ini_file('settings.ini');
  22. }
  23.  
  24. public function get_instance(){
  25. $class = __CLASS__;
  26. return self::$instance == null ? self::$instance = new $class : self::$instance;
  27. }
  28.  
  29. function __get( $name ){
  30. return strtolower( $this->settings[$name] );
  31. }
  32. }
  33. ?>

Tak więc mam główną klasę po której dziedziczą inne. Zawiera ona 2 odwołania do singletonów. Tworząc nową klasę np news dziedziczę po main

  1. <?php
  2. class news extends main_object
  3. {
  4. public function drop_linik()
  5. {
  6.  // wewnątrz funkcji mogę korzystać z settingsów bez zmiennych $GLOBALS których pon
    oć nie powinno sie używać.
  7.  print( $this->settings()->base_href . "podstrona" ); //pobieram z settingsów "base_href";
  8. }
  9. }
  10. $object_news = new news;
  11. $object_news->drop_link();
  12. ?>


Jak mam to robić inaczej ? Sugerujesz, że powinienem przekazywać obiekt $settings do konstruktora object_news ? To strasznie niewygodne.
Cysiaczek
Wygoda jest tu na drugim miejscu. Co ma klasa News wspólnego konfiguracją Twojego systemu? Nic, a przynajmniej bardzo niewiele.
Powinieneś przekazać jej tyle danych, ile jest jej potrzebne. Nawet przekazanie obiektu $settings jako parametr w konstruktorze jest kontrowersyjne, choć lepsze niż dziedziczenie po jakimś dziwnym obiekcie. W idealnym przypadku powinieneś posiadać dodatkową klasę NewsManager/NewsBase/NewsHelper/NewsVendor/CoTamChcesz, która się zajmie rozmową z resztą systemu. Możesz wykorzystać coć na podobieństwo wzorca Prototype/Fabryki obiektów.

  1. <?php
  2. class newsFactory
  3. {
  4. static function createOne()
  5. {
  6. $obj=new News();
  7. $obj->setAdditionalConfig($settings);
  8. return $obj;
  9. }
  10. }
  11.  
  12. $news=newsFactory::createOne();
  13. ?>

Omijasz w ten sposób te niedogodności.

Pozdrawiam.
mike
Ja mam tylko taką uwagę:

Wiesz jaką funkcję (między innymi) pełnią wzorce projektowe? Wprowadzają ujednolicenie nomenklatury i standardy.
Jednym z największych plusów jest to, że jak mówię komuś innemu, nawet na końcu globu (nie kojarzyć z globals tongue.gif ) na przykład Intercepting Filter to on wie co ja mam na myśli.

A czemu to mówię? Bo Twoja klasa main_object to taki Context i tego raczej się trzymaj. Gdybyś nie podał ostatniego listingu to wiele osób nadal mogłoby nie wiedzieć czym u licha jest to Twoje main_object.
Już sama nazwa jest nie bardzo bo prędzej powinno być: main_class.

A teraz uwaga!
Polecam najlepsze książki do nauki wzorców dla PHP: php|architect's Guide to PHP Design Patterns, J2EE. Wzorce projektowe, Java. Wzorce projektowe
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.