Dynamiczne ładowanie Zend Plugins

February 7th, 2010

Jak wiadomo Zend vanilia jest nieco toporny i mało przyjazny dla projektanta, dlatego trzeba deko posiedzieć, żeby wszystko zadziałało w miarę przyjemnie i tak jak chcemy.

Integracja Zend’a z Doctrine, Smarty’mi jest powszechnie znana i opisywana na różnych stronach, dlatego nie będę tego powielać.

Wszystko działa fajnie, jednak w przypdku rozbudowy serwisu i chęci automatyzacji obsługi żądań w odniesieniu do Zend_Loader_PluginLoader wymagała implementacji loader’a - zamiast wyważać otwarte drzwi, zabuszowałem w internecie i znalazłem całkiem fajny Loader do pluginów, oczywiście wymagał on u mnie pewnych zmian, bo inna idea - ale ogólnie pomysł dobry i działa:

http://www.zfsnippets.com/snippets/view/id/57/plugger-a-plugin-manager

Ogólnie polecam w celu definiowania różnych pluginów pod względem “areas”, definiowanych za pomocą obsługi requestów np.
inne pluginy dla modułu “admin”, inne dla kontrollera “users” etc… - wszstko jest opisane.

Jeżeli jakieś informacje okazały się przydatne to zapraszam na wspólną kawę, chętnie podyskutuję.

PHP, develop

Szybszy PHP dzięki Facebook, czyli Hip-Hop for PHP

February 4th, 2010

Wczoraj na blogu developerów Facebook’a pojawiła się informacja o wypuszczeniu ich kompilatora PHP. Sprawa ciekawa i godna zainteresowania szczególnie, że owe ustrojstwo tłumaczy kod PHP na C++, jak to robi w praktyce jeszcze nie wiem - ale mam nadzieję, że niebawem znajdę chwilkę czasu i zgłębię temat bardziej.

Zasada działania kompilatora:
Facebook blog

Poczekamy zobaczymy - na razie zapowiada się ciekawie.

Jeżeli jakieś informacje okazały się przydatne to zapraszam na wspólną kawę, chętnie podyskutuję.

PHP, develop

Doctrine + NestedSet + Ajax + Smarty + ZF

January 30th, 2010

Na pewno nie raz okazuje się, że na stronie czy w innej aplikacji trzeba umieszczać i zarządzać danymi hierarchicznymi. Jeżeli korzystamy z Doctrine’a to mamy do dyspozycji NestedSet - bardzo przydatne narzędzie

Zaczynamy

Po pierwsze określamy strukturę tabeli dla danych hierarchicznych:

App_Menus:
  actAs:
    NestedSet:
      hasManyRoots: true
      rootColumnName: parent_id
  tableName: menus
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    name: string(64)
    type: integer

Powyżej mamy definicję tabeli w której może występować wiele drzeni drzewa, a pole określające dane drzewo nazwane zostało parent_id (w dokumentacji Doctrine, używają root_id jednak w moim przypadku z racji zaszłości historychnych wolę parent_id)

Dzięki temu wpisowi orzymujemy takiego SQL’q:

CREATE TABLE `t_menus` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `name` varchar(64) DEFAULT NULL,
    `parent_id` bigint(20) DEFAULT NULL,
    `type` bigint(20) DEFAULT NULL,
    `lft` int(11) DEFAULT NULL,
    `rgt` int(11) DEFAULT NULL,
    `level` smallint(6) DEFAULT NULL,
    PRIMARY KEY  (`id`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8

Implementacja:

Dobra wszystko fajnie, ale jak to teraz używać?

Nie ma nic prostrzego, zakładam używanie smartów i to wersji 3, zdaje sobie sprawę że Smarty 3 nie doczekały się jeszcze dobrej dokumentacji, ale zawsze jest kod systemu szablonów - można poczytać :)

Po pierwsze wyciągamy dane z bazy:

public function getTreeFromRoot()
{
  $treeObject = Doctrine_Core::getTable(‘Model_App_Menus’)->getTree();
  $rootColumnName = $treeObject->getAttribute(‘rootColumnName’);
  foreach ($treeObject->fetchRoots() as $root)
  {
    $options = array(‘root_id’ => $root->$rootColumnName);
    return $treeObject->fetchTree($options)->toHierarchy()->toArray();
  }
}

Wynikiem jest tablica wielowymiarowa z zależnościami

Dla ułatwienia sobie wykorzystania tejże tablicy w systemie szablonów deko sobie poczyśćmy wynik, chodzi głównie o to, że tablica z Doctrine’a zawsze zawiera element tablicowy __children nawet jeżeli jest on pusty.

Trywialna funkcja wywala nam puste tablice:

public function flatArray($array)
{
  foreach ($array as $key => $value)
  {
    if(is_array($value))
    {
      if(count($value) != 0) $out[$key] = $this->flatArray($value);
    }
    else
    {
      $out[$key] = $value;
    }
  }
  return $out;
}

Wynik możemy przekazać do Smartów i wyświetlić za pomocą małej rekurencji:

{function name=menu level=0}
{strip}
{foreach $data as $fields}
  <ul class="{if $level eq "0"}sortable{/if}">
    {foreach from=$fields item=field key=key}
      {if $level neq "0"}
        {if $key eq "id"}<li id="list_{$field}">{assign var="ids" value=$field}{/if}
        {if $key eq "name"}<div class="ekgreybox">{$field}  (lorem ipsum…)</div>{/if}
        {if $key eq "level"}{if $fields|@count eq ‘7′}</li>{/if}{/if}
      {/if}
      {if $key eq "__children"}
        {menu data=$field level=$level+1}
        {if $level neq "0"}</li>{/if}
      {/if}
    {/foreach}
    </ul>
  {/foreach}
{/strip}
{/function}

{menu data=$childs}

Dzięki temu otrzymamy ładne rzewko w liście.

Zarządzanie:

Budujemy ładną aplikację i chcemy mieć drag-n-drop’owe określenie menu, fajnie ale jak?

Najszybciej :)

Ja jestem strasznie leniwy i średnio lubię javascript’a, więc korzystam z gotowców :) Trzeba zassać sobie mały kodzik do drag-n-dropowego zarządzania drzewami:

Tutaj….

Fajnie działa, jednak zwraca mało ciekawy wynik, zobacz stronę demo ;)

Nie ma problemu, za pomocą Ajaxa obsługujemy i to (funkcja jeszcze nie zoptymalizowana, ale działa):

public function sortmenuAction()
{
  $root_node = $_POST[‘menu_id’];
  $pola  =$_POST[‘list’];
  $childs = 0;
  foreach ($_POST[‘list’] as $key => $value)
  {
    $run=0;
    if($childs != 0)
    {
      $run = 1;
      $childs–;
      $parent_pos = $key - 1;
      while (strstr($pola[$parent_pos],"_") == false){
        $parent_pos–;
      }
      $tmp = explode("_",$pola[$parent_pos]);
      $data = $tmp[0];
      if (strstr($value,"_") != false) {
        $tmp = explode("_",$value);
        $dzieciak = $tmp[0];
      }
      else{
        $dzieciak = $value;
      }
    }
    if($run == 0)
    {
      if (strstr($value,"_") != false)
      {
        $tmp = explode("_",$value);
        $data = $tmp[0];
        $childs = $tmp[1];
        $dzieciak = $data;
        $data = $root_node;
      }
      else
      {
        $dzieciak = $value;
        $data = $root_node;
      }
    }
   
    $rootMenu = Doctrine_Core::getTable(‘Model_App_Menus’)->findOneById($data);
    $childMenu = Doctrine_Core::getTable(‘Model_App_Menus’)->findOneById($dzieciak);
    $childMenu->getNode()->moveAsLastChildOf($rootMenu);
  }
  echo "Done";
  die();
}

Wsio - działa, sortowanie Ajax’em i wyświetlanie - ogólnie problem drzewa załatwiony w 15 minut :)

Jeżeli jakieś informacje okazały się przydatne to zapraszam na wspólną kawę, chętnie podyskutuję.

PHP, develop

Wyciąganie akcji Zend_Controller w modułach systemu

January 30th, 2010

Czasami w przypadku tworzenia systemu kontroli dostępu do zasobów aplikacji chcemy mieć wszystko np. w bazie danych. W przypadku kiedy aplikacja jest spora to niestety okazuje się ze ręczne prowadzanie elementów systemu do bazy jest zwyczajnie męczące, a fixtures np. w Doctrine to zbędny wysiłek można posilić się prostą funkcją parsującą nasze pliki.

Oczywiście kod poniżej jest przystosowany do mojej aplikacji, ale myślę że nie trudno go zmienić pod Wasze potrzeby.

Wynikiem jest tablica z pełną ścieżką do akcji w ZF

