Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: sokzzuka, dodany: 26.11.2010 17:12, tagi: php

Może kogoś zdziwić ten tytuł. Co transmutacja, czyli znana z alchemii (i Diablo 2) zamiana jednego przedmiotu w inny ma wspólnego z PHP ? Ma wspólnego i to wiele. Wystarczy sobie uświadomić, że przedmioty to obiekty. To czym jest obiekt, determinuje jego klasa (a raczej podobieństwo obiektów tworzy klasę ale nie w tym rzecz). Jak wszyscy wiemy,  w języku PHP, rzutowanie możliwe jest tylko pomiędzy typami prostymi oraz object i array. Odnosząc to na świat rzeczywisty, rzutowanie jest właśnie ową „transmutacją”.Jak już wspominałem, rzutowanie jest mocno ograniczone. Może rzadko, ale zdarza się, że chcielibyśmy zmienić typ jakiegoś obiektu. Ostatnio natrafiłem się na poniekąd podobną sytuację. Chciałem zaimplementować prosty DataMapper. Tak dla małego przypomnienia jest to wzorzec projektowy, dzięki któremu możemy zapisywać obiekty w relacyjnej bazie danych oraz je stamtąd wyciągać. Czyli koniec końców jest to część składowa ORM-a. Jednak nie jest to mechanizm w stylu ActiveRecord (Doctrine 1) – zapisywane klasy nie dziedziczą z żadnej klasy bazowej.  DataMapper (Doctrine 2), dzięki refleksji, potrafi sam dowiedzieć się wszystkiego o dowolnym obiekcie i zapisać go w bazie a później odtworzyć, bez konieczności „dostosowywania” obiektu do jego wymagań.

O ile jeszcze zapisanie obiektu w bazie to pikuś, to odtworzenie go jest w pewien sposób problematyczne. Problemem jest to, że jeżeli obiekt ma w sobie prywatne pola, które mają być zapisane w bazie, natomiast nie ma żadnych metod na ustawianie ich, to obiekt zawsze będzie odtworzony w sposób niekompletny. Mały przykład dydaktyczny:

class Example {
    private $_foo = 5;
    private $_bar = 6;

    public function __get($name){
        $sField = '_'. $name;
        return $this->$sField;
    }

    public function __set($name, $value){
        throw new LogicException('This object is readonly!');
    }

    public function doSomething(){
        //...
    }
}

Jak widać, możemy pobierać zawartość pól, jednak nie możemy ich ustawiać. Po krótkim namyślę jak rozwiązać problem nie zmieniając klasy Example, można się rozmarzyć, że w innym języku może dało by się zrzutować array z danymi pobranymi z bazy na obiekt klasy Example i było by po sprawie. Jak wiadomo, w PHP się nie da.  Ale od czego mamy zakazane techniki ? Ta krótka funkcja zrealizuje to, czego nam potrzeba:

function transmutate(array $data, $className) {
    $oReflector = new ReflectionClass($className);
    $aDefaultProperties = $oReflector->getDefaultProperties();
    $aInstanceVars = array_merge($aDefaultProperties, $data);

    $aObjectPrototype = array();

    foreach ($aInstanceVars as $field => $value) {
        $sField = "\0" . $className . "\0" . $field;
        $aObjectPrototype[$sField] = $value;
    }

    $oContainer = (object) $aObjectPrototype;
    $sContainer = serialize($oContainer);

    $aContainer = explode(':', $sContainer);
    $aContainer[1] = strlen($className);
    $aContainer[2] = '"' . $className . '"';
    $sContainer = implode(':', $aContainer);

    $oResult = unserialize($sContainer);
    return $oResult;
}

Oraz przykład użycia:

$aData = array('_foo' => 7, '_bar' => 8);
$oExample = transmutate($aData, 'Example');
var_dump($oExample);
/* efekt:
object(Example)#3 (2) {
  ["_foo:private"]=>
  int(7)
  ["_bar:private"]=>
  int(8)
}
 */

