Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM    Subskrybuj kanał ATOM dla tagu php Kanał ATOM (tag: php)

Autor wpisu: cojack, dodany: 15.05.2010 13:12, tagi: php

Kto z Was nigdy nie łamał sobie głowy jakie jest najlepsze środowisko edytorskie dla naszego “ukochanego” języka skryptowego pod linuksem? Założę się że każdy z Was, a ja chciałbym Wam zaproponować KDevelop. Nie tak dawno temu zespół KDevelop ogłosił publicznie finalną ver. oznaczoną numerkiem 4.0, w całości zostało przeportowane na qt 4. Nie dość że ślicznie wygląda to jeszcze komuś się chciało napisać plugin dla PHP! To już całkiem niezły wyczes z wypasem.

Co nam oferuje KDevelop

Planeta PHP

KDevelop i PHP

  • Tworzenie projektów
  • Obsługa SVN z poziomu programu
  • Kolorowanie składni
  • Integracja z manualem PHP
  • Autosugestia metod w klasach
  • Autosugestia nazw zmiennych ( :p )
  • i wiele wiele wiele… more

Otóż po rozmowie z twórcą pluginu i zgłoszeniu paru błędów wiem czego na razie nie ma, nie działają podpowiedzi w statycznym wywoływaniu metod np:

SomeClassName::

Nie dostaniemy listeningu metod statycznych. Mi przynajmniej nie działa, on mówi że mu działa, eee nie wiem co jest grane ;]

KDevelop posiada kolorowanie składni również dla wielu wielu innych języków skryptowych. Wspaniałością jest to iż posiada kolorowanie składni dla skryptów SQL, tudzież PostgreSQL. Gdzie dla mnie to jest po prostu cudowna sprawa, ale był błąd w kolorowaniu składni procedur w języku pl/pgsql (będzie mini kurs wprowadzający w programowaniu pl/sql). By naprawić kolorowanie w tymże języku należy pobrać: sql-postgresql.xml plik i wrzucić go do:

$ /usr/share/kde4/apps/katepart/syntax/

tam już takowy plik będzie, zróbmy sobie pierw jego kopie, a następnie wrzućmy nowy. Po tej całej operacji restart KDevelop i będzie nam piknie działać. Napisałem że ma błąd w kolorowaniu składni ale nie napisałem jaki, otóż sprawa ma się tak, przyjrzyjmy się funkcji:

CREATE FUNCTION "getMenuPath" ( "_idMenu" INT ) RETURNS LTREE AS $BODY$
	SELECT
	   "menuPath"
	FROM
	   "menu"
	WHERE
	   "idMenu" = $1;
$BODY$ LANGUAGE 'SQL' WITH (ISCACHABLE);

Jak widzimy po strukturze $BODY$ mamy ciało SQL, natomiast KDevelop interpretował to jako string, i tutaj był problem z kolorowaniem składni.

Błędy w KDevelop

Jest parę błędów w KDevelop które często powodują że nurtują mnie pytania czy dobrze zrobiłem że się na KDevelop przesiadłem, otóż mimo iż jest to oficjalne wydanie środowisko jest dosyć nie stabilne. Potrafi się często wyłożyć w najmniej oczekiwanych momentach, dlatego np odradzam korzystanie z SVN w KDevelop a wykorzystać do tego zewnętrzny program np: kdesvn, lub po prostu jechać z konsoli. Czasami potrafi się też wysypać przy zamykaniu zakładek otwartych dokumentów. Innym ficzerem jest też taka opcja że gdy się najedzie na funkcję w php to pokazuje się tooltip ballon z informacją o funckji z linkiem w środku: Show uses, po kliknięciu na niego najprawdopodobniej powinny się pojawić jakieś przykłady jak to użyć, ale pojawia się nowe okno z paskiem postępu i cały KDevelop zdechł.

Praca z KDevelop

Wszystko co nam potrzebne do pracy z KDevelop to kawałek internetu, 3kilo root’a i z 2 głośniki. Polecam też zainstalowanie paczek z debug symbols.

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

Autor wpisu: Michał Środek, dodany: 14.05.2010 21:40, tagi: php

