Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: sokzzuka, dodany: 22.03.2011 22:38, tagi: javascript, php

Kolejny odcinek serii o języku Scala zajmie się kwestią traits – cech. Jest to o tyle ciekawa część języka, że w PHP również zostaną one wprowadzone w najbliższej wersji 5.4 . Traits w PHP zainspirowane zostały właśnie bezpośrednio implementacją z Scali.

Czym jest trait ? Trait jest elementem języka służącym do zapewnienia dziedziczenia poziomego. Co oznacza dziedziczenie poziome ?

Ażeby dowiedzieć się czym jest dziedziczenie poziome, najpierw musimy ustalić czym jest dziedziczenie pionowe. Dziedziczenie pionowe, takie jakie znamy np. z PHP i Javy zakłada, że każda klasa potomna może dziedziczyć tylko z jednej klasy bazowej. Wszelkie metody i pola oznaczone przez „protected” obecne są też w klasie potomnej.  Jednak co najważniejsze – klasa potomna jest podtypem klasy bazowej. Dziedziczenie oznacza, że klasa B jest również typu A .Ilustruje to poniższy przykład hierarchii klas znany z lekcji biologii:

Zwierzęta -> Strunowce -> Kręgowce -> Ssaki -> Walenie -> Delfiny -> Delfin Słodkowodny

Dziedziczenie poziome natomiast jest sytuacją gdy jakiejś klasie chcemy rozszerzyć funkcjonalność nie zaburzając wcześniej przedstawionej pionowej hierarchii klas. Weźmy dla przykładu naszego delfina i jego kolegę po miedzy – szympansa. Załóżmy, że chcemy zarówno delfina jak i szympansa nauczyć jakiś sztuczek np. salta w tył. Oczywiście moglibyśmy dodać metodę „salto w tył” abstrakcyjnej klasie „ssaki” z której dziedziczą szympans i delfin lub dodać kolejną klasę pośrednią. Natomiast pada pytanie jaki ma to sens ? W końcu tylko szympansy i delfiny umieją takie śmieszne sztuczki, natomiast inne ssaki nie są na tyle sprytne, żeby to wykonać. Generalnie wtłaczanie takiej cechy  w dziedziczenie pionowe jest działaniem troszkę „na siłę”.  Na szczęście mamy traity zwane też cechami. Traity w dowolnej ilości można „wczepić” do dowolnej klasy.

Traity często opisywane są jako interfejsy posiadające implementacje. Jest to dobre skojarzenie – implementacja przez jakąś klasę interfejsu oznacza, że posiada ona pewną funkcjonalność. Dołączenie traita do klasy znaczy dokładnie to samo, z tą różnicą, że trait może posiadać konkretną implementację.

Najwyższy czas pokazać, jak traity wykorzystywane są w praktyce w języku Scala. Trait, który przedstawię, będzie posiadał tylko jedną metodę – „toArray”.  Będzie ona zwracała wszystkie zmienne istniejące w obiekcie w postaci obiektu klasy HashMap, który jest odpowiednikiem PHP-owego „arraya„. Przy okazji dowiemy się co nieco o refleksji oraz o domknięciach leksykalnych i iteracji.

Kod:


trait ToArray {
  def toArray: HashMap[String, Any] = {
    val vars = new HashMap[String, Any]()
    val className = this.getClass.getName

    def extractFields(className: String):HashMap[String, Any] = {
      val currentClass = java.lang.Class.forName(className)
      val superClass = currentClass.getSuperclass

      if(superClass == null){
        return vars
      }
      val fields = currentClass.getDeclaredFields

      fields.foreach((field:java.lang.reflect.Field) => {
          field.setAccessible(true)

          val name = field.getName
          val value = field.get(this)
          vars += name -> value

          field.setAccessible(false)
        })

      return extractFields(superClass.getName)
    }
    extractFields(className)

    return vars
  }
}

Metoda „toArray” jest funkcją zwracającą obiekt typu HashMap, gdzie klucz ma postać tekstową (String), natomiast wartość może być dowolnego typu (Any), jest ona również zadeklarowana jako stała – „vars„.

