Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: Wojciech Sznapka, dodany: 28.10.2009 00:47, tagi: symfony, php

Ostatnio zetknąłem się z problemem wspólnych partiali dla wszystkich aplikacji w projekcie Symfony (dokładnie frontend i backend). Dokładniej, to te partiale były templatkami mailowymi, wysyłanymi zarówno przy zdarzeniach wygenerowanych w frontendzie jak i w panelu administracyjnym. Jako, że ponad wszystko cenię zasadę DRY (Don’t Repeat Yourself, czyli Nie Powtarzaj Się), chciałem, aby moje templatki były [...]

Autor wpisu: batman, dodany: 25.10.2009 01:24, tagi: javascript

Dzisiaj pokażę jak w prosty i szybki sposób można debugować aplikacje napisane w Adobe AIR. W tym celu posłużę się debugerem wbudowanym w Aptanę oraz specjalnie przygotowaną do tego celu bliblioteką – AIR Introspector. Naukę debugowania zaczniemy od utworzenia nowego projektu. Ponieważ nie będziemy dzisiaj poznawać żadnych wywołań API poza debugerem, pozostawiamy wszystkie ustawienia domyślne

Autor wpisu: cojack, dodany: 23.10.2009 09:08, tagi: php, mvc

Tak więc chciałbym rozwinąć swoją myśl w poprzednim wpisie dotyczącym mvc w php, o co mi tu chodzi oraz czy temat i kategoria ma się jakoś do treści tutaj przedstawionej. Otóż uważam że tak, wzorzec mvc jak samo rozwiniecie jego skrótu nam mówi, model, widok, kontroler. Chodzi o prezentacje kodu złożoną z warstw, i połączeniem tego z sobą, dobrze wiemy że kontroler czyli nasz cały mózg operacji powinien wywoływać metody z modelu do pobierania danych z bazy danych, tak że end user nie ma że tak powiem bezpośredniego dostępu do tej że warstwy prezentacji kodu, chyba że jesteśmy na tyle upośledzeni że nie zabezpieczymy sobie katalogów i struktura naszych katalogów pozwala użytkownikowi na przeglądanie zawartości katalogów gdzie mamy poskładane nasze klasy. W różnych książkach można spotkać różnie przedstawione formy zapisu nazewnictwa plików, *.phpm itp ale nie o tym chcę pisać, ponieważ dla mnie to powinno być na tyle intuicyjne i poprawne by nam później było łatwiej się odnaleźć w utworzonej przez nas aplikacji.

Wracając do tematu, bo wydaje mi się że trochę od niego odbiegłem, chciałbym rozwinąć swoją myśl przedstawioną w poprzednim poście (czuje jakbym się powtarzał…). Pisałem o tym że użytkownicy Doctrine dostali narzędzie i ogromnej mocy do utworzenia aplikacji zorientowanej obiektowo oraz o wzorzec MVC, i w cale nie chcę się z tego wycofać a poprzeć tą tezę argumentami.

Do czego bym zachęcał? Otóż by każdy zainteresowany pobrał sobie sandbox’a doctrine z strony projektu, standardowo linki na samym dole. Sandbox jest w pewnym stopniu za nas skonfigurowany, i jeżeli nie czujemy potrzeby modyfikacji jego ustawień proponowałbym zostawić układ taki jaki jest, chociażby dla samego tego artykułu. Ja go osobiście trochę przerobiłem na wzór układu katalogów z symfony ale nie ważne jest to teraz.

Pisałem o tym że nie będziemy musieli ładować w kontrolerach modułów a same widoki (widok), tak zakładam że jeden widok dla jednego kontrolera, jeden model dla jednego kontrolera. Wychodząc z założenia DRY ( Don’t Repeat Yourself ), jedna metoda dla jednej i tej samej akcji, bo po co się powtarzać?

Nie chciałbym by ten topic zszedł do tematu konfiguracji sandboxa, dlatego o konfiguracji Doctrine w innym temacie.

A teraz jak to nam uprzyjemnia życie? A dajmy na to że mamy jakiś kontroler, np HandlerNews

class HandlerNews extends EventHandler  {
 
	private $_tpl;
	private $_handle;
	private $_lang;
 