Spróbujmy udoskonalić nasz serwer tak aby posiadał możliwości prostego chatu — wysyłanie wiadomości ogólnych do wszystkich użytkowników oraz prywatnych tylko do jednej osoby. Mój kod urósł prawie do 150 linijek przy czym nie uwzględnia on kilku rzeczy, o których wspomnę podczas pisania protokołu lub tworzenia klientów.(w końcu nie piszę MUD-a i telnet muszę zastąpić czymś innym).

Poprawiony kod wygląda tak:

<?php 
set_time_limit(0);
 
class GameClient
{
   public $id;
   private $socket;
 
   public function __construct(&$socket, $id)
   {
      $this->socket = $socket;
      $this->id = $id;
   }
 
   public function sendMessage($message)
   {
      socket_write($this->socket, $message."\n".chr(0));
      echo 'Wysylam wiadomosc do '.$this->id.': '.$message."\n";
   }
 
}
 
class GameServer
{
   private $master;
   private $address; 
   private $port; 
   private $maxClients;
   private $sockets = array();
   private $clients = array();
 
   public function __construct($address = '127.0.0.123', $port=14117, $maxClients = 10)
   {
      $this->address = $address;
      $this->port = $port;
      $this->maxClients = $maxClients;
 
      $this->master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
      socket_bind($this->master, $this->address, $this->port);
      socket_listen($this->master);
      $this->sockets[] = $this -> master;
 
      while(true)
      {
         $changedSockets = $this->sockets;
         socket_select($changedSockets,$write=null,$exceptions=null,null);
 
         foreach($changedSockets as $socket)
         {
            // zmiana gniazda głównego => nowe polaczenie
            if($socket == $this->master)
            {
               $socket = socket_accept($this->master); 
 
               $this->sockets[] = $socket;
               $id = array_search($socket, $this->sockets);
                $this->clients[] = new GameClient(&$this->sockets[$id], $id);
 
            }
            // zmiana gniazda jednego z klientów
            else
            {
               $input = socket_read($socket, 1024); 
               $input = trim($input," \t\n\r");
 
               if(strlen($input)==0 || $input=='exit')
               {
                  $output = 'Bye bye!'."\n".chr(0); 
 
                  // send data to socket 
                  socket_write($socket, $output);
 
                  $id = array_search($socket, $this->sockets);
                  unset($this->sockets[$id]);
                  unset($this->clients[$id-1]);
 
                  socket_close($socket);
               }
               else
               {
                  $command = (strpos($input,' ')!==false)
                      ? substr($input,0, strpos($input,' '))
                      : $input;
 
                  switch($command)
                  {
                     case 'hello':
                        $output = 'Hello!';
                        break;
                     case 'list':
                        // identyfikatory wszystkich gniazd
                        $all = array_keys($this->sockets);
                         // identyfikator uzytkownika
                        $id = array_search($socket, $this->sockets);
                        // usuniecie ID glownego gniazda oraz gniazda uzytkownika
                        $all = array_diff($all, Array(0, $id));
 
                        if(empty($all))
                           $output='Nie ma innych osob';
                        else
                           $output='ID innych osob to: '.implode(', ',$all);
                        break;
                     default:
                        if(is_numeric($command))
                        {
                           // identyfikator uzytkownika
                           $id = array_search($socket, $this->sockets);
                           // wyslanie wiadomosci do wszystkich
                           if($command=='0')
                           {
                              foreach($this->clients as $client)
                              {
                                 // nie wysylamy do siebie
                                 if($client->id!=$id)
                                    $client->sendMessage(substr($input,strpos($input,' ')+1));
                              }
                              $output = 'Do wszystkich';
                           }
                           // nie wysylamy do siebie, uzytkownik istnieje
                           elseif($command!=$id && isset($this->sockets[$command]))
                           {
                              // jeden mniejszy ponieważ $this->master znajduje sie
                              // w tablicy gniazd a nie jest klientem
                              $this->clients[$command-1]->sendMessage(substr($input,strpos($input,' ')+1));
                              $output = 'OK';
                           }
                           else
                              $output ='Bledny ID'; 
                        }
                        else
                           $output = 'Niezrozumiale polecenie: '.$input.''; 
                  }
                  socket_write($socket, $output."\n".chr(0));
               }
            }
         }
      }
   }
 
   public function __desctruct()
   {
      socket_close($this->master); 
   }
}
 
$gameServer = new GameServer();
?>

