Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM    Subskrybuj kanał ATOM dla tagu php Kanał ATOM (tag: php)

Autor wpisu: Jacek Skirzyński, dodany: 04.09.2013 21:02, tagi: javascript, php

NetBeans jest moim ulubionym IDE, jeżeli chodzi o język PHP i od kilku dni przyglądam się wersji beta kolejnego wydania – 7.4. Jak zwykle jest po kilka nowości dla różnych kierunków zastosowań IDE – HTML5, PHP, JavaScript, Java, Java EE i innych.

Nowości istotne dla programisty aplikacji internetowych (PHP/JavaScript/HTML5) to między innymi:

Z nowości, z których w tym czasie korzystałem, najbardziej przypadł mi do gustu rozwój pluginu obsługi Gita. Pojawiła się na przykład obsługa rebase czy amend i całe menu Git zostało zorganizowane na nowo – bardziej użytecznie. Na uwagę zasługuje również zmiana nazewnictwa opcji na bardziej analogiczne do poleceń „rdzennego”, konsolowego Gita. Teraz obsługa jest bardziej intuicyjna przy przesiadce z konsoli na plugin Git w IDE.

Polecane linki:

Autor wpisu: Jacek Skirzyński, dodany: 02.09.2013 23:44, tagi: php

Co jakiś czas mam do czynienia z różnymi starszymi projektami napisanymi przez inne osoby. Jedną z bardziej irytujących mnie rzeczy są „magiczne” cyferki. Może jest ktoś (oprócz autora), kto patrząc na poniższy fragment kodu będzie wiedział jakich dokładnie użytkowników zwraca metoda getUzytkownicy()? Niestety ja się do takich osób nie zaliczam.

class Uzytkownik extends AppModel
{
    public function getUzytkownicy() {
        return $this->find('all', array(
            'conditions' => array(
                'Uzytkownik.status' => array(2, 3)
            )
        ));
    }
}

Fragment kodu jest wzorowany na klasie modelu dla CakePHP 1.3, ale pokazany problem jest niezależny od szkieletu programistycznego lub jego braku – to brak czytelności. Nie znająć frameworka z kodu można odczytać, że zwraca on kolekcję obiektów użytkowników o statusach… no właśnie – 2 i 3. Co to znaczy? To najczęściej wie autor i osoby, które musiały już tego poszukać. Pozostali dopiero będą szukali znaczenia tytułowych cyferek. Najczęściej w takich sytuacjach brakuje również komentarza, czy to wewnątrz metody czy PHPDoc dla metody.

Prywatnie rozwiązuję powyższy problem w taki sposób:

class Uzytkownik extends AppModel
{
    const STATUS_NIEPOTWIERDZONY = 1;
    const STATUS_POTWIERDZONY = 2;
    const STATUS_ZABLOKOWANY = 3;
    const STATUS_USUNIETY = 4;
    
    /**
     * Zwraca tablice uzytkownikow potwierdzonych i zablokowanych
     * @return array
     */
    public function getUzytkownicy() {
        return $this->find('all', array(
            'conditions' => array(
                'Uzytkownik.status' => array(
                    self::STATUS_POTWIERDZONY, 
                    self::STATUS_ZABLOKOWANY
                )
            )
        ));
    }
}

Kod z drugiego fragmentu jest o wiele bardziej czytelny i klarowny. Przede wszystkim nie wymaga dodatkowego przeszukiwania kodu i aplikacji, żeby dowiedzieć się co oznaczają poszczególne numery statusów – nazwa stałej jest wystarczająco jasna. Dobrym pomysłem jest również pisanie komentarzy dla metod i późniejsze ich utrzymywanie. Dlaczego utrzymywanie? Ponieważ jeżeli statusy w zapytaniu zostaną zmienione a komentarz nie to będzie wprowadzał w błąd podczas programowania (IDE wyświetli w podpowiedziach metod tylko treść komentarza). W takim wypadku można by stwierdzić, że brak komentarza dla metody jest lepszy niż błędy komentarz – przy braku będziemy się sugerować nazwą lub zajrzymy do kodu, żeby sprawdzić działanie.

Dodatkową kwestią jest też nazwa metody: getUzytkownicy(), można by ją zastąpić getPotwierdzeniIZablokowaniUzytkownicy(). Jednak w tym momencie nazwa metody robi się już trochę długa. Prywatnie metody tego typu staram się nazywać raczej odnosząc się do miejsca lub kontekstu ich wykorzystania. Na przykład getListaUzytkownikowDlaAdm(). Taka nazwa również jest dość długa, ale pozwala dużo lepiej zidentyfikować zastosowanie metody. Dodatkowo w jednej z aplikacji, które rozwijam/utrzymuję obiekt odwzorowujący proces ma 18 statusów wskazujących na różne etapy procesu. Tworząc metodę, której nazwą byłby zlepek np. nazw 6 statusów (których nazwy mogą i często są wieloczłonowe), które powinny mieć obiekty pokazywane na liście byłoby pomyłką.