	public function __construct($tpl,$event,$trans)	{
		$this->_tpl = $tpl;
		$this->_handle = $event;
		$this->_lang = $trans->getLanguage();
 
	}
 
	public function handledEvent($route) {
		if( $route[2] != '' && method_exists($this,$route[2]) ) {
			$this->_{$route[2]}();
		} else 
		  throw new Exception ('Brak akcji');
	}
 
	private function _show()	{
		$news = Doctrine::getTable('News')->getNews(Route::getId(), $this->_lang);
                $this->tpl->assign('news',$news);
	}
}

No i nasza metoda getNews wyglądała by mniej więcej tak (plik NewsTable.php):

class NewsTable extends Doctrine_Table
{
  public function getNews( $id, $lang ) {
    $query = $this->createQuery( 'n' )
                           ->where( 'n.id = ?', $id)
                           ->andWhere( 'n.lang = ?', $lang)
                           ->execute();
    return $query;
  }
}

Oto całe nasze mvc, mamy model, który jest organizowany za pomocą doctrine, mamy plik kontrolera który sobie pobiera z bazy danych dane, wrzuca je do templatki no i jakoś tam musimy wykombinować żeby jeszcze templatke wczytywać, ale to już inna kwestia.

No więc jak widać implementacja takiego wzorca MVC nie jest trudna, i nie uprzykrzajcie sobie ludzie życia wymyślając nie wiadomo co, nie wiadomo jak złożone struktury katalogów jak to jest proste jak budowa cepa ;)

Ja wiem że równie dobrze możemy sobie utworzyć klasę w której będziemy mieli standardowe zapytania do bazy danych np na PDO, z zwykłą składnią SQL’ową. Nikt nie broni, a nawet dlaczego nie? np:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: JoShiMa, dodany: 23.10.2009 01:15, tagi: php, sql

Jak pisałam w poprzednim odcinku dotyczącym drzewek w bazie danych bardzo mi się spodobała idea drzewka typu Nested set, choć niektórzy namawiali mnie do zainteresowania się drzewami Depesza. Może kiedyś. Tymczasem porządkując swoją świeżo nabytą wiedzę i przemyślenia napiszę kilka słów o idei i typu Nested set. Jak każde rozwiązanie to ma zarówno wady i zalety. [...]

Autor wpisu: JoShiMa, dodany: 22.10.2009 15:22, tagi: php

Ależ mnie dziś przeszkoliło. Po reinstalacji systemu zainstalowałam sobie nowsze wersje prawie wszystkiego. Między innymi EasyEclipse zamiast Eclipse, oraz nową wersję xamppa. Potem motałam w mojej instalacji xamppa, bo chciałam sobie skonfigurować debugera. Kiedy uruchomiłam skrypt nad którym pracuję okazało się, że nie jest on interpretowany prawidłowo. Fragmenty kodu php w template, w ogóle [...]

Autor wpisu: JoShiMa, dodany: 21.10.2009 22:01, tagi: php, sql

Chyba każdy programista tworzący dynamiczne strony internetowe w PHP zetknął się z problemem zaimplementowania struktury drzewiastej w bazie danych. Najczęściej ma to związek z konstrukcją menu, ale każdy serwis WWW jest właściwie o taką strukturę oparty. Ja do niedawna konstruowałam takie struktury w oparciu o jedną tabelę rekurencyjną. Każdy rekord zawierał pole informujące wskazujące [...]

Autor wpisu: Vokiel, dodany: 20.10.2009 15:01, tagi: php

Pisząc nawet niewielkie aplikacje webowe często ilość klas rozrasta się do pokaźnej liczby. Rozwiązaniem problemu jest automatyczne dołączanie plików klas w momencie próby utworzenia obiektu danej klasy. Powszechnie stosuje się dwa rozwiązania: __autoload() oraz spl_autoload_register() Aby możliwe było wykorzystanie którejś z funkcji należy sprawdzić czy są dostępne. W przypadku funkcji __autoload() sprawa wydaje się prosta – przede wszystkim wymagane jest PHP 5.0 (nie jest dostępna w przypadku korzystania z PHP jako CLI). W przypadku spl_autoload_register() wymagane jest PHP w wesji >=5.1.2.

Główne różnice

__autoload() spl_autoload_register()
Wiele funkcji ładujących NIE TAK
Obsługa wyjątków NIE TAK