Czas na krótką analizę. Pierwsze co rzuca się w oczy to nowa klasa GameClient. Jest to klasa, z którą wiążę pewne plany. Obiekty tej klasy przechowują dwie rzeczy — gniazdo oraz jego identyfikator. Metoda sendMessage() służy do wysyłania wiadomości do użytkownika, który jest podpięty do tego gniazda.

W klasie GameServer pojawiły się dwa nowe pola prywatne, tablica sockets przechowująca wszystkie gniazda dostępne dla serwera oraz tablicę clients przechowującą obiekty klasy GameClient.

Ogólne założenia się nie zmieniły — wciąż istnieje pętla nieskończona jednak jej zawartość została zmodyfikowana.

$changedSockets = $this->sockets;
socket_select($changedSockets,$write=null,$exceptions=null,null);

Użyliśmy tutaj funkcji socket_select(). W parametrach podajemy referencje(dlatego pierwsza linijka jest konieczna) do tablic gniazd, a funkcja pozostawia w nich jedynie te elementy, w których zaszły pewne zdarzenia. Pierwszy parametr odpowiada czy czytanie, czyli wybrane zostaną jedynie te gniazda, które coś przesyłają do serwera. Drugi i trzeci parametr odpowiadają za pisanie oraz wyjątki lecz nas one nie interesują. Ostatni parametr dotyczy limitu czasu oczekiwania na wybranie poszczególnych gniazd. Null oznacza brat limitu czasowego.

Następnie sprawdzamy każde z gniazd z tablicy $changedSockets. Jeśli gniazdo jest tym samym co gniazdo główne serwera oznacza to, że nowy użytkownik chce ustanowić połączenie. Robimy to tworząc nowe gniazdo i dopisując informacje o nim do tablic $this->sockets oraz $this->clients. W przypadku innych gniazd odczytywane są dane przesyłane do serwera.

$input = socket_read($socket, 1024); 
$input = trim($input," \t\n\r");

Używam funkcji trim() aby wyczyścić dane przychodzące do serwera z różnych niepotrzebnych białych znaków.

Pozostały kod to pseudo-protokół chatu. W przypadku przesłania komunikatu pustego lub wiadomości exit połączenie z użytkownikiem jest zrywane. Polecenie hello jest czysto demonstracyjne. W przypadku wpisania list pojawia się lista identyfikatorów innych użytkowników dostępnych aktualnie lub komunikat o ich braku. Wysyłanie komunikatów do innych użytkowników odbywa się w następujący sposób:

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

Autor wpisu: Michał Środek, dodany: 14.05.2010 00:47, tagi: php

Pisząc grę internetową trzeba zastanowić się nad sposobem komunikacji między graczami oraz bazą danych. W przypadku aplikacji przeglądarkowych dużego wyboru nie ma. Praktycznie wszystkie gry wykorzystują technologię AJAX. Jak to działa w praktyce? Nie za dobrze. Spróbujmy stworzyć coś dużo bardziej wydajniejszego.

Sposób działania technologi AJAX

AJAX to rozwiązanie jednostronne. Klient prosi serwer o pewne informacje, a ten je wysyła użytkownikowi. Serwer nie posiada dokładnych informacji na temat ilości aktualnie połączonych użytkowników oraz nie może wysłać do żadnego z nich samodzielnie żadnej informacji(tj. może jedynie odpowiadać na ich zapytania).

Kocham robić te fajne obrazki i choć nie mają one niczego wspólnego z UML-em mam nadzieję, że jesteś w stanie je odczytywać

Przeanalizujmy przykład czatu internetowego w którym mamy trzech użytkowników(Client1, Client2, Client3). Pierwszy z nich chce wysłać informację do trzeciego. Wygląda to następująco:

  • (1) Client1 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (2) Client2 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (3) Client3 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (4) Client1 wysyła do serwera wiadomość przeznaczoną dla użytkownika Client3. Serwer zwraca informację o przyjęciu danych.
  • (4,5) Serwer zapisuje wiadomość do swojego bufora(w tym przykładzie bazy danych)
  • (5) Client2 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (6) Client3 pyta serwer czy są jakieś wiadomości do niego.
  • (6,5) Serwer odczytuje z bazy danych wiadomość oraz zwraca ją użytkownikowi.
  • (7) Client1 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (8) Client2 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (9) Client3 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (…)

