Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: batman, dodany: 20.08.2010 21:39, tagi: css

Rozpakowując ostatnie pudła, natrafiłem na trzy książki, które przez długi czas służyły mi pomocą. Aż się łezka w oku zakręciła, gdy je ponownie zobaczyłem. Z racji tematyki, były dosyć mocno eksploatowane, więc nie są pierwszej świeżości. Niemniej będą stanowić łakomy kąsek dla wszystkich zainteresowanych CSS. Książki, które dzisiaj mam zamiar wam oddać to:

CSS. Nieoficjalny podręcznik

HTML, XHTML i CSS. Biblia

CSS według Erica Meyera. Sztuka projektowania stron WWW

Jeśli chcecie otrzymać te książki, wystarczy, że napiszecie wiadomość korzystając z formularza, do którego link znajdziecie w prawej kolumnie, z odpowiedzią na pytanie ile MB zajmuje moja poczta na koncie Gmail. Utrudnieniem będzie tutaj fakt, iż ilość zajmowanego miejsca przez pocztę sprawdzę dopiero po zakończeniu konkursu. Na poprawne odpowiedzi czekam do końca poniedziałku (23.08.2010). Powodzenia.

Autor wpisu: cojack, dodany: 20.08.2010 20:10, tagi: php

PHP Dobra, trochę na speedzie jest pisany ten wpis, także może być w nim parę nieścisłości i niedociągnięć, ale mam nadzieje że poprawicie mnie w komentarzach. O co chodzi? Kod tutaj opisany poniżej nie jest mojego autorstwa, niektóre treści też zrzynam bezpośrednio z książki bo nie ma innych słów by to opisać. Jest prawie na żywca zdarty z książki „PHP 5 Zaawansowane Programowanie”, także odczepić się proszę, nie piszę że ja to napisałem, jak już ktoś coś wymyślił, to nie mam zamiaru wymyślać koła na nowo, tylko poskładać wszystko do kupy i połączyć by to działało. No dobra to jedziemy. Trochę nie po kolei, z tymi klasami, ale wybaczcie. Zaczynamy.

Słowem wstępu

Jest sobie taki interfejs w php, który się zwie Iterator, posiadający 5 metod, które informują foreach jak sobie ma radzić z argumentami niebędącymi tablicą. On zaś (co jeszcze dziwniejsze) dziedziczy po kolejnym interfejsie który się zwie Travesrable. To co poniżej zobaczycie w pełnej krasie, jest implementacją mapy. Ale do rzeczy, po cholerę nam takie pyszne rzeczy? Otóż jeżeli chcielibyśmy sobie obiektowo przechowywać elementy w zmiennej nie będącej tablicą i przeiterować jest foreachem, to jak to zrobicie? No to pokaże Wam jak to można było by zrobić:

 
/* odpowiedni foreach dla ($objIt as $key => $value ) */
$objIt = new MyIterator();
for( $objIt->rewind(); $obj->valid(); $objIt->next() ) {
  $key = $objIt->key();
  $member = $objIt->current();
}

Trochę mało to Wam mówi jeszcze, ale jak spojrzycie na dalszą część tekstu to się sami przekonacie.

Klasa Collection

Na omówieniu tej klasy, przysłużę się przykładem z książki.

Pisząc aplikację, często zachodzi potrzeba utworzeniu obiektów, które zawierają w sobie grupę innych obiektów. Na przykład w systemie obsługi dziekanatu potrzebna będzie klasa Student oraz Course. Obiekt Student zapewne będzie miał przypisany więcej niże jeden obiekt Course. Pierwsze nasuwające się rozwiążanie to dodanie tablicy obiektów Course jako zmiennej składowej obiektu Student.

Przykład z książki:

class Student {
  public $courses = array();
  //... itd
}
 
$objStudent = new Student( 124 );
foreach( $objStudent->courses as $objCourse ) {
  print $objCourse->name;
}

I wracamy do omówienia problemu:

Oczywiście gdyby taki sposób był najlepszy, to by nie było mowy o klasie Collection (trochę to przerobiłem :D )