Co do samej funkcji, to pomijając aspekt wyciągania informacji za pomocą refleksji. To używa ona funkcji serialize i unserialize. Jest to spowodowane tym, że PHP, odtwarzając zserializowany obiekt po pierwsze nie uruchamia jego konstruktora, a po drugie nie przejmuje się widocznością zmiennych i jest to główny klucz do sukcesu.

Podsumowując,  jest to ciekawy trik, jednak jeżeli nie piszecie DataMappera, lub nie jest to wasza ostatnia deska ratunku, nie używajcie go. Nie bez powodu jest to „zakazana” technika ;)

P.S

Od bodajże PHP 5.3.2 albo 5.3.3 można uzyskać podobny efekt (zmiana wartości zmiennych prywatnych/chronionych z zewnątrz obiektu) poprzez metodę ReflectionProperty::setAccessible.

Autor wpisu: Kamil, dodany: 26.11.2010 01:16, tagi: php

Jaka jest przyszłość PHP? Czy z biznesowego punktu widzenia nadal warto interesować się PHP? W tym krótkim wpisie pragnę zastanowić się nad przyszłością branży, w której głównie rozwijałem się w ostatnim czasie i co do której mam wielkie obawy oraz wątpliwości. Dlaczego? Ano wystarczy przyjrzeć się rynkowi i wysunąć kilka prostych wniosków. Oferty pracy dla [...]

Autor wpisu: Zyx, dodany: 25.11.2010 09:18, tagi: php

Ponad rok temu popełniłem wpis zatytułowany Unicode w PHP 5.3 cz. 1, w którym omawiałem tajniki rozszerzenia Intl domyślnie dostępnego od tej wersji. Dzisiaj pragnę zaprezentować niejako jego kontynuację, omawiając jedną z klas wchodzących w skład Intl, MessageFormatter. Służy ona do dynamicznego, inteligentnego tłumaczenia tekstów w systemach tłumaczeń. Jej największą siłą, zwłaszcza w porównaniu do amatorskich wynalazków i sprintf(), jest dobre wsparcie dla argumentów tekstów oraz obsługa warunków.

Autor wpisu: Daniel Burchardtt, dodany: 24.11.2010 22:09, tagi: php

Najprostszym sposobem na wygenerowanie unikalnego ciągu znaków składającego się z liter i liczb jest użycie funkcji haszującej w której jako parametr zostanie podany unikalny parametr.

Parametr

W naszym przykładzie do wygenerowanie unikalnego parametru użyjemy funkcji date() oraz rand(), dzięki którym otrzymamy za każdym razem inny ciąg do zakodowania.

$param = rand(1,1000000).date("d-m/Y:H:i.s");

SHA256

Jako algorytmu do wygenerowania losowego ciągu zastosujemy kodowanie sha256, przy pomocy funkcji hash().

function generatePassword($limit) {
return substr(hash('sha256', rand().time()) , 0 , $limit);
}

Dzięki zastosowaniu funkcji substr() możemy wygenerować hasło o podanej długości, jednak nie dłuższe niż 64 znaki. Jest tak dlatego, ponieważ hash generowany przez sha256 ma długość 64 znaków.

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

Przed miesiącem rozpocząłem cykl zatytułowany ASP.NET MVC dla programistów PHP. Niestety nie udało mi się publikować co tydzień kolejnych części tej serii, czego bardzo żałuję. Od dzisiejszego wpisu postaram się zintensyfikować wysiłki, aby seria pojawiała się częściej. Zgodnie z zapowiedzią z poprzedniej części, zajmiemy się dzisiaj aplikacją ASP.NET MVC od zera. Pozwoli to nam na wstępne zapoznanie się ze strukturą katalogów oraz konwencjami stosowanymi w tej technologii. Zajmiemy się również kontrolerami.

Nowy projekt

Pracę rozpoczniemy od utworzenia nowego projektu. Z menu File należy wybrać opcję New Project, a następnie w zakładce Web kliknąć na ASP.NET MVC 2 Empty Web Application.

new-project

Nazwę oraz lokalizację projektu pozostawiamy bez zmian. Tak przygotowana aplikacja jest tylko pustym szkieletem, złożonym z kilku katalogów. Próba jej uruchomienia zakończy się niepowodzeniem.

