Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: sokzzuka, dodany: 15.06.2010 00:02, tagi: zend_framework, php

Kaskadowość większości ludzi związanymi z web developementem pewnie kojarzy się z kaskadowymi arkuszami styli (CSS). Jest to poniekąd słuszne skojarzenie, ponieważ daje pewne wyobrażenie czym ona jest.

W CSS-ach kaskadowość znaczy nie mniej, nie więcej tyle, że właściwości stylu zdefiniowane dla elementów wyżej w drzewie dokumentu propagują się w dół drzewa aż do momentu kiedy nie zostaną nadpisane przez właściwości elementów niżej w hierarchii.

W PHP istnieje technika oparta na podobnych założeniach, realizowana dzięki magicznej funkcji __autoload. Na czym więc polega ? Załóżmy, że mamy pewną hierarchię klas: --A

---B ----E

---C ----D ----E Każda z tych klas dziedziczy bezpośrednio lub pośrednio z klasy A. Załóżmy teraz, że chcielibyśmy zmienić zachowanie wszystkich klas dziedziczących z A. Jednym z rozwiązań jest po prostu modyfikacja odpowiedniej metody z klasy A, jest to oczywiście najlepsze wyjście, z kilkoma wyjątkami, z których najpoważniejszym jest to, że klasa A należy do pewnej zewnętrznej biblioteki.

Klasycznym przykładem tego typu są formularze dziedziczące z Zend_Form. Mamy już gotowych n-bardzo dużo formularzy, jednak nagle okazało się, że trzeba im globalnie coś zmienić. Nie możemy za bardzo modyfikować samego Zend_Form-a ponieważ należy on do zewnętrznej biblioteki i w razie modyfikacji go, będzie problem z migracją do nowszych wersji frameworka.

Zmiana tych n-bardzo wielu klas, aby dziedziczyły z innej pośredniej klasy, która dziedziczy z Zend_Form będzie procesem bardzo pracochłonnym.

W tym momencie z pomocą przychodzi nam kaskadowość. Dzięki niej będziemy mogli podmienić oryginalną klasę Zend_Form, bez modyfikacji jej kodu.

Po pierwsze będzie nam potrzebna odpowiednia struktura katalogów: -test_cascading --base ---application ----forms ---library ----Zend --modified ---library ----Zend

Naszą zmodyfikowaną klasę Zend_Form umieścimy w podkatalogu “modified” w takiej samej ścieżce jak w katalogu “base”.

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

Autor wpisu: batman, dodany: 13.06.2010 14:00, tagi: zend_framework

Razem z Zend Framework otrzymujemy kilka ciekawych helperów akcji. Jeden z nich opisałem we wpisie zatytułowanym Zend Framework i AjaxContext. Innym ciekawym helperem jest FlashMessenger.

Jego działanie polega na jednokrotnym wyświetleniu użytkownikowi wiadomości o pewnym zdarzeniu, np pomyślnym zapisaniu danych w bazie. Po odświeżeniu strony z wiadomością, nie zostanie ona wyświetlona ponownie (chyba że znów będzie miało miejsce odpowiednie zdarzenie).

Korzystanie z FlashMessengera jest bardzo proste i sprowadza się do kilku linii kodu.

class JakisController extends Zend_Controller_Action
{
	protected $_flashMessenger = null;

	public function init()
	{
		// inicjalizacja helpera
		$this->_flashMessenger = $this->_helper->getHelper('FlashMessenger');
	}

	public function indexAction()
	{
		// pobranie wiadomości błyskawicznych i przekazanie ich do widoku
		$this->view->messages = $this->_flashMessenger->getMessages();
	}

	public function editAction()
	{
		// dodanie wiadomości
		$this->_flashMessenger->addMessage('Treść wiadomości błyskawicznej');
	}
}

Samo wyświetlenie wiadomości w widoku jest banalnie proste

<?php if(count($this->messages) > 0): ?>
	<ul id="messages">
		<?php foreach($this->messages as $message): ?>
			<li><?php echo $message; ?>
		<?php endforeach; ?>
	</li></ul>
<?php endif; ?>

Powyższy kod to tylko przykład. Najlepszym rozwiązaniem będzie zamieszczenie go w helperze widoku.

W niektórych przypadkach obraz wart jest więcej niż tysiąc słów. Tak jest też w tym przypadku. Demo wiadomości błyskawicznych możecie zobaczyć pod adresem http://demo.wilgucki.pl/flashmessenger

Autor wpisu: batman, dodany: 10.06.2010 11:28, tagi: zend_framework

W jednym z poprzednich wpisów poświęconych Zend_Form opisałem sposób dekorowania formularzy w Zend Framework. Niestety poważną wadą tej metody było powtarzanie kodu, co w przypadku rozbudowanej aplikacji nie jest najlepszym pomysłem. Dobrym wyjściem z tej sytuacji będzie zastosowanie klasy bazowej dla naszych formularzy, dziedziczącej po Zend_Form. Klasa ta będzie odpowiedzialna za ustawienie dekoratorów oraz wyrenderowanie formularza.

Przykładowy formularz wygląda następująco

