Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: sokzzuka, dodany: 09.05.2011 09:53, tagi: php

Wczoraj Stas Malyshev ponownie podniósł kwestię rozwoju PHP 5.4.  Zaproponował następujący plan:

  • od obecnej chwili do 18 maja mają być zgłaszane propozycje cech, które są pożądane w tej wersji
  • 18 maja – początek dyskusji i głosowania nad cechami, które się znajdą w wersji finalnej
  • 15 czerwiec – wersja alfa, wydzielenie brancha 5.4 z trunka, koniec z dodawaniem nowych ficzerów, tylko poprawki błędów i rozwój zaakceptowanych cech
  • 20 lipiec – beta tylko poprawki błędów
  • 24 sierpień – Release Candidate 1 i kolejne RC co 2 tygodnie
  • Październik / Listopad – wersja finalna

Plan jaki zaproponował Stas wydaje się dość realistyczny i zyskał już poparcie Rasmusa Lerdorfa (BDFL PHP). Wszystkich ciekawych, co znajdzie się w PHP 5.4 zachęcam do czytania dokumentu „TODO„.

Autor wpisu: batman, dodany: 09.05.2011 08:00, tagi: jquery

Sliderów jQuery nigdy dosyć. Tym razem natknąłem się na takie oto cudo – Awkward Showcase. Jest to slider, do wnętrza którego można zapakować dosłownie wszystko – od tekstu począwszy, przez obrazki, na wideo kończąc. Poza standardowymi dla sliderów funkcjonalnościami znajdziemy w nim również miniaturki (umieszczone pionowo lub poziomo), tooltip na wyświetlanym zdjęciu oraz szereg konfiguracji wyglądu. Koniecznie obejrzyjcie wszystkie dema – robią wrażenie.

Strona projektu – http://www.awkwardgroup.com/sandbox/awkward-showcase-a-jquery-plugin/

Autor wpisu: Tomasz Kowalczyk, dodany: 08.05.2011 21:33, tagi: internet

Przeglądając różne informacje w Internecie trafiłem na stronę skierowanego w stronę programistów konkursu "Potyczki Algorytmiczne", edycja 2011. Jednym z organizatorów jest wydział Matematyki, Informatyki i Mechaniki Uniwersytetu Warszawskiego [MIMUW], co gwarantuje dobry poziom zawodów.  Jako, że lubię czasem sprawdzić swoje umiejętności programistyczne, zarejestrowałem się w serwisie. Zapraszam do lektury krótkiego komentarza i analizy rozwiązania pierwszego, [...]

Autor wpisu: Tomasz Kowalczyk, dodany: 08.05.2011 19:40, tagi: php, mysql, framework, symfony2

Ze wszystkich języków programowania, jakich tematykę poruszam / poruszałem na tym blogu, PHP zajmuje zaszczytne, pierwsze miejsce pod względem liczby wpisów. Zastanawiający jest zatem fakt, że w Linkdumpie jest go relatywnie najmniej. W ramach poprawy tej statystyki zapraszam do zapoznania się z listą dziesięciu wyselekcjonowanych linków o PHP właśnie. Fotografia: totalAdo, CC-BY. Linkdump: Chłopcy PeHaPowcy. [...]

Autor wpisu: Śpiechu, dodany: 07.05.2011 12:56, tagi: php, mysql

Dzisiaj kończę temat wstrzykiwania zależności. Punktem wyjścia będzie poprzedni kod. Kontener posłuży do skonfigurowania jeszcze dwóch obiektów. Napisałem sobie 2 proste klasy: SelectQuery, który odpyta bazę danych na podane zapytanie oraz SelectQueryCache, który zachowa wynik zapytania do pliku. Wynik będzie ważny tylko przez podany czas.

Przy okazji zmieniłem trochę formatowanie składni na bardziej „Zend-Frameworkowe”. Mam nadzieję, że bardziej czytelne. Kolejną zmianą jest używanie w nazwach klas/zmiennych wyłączenie języka angielskiego. Wam to nie będzie przeszkadzać, a mnie oszczędzi masę czasu gdybym chciał coś kiedyś rzucić na szerokie wody.

W metodzie loadDefaults() dorzucamy zmienne konfigurujące obiekt cachujący i dwa domknięcia potrafiące wyprodukować gotowe obiekty:

//zmienne konfigurujące pdo z poprzedniego wpisu
 
$this->cache_filename = 'queries.cache';
$this->cache_interval = 30;
$this->cache_class = 'SelectQueryCache';
 
$this->selectQueryCache = function (DBKontener $k)
{
  return new $k->cache_class($k->cache_filename , k->cache_interval);
};
 
$this->selectQuery = function (DBKontener $k)
{
  $q = new SelectQuery($k->pdo_getPDO);
  // wstrzykujemy zaleznosc
  $q->setCache($k->selectQueryCache);
  return $q;
};

Właściwie to wpis można by teraz zamknąć. Widać jak cache tworzony jest na podstawie zmiennych oraz widać wstrzyknięcie zależności w postaci metody setCache(). Innym sposobem wstrzykiwania jest konstruktor. Nie zrobiłem tak z uwagi na to, że SelectQuery może sobie radzić bez obiektu cachującego, więc po co wymuszać.

Poniżej załączam kod dwóch wspomnianych wyżej klas.

class SelectQuery
{
  /**
   * @var PDO
   */
  protected $pdo;
 
  /**
   * @var SelectQueryCache 
   */
  protected $cache = null;
 
  public function __construct(PDO $pdo)
  {
    $this->pdo = $pdo;
  }
 