Powyższe rozwiązanie sprawia kilka problemów. Po pierwsze, publiczny dostęp do tablicy obiektów Course nie jest zgodny z zasadą hermetyzacji. Nie ma możliwości weryfikacji zmian w tablicy czy modyfikacji stanu obiektu Student, gdyby zaszła taka potrzeba. Po drugie, taka implementacja nie określa porządku elementów w tablicy ani sposobu odnalezienia poszukiwanego obiektu. Po trzecie, i najważniejsze, aby zapewnić dostęp do informacji o kursach każdemu użytkownikowi klasy Student, informacje te muszą zostać pobrane z bazy danych za każdym razem, gdy pobierane są informacje o studencie. Oznacza to że nawet jeśli konieczne jest jedynie wyświetlenie imienia studenta, pobierane są wszystkie informacje o kursach. Niepotrzebnie zwiększa to obciążenie serwera baz danych i zmniejsza wydajność aplikacji. Klasa Collection została zaprojektowana tak, aby rozwiązać wszystkie te problemy. Zapewnia obiektową otoczkę dla tablicy i implementuje mechanizm leniwej konkretyzacji, czyli opóźnienia procesu tworzenia elementów kolekcji aż do czasu, gdy są one naprawdę potrzebne. Nazywa się ją „leniwą”, ponieważ decyzja o tym, kiedy tworzyć konkretne egzemplarze obiektów, jest podejmowana przez samą aplikację.

Dobra, o co ogólnie chodzi? Chodzi o to że nasza klasa Collection, jak sama nazwa wskazuje jest kolekcją obiektów, czyli dodajemy do niej obiekty, a ona zgrabnie je przechowuje w swoim ciele. I to by było na tyle z filozofią klasy Collection, żeby zbytnio nie przeciągać, to poniżej mamy już dwie gotowe klasy które razem z sobą współpracują, są na żywca wydarte z mojego FW, także BDT_Loader, jak po samej nazwie można się domyślić, wczytuje klasy, także nie mam tu nic więcej do dodania. Klasa BDT_Collection_Exception jest po prostu klasą wyjątków, i tu też nie mam nic więcej do dodania. W naszym przykładzie będziemy potrzebowali dwie klasy, Collection (BDT_Collection) oraz CollectionIterator (BDT_Collection_Iterator). Obiekt klasy CollectionIterator jest tworzony w metodzie getIterator. Pod ciałem klasy, krótki opis.

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

Autor wpisu: batman, dodany: 19.08.2010 08:00, tagi: css

Od czasu do czasu trafia się do pocięcia layout, którego autor wpadł na pomysł, że stopka będzie miała dynamiczną wysokość, zależną od ilości treści na stronie. Zmienną wysokość uzyskiwałem zazwyczaj przy pomocy prostego skryptu Javascript, jednak zawsze wiedziałem, iż nie tędy droga. Niestety terminy są nieubłagane i nigdy nie było czasu poszukać rozwiązania tego problemu. W końcu zabrałem się za zbadanie problemu i okazało się, że jego rozwiązanie jest o wiele bardziej banalne niż na początku sądziłem. Wszystko sprowadza się do ustawienia koloru tła nie dla stopki, a dla znacznika body. Oczywiście należy ustawić pierwotny kolor tła dla diva, będącego kontenerem strony. Przykładowy dokument
<div id="page-content">
 <div class="page">
  lorem ipsum
 </div>
</div>
<div id="footer">
 <div class="page">
  text 1 | text 2 | text 3
 </div>
</div>
oraz styl
body {
    background-color: #dbdbdb;
    /* margin oraz padding powinny zostać zresetowane w pliku reset */
    margin: 0;
    padding: 0;
}

#page-content {
    background-color: #ffffff;
    /* height jest tylko na potrzeby przykładu */
    height: 400px;
}

/* przykładowe ustawienie szerokości treści */
.page {
    width: 800px;
    margin: 0 auto;
}

Autor wpisu: batman, dodany: 17.08.2010 08:00, tagi: zend_framework