By pobrać nazwę klasy, w której znajduje się trait, używamy metody this.getClass, która zwraca nam Javowy obiekt reprezentujący klasę. Posiadający metodę, która zwraca nam jej nazwę „getName„. Następnie zdefiniowana jest funkcja extractFields, która jest jednocześnie domknięciem – importuje do swojego kontekstu stałą „vars„. Rekurencyjnie przemieszcza się ona w górę hierarchii klas i pobiera listę zadeklarowanych pól i dołącza je do stałej vars. Pragnąłbym zwrócić tutaj szczególną uwagę na sposób w jaki jest dołączany kolejny element do „arraya„. W PHP zrobilibyśmy coś takiego:

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

Autor wpisu: Wojciech Sznapka, dodany: 22.03.2011 17:13, tagi: php, apache

If you are developing PHP application on your own PC, you probably have some vhost based configuration of your Apache. With some tricks, you can turn your Linux box into powerful development server without configuring vhost for every app . In the minimum configuration effort, you need to pass those steps: checkout repository to disk [...]

Autor wpisu: nospor, dodany: 21.03.2011 22:18, tagi: php

Dziś przedstawię Wam jak w łatwy sposób stworzyć ładne url'e we własnej aplikacji. Wielu początkujących programistów tworzy cały mechanizm ładnych url'i w całości oparty na mod-rewrite i pliku htaccess. Niestety takie podejście jest mało elastyczne i na dłuższą metę uciążliwe. Pokażę Wam inną metodę, gdzie cały mechanizm przetwarzania linków zawarty jest w kodzie php. Chcę od razu zaznaczyć, iż nie będzie tu żadnej super hiper obiektowości, rutingu i innych super hiper bajerów. Artykuł ma na celu pokazać jak prosto zrobić ładne linki i poznać podstawy tej konstrukcji.

Autor wpisu: batman, dodany: 21.03.2011 08:00, tagi: php

Omawiając interfejsy dostępne w ramach biblioteki SPL, celowo pominąłem dwa z nich – SplObserver oraz SplSubject. Zrobiłem to dlatego, by ich opis nie zaginął w gąszczu pozostałych interfejsów. Dlaczego akurat te dwa zasłużyły na osobny wpis? Ponieważ przy ich pomocy możemy zaimplementować wzorzec obserwatora.

Nudna teoria

Wzorzec obserwatora należy do grupy wzorców czynnościowych. Wykorzystywany jest do powiadomienia jednego obiektu (obserwatora) o zmianie stanu drugiego (obserwowanego). Powiązane w ten sposób obiekty nie muszą być od siebie zależne, co więcej, nie muszą być świadome swojego istnienia. W ten sposób oba obiekty można niezależnie od siebie rozszerzać, nie wypływając na działanie obiektu powiązanego.

Akademicki przykład

Zacznijmy od prostego przykładu, w którym mamy dwa obiekty obserwujące i jeden obserwowany.

class Obserwator1 implements SplObserver
{
	public function update(SplSubject $subject)
	{
		echo 'aktualizacja trafiła do klasy Obserwator1' . PHP_EOL;
	}
}

class Obserwator2 implements SplObserver
{
	public function update(SplSubject $subject)
	{
		echo 'aktualizacja trafiła do klasy Obserwator2' . PHP_EOL;
	}
}

class Obserwowany implements SplSubject
{
	protected $_observers = array();

	public function attach(SplObserver $observer)
	{
		$this->_observers[spl_object_hash($observer)] = $observer;
	}

	public function detach(SplObserver $observer)
	{
		unset($this->_observers[spl_object_hash($observer)]);
	}

	public function notify()
	{
		foreach($this->_observers as $observer) {
			$observer->update($this);
		}
	}
}

$obserwator1 = new Obserwator1();
$obserwator2 = new Obserwator2();

$obserwowany = new Obserwowany();
$obserwowany->attach($obserwator1);
$obserwowany->attach($obserwator2);
$obserwowany->notify();

Wyniku działania powyższego kodu jest prosty do przewidzenia.

Jeśli zajdzie taka potrzeba, możemy odpiąć obiekt obserwatora i ponownie wysłać informację o aktualizacji stanu obiektu.