  /**
   * @param SelectQueryCache $sqc dependency injection
   */
  public function setCache(SelectQueryCache $sqc)
  {
    $this->cache = $sqc;
  }
 
  /**
   * @param string $query
   * @return array
   */
  public function getResults($query)
  {
    if ($this->cache)
    {
      $cachedResults = $this->cache->getCachedResults($query);
      if ($cachedResults !== null)
      {
        return $cachedResults;
      }
    }
    $q = $this->pdo->prepare($query);
    $q->execute();
    $rows = array();
    while ($row = $q->fetch(PDO::FETCH_ASSOC))
    {
      $rows[] = $row;
    }
    if ($this->cache)
    {
      $this->cache->cacheQuery($query , $rows);
    }
    return $rows;
  }
}
 
class SelectQueryCache
{
  /**
   * @var array contains all cached queries
   */
  protected $cachedQueries = array();
 
  /**
   * @var SPLFileInfo
   */
  protected $cacheFile;
 
  /**
   * @var int time interval in secs to check if cache is still valid
   */
  protected $validTime;
 
  public function __construct($filename , $validtime = 60)
  {
    $this->cacheFile = new SplFileInfo(__DIR__ . '/' . $filename);
    $this->validTime = (int) $validtime;
    $this->loadCache();
  }
 
  protected function loadCache()
  {
    if (!file_exists($this->cacheFile))
    {
      touch($this->cacheFile);
    }
    $file = $this->cacheFile->openFile('r');
    if ($file->flock(LOCK_SH))
    {
      $this->cachedQueries = json_decode(file_get_contents($file) , true);
      $file->flock(LOCK_UN);
    }
    else
    {
      throw new Exception('Cannot acquire file lock to read file');
    }
  }
 
  public function cacheQuery($query , $result)
  {
    $this->cachedQueries[$query] = array(
      'time' => time() ,
      'result' => $result);
  }
 
  public function getCachedResults($query)
  {
    if ($this->isValidCache($query))
    {
      return $this->cachedQueries[$query]['result'];
    }
    else
    {
      return null;
    }
  }
 
  protected function isValidCache($query)
  {
    if ($this->cachedQueries !== null
      && array_key_exists($query , $this->cachedQueries)
      && $this->isValidTime($this->cachedQueries[$query]['time']))
    {
      return true;
    }
    else
    {
      return false;
    }
  }
 
  protected function isValidTime($timestamp)
  {
    return ((time() - $this->validTime) < $timestamp);
  }
 
  protected function cleanUpOldCache()
  {
    foreach ($this->cachedQueries as $key => $cq)
    {
      if (!$this->isValidTime($cq['time']))
      {
        unset($this->cachedQueries[$key]);
      }
    }
  }
 
  protected function save()
  {
    $serializedData = json_encode($this->cachedQueries);
    $file = $this->cacheFile->openFile('w');
    if ($file->flock(LOCK_EX))
    {
      $file->fwrite($serializedData);
      $file->flock(LOCK_UN);
    }
    else
    {
      throw new Exception('Cannot acquire exclusive file lock to save file');
    }
  }
 
  public function __destruct()
  {
    $this->cleanUpOldCache();
    $this->save();
  }
}

Myślę, że w SelectQuery nie ma nic specjalnego, no może poza getResults(), które najpierw sprawdza czy jest cache i jakiś wynik, a jak nie to odpytuje bazę danych i zapisuje wynik do cache.

Za to w SelectQueryCache znajdzie się trochę mięska:

  1. Do serializacji danych używam json_encode, które jest ponoć trochę szybsze od zwykłej serializacji, a zapisane dane mają formę strawniejszą dla humanoidów.
  2. Dane w pliku trzymam w postaci tablicy asocjacyjnej, której kluczem jest zapytanie, a wartościami wynik zapytania i czas utworzenia.
  3. Do sprawdzania czy cache nie jest przeterminowany odejmuję liczbę sekund od obecnego czasu i sprawdzam czy jest wcześniejsza od czasu utworzenia danego klucza.
  4. Oczyszczam cache sprawdzając czy poszczególne klucze nie są już przeterminowane i w razie czego wywalam cały klucz.
  5. Do zapisu do pliku używam destruktora. Mam pewność, że obiekt zaraz przed zakończeniem żywota zapisze dane do pliku.

Na koniec przykład użycia całości:

$c = new DBKontener();
$query = $c->selectQuery;
$results = $query->getResults('SELECT nazwa_pola FROM jakas_tabela');

Za pierwszym razem dane zostaną pobrane z bazy, a następnie przez 30 sekund z pliku cache.

Autor wpisu: Kamil, dodany: 07.05.2011 00:25, tagi: css

Media Queries w CSS2 to nic innego jak wybór medium, dla którego ma być serwowany bieżący plik CSS. Czyli możemy zdecydować, które pliki wyświetlać w wersji do druku, a które dla np. odbiorników telewizyjnych. Tak było dotychczas. Wraz z nadejściem CSS3 rozszerzono możliwości Media Queries. Teraz możemy dodatkowo decydować o dołączaniu odpowiedniego pliku/kodu CSS na [...]

Autor wpisu: Tomasz Kowalczyk, dodany: 06.05.2011 12:48, tagi: eclipse

Narzędzia pochodzące ze strony Tigris.org są bardzo przydatne w pracy programisty. Szczególnie pod systemem Windows, gdzie mamy do wyboru kilka związanych z kontrolą wersji. Od kilku lat używam programu TortoiseSVN - klienta Subversion, który w bardzo wygodny dla użytkownika sposób integruje się z menu kontekstowym plików i katalogów dostępnym pod prawym przyciskiem myszy, pokazując także [...]
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.