Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: batman, dodany: 28.11.2014 12:00, tagi: php

Przez bardzo długi czas byłem zapalonym zwolennikiem Zend Frameworka. Prawie każdy projekt PHP, jaki wychodził spod mojej ręki, oparty był o ten framework. Czas mijał, kolejne projekty powstawały, a framework się starzał, więc z ogromną niecierpliwością wypatrywałem kolejnej jego wersji. Niestety wraz z pojawiającymi się betami i RC, zniechęcałem się do tego frameworka coraz bardziej. Problemy z ZF2 spowodowały, iż zacząłem rozglądać się za alternatywą. Po kilku miesiącach testów różnych frameworków, wygrał Laravel.

Bardzo zadowolony ze swojego wyboru, zacząłem tworzyć kolejne projekty w tym frameworku i każda kolejna realizacja, utwierdzała mnie w przekonaniu, że był to dobry wybór. Najnowszą stabilną wersję (4.2) poznałem całkiem dobrze, gdy doszły mnie informacje, że niedługo światło dzienne ujrzeć ma wersja 5. Jak się okazało, termin listopadowy nie zostanie dotrzymany i możemy spodziewać się wydania Laravela 5 dopiero w styczniu, niemniej już teraz warto wiedzieć czego się spodziewać.

  1. Nowa struktura katalogów
  2. Nowe generatory
  3. Adnotacje route'ów
  4. Adnotacje zdarzeń
  5. Kontrakty
  6. Formularze
  7. Helpery
  8. Middleware
  9. Harmonogramowanie zadań

Nowa struktura katalogów

W obecnej wersji frameworka, zdecydowana większość kodu znajduje się w katalogu app. Znajdziemy w nim konfigurację, testy, kontrolery, wersje językowe, magazyn na pliki, cache, sesje, itp. Wszystkie te elementy są niezbędne do działania aplikacji, jednak nie koniecznie powinny znajdować się w katalogu aplikacji. Twórcy frameworka doszli do takich właśnie wniosków i przenieśli większość tych katalogów do głównej gałęzi projektu. Teraz w katalogu app znajdują się jedynie kontrolery, modele, klasy odpowiedzialne za konsolową część aplikacji (wcześniej znajdowały się w katalogu commands, teraz jest to Console) oraz providery . Zmiana zaszła również w filtrach, które nie są już przechowywane w jednym pliku. Zamiast tego, każdy filtr to osobna klasa. Nowa struktura katalogów wygląda następująco:

Drzewo katalogów

Kolejną nowością w Laravel 5 jest obecność folderu Middleware. Przy pomocy klas tego typu będziemy w stanie napisać wrappery dla requestów i odpowiedzi na nie. Upraszczając nieco ich rolę, będzie to nowy sposób tworzenia filtrów, które nie są bezpośrednio związane z logiką aplikacji.

Jeśli przyjrzeliście się powyższej grafice, na pewno zauważyliście, że pojawił się folder resources. Od wersji 5 będzie on miejscem, w którym przechowywane będą widoki, pliki językowe oraz zasoby takie jak np. pliki sass.

Nowe komendy wiersza poleceń

Wiersz poleceń we frameworku Laravel doskonały nie jest. Mimo iż wiele przy jego pomocy można uzyskać (na pewno więcej niż w przypadku Zend Frameworka), do doskonałości jeszcze mu trochę brakuje. Piąta wersja frameworka wprowadza kilka zmian, dzięki którym łatwiej się będzie poruszać w konsoli. Najbardziej rzucającą się w oczy zmianą jest utowrzenie wspólnej przestrzeni dla generatorów. Od piątej wersji dostępna będzie komenda make, z poziomu której będziemy tworzyć kontrolery, migracje, itd. Pojawił się generator schedule pozwalający na ustawienie zadań cyklicznych (napiszę o tym więcej przy okazji jednego z kolejnych wpisów poświęconych temu frameworkowi). Dodane zostały również kolejne komendy do zarządzania route'ami. Również publikacja została zaktualizowana i teraz publikowanie zasobów czy plików konfiguracyjnych zostało przeniesione do publish:.

Adnotacje route'ów