Dodajemy kontroler…

Aby powołać naszą aplikację do życia, musimy stworzyć co najmniej jeden kontroler, który obsłuży request, wykona magię z modelem (nie jest to konieczne), a na koniec wskaże widok, który zostanie zwrócony klientowi. W przeciwieństwie do znanych frameworków PHP, nie musimy się bawić w ręczne dodawanie kontrolera. Co więcej, nie musimy korzystać z żadnych poleceń w konsoli. Wszystko możemy wyklikać w Visual Studio. Wystarczy kliknąć prawym przyciskiem myszy w na katalogu Controllers i wybrać z menu kontekstowego opcję Add –> Controller.

add-controller

Nazwijmy nowy kontroler Home (dlaczego akurat Home, za chwilę wyjaśnię). Zwróćcie uwagę, że podobnie jak w przypadku Zend Frameworka do nazwy kontrolera należy dodać przyrostek Controller. Checkbox zostawmy na razie w spokoju.

HomeController

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

Autor wpisu: Wojciech Sznapka, dodany: 23.11.2010 22:58, tagi: php

Probably most of us heard about streams in PHP. They are background of all files and network operations in PHP, even if we don't see it. Everytime when you use file_get_contetnts or fopen you are actually using streams. But there are many stream wrappers I haven't used, because they aren't well known.

Autor wpisu: sokzzuka, dodany: 23.11.2010 09:59, tagi: php

Felipe Pena, jeden z najaktywniejszych deweloperów PHP wraz z całym szeregiem innych prominentnych uczestników projektu ogłosił RFC – propozycje zmian w cyklu wydawniczym interpretera. Jak dotąd, wszelkie nowe wydania powstawały spontanicznie. Po prostu po zakumulowaniu się jakiejś masy krytycznej nowych rzeczy w repozytorium, ktoś wyskakiwał jak to „Filip z konopi indyjskich” i mówił, że robimy nowego releasa. Skutkowało to tym, że nikt nigdy nie wiedział, kiedy wyjdzie nowa wersja interpretera. Przez to też między innymi tak wolno nowe wersje dostają się na hostingi, czy do stabilnych wydań Debiana. Nie ma też żadnej ścieżki, dzięki której, można by informować o zmianach we wstecznej kompatybilności, przez co bardzo wiele czasu zajmuje usunięcie jakiś śmieci z poprzednich wersji (magic_quotes etc).

RFC proponuje:

  • cykliczny okres wydawniczy
  • demokratyczny proces podejmowania decyzji, wszelkie zmiany wprowadzane będą poprzez RFC, a decyzja podejmowana poprzez anonimowe głosowanie
  • typ zmian, jakie mogą być wprowadzane w poszczególnych rodzajach wydań
  • demokratyczny proces wybierania menedżerów wydań dla danego wydania
  • efektywniejsze użycie bugs.php.net do śledzenia zmian i błędów
  • skrócony czas między wydaniami poprawiającymi błędy
  • skrócony czas wprowadzania nowych rzeczy do języka
  • brak zrywania kompatybilności wstecznej dla wydań poprawiających błędy
  • wydania podglądowe, mające na celu przedstawienie jakiejś funkcjonalności szerszej publice

Więcej szczegółów znajdziecie w RFC, natomiast chciałem jeszcze pokrótce omówić rodzaje wydań.

  • Wydania serwisowe – zmiana numerów wersji wg porządku x.y.z -> x.y.z+1 – tylko poprawki błędów, konieczność zachowania kompatybilności wstecznej, nie można usuwać rozszerzeń
  • Małe wydania – x.y.z  -> x.y+1.z – poprawki błędów, nowe cechy języka, można usuwać rozszerzenia, konieczność zachowania kompatybilności wstecznej
  • Duże wydania – x.y.z -> x+1,y,z – wszystko to samo co w przypadku małych wydań z tą różnicą, że można zerwać kompatybilność wsteczną

Osobiście uważam, że ta propozycja to świetny pomysł. Na pewno przyśpieszy wydawanie nowych wersji, które dzięki przewidywalności daty pojawienia się będą szybciej adoptowane przez hostingi.

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