Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

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...

Autor wpisu: batman, dodany: 13.08.2010 23:11, tagi: javascript, jquery

Ekipa odpowiedzialna za jedną z najlepszych bibliotek Javascript, powiadomiła o starcie nowego projektu – jQuery Mobile. Jego celem jest przygotowanie jQuery do poprawnego działania w przeglądarkach mobilnych. Co najważniejsze projekt ten zakłada, że nie będzie wydzielana specjalna wersja biblioteki, dzięki czemu nie trzeba martwić się o dołączenie odpowiedniej biblioteki zależnej od platformy.

Równolegle do prac nad podstawową biblioteką, trwają prace na jQuery UI. Wprowadzane zmiany mają na celu umożliwienie korzystanie z jQuery UI na większości przeglądarek mobilnych. Oprócz zmian umożliwiających wykorzystanie już istniejących kontrolek, w nowej wersji biblioteki znajdą się nowe kontrolki przygotowane specjalnie z myślą o urządzeniach przenośnych.

Wraz ze zmianami w podstawowej bibliotece oraz UI, pojawią się modyfikacje w ThemeRoller, narzędziu do tworzenia dedykowanych stylów. Programiści tworzący mobilne wersje stron będą mogli w kilka chwil dopasować wygląd kontrolek do aktualnie tworzonych stron.

źródło: blog.jquery.com

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

Nie od dziś wiadomo, że PHP obsługuje operacje wejścia/wyjścia. Nic nie stoi na przeszkodzie, aby pisać aplikacje konsolowe, które “rozmawiają” z użytkownikiem. Generalnie wszystko sprowadza się do jednego wiersza kodu, który pobiera wpisany przez użytkownika tekst, a następnie zwraca go na przykład do zmiennej.

$input = trim(fgets(STDIN));
echo $input;

Dane od użytkownika można pobierać w pętli, dzięki czemu istnieje możliwość przeprowadzenia dłuższej konwersacji.

while(true) {
 echo 'Introduce yourself (to quit, type Q): ';
 $input = trim(fgets(STDIN));
 if($input === 'Q') break;
 echo "Your name is: " . $input . PHP_EOL;
}

echo 'Bye' . PHP_EOL;

Wprawdzie powyższy skrypt będzie w kółko nas pytał o imię, ale i tak jest to spory postęp w stosunku do pierwszego skryptu. Idąc dalej, można udostępnić użytkownikowi możliwość wywoływania funkcji (uwaga! kod jest nieco zabałaganiony – jego celem jest tylko prezentacja możliwości komunikacji z użytkownikiem).

echo 'Type function name to run (Q to quit): ';

$functionToCall = null;
$args = array();

while(true) {
 $input = trim(fgets(STDIN));
 if($input === 'Q') break;
 if($input === 'F') {
  echo call_user_func_array($functionToCall, $args);
  echo PHP_EOL;
  $functionToCall = null;
  $args = array();
  echo 'Type function name to run (Q to quit): ' . PHP_EOL;
  continue;
 }

 if($functionToCall === null) {
  $functionToCall = $input;
  echo 'Type function arg (F to finish): ';
 }
 else {
  echo 'Type function arg (F to finish): ';
  $args[] = $input;
 }
}

echo 'Bye' . PHP_EOL;

function Foo($arg1, $arg2)
{
 return 'Hello from Foo! - args: ' . $arg1. ', ' . $arg2;
}

function Bar()
{
 return 'Hello from Bar!';
}

Na koniec pozostawiłem ciekawą funkcjonalność – przekazywanie parametrów do skryptu.

echo 'Number of args passed: ' . $argc;
echo PHP_EOL;
echo 'Args passed: ';
print_r($argv);

Powyższy kod po wywołaniu go z wiersza poleceń z dodatkowymi parametrami

php skrypt.php -a -b "tekst ze spacjami" -c

wyświetli

Number of args passed: 5
Args passed: Array
(
    [0] => skrypt.php
    [1] => -a
    [2] => -b
    [3] => tekst ze spacjami
    [4] => -c
)

Pierwszym elementem tablicy jest nazwa wywołanego skryptu, kolejnymi – oddzielone spacjami parametry. Jeśli zmienne $argv oraz $argc z jakiegoś powodu nie zawierają żadnych danych, proponuję skorzystać z ich odpowiedników $_SERVER[‘argv’] oraz $_SERVER[‘argc’].

W ten oto prosty sposób można rozmawiać z PHP.

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