$obserwowany = new Obserwowany();
$obserwowany->attach($obserwator1);
$obserwowany->attach($obserwator2);
$obserwowany->notify();
$obserwowany->detach($obserwator1);
$obserwowany->notify();

Przykład z życia wzięty

Przykłady akademickie mają to do siebie, że nijak nie pasują do twardej rzeczywistości i bardziej przeszkadzają niż pomagają w zrozumieniu zagadnienia. Dlatego też do lepszego poznania wzorca obserwatora posłużymy się praktycznym przykładem.

Załóżmy, że mamy aplikację, w której użytkownicy mogą zakładać konta oraz się na nie logować. Zalogowany użytkownik może zmienić swoje dane. Dane te od razu powinny trafić do obiektu sesji, by przy kolejnym żądaniu można było pobrać aktualne informacje z sesji. Tutaj z pomocą przychodzi obserwator (obiekt Session), który monitoruje stan użytkownika (obiekt User) i aktualizuje dane sesji w momencie edycji użytkownika.

class Session implements SplObserver
{
	public function update(SplSubject $subject)
	{
		$this->_updateSession($subject);
	}

	protected function _updateSession(User $user)
	{
		// zapisz nowe dane użytkownika do sesji
	}
}

class User implements SplSubject
{
	protected $_observers = array();

	public function editUser(array $data)
	{
		// dokonaj aktualizacji użytkownika (zapis do bazy, generowanie awatara, itd)
		// a nastepnie wyślij powiadmienie do sesji

		$this->notify();
	}

	public function attach(SplObserver $observer)
	{
		$this->_observers[spl_object_hash($observer)] = $observer;
	}

	public function detach(SplObserver $observer)
	{
		unset($this->_observers[spl_object_hash($observer)]);
	}

	public function notify()
	{
		foreach($this->_observers as $observer) {
			$observer->update($this);
		}
	}
}

$user = new User();
$user->attach(new Session());

// za siedmioma klasami
// za siedmioma obiektami

$user->editUser(array(
	'imie' => 'Jan',
	'nazwisko' => 'Kowalski'
));

Powyższy przykład jest poprawny tylko w przypadku, gdy obserwatorem jest Session, a obserwowanym User. Jeśli chcielibyśmy aby Session obserwował więcej obiektów o różnych typach, należało by zmodyfikować metodę update tak, aby wykryć typ obiektu zgłaszającego aktualizację stanu i w zależności o niego wykonac stosowną akcję.

Podsumowanie

Wzorzec obserwatora doskonale sprawdza się wszędzie tam, gdzie stan jednego obiektu uzależniony jest od stanu drugiego obiektu. Dzięki temu, że obiekty nie są ze sobą ściśle powiązane, można je dowolnie rozbudowywać bez obawy, że wpłynie to negatywnie na proces obserwacji.

Autor wpisu: singles, dodany: 19.03.2011 23:06, tagi: php, zend_framework

Słowem wstępu – ZFQT – zapytacie pewnie co to znaczy? Nie, nikt nie implementuje Zend Framework’a korzystając bibliotek Qt – przynajmniej nic mi na ten temat nie wiadomo. Skrót ten oznacza Zend Framework Quick Tip. Tym wpisem chciałbym zacząć serię stosunkowo krótkich (postaram się:) notek zawierających porady/sztuczki w ZF. Niektóre mogą się wydawać oczywiste, ale nawet jeśli jedna osoba nauczy się czegoś nowego albo zrozumie dzięki temu, jak działa ZF, to uważam, że i tak warto prowadzić taką serię. Tym bardziej, że także komentarze często zawierają wartościową wiedzę. Tak więc czas zacząć!

Czym jest helper widoku?

View Helpers w ZF to klasy, które najczęściej implementują skomplikowaną logikę powiązaną z widokiem. Reference Guide od ZF opisuje je w ten sposób:

In your view scripts, often it is necessary to perform certain complex functions over and over: e.g., formatting a date, generating form elements, or displaying action links. You can use helper classes to perform these behaviors for you.