public function getAllSystemResources()
{

  $d = Zend_Registry::getInstance();

  $module_dir = $d->config[‘doctrine’][‘models_path’]."/../modules";
  $temp = array_diff( scandir( $module_dir), Array( ".", "..", ".svn"));
  $modules = array();
  $controller_directorys = array();

  foreach ($temp as $module) {
    if (is_dir($module_dir . "/" . $module."/controllers/")) {
        array_push($modules,$module);
        array_push($controller_directorys, $module_dir . "/" . $module."/controllers/");
    }
  }

  foreach ($controller_directorys as $dir) {
    foreach (scandir($dir) as $dirstructure) {
        if (is_file($dir  . "/" . $dirstructure)) {
            if (strstr($dirstructure,"Controller.php") != false) {
                include_once($dir . "/" . $dirstructure);
            }
        }
    }
  }
  $db_structure = array();
  $db_path = array();

  foreach(get_declared_classes() as $c)
  {
    if(is_subclass_of($c, ‘App_Controller_Action’))
    {
      $functions = array();
      foreach (get_class_methods($c) as $f)
      {
        if (strstr($f,"Action") != false)
        {
          array_push($functions,substr($f,0,strpos($f,"Action")));
        }
      }
      $c = strtolower(substr($c,0,strpos($c,"Controller")));

      if (strstr($c,"_") != false)
      {
        $db_structure[substr($c,0,strpos($c,"_"))][substr($c,strpos($c,"_") + 1)] = $functions;
        foreach($functions as $fun)
        {
          $index = substr($c,0,strpos($c,"_")).substr($c,strpos($c,"_") + 1).$fun;
          $db_path[$index] = substr($c,0,strpos($c,"_"))."/".substr($c,strpos($c,"_") + 1)."/".$fun;
        }
      }else
      {
        $db_structure[$default_module][$c] = $functions;
        $db_path[] = $default_module."/".$c."/".$functions;
      }
    }
  }
  return $db_path;
}

Jeżeli jakieś informacje okazały się przydatne to zapraszam na wspólną kawę, chętnie podyskutuję.

PHP, develop

Debugowanie PHP i TextMate…

January 29th, 2010

Prosta acz przydatna funkcja XDEbug’a czyli określenie linku:

[xdebug]
        zend_extension=/Applications/MAMP/bin/php5/lib/php/extensions/no-debug-non-zts-20050922/xdebug.so
        xdebug.file_link_format = "txmt://open?url=file://%f&line=%l"
        xdebug.profiler_enable=1
        xdebug.profiler_output_dir="/Users/paramah/Sites/Debug"
        xdebug.trace_format=1
        xdebug.trace_output_dir="/Users/paramah/Sites/Debug"
        xdebug.var_display_max_children=3
        xdebug.extended_info=1
        xdebug.collect_vars=1
        ; cgi.force_redirect = 1

Jeżeli jakieś informacje okazały się przydatne to zapraszam na wspólną kawę, chętnie podyskutuję.

PHP

OSX i kodowanie w PHP

January 27th, 2010

Złammy przerwę ;)

Niebawem 4 lata jak używam sprzętów z pod znaku jabłka, muszę pomyśleć jak to uczcić…

Niedawno przeszedłem na czyściutką instalację Leoparda Snow na moim wysłużonym już MacBook’u (polecam wszystkim - druga młodość laptopa).

Na szybko musiałem strorzyć sobie platformę do klikania w PHP, sami wiecie jak to jest - projekty, projekty i jeszcze raz projekty. Dobrze więc jest mieć wszystko czego tylko dusza zapragnie
do szybkiego budowania kodu.

Co zassywałem:

Generalnie przygotowanie na szybko środowiska nie jest trudne, szczególnie jak używa się gotowców.


Ctags w TextMate

Dla przyśpieszenia pracy przy projektach, szczególnie tych wykorzystujących jakieś Zendy czy inne Symfony polecam TmCodeBrowser, u mnie na Snow niestety nie ruszył z palca, powodem problemów było wpisanie w sktypcie parsującym pliki tagów ctags kodu zmieniającego wielkość znaków katalogów. Skrypt jest w Ruby’m więc
zmiana go nie powinna być dla nikogo problematyczna (a jeżeli tak, to może warto deko poczytać o ruby’m - bo to fajny język jest).

Jeżeli jakieś informacje okazały się przydatne to zapraszam na wspólną kawę, chętnie podyskutuję.

PHP, develop

Telemarketing

November 10th, 2009

Old school Atari poster.

September 5th, 2009

Pomysły Tesli wprowadzane w życie.

September 1st, 2009

Źródło: www.ted.com





Świetna sprawa, szczególnie kiedy okablowanie jest jedyną rzeczą, która tak naprawdę ogranicza.

Jeżeli jakieś informacje okazały się przydatne to zapraszam na wspólną kawę, chętnie podyskutuję.

Ogólne

Font’s for programmers

July 16th, 2009

To co widzisz w swoim ulubionym edytorze jest ważne i to nie tylko dlatego, że ma działać, ale też dlatego żeby “łagodziło oko”. Nuda jest straszna to prawda, dlatego zmieniłem sobie font’y w TextMate na
Inconsolata jest naprawdę świetna i wygląda doskonale w małych jak i dużych rozmiarach:

Jeżeli jakieś informacje okazały się przydatne to zapraszam na wspólną kawę, chętnie podyskutuję.

develop