Nie jestem fanem adnotacji, zwłaszcza w PHP, ponieważ zaciemniają one obraz aplikacji, a źle używane mogą spowodować ból głowy u każdej osoby, która chce debugować nie swój kod. Z drugiej strony, jeśli mamy bardzo dużą aplikację z ogromną ilością route'ów, trzymanie ich wszystkich w jednym pliku na pewno spowoduje bałagan. Niestety złotego środka nie ma, więc wszystko zależy od zdrowego rozsądku programistów oraz od narzędzi z jakich korzystają. Laravel 5 pozwala tworzyć adnotacje w kontrolerach i na ich podstawie generuje route'y do naszej aplikacji.

Korzystanie z adnotacji jest banalnie proste. W podstawowej wersji wygląda następująco:

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

Autor wpisu: bastard13, dodany: 25.11.2014 21:25, tagi: design

porozmawiajmy o diagramach

Zdaję sobie sprawę, że pewnie wielu z Was odrzuca na samą myśl o UML-ach, ale chcąc nie chcąc, na pewnym etapie Waszej kariery się z nimi spotkacie i możliwe, że nawet sami będziecie musieli je wykorzystać do pracy twórczej. Dlaczego tylu programistów czuje awersję do diagramów? Cóż, przypuszczam, że wynika to z pewnej niechęci do tego, czego nie znamy, w tym konkretnym przypadku – do języka, który jest nam obcy. Bo tym właśnie jest UML, językiem, który nie wszyscy rozumiemy, którym nie wszyscy mówimy. Dzisiaj jednak nie o tym. Czytaj więcej »

Autor wpisu: Łukasz Socha, dodany: 18.11.2014 17:50, tagi: php

W poprzednim wpisie opisałem technikę ataku SQL injection. W kolejnym artykule cyklu pokażę na czym polega równie popularny atak XSS i jak się przed nim uchronić. Trochę teorii Cross-site scripting (XSS) polega na osadzeniu w treści atakowanej strony kodu (zazwyczaj JavaScript), który wyświetlony przez innego użytkownika może doprowadzić do wykonania przez niego niepożądanych akcji. Jedną […]

Autor wpisu: Kamil Adryjanek, dodany: 15.11.2014 16:01, tagi: php, symfony2

bc_circle_symfony2In my recent project i had great opportunity to work together with powerful Symfony2 and amazing ExtJS5 frameworks. In the next few entries i will try to show you how to setup and configure Symfony2 application to serve REST API, than how to build ExtJS UI that will communicate with our REST API and finally how to setup basic authentication for REST API and ExtJS application… and maybe more.

Post RESTful ExtJS 5 and Symfony2 REST API: Symfony2 pojawił się poraz pierwszy w Kamil Adryjanek.

Autor wpisu: Łukasz Socha, dodany: 12.11.2014 15:31, tagi: php

SQL injection jest techniką ataku starą jak świat. Mimo tego wciąż jest niestety dość powszechną i prostą metodą ataku na strony www (nawet na te największe jak portale). Dzieje się tak, ponieważ przy tej metodzie najsłabszym ogniwem jest programista. Zobacz na czym polega ten atak i jak się przed nim zabezpieczyć. Trochę teorii SQL injection […]

Autor wpisu: Piotr Śliwa, dodany: 10.11.2014 14:42, tagi: php

Na początku nakreślę problem. Mamy klasę Product oraz interfejs ProductRepository.

interface ProductRepository {  
    function save(Product $product);
    function delete(Product $product);
    function findOne($id);
    function findAll();
    //...
}

ProductRepository może mieć kilka implementacji, np.:

  • DoctrineProductRepository - zapisywanie obiektów do bazy danych z wykorzystaniem EntityManagera z Doctrine, nasza "rzeczywista" implementacja używana przez aplikację
  • InMemoryProductRepository - trzymanie obiektów w pamięci, klasa wykorzystywana np. do testów funkcjonalnych kontrolerów lub serwisów - nie chcemy angażować bazy danych aby testy były szybsze, prostsze do konfiguracji itp.

Obie implementacje muszą działać tak samo, tak więc powinny mieć taki sam zestaw testów.

Rozwiązanie problemu

Jednym z rozwiązań jest napisanie abstrakcyjnej klasy testu, testowany obiekt oraz tworzenie danych testowych są w formie metod abstrakcyjnych.