class Application_Form_Example extends Batman_Form
{
	protected function _renderForm()
	{
		$this->setName('form-example');

		$name = new Zend_Form_Element_Text('name');
		$name->setLabel('Nazwa');
		
		$submit = new Zend_Form_Element_Submit('btn_save');
		$submit->setLabel('Zapisz');
		
		$this->addElement($name);
		$this->addElement($submit);
	}
}

Jak widać jedyną różnicą w stosunku do standardowego podejścia jest zmiana nazwy metody, w której znajduje się kod odpowiedzialny za formularz. Ponadto metoda ta nie zawiera kodu odpowiedzialnego za dekoratory.

Cała magia dzieje się w klasie Batman_Form

abstract class Batman_Form extends Zend_Form
{
	abstract protected function _renderForm();
	
	public function init()
	{
		$this->_renderForm();
		$this->_resetDecorators();
	}
	
	protected function _resetDecorators()
	{
		$this->clearDecorators();
		$this->addDecorator('FormElements')
			 ->addDecorator('HtmlTag', array('tag' => 'div'))
			 ->addDecorator('Form');

		$this->setElementDecorators(array(
			array('ViewHelper'),
			array('Errors'),
			array('Label'),
			array('HtmlTag', array('tag' => 'div', 'class' => 'element-group'))
		));
        
		// dodatkowe operacje na konkretnych elementach formularza
		// np zmiana nazwy klasy css dla przycisków
		foreach($this->getElements() as $element) {
			if($element instanceof Zend_Form_Element_Submit) {
				$element->removeDecorator('Label');
				$element->addDecorator('HtmlTag', array('tag' => 'div', 'class' => 'submit-group'));
			}
		}
	}
}

Klasa przesłania metodę init, która jest wywoływana z konstruktora Zend_Form. W metodzie tej wywoływana jest z kolei metoda klasy potomka o nazwie _renderForm oraz metoda _resetDecorators. Konstrukcja ta posiada dwie zalety. Po pierwsze klasa formularza odpowiada jedynie za utworzenie elementów. Po drugie nie musimy powielać kodu odpowiedzialnego za dekoratory. Dla zachowania porządku oraz dla zapewnienia poprawności kodu, klasa Batman_Form jest klasą abstrakcyjną, zawierającą abstrakcyjną metodę _renderForm.

A co jeśli w jednym formularzu mają być użyte inne dekoratory? Nic prostszego. Wystarczy w klasie formularza przesłonić metodę _resetDecorators i napisać własny kod odpowiedzialny za dekoratory.

Autor wpisu: sokzzuka, dodany: 09.06.2010 21:29, tagi: php

Witam w drugiej części tutoriala. Tematem na dziś będzie łączenie się z bazą MySql i wykonywanie prostych zapytań typu insert czy select. Pierwszą rzeczą jaką trzeba wykonać by móc podłączyć się do bazy MySql jest ściągnięcie sterownika. Paczki dla *nixów są na stronie projektu.Dostępne są też instalki dla Windowsa.

Po zainstalowaniu drivera tworzymy dwa pliki. Pierwszy będzie się nazywał common_db, będziemy go includować za każdym razem gdy będziemy coś robić z bazą, w pliku tym jest funkcja connect, która utworzy nam połączenie z odpowiednimi parametrami:

import MySQLdb
 
def connect():
    oDb = MySQLdb.connect (host="localhost", user="root", db="test")
    return oDb

Dla porównania plik php-owy, który robi dokładnie to samo:

$oDb = new PDO('mysql:dbname=test;host=127.0.0.1', 'root');

Natomiast drugi plik nazywa się test_insert.py , w którym mamy insertowanie danych do bazy:

import common_db
 
oDb = common_db.connect()
content = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
 
def test(path):
    global oDb
    global content
 
    oDb.begin()
    cursor = oDb.cursor()
 
    result = ''
    for i in range(0,1000):
        cursor.execute ("INSERT INTO test1(content) values ('"+content+"')")
        result += "inserted row number"+str(i)+"<br/>"
 
    oDb.commit()
    cursor.close()
    oDb.close ()
 
    return result

Ekwiwalent php:

require 'lib/common_db.php';
 
$sContent = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ';
 
set_time_limit(0);
 
for ($i=0; $i < 1000; $i++){
    $sQuery = "INSERT INTO test1(content) values ('$sContent')";
    $oDb->exec($sQuery);
    echo "inserted row number $i <br/>";
}

Są to skrypty do testów obciążeniowych więc nie dziwcie się, że zapytania tam idą w pętli, oczywiście globale też są złe ;) . Driver Pythonowy nie ma defaultowo ustawionego auto-commita więc wszystkie zapytania typu insert, update, delete trzeba przeprowadzać w transakcji.

Pobieranie z bazy – test_select.py:

import common_db
import random
 
oDb = common_db.connect()
 
def getRandomId(table):
    global oDb
    cursor = oDb.cursor()
    sQuery = 'select max(id) as max, min(id) as min from '+table;
    cursor.execute(sQuery)
    iMax, iMin = cursor.fetchone()
 
    return random.randint(int(iMin),int(iMax))
 
