Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: batman, dodany: 04.02.2010 20:01, tagi: zend_framework, jquery

Podstawową biblioteką Javascript dostępną w Zend Framework jest Dojo. Wybór ten został przyjęty co najmniej chłodno i był szeroko komentowany przez programistów. Zend nie czekał długo z wydaniem nowego komponentu – ZendX_JQuery. Wybrano jQuery, ponieważ biblioteka ta była wymieniana jako ta, która powinna zostać wybrana zamiast Dojo. ZendX_JQuery nie jest tak rozbudowany jak Zend_Dojo, co nie

Autor wpisu: piotrooo89, dodany: 30.01.2010 22:15, tagi: javascript, sql, jquery

W pierwszej części poradnika http://piotrooo.com/2010/01/kalendarz-google-w-jquery-cz-1/ pokazałem jak generować kalendarz, jak dodawać nowe zdarzenia i wyświetlać je w kalendarzu czas na pozostałą obsługę zdarzeń mianowicie zmiana rozmiaru zdarzenia (czyli zmiana czasu), edycja i usuwanie. Zapraszam do lektury.

1. Zmiana godzin zlecenia – czyli rozszerzamy i przenosimy zdarzenia

To zmian rozmiarów (czasów, aczkolwiek dla uproszczenia będę używał słów zmian rozmiarów) zdarzenia odpowiedzialna jest metoda eventResize. A do zmiany całych dni za pomocą Drag ‘n Drop odpowiedzialna jest funkcja eventDrop. Oczywiście do zmiany będą nam potrzebne dane które przechwycimy w pliku kalnedarz_do.php. Obsłużenie tych metod po strobie jQuery wygląda następująco:

  1. eventDrop : function(calEvent, $event) {
  2. $.ajax({
  3. type : "GET",
  4. url: "kalendarz_do.php?co=resize&id="+calEvent.id+"",
  5. data: ({start: new Date(calEvent.start)/1000, end: new Date(calEvent.end)/1000})
  6. });
  7. },
  8. eventResize : function(calEvent, $event) {
  9. $.ajax({
  10. type : "GET",
  11. url: "kalendarz_do.php?co=resize&id="+calEvent.id+"",
  12. data: ({start: new Date(calEvent.start)/1000, end: new Date(calEvent.end)/1000})
  13. });

I teraz obsługa tych zdarzeń po stronie serwera aby w naszej bazie coś się zmieniło. Jak pewnie zauważyliście przekazuje również ID tego zdarzenia aby można było jednoznacznie określić co ma być edytowane, plik kalendarz_do.php:

  1. if ($_GET['co']=='resize')
  2. {
  3. $baza->quick_sel("UPDATE kalendarz SET start=('1970-01-01 00:00'::timestamp + interval '{$_GET['start']}')::timestamp at time zone 'GMT',
  4. koniec=('1970-01-01 00:00'::timestamp + interval '{$_GET['end']}')::timestamp at time zone 'GMT'
  5. WHERE id={$_GET['id']}");
  6. }

I teraz po zmianie rozmiaru (czasu), przeciągnięciu i upuszczeniu na inny dzień możemy zaobserwować zmiany.

2. Edytowanie i usuwanie zdarzeń

Umiemy już dodać, wyświetlić, zmienić dane to teraz czas na edycję i usuwanie. Można powiedzieć że jest to najbardziej skomplikowana część naszego kalendarza. Aby zrealizować tą funkcjonalność należy obsłużyć metodę eventClick. Obsługa tej metody wygląda następująco:

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

Autor wpisu: Piotr Śliwa, dodany: 30.01.2010 13:28, tagi: php

Dziś pora na trzeci artykuł z serii "wzorce w praktyce". Tym razem postanowiłem omówić praktyczne zastosowanie mniej znanego i stosowanego (w programowaniu w php) wzorca.

Każdy z Was zapewne wie co to jest transakcja bazodanowa. Jeśli jednak nie, to przypomnę, że transakcja w systemach baz danych polega na tym, że określony zbiór zapytań wykona się poprawnie w całości lub wogóle żadne zapytanie nie zostanie wykonane (de facto "nie wykona się" jest błędnym określeniem, raczej "nie zostanie zatwierdzone"). Więcej na ten temat znajdziecie na wikipedii. Transakcja jest implementacją wzorca projektowego koordynator, a raczej rozbudowanej specjalizacji tego wzorca o nazwie "Zatwierdzanie trójfazowe" (Three-Phase Commit) - właśnie tą odmianę Koordynatora będe omawiał.

Wyjątkowo w skrócie opiszę ideę tego wzorca, gdyż jest on mniej powszechny niż dwa poprzednie wzorce opisywane przeze mnie.
Uczestnikami są Koordynator, Użytkownik, Zadanie oraz Klient. Klient zleca Koordynatorowi do wykonania Zadanie, które jest podzielone na kilka części, jedna część Zadania może być wykonana tylko przez jednego Użytkownika. Rola Koordynatora polega na zapewnieniu spójności systemu, czyli podzielne Zadanie musi się wykonać w całości lub żadna z części tego Zadania przydzielona do jednego Użytkownika nie może się w ogóle wykonać.

Przedstawienie problemu

W naszym przykładzie Zadaniem będzie zaktualizowanie jakiegoś rekordu w kilku zdalnych i niezależnych usługach sieciowych będących na różnych serwerach, komunikacja odbywać się może przykładowo przez SOAP. Dla nas ważne jest, aby w każdej usłudze sieciowej był rekord o tym samym stanie, nie możemy dopuścić do sytuacji w której rekord w jednej z usług ma inny stan niż ten rekord w pozostałych usługach.

Rozwiązanie nie stosując Koordynatora

[PHP]
  1. //tablica obiektów reprezentujących różne usługi sieciowe
  2. //dla ułatwienia przyjmuję, że mają taki sam interfejs - jeśli
  3. //tak nie jest, można zastosować wzorzec Adapter opisywany w pierwszym
  4. //artykule z cyklu
  5. $services = ...;
  6.  
  7. //aktualny rekord, który ma być zapisany w zdalnych usługach
  8. $record = ...;
  9. foreach($services as $service)
  10. {
  11. //zapisanie rekordu w jednej ze zdalnych usług
  12. $service->save($record);
  13. }

Kod ten będzie działał, ale jeśli pewnego razu wystąpi problem z połączeniem z jedną ze zdalnych usług lub z innych nieistotnych powodów rekord nie zostanie zapisany, to stracimy spójność - ten sam rekord będzie miał inne wartości w różnych usługach.

Rozwiązanie problemu

Wydzielamy dwie klasy: Koordynatora (Coordinator) oraz Użytkownika (Coordination).

Najpierw zajmiemy się szkieletem klasy Użytkownika (Coordination). Obiekt, który może być koordynowany powinien umieć określić (nie wykonując swojej części zadania) czy wykonanie zadania się powiedzie (metoda prepare()), anulować wykonywanie zadania jeśli metoda prepare() zwróciła false - obiekt ten nie jest gotowy na jego wykonanie (metoda abort()). Powinien również umieć zatwierdzić (wykonać) zadanie (metoda commit()) oraz opcjonalnie wycofać zmiany, które nastąpiły po pomyślnym zatwierdzeniu (metoda rollback()).

[PHP]
  1. class Coordination
  2. {
  3. //obiekt jednej usługi zdalnej
  4. private $service = null;
  5. private $state = null;
  6. private $isAborted = false;
  7.  
  8. public function __construct($service)
  9. {
  10. $this->service = $service;
  11. }
  12.  
  13. /**
  14.   * @return bool Czy zadanie ma szansę się powieść?
  15.   */
  16. public function prepare()
  17. {
  18. try
  19. {
  20. //wykonanie jakiegoś testowego żądania, można np. pobrać w tym
  21. //żądaniu obecny obiekt rekordu który ma być zaktualizowany,
  22. //aby przy ewentualnym wywołaniu metody rollback() obiekt ten dysponował
  23. //stabilnym (przed wykonaniem zadania) stanem rekordu.
  24. $this->state = $this->service->test();
  25. }
  26. catch(Exception $e)
  27. {
  28. //załóżmy, że jeśli zostanie wyrzucony wyjątek, to żądanie testowe nie powiodło się
  29. //poprawność testu można stwierdzić również np. po wartości zwracanej
  30. return false;
  31. }
  32.  
  33. return true;
  34. }
  35.  
  36. /**
  37.   * Anulowanie wykonania zadania
  38.   */
  39. public function abort()
  40. {
  41. $this->isAborted = true;
  42. $this->state = null;
  43. }
  44.  
  45. /**
  46.   * Zatwierdzenie zadania
  47.   * @throws Exception Zadanie nie powiodło się
  48.   */
  49. public function commit()
  50. {
  51. if($this->isAborted)
  52. {
  53. throw new LogicException('Zadanie zostało anulowane');
  54. }
  55.  
  56. $this->service->doTask(...);
  57. }
  58.  
  59. /**
  60.   * Przywrócenie starego stabilnego stanu
  61.   */
  62. public function rollback()
  63. {
  64. $this->service->doTask($this->state);
  65. }
  66. }

W zamyśle metoda abort() wykona się jeśli metoda prepare() zwróci false, jeśli jednak zwróci true to powinna zostać wykonana metoda commit(). Jeśli metoda commit() wyrzuci jakiś wyjątek (zadanie nie powiodło się), to powinna zostać wykonana metoda rollback(). Pamiętajmy jednak, że jeśli metoda prepare() i-tego obiektu Użytkownika zwróci false, to mają zostać wywołane metody abort() obiektów od 0 do i-1, gdyż dany obiekt który uważa że nie jest w stanie wykonać zadania, nie musi anulować swojej gotowości do jego wykonania, gdyż sam powiedział że się nie przygotował ;) To samo tyczy się metody commit(), jeśli i-ty obiekt wyrzuci w niej wyjątek, to powinna zostać wywołana metoda rollback() obiektów od 0 do i-1, gdyż i-ty obiekt tego zadania nie wykonał.

Klasa Koordynatora powinna umieć zarejestrować Użytkowników (metoda register()) oraz w skoordynowany sposób wykonać zadanie (metoda commit()).

[PHP]
  1. class Coordinator
  2. {
  3. private $coordinations = array();
  4. private $index;
  5.  
  6. public function register(Coordination $coordination)
  7. {
  8. $this->cordinations[] = $coordination;
  9. }
  10.  
  11. public function commit()
  12. {
  13. $count = count($this->coordinations);
  14. $abort = false;
  15. //sprawdzenie, czy wszyscy uczestnicy są gotowi na wykonanie swojej części zadania
  16. for($this->index=0; $this->index < $count; $this->index++)
  17. {
  18. if(!$this->coordinations[$this->index]->prepare())
  19. {
  20. $abort = true;
  21. break;
  22. }
  23. }
  24.  
  25. //jeden z Użytkowników nie jest gotowy na wykonanie zadania, anuluj zadanie
  26. if($abort)
  27. {
  28. for($i=($this->index-1); $i >= 0; $i--)
  29. {
  30. $this->coordinations[$i]->abort();
  31. }
  32.  
  33. return false;
  34. }
  35.  
  36. try
  37. {
  38. //zatwierdź zadanie
  39. for($this->index=0; $this->index < $count; $this->index++)
  40. {
  41. $this->coordinations[$this->index]->commit();
  42. }
  43. }
  44. catch(Exception $e)
  45. {
  46. //jeden z Użytkowników nie zdołał zatwierdzić zadania, wycofaj zmiany
  47. for($i=($this->index-1); $i >= 0; $i--)
  48. {
  49. $this->coordinations[$i]->rollback();
  50. }
  51.  
  52. return false;
  53. }
  54.  
  55. return true;
  56. }
  57. }

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

Autor wpisu: batman, dodany: 29.01.2010 10:42, tagi: zend_framework

Zend Framework oferuje wiele różnych sposobów na przechowywanie wersji językowych. Spośród wszystkich wymienionych, najbardziej zachwalany jest Zend_Translate_Adapter_Gettext. Adapter ten, w przeciwieństwie do większości pozostałych, wymaga narzędzi do stworzenia odpowiedniego pliku (o rozszerzeniu mo), który nie jest możliwy do odczytania przez człowieka. Dokumentacja poleca skorzystanie w tym

Autor wpisu: Kamil Adryjanek, dodany: 28.01.2010 19:39, tagi: javascript

Lastely, building quite big Symfony and Ext.js application i was looking for simple way to make my application internationalized. I haven’t found any good solutions that would suits my needs. I found this on extjs forum: ‘The simplest way, perhaps, is to extract hardcoded strings to locale files. Then your framework just have to load the selected language file together with YUI-ext.” I didn’t like that idea, i think it would be good for building some custom components but not for internationalize the whole application. I needed something quicker and less complicated.
Than, i thought that i can write my own simple i18n mechanism - maybe there is better way (files can be generated on the server side), but this work for sure.

I simple wrote custom JavaScript function __(string) and put it into one of my .js files:


function __(string) {

	 if (typeof(i18n)!='undefined' &amp;amp;amp;amp;&amp;amp;amp;amp; i18n[string]) {

		return i18n[string];
	}

	return string;
}

Then i attached another JavaScript file with translations object (before including __() function), for example we can call this file “pl_PL.js” and put there code:


var i18n = {
	'Country.'							: 'Kraj',
	'Description'						: 'Opis',
	'Population'						: 'Populacja',
	'Created at'						: 'Data utworzenia',
	'Symfony 1.2 and Ext.js example'	: 'Przykład wykorzystania Symfony 1.2 i Ext.js '
}

In our ExtJS components (or any other JavaScript code) we just simple call (example code from latest entry):


	//columns structure
	var columns = [
		{id:'name',header: __('Country'), width: 160, sortable: true, dataIndex: 'name'},
		{header: __('Description'), width: 160, sortable: false, dataIndex: 'description'},
		{header: __('Population'), width: 160, sortable: true, dataIndex: 'population'},
		{header: __('Created at'), width: 100, sortable: true, dataIndex: 'created_at'}
	];

	// gridPanel object
	var grid = new Ext.grid.GridPanel({
		title: __('Symfony 1.2 and Ext.js example'),
		loadMask: true,   // mask panel when data is loading
		store: store,
		columns: columns,
		autoExpandColumn: 'name',
		height: 400,
		width: 600,
		renderTo: 'grid-example'  // DOM element
	});

});

For me it’s simple, powerfull and really usefull.

Autor wpisu: Zyx, dodany: 27.01.2010 17:45, tagi: php

Ostatnio w wolnych chwilach trochę zastanawiałem się, jak mógłby wyglądać następca PHP. Nie chodzi mi o jakieś mityczne PHP 7, ale o zwyczajne wzięcie się i zaprojektowanie tego języka od zera, na wstępie wyrzucając wszystkie irytujące niedociągnięcia. W tym wpisie chciałbym podzielić się wynikami tego eksperymentu myślowego.

Autor wpisu: Grzegorz Świrski, dodany: 26.01.2010 23:12, tagi: php

Każdy z nas korzystał już chyba z relacyjnych baz danych. Nawet jeżeli nie było to MySQL, PostgreSQL czy Oracle to prawdopodobnie spotkaliście się z nimi na zajęciach z informatyki, gdzie był prezentowany Microsoft Access. Nie sposób przedstawić zalet i korzyści wynikających z teorii relacyjnych baz danych i matematycznego podejścia do przechowywania danych. Niestety czekają nas także [...]
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.