abstract class ProductRepositoryTest extends PHPUnit_Framework_TestCase {  
    protected $repository;

    protected function setUp() {
        $this->repository = $this->createSUT();
    }

    //tworzenie obiektu testowanego
    abstract protected function createSUT();

    //umieszczanie Produktu w źródle danych    
    abstract protected function insertProduct(Product $product);

    /**
     * @test
     */
    public function givenExistingProduct_whenItIsDeleted_thenProductCouldNotBeFound() {    
        //given        
        $product = new Product(...);
        $this->insertProduct($product);

        //when        
        $this->repository->delete($product);
        $actualProduct = $this->repository->findOne($product->getId());

        //then        
        $this->assertNull($actualProduct);
    }

    //...
}

W konkretnych podklasach nadpisujemy metody createSUT i insertProduct.

Jest jednak problem... Klasa testu operującego na rzeczywistej bazie danych niekoniecznie rozszerza bezpośrednio PHPUnit_Framework_TestCase. Klasa bazowa dla testów na bazie dostarcza tworzenie połączenia, obtacza testy w transakcję która na końcu jest rollbackowana itp. Tak więc występuje potrzeba wielodziedziczenia, DoctrineProductRepositoryTest powinien rozszerzać zarówno ProductRepositoryTest oraz DoctrineTestCase. Nie jest to możliwe, chyba że zamienimy ProductRepositoryTest w trait.

/**
 * @mixin \PHPUnit_Framework_TestCase
 */
trait ProductRepositoryTest {  
    //to samo co w klasie ProductRepositoryTest
    //w poprzednim listingu
}

Adnotacja @mixin jest interpretowana przez PhpStorm tak, jakby ProductRepositoryTest "rozszerzał" PHPUnit_Framework_TestCase, dzięki czemu poprawnie działa podpowiadanie metod (np. asercji).

Możemy zatem wykorzystać trait do stworzenia testu dla DoctrineProductRepository.

class DoctrineProductRepositoryTest extends DoctrineTestCase {  
    use ProductRepositoryTest;

    protected function createSUT() {
        return new DoctrineProductRepository($this->em);
    }

    protected function insertProduct(Product $product) {
        $this->em->persist($product);
        $this->em->flush();
    }
}

Podobnie by wyglądał InMemoryProductRepositoryTest. Gdy dopisujemy jakiś test do ProductRepositoryTest, automatycznie będzie on wykonywany dla dwóch różnych implementacji ProductRepository. Minusem tego rozwiązania może być zaburzenie pętli TDD. Pisząc jeden test tak naprawdę mamy w rezultacie dwa czerwone testy - czyli w następnym kroku musimy zaimplementować dwie funkcjonalności dla dwóch całkowicie różnych klas, aby na nowo mieć przed oczami tylko zieleń. Pętla "Red -> Green -> Refactor" zamienia się w "Red x2 -> Green, Red -> Green x 2 -> Refactor x 2". Można temu przeciwdziałać wstawiając test najpierw do DoctrineProductRepositoryTest, a po zaimplementowaniu funkcjonalności i refaktoryzacji, przenieść go do ProductRepositoryTest.

Mając na początku interfejs ProductRepository i pisząc pierwszą implementację (np. DoctrineProductRepository), nie powinniśmy zaczynać od razu od tworzenia cechy/klasy abstrakcyjnej ProductRepositoryTest, gdyż tak naprawdę nie wiemy czy ona będzie potrzebna. Metody testowe należy umieszczać bezpośrednio w DoctrineProductRepositoryTest, a gdy będziemy mieć drugą implementację ProductRepository, powinniśmy dokonać refaktoryzacji wydzielenia cechy (trait) bądź klasy.

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

Autor wpisu: Łukasz Socha, dodany: 07.11.2014 19:04, tagi: jquery

Czym jest pasek ładowania nie muszę chyba tłumaczyć :). Jest to bardzo przydatne narzędzie, gdy wczytujemy większą ilość danych co zabiera trochę czasu – dzięki temu użytkownik wie, że „coś” się dzieje. Pokażę tobie jak stworzyć taki pasek za pomocą dwóch klas CSS oraz jednej funkcji jQuery. Na początek stwórzmy szkielet dokumentu HTML: Zwróć uwagę […]
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.