def test(path):
    global oDb
    cursor = oDb.cursor()
    cursor.execute('select * from test1 where id = %s',getRandomId('test1'))
    return cursor.fetchall()

Ekwiwalent php-owy

require 'lib/common_db.php';
function getRandomId($table) {
    global $oDb;
    $sCountStatement = 'select max(id) as max, min(id) as min from '.$table;
    $oCountStatement = $oDb->query($sCountStatement);
    list( $iMin,$iMax ) = $oCountStatement->fetch(PDO::FETCH_NUM);
 
    return rand($iMin,$iMax);
}
 
$sStatement = 'select * from test1 where id = ?';
$oQuery = $oDb->prepare( $sStatement );
 
$iId = getRandomId('test1');
 
$oQuery->execute(array($iId));
$aResult = $oQuery->fetch(PDO::FETCH_ASSOC);
 
echo($aResult['content']);

Aby przetestować powyższy kod, należy utworzyć w katalogu z projektem z pierwszej części tutorialu ww. pliki, uruchomienie jak poprzednio – http://localhost/py/nazwa_pliku_z_przykladem.py.

Jeszcze na koniec taka mała dygresja, w pierwszej części opisałem jak obsługiwać błędy, niestety informacje, które dostawaliśmy z wyjątku były dość skąpe i rzadko pozwalały zidentyfikować problem.

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

Autor wpisu: sokzzuka, dodany: 09.06.2010 18:12, tagi: php

Dzisiejszy post będzie o dwóch przydatnych funkcjach, których dość nagminnie używam. Nie widziałem ich jeszcze nigdzie w internecie za bardzo więc stwierdziłem, że podzielę się nimi z publiką, a nuż się komuś przydadzą. Pierwsza funkcja jest pewnym ulepszeniem var_dump. Pewnie nie raz się Wam zdarzyło, że zostawiliście gdzieś samotnego var_dumpa w kodzie i nie mogliście dość do tego gdzie on się podziewa.

Ta funkcja przy wywołaniu podaje nazwę pliku i linie w której została wywołana, jest to podawane nad dumpem. Z innych ekstrasów dołącza ona formatowanie dumpowanej zmiennej (ta funkcjonalność ma już Zend_Debug), więc wynik jest bardziej czytelny. A więc Pani i Panowie oto ona wraz z przykładem:

function dump() {
    $aTrace = debug_backtrace(false);
    $aArgs = func_get_args();
    echo "<code style='white-space: pre'>";
    echo "Line {$aTrace[0]['line']} \n";
    echo "File {$aTrace[0]['file']} \n";
    call_user_func_array('var_dump',$aArgs);
    echo "</code>";
}
dump('test');
 
/*wynik
Line 4
File D:\www\projekt\index.php
string(4) "test"
*/

Natomiast druga funkcja jaką chciałem przedstawić, to funkcja zamieniająca polskie znaki diakrytyczne na ich odpowiedniki bez ogonków – przydatna przy tworzeniu przyjaznych url-i.

function ascii_encode($input, $encoding = 'utf-8'){
$sResult = iconv($encoding,'ascii//translit', $input);
$aSearch = array(',',"'");
$sResult = str_replace($aSearch, '', $sResult);
return $sResult;
}
 
if(PHP_OS === 'WINNT'){
    setlocale(LC_ALL,'polish');
} else {
    setlocale(LC_ALL,'pl_PL.utf8');
}
 
echo ascii_encode('zażółć gęślą jaźń');
//wynik: zazolc gesla jazn

Bardzo ważną rzeczą w przypadku funkcji ascii_encode jest wcześniejsze wywołanie setlocale, inaczej konwersja nie przebiegnie pomyślnie, co więcej jak zauważyliście inaczej ustawia się locale dla windowsa a inaczej dla całej reszty.

Autor wpisu: Zyx, dodany: 08.06.2010 21:26, tagi: php

Pierwsza rewolucja PHP miała miejsce, gdy programiści odkryli słowo framework i zaczęli tak oto zwanych systemów masowo używać. PHP jest jednym z nielicznych języków, gdzie rynek nie został zdominowany przez "jedyny słuszny" framework. Jedni twierdzą że to wada, inni że zaleta, ponieważ pozwala wypróbować wiele różnych rozwiązań. Ostatnio jednak powoli pojawiają się nowe trendy programistyczne, z których już teraz zaczynają wykluwać się frameworki nowej generacji, które będą podstawą drugiej rewolucji.

Autor wpisu: sokzzuka, dodany: 08.06.2010 09:47, tagi: php

Dzisiaj mija 15 lat od wypuszczenia w świat przez Rasmusa Lerdorfa pierwszej wersji PHP. Więc sto lat niech żyje nam. A tu mały fragmencik kodu z tej archaicznej wersji:

<?
      Function Sum $a,$b,$c (
        return($a+$b+$c);
      );
 
      echo Sum($a,$b,$c);
    >

Dla chętnych na więcej sampli kodu z prehistorycznego PHP polecam manual tej właśnie wersji.

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