Podsumowując mam mały apel:

  • nazywajmy klasy/metody/stałe/zmienne/etc w sposób bardziej odzwierciedlający to co robią;
  • piszmy i utrzymujmy komentarze (najlepiej PHPDoc, żeby można było z nich korzystać poprzez IDE i wygenerować dokumentację);
  • nie używajmy „magicznych” cyferek tylko stałych.

Dziękuję :)

Autor wpisu: Marek, dodany: 29.08.2013 23:56, tagi: javascript, php

Twitter Bootstrap z gałęzi 2.3.x oferuje proste boksy, tzw. popovers (http://getbootstrap.com/2.3.2/javascript.html#popovers), których możemy używać do wyświetlania w całkiem ładny sposób różnych informacji.  Podstawowa funkcjonalność tych elementów jednak nie była dla mnie wystarczająca.

Co chciałem uzyskać:

  • tylko jeden aktywny boks na stronie,
  • otwierany po kliknięciu,
  • zamykany po ponownym kliknięciu gdziekolwiek poza aktywnym boksem (tak żeby można było skopiować zawartą w nim informację)

Poniżej kod, który dostosowuje popovers zgodnie z powyższymi założeniami:

// zniszcz otwarte boksy
function destroyOpenedPopovers() {
    //jeśli obiekt, z którego wywołaliśmy boks, posiada id, niszczymy jego boks
    if ($('#closingDiv').length && $('#closingDiv').attr('data-popover-id') !== 'undefined') {
        var popoverLinkId = $('#closingDiv').attr('data-popover-id');
        $('#' + popoverLinkId).popover('destroy');
        $('#' + popoverLinkId).removeClass('popover-active');
    } else {
        // w przeciwnym razie niszczymy wszystkie możliwie otwarte boksy
        $('.popover-area').each(function () {
            $(this).popover('destroy');
            $(this).removeClass('popover-active');
        });
    }
}
//uruchamiamy popover
function triggerPopover(obj) {
    // klasa popover-active nadawana jest obiektowi, na którym otwieramy boks
    $(obj).toggleClass('popover-active');

    // jeśli boks powinien zostać otwarty
    if ($(obj).hasClass('popover-active')) {
        $(obj).popover({
            html: true,
            trigger: 'manual'
        });
        $(obj).popover('show');
// obszar zamykający otwarty boks
    var closingDiv = '<div id="closingDiv" style="z-index: 1008; background-color: rgba(0, 0, 0, 0.1); width:' + $(document).width() + 'px; height: ' + $(document).height() + 'px; position: absolute; top: 0; left: 0;" data-popover-id="' + $(obj).attr('id') + '"></div>';
    $('body').append(closingDiv);
    $('#closingDiv').click(function () {
        destroyOpenedPopovers();
        $(this).remove()
    });
  }
}

$(document).ready(function () {
    $('.popover-area').click(function () {
        triggerPopover(this);
    });
});

Kilka słów komentarza:

  • w powyższym przykładzie do każdego elementu drzewa DOM, który posiada klasę „popover-area” podpinam funkcję, która utworzy boks
  • w momencie wywołania popover, nadaję elementowi wywołującemu boks klasę popover-active oraz tworzę zamykający obszar, który rozciągam na cały ekran
  • zamykający obszar posiada atrybut data-popover-id, którego wartość to id elementu, którego kliknięcie wywołało utworzenie boksa – dzięki temu wiemy co trzeba zamknąć

Przykład użycia: http://jsfiddle.net/mheki/Dg8Z8/

Autor wpisu: Łukasz Socha, dodany: 26.08.2013 20:14, tagi: php

Pełnomocnik jest wzorcem projektowym, którego celem jest utworzenie obiektu zastępującego inny obiekt. Stosowany jest on w celu kontrolowanego tworzenia na żądanie kosztownych obiektów oraz kontroli dostępu do nich.

proxy Diagram klas wzorca Proxy

Interfejs Subcject definiuje pewną metodę. Klasy Proxy i RealSubject realizują powyższy interfejs na dwa różne sposoby. W klasie Proxy zostaje wywołana metoda doSmething() obiektu klasy RealSubject. Przed wywołaniem tej metody można oczywiście wykonać inne operacje. Obrazuje to poniższy listing.

Przykładowa implementacja

<?php

interface Subject {

    function doSomething();
}

class RealSubject implements Subject {

    public function doSomething() {
        echo 'I do something...';
    }

}

class Proxy implements Subject {

    private $realSubject;

    public function doSomething() {
        if ($this->realSubject == null) {
            echo 'Proxy';
            $this->realSubject = new RealSubject();
        }
        $this->realSubject->doSomething();
    }

}

$obj = new Proxy();
$obj->doSomething(); // wyswietli najpierw "Proxy", a nastepnie "I do something..."
$obj->doSomething(); // wyswietl "I do something..."
?>

Przykład z życia wzięty

Zapewne zastanawiasz się jaki jest sens stosowania klasy pośredniczącej. Przeanalizujmy przykład, w którym wykorzystamy wzorzec Proxy dla biblioteki generującej obrazki w wysokiej rozdzielczości. Dodatkowo chcemy zabezpieczyć dostęp hasłem.

<?php
interface HighResolutionImage{
    function display();
}
class Image implements HighResolutionImage{
    private $options;
    public function __construct($options) {
        $this->options=$options; 
        // generate image
    }
    public function display() {
        echo 'display image';
    }
}
class ProxyImage implements HighResolutionImage{
    private $options;
    private $passwrd;
    private $image = null;
    public function __construct($options, $password) {
        $this->options=$options; 
        $this->passwrd=$password;
    }
    public function display() {
        if($this->passwrd=='tajne') {
        if($this->image==null) {
            $this->image=new Image($this->options);
        }
        $this->image->display();
        } else {
            echo 'Access denied';
        }
    }
}

$image = new ProxyImage(array('width' => 3800, 'height' => 2000), 'tajne');
$image2 = new ProxyImage(array('width' => 3800, 'height' => 2000), 'tajne2');
$image->display(); // wyswietli "display image"
$image2->display(); // wyswietli "Access denied"
?>

Dzięki wykorzystaniu ProxyImage obrazek zostanie wygenerowany tylko w przypadku podania prawidłowego hasła oraz w sytuacji, gdy naprawdę istnieje potrzeba jego wyświetlenia.

Zastosowanie

Wzorzec Proxy możemy wykorzystać w sytuacji, gdy koszt utworzenia obiektu jest wysoki, a wykorzystanie danego obiektu uzależnione jest od spełnienia pewnych warunków.

Powiązane tematy

Autor wpisu: matipl, dodany: 21.08.2013 08:48, tagi: php

PHPCon Poland - logoOd początku sierpnia została udostępniona na stronie PHPCon Poland możliwość głosowania na zgłoszone prelekcje.

Pierwszy raz taką możliwość uczestnicy dostali rok temu. Dzięki temu każdy z Was może współtworzyć to coroczne wydarzenie w polskim świecie PHP. Obecnie możecie głosować na 34 zgłoszone tematy, jeden głos na jedną prelekcję. Proszę przeglądajcie listę od dołu zestawienia, bo jest kilka wartościowych perełek, które zostały przez innych przeoczone.

Wstępnie chciałem napisać, kogo z miłą chęcią zobaczę i posłucham. Ale uznałem, że nie napiszę abyście przypadkiem nie sugerowali się tym w głosowaniu.

Natomiast powiem Wam, czego ja zawsze oczekuję od spotkania/konferencji. Stawiam na przykłady, historie z życia i pracy przy bardziej złożonych środowiska niż Apache + mod_php. Natomiast, aż mi się niedobrze robi gdy mam słuchać kolejnego wystąpienia o kolejnym CMS-ie czy frameworku, który pojawia się na takim spotkaniu wyłącznie dlatego, bo jest napisany w PHP. To można poczytać w pierwszym lepszym how-to.

Polecam zapoznać się z agendę. Natomiast przypominam, że tegoroczny PHPCon Poland odbędzie się w Szczyrku w dniach 25-27 października 2013. Obecna cena obowiązuje do końca sierpnia (liczy się data księgowania płatności) i kształtuje się od 300 zł (nocleg od piątku, pokój wieloosobowy, bez obiadu w piątek i niedzielę) do 422 zł. Jeśli ktoś chce opłacić zgłoszenie dopiero we wrześniu będzie to kwota minimum 350 zł.

Autor wpisu: vonski, dodany: 20.08.2013 01:16, tagi: php

Wraz z pojawieniem się PHP w wersji 5.3, światło dzienne ujrzała nowa właściwość języka o bardzo groźnie brzmiącej nazwie Late Static Binding. Na czym owa własność polega? Jest ona ściśle związana z metodami statycznymi oraz widocznością / kontekstem poszczególnych metod w klasach. Żeby lepiej pokazać po co w ogóle dodano do języka statyczne wiązanie, warto zobaczyć jakie limity nakłada na nas słowo kluczowe self – bo dotychczas tylko ono pozwalało statycznie wywołać metodę z klasy (oczywiście jeszcze jest parent w przypadku kiedy mówimy o metodach rodzica).

	class A
	{
		public static function who()
		{
			echo __CLASS__; // 3
		}
		
		public static function test()
		{
			self::who(); // 2
		}
	}
	
	class B extends A
	{
		public static function who()
		{
			echo __CLASS__;
		}
	}
	
	B::test(); // 1

Powyższy kod wyświetli na ekranie „A”. Prześledźmy w takim razie kod. Cały „przepływ” zaczyna się oczywiście od wywołania metody B::test(); w pierwszym kroku. Metoda ta nie robi nic poza wywołaniem kolejnej metody o nazwie who(). I tutaj zaczynają się „schody”. Jako że łańcuch wywołań owych metod zaczynamy z klasy B sugeruje to, że zależy nam na wykonaniu metody who() również z klasy B. self jednak działa inaczej, a mianowicie, działa ono w kontekście klasy, w której dana metoda została zdefiniowana. Dlatego też egzekucja takiego kodu self::who(); z klasy A, to mniej więcej tak jak napisanie A::who(). I tutaj z pomocą przychodzi „nowe stare” słowo static. Stare dlatego, że w PHP już przecież z takim słowem nieraz się na pewno spotkałeś, a nowe bo może być teraz użyte w nieco innym kontekście niż dotychczas (oczywiście jego dawne użycie nadal jest aktualne!). Zmodyfikujmy powyższy kod dodając jedną linijkę do metody A::who():

	class A
	{
		public static function who()
		{
			echo __CLASS__; // 2.2
		}
		
		public static function test()
		{
			self::who(); // 2.1
			static::who(); // 3.1
		}
	}
	
	class B extends A
	{
		public static function who()
		{
			echo __CLASS__; // 3.2
		}
	}
	
	B::test(); // 1

Powyższy kod wypisze na ekranie: „AB”. Kroki drugi i trzeci zostały podzielone na dwa etapy w celu polepszenia czytelności przykładu. Z kroku 2.1 idziemy do 2.2 czyli do metody A::who() – jak widać, do tej pory wszystko jest tak samo jak w pierwszym przykładzie, stąd też na ekran zostaje wypisane „A”. Następnie w kroku trzecim program wykonuje metodę who() ale „wyskakuje” z klasy w której aktualnie się znajduje i „idzie” do klasy B – do tej, która zaczęła cały łańcuch wywołań. I tym właśnie różni się wywołanie static od self. static odwołuje się do klasy, z której nastąpiło początkowe wywołanie – czyli krok 3.1 w momencie wykonywania skryptu „wygląda” dla interpretera tak: B::who().

Pułapki z widocznością

Late static binding to naprawdę fajny wynalazek, ale jeśli nie masz doświadczenia w jego użyciu musisz mieć się na baczności – zwłaszcza jeśli chodzi o zmienne prywatne. Popatrz na poniższy przykład:

	class A
	{
		private static function who()
		{
			echo __CLASS__;
		}
		
		public static function test()
		{
			self::who(); // 1.1, 2.1
			static::who(); // 1.2, 2.2
		}
	}
	
	class B extends A
	{
		
	}
	
	class C extends A
	{
		private static function who()
		{
			echo __CLASS__;
		}
	}
	
	B::test(); // 1
	C::test(); // 2

Ten przykład wyświetli na ekranie „AAA” a następnie błąd „Fatal error: Call to private method C::who() from context ‚A’”. Jeśli uważnie przeanalizowałeś poprzednie przykłady powinieneś się przynajmniej domyślać dlaczego na koniec dostajemy błąd. Najpierw do słowa dochodzi klasa B i tutaj nic nadzwyczajnego się nie dzieje: krok 1.1 to wywołanie metody A::who, natomiast w kroku 1.2 odpalamy metodę B::who (pamiętając, że nadal jesteśmy w kontekście A) – ale jako że metoda ta nie jest zdefiniowana w klasie B interpreter „szuka” jej w klasie A. W przypadku klasy C sytuacja jest już nieco inna, jako że klasa ta definiuje własną metodę prywatną o nazwie who. Dlatego w kroku 2.1 wszystko jest jeszcze w porządku, jako że self::who() odwołuje się do metody, co prawda również prywatnej, ale z tego samego kontekstu z którego następuje wywołanie – w skrócie mówiąc: self::who() wywołane z A wykonuje rzecz jasna metodę A::who(). Problem natomiast pojawia się przy wywołaniu static::who() gdyż tutaj z kontekstu A chcemy wywołać prywatną metodę innej klasy – co oczywiście jest zabronione. Jeszcze uwaga dla ciekawych świata – zamień private na protected w klasie C i zobacz co się stanie. I oczywiście zastanów się dlaczego :)

Autor wpisu: Wojciech Sznapka, dodany: 05.08.2013 10:19, tagi: php

Today I discovered neat PHP extension named Gender: http://www.php.net/manual/en/book.gender.php. It determines gender based on name and country. Probably this class will be useful on some point of your software development career :-)
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.