Jak widać wykonywanych jest wiele niepotrzebnych zapytań. Każdy z klientów musi stale wysłać zapytanie do serwera co w przypadku małego czasu może powodować spore zużycie procesora serwera. W sytuacji, gdy czas będzie większy w grze pojawią się lagi. Jak ten problem rozwiązuje się w „normalnych“ grach internetowych? Używane są gniazda.

Jak działają gniazda

Szerokie linie oznaczają nasłuchiwanie serwera oraz klientów

Każdy z klientów musi ustanowić połączenie z serwerem. Serwer dla każdego z nich tworzy gniazdo za pomocą którego w dowolnym momencie może wysłać informację do jednego z użytkowników.

Wygląda to tak:

  • (0) Client1, Client2, Client3 nawiązują połączenie z serwerem(tworzone są gniazda)
  • (1) Client1 wysyła wiadomość do serwera (serwer zwraca komunikat o sukcesie)
  • (2) Serwer odnajduje gniazdo trzeciego użytkownika
  • (3) Serwer wysyła wiadomość do Client3

W odróżnieniu do technologi AJAX w tym przypadku nasz serwer napisany w php musi ciąglę nasłuchiwać, a więc proces tego skryptu musi być cały czas uruchomiony. W tym celu tworzy się pętlę nieskończoną, którą cięgle sprawdza stan gniazda serwera.

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

Autor wpisu: Wojciech Sznapka, dodany: 13.05.2010 23:00, tagi: symfony, php

The sfWidgetFormSelect doesn't provide ability to render disabled options. It's rarely used feature of a HTML select element, but sometimes it could save your life :-) In fact, we can achieve this feature by creating our own widget, which inherits from sfWidgetFormSelect.

Autor wpisu: sokzzuka, dodany: 13.05.2010 14:21, tagi: php

Niejednokrotnie podczas pisania różnych skryptów, mam do czynienia z arytmetyką dat. Tak było również i tym razem, kiedy miałem zaimplementować funkcjonalność polegającą na ograniczeniu oddawania ponownego głosu w sądzie do 24 godzin.

Istnieje kilka rozwiązań tego problemu, pierwszym rozwiązaniem jest odejmowanie timestamp-ów. Nie jest to rozwiązanie zbyt wygodne, ponieważ trzeba ręcznie obliczać ilość sekund etc. Poza tym dochodzą problemy z strefami czasowymi. Może się zdarzyć sytuacja, że PHP ma ustawioną inną strefę czasową niż baza danych i wtedy wychodzą nam jakieś dziwne wyniki.

Jest łatwe rozwiązanie tego problemu, na które ostatnio natknąłem się właśnie przy okazji ww. zadania. Są to MySQL-owe funkcje date_add i date_sub. Przejdźmy więc do przykładów.

Obliczenie daty 5 godzin wcześniej od teraz:

SELECT date_sub(now(),interval 5 hour)

Obliczenie daty miesiąc wcześniej od teraz:

SELECT date_sub(now(),interval 1 month)

Generalnie reguła jest taka, że w drugim argumencie piszemy “interval <liczba> <jednostka>” gdzie liczba jest liczbą całkowitą, natomiast jednostka jest angielską nazwą jednostki daty(dzień, miesiąc, rok, sekunda…) w liczbie pojedynczej.

Autor wpisu: JoShiMa, dodany: 12.05.2010 01:45, tagi: php, sql

W poprzednich artykułach tej serii pokazałam jak wygląda konstrukcja drzewa typu nested set a także jak wczytać zawartość drzewa tego typu. W tym odcinku pokażę, że wystarczą niewielkie modyfikacje omówionych wcześniej zapytań, by bez trudu odczytać dowolnie wybraną gałąź naszej struktury. Dla przypomnienia Na początek przypomnę tabelę zawierająca strukturę drzewa, którą wykorzystywałam w poprzednich artykułach oraz [...]

Autor wpisu: eRIZ, dodany: 10.05.2010 09:45, tagi: php

Ostatnio musiałem się zmierzyć z pewnym algorytmem, który wymieniał dane z aplikacją kliencką pisaną we Flashu pomiędzy PHP. Niby nic skomplikowanego, przesyłanie znaków z kodami ASCII uzyskiwanych flashowym odpowiednikiem metody urlencode(). Jednak pomimo prawidłowej realizacji algorytmu, nadal uzyskiwałem dziwne wyniki.

Jakież było moje zdziwienie, gdy odkryłem, co było grane.

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