Dawno temu obiecałem noose’owi napisać tutorial na temat tłumaczenia tras w Zend Frameworku. Niestety dopadła mnie masa odciągaczy uwagi i z tygodnia zrobiło się wiele tygodni. Udało mi się w końcu pozbyć niektórych odciągaczy i zbadać oraz opisać wspomniany temat.

Wszystko zaczyna się w pliku Bootstrap.php. Należy stworzyć w nim metodę, która doda do rejestru obiekt z tłumaczeniami. W przykładach posłużę się tłumaczeniami opartymi na tablicach, nic nie stoi na przeszkodzie, aby skorzystać z innego adaptera.

protected function _initTranslate()
{
    $translate = new Zend_Translate(
        'array',
        array(
            'users' => 'uzytkownicy',
            'list' => 'lista',
            'title' => 'tytul',
            'news' => 'aktualnosci',
	    // przykladowe tytuly artykulow
            'title1' => 'tytul1',
            'title2' => 'tytul2'
        ),
        'pl'
    );

    $translate->addTranslation(
        array(
            'users' => 'benutzer',
            'list' => 'liste',
            'title' => 'titel',
            'news' => 'nachrichten',
	    // przykladowe tytuly artykulow
            'title1' => 'titel1',
            'title2' => 'titel2'
        ),
        'de'
    );

    $translate->setLocale('de');

    Zend_Registry::set('Zend_Translate', $translate);
}

Powyższa metoda doda do aplikacji dwa języki – polski oraz niemiecki (jeśli pomyliłem jakiś wyraz, proszę o korektę) oraz ustawi domyślny język na polski. Na koniec do rejestru dodany zostanie obiekt z tłumaczeniem. Dzięki temu wszystkie “podatne na tłumaczenie” elementy Zend Frameworka będą mogły z niego skorzystać.

Ustawienie aktualnego języka nie musi odbywać w Bootstrapie. Można to zmienić później, np w pluginie.

$translate = Zend_Registry::get('Zend_Translate');
$translate->setLocale('de');

Jedyne co pozostało, to stworzenie odpowiednich tras, co również można wykonać w Bootstrapie. Do wyboru są trzy rodzaje tras: dynamiczna, statyczna oraz mieszana.

protected function _initRouting()
{
    $this->bootstrap('frontController');
    $front = $this->getResource('frontController');
    $router = $front->getRouter();

    $dynamicRoute = new Zend_Controller_Router_Route(
        ':@controller/:@action/*',
        array(
            'controller' => 'index',
            'action' => 'index'
        )
    );

    $staticRoute = new Zend_Controller_Router_Route(
        '@news',
        array(
            'controller' => 'news',
            'action' => 'index'
        )
    );

    $mixedRoute = new Zend_Controller_Router_Route(
        '@title/:@nazwa',
        array(
            'controller' => 'index',
            'action' => 'index',
            'nazwa' => ''
        )
    );

    $router->addRoute('dynamicRoute', $dynamicRoute);
    $router->addRoute('staticRoute', $staticRoute);
    $router->addRoute('mixedRoute', $mixedRoute);
}

Trasa dynamiczna to taka, która korzysta z dynamicznych segmentów, np kontrolera i/lub akcji (oraz modułu jeśli są wykorzystywane). Statyczna trasa zawiera jedynie statyczne elementy adresu, czyli takie, które wskazują na jeden konkretny zasób. Mieszana trasa daje możliwość skorzystać ze statycznego wskazania na konkretny zasób oraz dynamicznej zmiany innych segmentów adresu.

W każdym z wyżej wymienionych przypadków, kluczowym elementem jest symbol @, znajdujący się przed nazwą “zmiennej”. Informuje on router, iż należy skorzystać z tłumaczeń. Router pobiera tłumaczenie dla aktualnie ustawionego języka i zwraca je w tym właśnie języku.

Trasę można przetestować korzystając z helpera widoku url

echo $this->view->url(
    array(
        'controller' => 'users',
        'action' => 'list'
    ),
    'dynamicRoute'
);

echo $this->view->url(
    array(),
    'staticRoute'
);

echo $this->view->url(
    array('nazwa' => 'title1'),
    'mixedRoute'
);

