Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

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: Śpiechu, dodany: 11.08.2013 22:47, tagi: internet

Napiszę o ciekawym problemie, który przy odrobinie pośpiechu, nieuwagi, modyfikacji czyjegoś kodu może dawać solidną dawkę WTF podczas testowania (mnie dało). Żeby nie było, w dokumentacji foreach pisze jak byk: Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

Powiedzmy, że mamy tablicę jednowymiarową, którą chcemy przeiterować w celu zmiany wartości. Nic prostszego powiecie:

$array = ['arr_item1', 'arr_item2', 'arr_item3'];
 
foreach ($array as &$item) { // $item z referencją
  // modyfikuje elementy
}

Na tym etapie wszystko jest OK. Jedziemy sobie z kodem dalej.

// 150 linii kodu dalej
 
foreach ($array as $item) { // $item BEZ referencji
  // robie cokolwiek z $item
}

W tym momencie pojawia się WTF. Zawartość $array1 to arr_item1, arr_item2, arr_item2. Jeśli za drugim razem robimy jakąś agregację danych w stylu wyliczanie średniej czy sumy, błąd może przez długi czas pozostać niezauważony (mediana) lub delikatnie przeinaczony (średnia arytmetyczna dla dużej liczby elementów).

Pytanie dlaczego tak się dzieje? $item po pierwszej iteracji w dalszym ciągu trzyma referencję do $array[2]. Wobec tego przy drugiej iteracji przypisuje kolejne elementy do $array[2]. Wszystko jest OK dopóki nie docieramy do ostatniego elementu. Mamy tam do czynienia z instrukcją w stylu „przypisz do $item[2] wartość $item[2]”. Jako iż $item[2] ma aktualnie wartość z $item[1] to buch i mamy arr_item2.

Iterując po kilku różnych tablicach za pomocą tej samej zmiennej zawsze powodujemy nadpisanie ostatniego elementu pierwszej tablicy.

Jak się przed tym uchronić?

  • użyć unset($item) po foreach (najlepsze wyjście)
  • unikalnie nazywać zmienne $item (ryzykowny krok)
  • rozbić funkcję wykorzystującą iteracje na kilka mniejszych, prawdopodobnie robi kilka różnych rzeczy

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 :-)

Autor wpisu: Łukasz Socha, dodany: 03.08.2013 13:59, tagi: php

W drugim wpisie poruszającym tematykę związaną z WordPressem opiszę mechanizm shortcode.

Shortcode – o co chodzi?

Mechanizm shortcode możemy wykorzystać do uproszczenia struktury kodu w edytorze – łatwiej będzie użyć klientowi dostosowany dla niego znacznik niż pisać bezpośrednio w HTMLu :) .

Przykład

Stwórzmy znacznik, który będzie można wykorzystać do cytowania wypowiedzi.

Własny znacznik tworzymy dodając nową funkcję w pliku functions.php:

function my_cite($atts, $content) {
    $output = '<span class="cite" id="'.$atts['id'].'">"'.$content.'"</span>';
    return $output;
}
add_shortcode('cite', 'my_cite');

Gdy chcemy wykorzystać stworzony przez nas znacznik podczas edycji treści dodajemy:

[cite]Cytat[/cite]

Prawda, że łatwiej wyjaśnić klientowi, jak użyć powyższy znacznik niż znaczniki HTML? :) . Więcej o shortcode na stronach WordPressu.

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