W ZF helpery definiujemy domyślnie jako klasy o nazwie pasującej do schematu Zend_View_Helper_[nazwaKlasy] oraz zapisujemy w ścieżce application/views/helpers/ – oczywiście, nazwy klas helperów jak ich lokalizację można zmieniać. Helper musi posiadać metodę o nazwie takiej samej jak nazwa pliku, z tym że zaczynającą się od małej litery. Następnie możemy używać ich w plikach widoku *.phtml poprzez $this->nazwaHelpera() bądź w dowolnym miejscu aplikacji, gdzie mamy dostęp do instancji Zend_View.

Przykład najprostszego helpera, który zwróci odpowiednią formę rzeczownika w zależności od przekazanych parametrów. Zaprogramowany dla większości przypadków języka angielskiego, ponieważ implementacja jest zdecydowanie prostsza, a chodzi o pokazanie zasady działania.

<?php
// application/views/helpers/Pluralize.php
class Zend_View_Helper_Pluralize
{
    public function pluralize($noun, $number)
    {
        return $noun . ((intval($number) > 1) ? 's' : '');
    }
}
 
// application/views/index/index.phtml
<?php echo $this->pluralize('cat', 1); ?> // wyświetla 'cat'
<?php echo $this->pluralize('cat', 4); ?> // wyświetla 'cats'
<?php echo $this->pluralize('screen', 11); ?> // wyświetla 'screens'

Więcej informacji na temat helperów widoku, głównie tych standardowych znajdziecie w Reference Guide:View Helpers

Wiele metod dla jednego helpera

W momencie, kiedy wywołujecie nieistniejącą metodę obiektu widoku, Zend Framework automatycznie szuka klasy helpera pasującej do podanej nazwy. Jeśli takowa istnieje, tworzy obiekt tej klasy i wywołuje metodę zgodną z nazwą klasy – stąd wspomniane wcześniej wymaganie odnośnie nazywania metod. Rozwiązanie takie sprawdza się w większości przypadków.

Załóżmy jednak sytuację, że w naszej aplikacji musimy wyświetlać listę superbohaterów na dwa różne sposoby. Raz jako listę numerowaną, a drugi raz jako ciąg znaków oddzielony przecinkami. W drugim przypadku jednak imię i nazwisko bohatera musi być linkiem do strony wyświetlającej szczegóły na jego temat.

Pierwsza myśl niektórych programistów brzmi zazwyczaj:

no nic, muszę napisać dwie klasy – jedną do wyświetlania listy, drugą do linków oddzielonych przecinkami

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

Autor wpisu: cojack, dodany: 19.03.2011 20:30, tagi: framework

Gdyby ktoś, powtarzam GDYBY, korzystał jakimś cudem z mojego FW, w co wątpię :D to napisałem sobie skrypt instalacyjny, który na podstawie plików index w katalogach data/sql/create, data/sql/delete, data/sql/insert/init, data/sql/insert/demo wykonuje odpowiednie operacje, pliki index to zwykłe pliki tekstowe, w których znajdują się względne ścieżki do plików *.sql z treścią danych do wrzucenia do bazy danych. Względność ścieżek zależy od kontekstu, przykład pliku index w katalogu data/sql/create:

#
# Dobra sprawa jest taka, że sami musimy zadbać o kolejność instalacji elementów xD
# 
user/table.sql
session/table.sql
module/table.sql
#
# Ok, mamy utworzone tabele to możemy teraz zrobić resztę, widoki i procedury
# Czasami procedury korzystają z widoków, czasami widoki z procedur, ale drugi przypadek jest częstszy
# także jedziemy widokami
#
user/view.sql
session/view.sql
module/view.sql
#
# I teraz z czystym sumieniem dorzucamy procedury
#
user/procedure.sql
session/procedure.sql
module/procedure.sql
#
# Kwestia constrainow, czasami jest taka potrzeba że nie mamy możliwości założyć constraina
# na tabele której jeszcze nie ma więc czasami trzeba dorobić kolejny plik w którym to dorzucimy ;)
# 
# np:
# 
# user/constraint.sql
#
# Jeżeli jesteśmy jacyś strasznie nerdowi to możemy sobie dorzucić komentarze
# Z tego co pamiętam to nie wiem czemu ale transakcje nie działają przy dodawaniu komentarzy oO
# 
# np:
# 
# user/comment.sql
# itd...
#