echo $this->view->url(
    array('nazwa' => 'title2'),
    'mixedRoute'
);

Powyższy kod wyświetli dla języka polskiego

/uzytkownicy/lista
/aktualnosci
/tytul/tytul1
/tytul/tytul2

a dla niemieckiego

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

Autor wpisu: batman, dodany: 16.08.2010 08:00, tagi: zend_framework

Wraz z dokumentacją Zend Frameworka, otrzymaliśmy zgrabnie napisany Quick Start. Dzięki niemu można w bardzo prosty sposób rozpocząć swoją przygodę z ZF. Pośród wszystkich dobrych rad jakich on udziela, jedna nie za bardzo przypadła mi do gustu – modele. Według przewodnika należy stworzyć trzy klasy, gdzie jedna jest modelem, druga odpowiada za dostęp do danych, a trzecia to mapper łączący dwie poprzednie. Podejście to nigdy mi się nie podobało, ponieważ wymagało ode mnie dodatkowego nakładu pracy, który tak naprawdę nie miał przełożenia na wygodę w późniejszym programowaniu. Dlatego też w moich projektach nie korzystam z mappera, a obiekt dostępu do danych inicjalizowałem w konstruktorze modelu.

Przez długi czas podejście to w zupełności mi wystarczało, jednak w przypadku dużych projektów powodowało sporo kłopotów. Każda, nawet najdrobniejsza zmiana w sposobie tworzenia obiektu dostępu do danych musi zostać wprowadzona we wszystkich klasach, korzystających z tego sposobu. Postanowiłem to zmienić. Pogrzebałem w manualu i znalazłem funkcję get_class. Dzięki niej jestem w stanie określić które “dziecko” utworzyło obiekt i na podstawie nazwy klasy, stworzyć właściwy obiekt dostępu db table.

Najlepszym wyjaśnieniem będzie kod. Oto on:

// klasa, po której dziedziczą modele
class App_Model
{
    /**
     * @var Zend_Db_Table_Abstract
     */
    protected $_dbTable = null;

    public function __construct()
    {
        $class = get_class($this);
        $classParts = explode('_', $class);
        $className = array_pop($classParts);
        array_push($classParts, 'DbTable', $className);
        $dbTableClassName = implode('_', $classParts);
        $this->_dbTable = new $dbTableClassName();
    }

    /**
     * @return Zend_Db_Table_Abstract
     */
    public function getDbTable()
    {
        if($this->_dbTable === null) {
            throw new Exception('There id no db table object');
        }
        return $this->_dbTable;
    }
}
// klasa modelu
class Application_Model_User extends App_Model
{
}
// klasa dostępu do danych
class Application_Model_DbTable_User extends Zend_Db_Table_Abstract
{
    protected $_name = 'users';
}

W momencie utworzenia obiektu Application_Model_User zostanie automatycznie stworzony obiekt Application_Model_DbTable_User.

Autor wpisu: JoShiMa, dodany: 15.08.2010 00:23, tagi: skrypty

Joomla! daje możliwość tworzenia własnych modułów bez zagłębiania się w strukturę skryptów. Ba, nawet bez znajomości PHP. Wystarczy do witryny dołączyć moduł Własny kod HTML i we wskazanym miejscy, na wskazanych podstronach pojawi się dokładnie to co chcemy. Do stworzenia modu, którego potrzebowałam wystarczyłoby to. Postanowiłam jednak wykorzystać okazję i na prostym przykładzie spróbować stworzyć [...]

Autor wpisu: cojack, dodany: 14.08.2010 19:09, tagi: sql

PostgreSQL Na początku chciałbym przeprosić blogera Wojciecha Soczyńskiego, za to iż miałem napisać o klasie interpretującej interfejs Iterator, wpis już jest w trakcie budowy, ale nie mogę się zabrać by go skończyć. Także wyczekuj ;) Z cyklu artykułów o PL/pgSQL, chciałbym przedstawić kolejną z możliwości tego języka proceduralnego w bazie danych PostgreSQL.

Pętle cd.

Miałem napisać o pętlach, w poprzednim wpisie, ale materiał jest na tyle obszerny że postanowiłem to przenieść i poświęcić im cały wpis. No to jedziemy.