Możliwości rozwiązań

Możliwości rozwiązań może być tyle ilu programistów. Wszystko zależy od tego, czego wymagamy od projektu. Możemy skorzystać z prostego dołączania klas w jednej lokalizacji, rozbudować o większą liczbę lokalizacji, dodać możliwość zastosowania różnych postfiksów, sprawdzania czy klasa/interfejs zostały już wywołane, dodać możliwość przeszukiwania katalogów w głąb, stworzyć mapę klas i interfejsów i odwoływać się do nich jak do zwykłej tablicy. Możliwości jest na prawdę wiele.

Wersja super lite __autoload()

Jeśli mamy do czynienia z małą stroną, możemy ujednolicić nazewnictwo klas, przechowywać je w jednej lokalizacji i użyć najprostszego dołączania:

set_include_path($DOCUMENT_ROOT. 'classes');
// lub 
ini_set('include_path', $DOCUMENT_ROOT. 'classes');
function __autoload($classname) {
  require_once($classname.".class.php");
}

Jednak powyższe rozwiązanie może zostać wykorzystane tylko w bardzo prostych projektach, nie daje żadnej elastyczności, możliwości konfiguracji, zmian, narzuca szereg ograniczeń.

Wersja bardziej rozbudowana __autoload()

W przypadku korzystania chociażby z interfejsów w nazewnictwie interfejsA.interface.php poprzednia metoda już nie zadziała (zresztą nie zadziała w prawie żadnym wypadku poza podstawowym ;-) ). W pierwszej kolejności możemy rozszerzyć lokalizacje o dodatkowe katalogi:

set_include_path(
        get_include_path()
        .PATH_SEPARATOR."/classes/"
        .PATH_SEPARATOR."/interfaces/"
        .PATH_SEPARATOR."/modules/"
);

Dzięki temu pliki klas będą dołączane z wielu lokalizacji, nie tylko z jednej. Problem pojawia się w momencie próby użycia klasy, której nie ma. Rozszerzmy funkcję __autoload o dodatkowe funkcjonalności:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function __autoload($classname){
    try {
        if (class_exists($classname, false) || interface_exists($classname, false)){
            return;
        }
        $class = explode('_', strtolower(strval($classname)));
        $deeps = count($class);
        $file = 'class';
        for ($i=0;$i<$deeps;$i++){
            $file .= '/'.$class[$i];
        }
        $file .= '.class.php';
        if (!file_exists($file) || !is_readable($file) || class_exists($classname, false) || interface_exists($classname, false)){
            throw new Exception('Class cannot be found ( ' . $classname . ' )');
        }else{
            require_once($file);
        }
    } catch (Exception $e){
        echo $e->getMessage()."\n"; 
    }
}

Dodaliśmy kilka funkcjonalności:

  • Sprawdzanie czy klasa bądź interfejs zostały już zdefiniowane
  • Następnie dodaliśmy możliwość zagnieżdżania klas w głąb katalogów. Wymaganiem tutaj postawionym jest nazewnictwo klas z użyciem dolnego podkreślenia jako separatora katalogu katalog_nazwaKlasy.class.php lub katalog__podkatalog_nazwaKlasy.class.php
  • Sprawdzenie czy plik istnieje, czy jest możliwy do odczytu

Jednak nadal nie możemy przechwycić wyjątku blokiem try-catch, zatem przy stosowaniu tej metody wymagana jest pewność iż wszystkie wywoływane klasy mają swoje odpowiedniki w plikach.

Wersja lite spl_autoload_register()

Sam proces dołączania będzie identyczny jak wersji lite dla __autoload() z tą różnicą, że wywołanie loadera będzie inne.

1
2
3
4
5
6
7
8
9
function classLoader($classname){
    $file = $DOCUMENT_ROOT.'/class/'.$classname.'.class.php';
    if (file_exists($file) && is_readable($file) && !class_exists($class, false)){
        require_once($file);
    }else{
        throw new Exception('Class cannot be found ( ' . $classname . ' )');
    }
}
spl_autoload_register('classLoader');

Możliwość korzystania z funkcji w spl_autoload_functions nie jest jedyną, którą mamy do dyspozycji. Równie dobrze, możemy skorzystać z klas. Prosty przykład na pokazanie zasady funkcjonowania:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.