A w nim dodatkowo parę innych informacji ;)

#!/bin/bash
 
# Instalatron kufa!
my_dir="$(pwd)/data/sql";
user='';
pass='';
database='';
demo=0;
backup=0;
 
usage()
{
cat << EOF
Użycie $0 [Opcje]
 
Skrypt ten, wywołuje inne pliki tekstowe z bezpośrednim wpisem do bazy, operacja "nieodwracalna".
 
Wymagane ścieżki w katalogu:
 
$(pwd)/
 
to:
$(echo -e "\t") ./data/sql/delete/index
$(echo -e "\t") ./data/sql/create/index
$(echo -e "\t") ./data/sql/insert/demo/index
$(echo -e "\t") ./data/sql/insert/init/index
 
Należy zachować kolejność utwaiania dropowania schematów odrwotną niż przy tworzeniu gdyż zależności pomiędzy tabelami nam nie pozwolą inaczej wykonać operacji.
 
Pliki index, są to zwykłe pliki tekstowe, bez żadnego rozserzenia, przykład pliku ./data/sql/create/index:
 
user/table.sql
session/table.sql
module/table.sql
 
Gdzie odniesie jest do katalogu: ./data/sql/create/
 
Opcje:
   -b      Backup, tworzy pierw backup
   -d      Nazwa bazy danych
   -u      Nazwa użytkownika
   -p      Hasło użytkownika
   -e      (Demo) Przykładowe dane
   -h      Wyświetla pomoc
EOF
}
 
setup_sql()
{
   export PGUSER=$1
   export PGPASSWORD=$2
}
 
backup_sql()
{
   backup_file="$(pwd)/data/backup/$(date +'%F|%T').tar"
   pg_dump -F 'tar' -f "$backup_file" $1
}
 
run_sql()
{
   if [ ! -e "$1/index" ]
   then
      echo "Brak pliku $1";
      return 1;
   fi;
 
   files=$(cat "$1/index"|grep -e ^[^#]);
 
   for x in $files
   do
      if [ ! -e "$1/$x" ]
      then
         continue
      fi;
      psql --log-file "./tmp/install.log" --quiet -f "$1/$x" $2
   done
}
 
# hahaha to przez przypadek :D
while getopts "d:u:p:ebh" OPTION
do
   case $OPTION in
      b)
         backup=1
         ;;
      d)
         database=$OPTARG
         ;;
      u)
         user=$OPTARG
         ;;
      p)
         pass=$OPTARG
         ;;
      e)
         demo=1
         ;;
      h)
         usage
         exit 1
         ;;
      ?)
         usage
         exit
         ;;
   esac
done
 
#Wyczyścimy poprzednie logi z instalacji
rm -f "./tmp/install.log";
 
#Inicjalizujemy sql'a
setup_sql $user $pass;
 
if [ -n $backup ]
then
   backup_sql $database;
fi;
 
#Kasujemy
run_sql "$my_dir/delete/" $database;
 
#Tworzymy
run_sql "$my_dir/create/" $database;
 
#Inicjalizujemy
run_sql "$my_dir/insert/init/" $database;
 
#A jak chcemy demo to je dodajemy ;)
if [ -n $demo ]
then
   run_sql "$my_dir/insert/demo/" $database;
fi;

W sumie to tyle.

Autor wpisu: Tomasz Kowalczyk, dodany: 19.03.2011 03:17, tagi: php

Zainstalowałem i skonfigurowałem dzisiaj najnowszą wersję serwera WAMP - 2.1e. O niektórych problemach związanych z jego działaniem pisałem już wcześniej, także temat ten jest Wam na pewno znany. W dzisiejszym wpisie chciałbym pokazać, w jaki sposób ukryć "pomarańczowe komunikaty" o błędach wykonania skryptu PHP, jakie serwuje nam debugger XDebug. Wstęp. Na początku należą się Wam [...]
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.