Pętle jak nam ładnie pokazuje manual:

[ <<label>> ]
LOOP
    statements
END LOOP [ label ];

Proste co? A teraz, krótki opis, otóż każda pętla może zostać „nazwana”, czyli posiadać tzw. label ( z ang. etykietę ), po co? Po to gdy będziemy chcieli zakończyć pętle, a będziemy mieli zagnieżdżenie pętel, to w przypadku chęci wyjścia całkiem z wszystkich pętli, wystarczy podać nazwę pętli wyżej. Służy nam temu polecenie:

EXIT [ label ] [ WHEN boolean-expression ];

Dlaczego nie RETURN a EXIT? Otóż możemy równie dobrze użyć RETURN w pętli by z niej wyjść, ale słowo kluczowe RETURN mówi nam coś innego, zwróć. A co my zwracamy wychodząc z pętli? No nic, także te słowo jest mylne.

Wracając do pętli, może się dziwnie wydawać że nie wiadomo kiedy się ona skończy, gdyż nie jest podoba do żadnej z pętli znanych nam z języka php, ani to for, ani do … while, ani while itd. No właśnie, gdybyśmy nie mieli żadnego warunku w pętli kończącego ją, to dostalibyśmy pętlę nieskończoną. Dlatego taka pętla musi posiadać w sobie warunek skończenia. Musimy na własną rękę inkrementować (itp..) jakaś wartość i sprawdzać ją w pętli. Otóż samej pętli LOOP to uwierzcie mi lub nie, to rzadko będziecie używać. No jest sama w sobie mało przydatna.

Iteracja tablicy elementów

Definicja pętli:

[ <<label>> ]
FOR name IN [ REVERSE ] expression .. expression [ BY expression ] LOOP
    statements
END LOOP [ label ];

Tu jest moc, ukłony dla dev z postgre za wskaźniki. Dzięki językowi proceduralnemu PL/pgSQL, nie musimy się troszczyć o deklaracje wskaźników w pętli i ich wykorzystywanie, są one automatycznie definiowane i używane przez silnik bazy. Dobre co? W postgresie mamy typy tablicowe. Deklaracja jest bardzo podobna jak w innych językach:

  • INT[]
  • VARCHAR[]

I tak dalej, dobra dajmy na to że mamy funkcję której jednym z argumentów jest właśnie np VARCHAR[], co lepsze możemy zdefiniować argument funkcji jako ANYARRAY, i dzięki temu, możemy do takiej funkcji przesyłać tablicę różnego typu, bez potrzeby martwienia się o to, w jaki sposób to przesyłamy, i tak później przy wrzucaniu danych do bazy musimy rzutować typ. Wracając do sedna, to mamy taką tablice, która składa się np z 6 elementów. Indeksy tablic w postgresql są numerowane od 1 :D Też sobie wymyślili, no ale dobra. Mamy taką tablice, i dajmy na to że składa się z 240 wierszy. Czyli jest 240 indeksów. Albo i nie, ponieważ taka tablica może być dynamiczna i w sumie nie wiemy jak wielka jest ta tablica, wiemy jedynie że będzie posiadać 6 elementów jeden wiersz. I jak to zrobić? Patrzcie:

FOR i IN ARRAY_LOWER( "_someVar", 1 ) .. ARRAY_UPPER( "_someVar", 1 )
  LOOP
 
    INSERT INTO
      "someTable"
    (
      ... -- jakieś tam kolumny
    )
    VALUES
    (
      "_someVar"[ i ][ 1 ]::INT,
      "_someVar"[ i ][ 2 ]::VARCHAR,
      "_someVar"[ i ][ 3 ]::BOOLEAN,
      "_someVar"[ i ][ 4 ]::BIT,
      "_someVar"[ i ][ 5 ]::NUMERIC,
      "_someVar"[ i ][ 6 ]::BYTEA,
    );
 
  END LOOP;

Co to jest i ? i jest numerem indeksu, nie musimy go definiować w bloku DECLARE, jest on w biegu definiowany.

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

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