Vframe 2.0, Rewrited Strings

Dec 09

Frameworki najlepiej buduje się podczas wykonywania projektów. W odróżnieniu od Vframe 1.x, druga wersja ma lepiej rozwiązaną kwestię przygotowania ciągu znaków pod adres url (mod_rewrite).

Pierwszym zasadniczym irytującym błędem były podwójne myślniki wynikające z zamiany spacji na myślnik. A co jak będzie ciąg ” – “. Trzy myślniki z rzędu? Nieładnie to wygląda. Do Vframe 2 został dodany util niwelujący ten błąd.

Drugim problemem pisania aplikacji w Vframe 1.x było powtarzanie się takich samych rewrite w bazie. Klasa Vframe_Util_Rewrite obsługuje analizę stringów oraz przygotowuje nowy w ten sposób, aby żaden się nie powtórzył. Z bazy danych należy tylko wyciągnąć stringi LIKE ‘naszstring%’ i podać je klasie w formie tablicy asocjacyjnej. Do nowego stringu zostanie dodany numerek, bądź (uwaga) własny prefix.

Przykłady zastosowań:

http://cpaste.com/4079

Klasa:

http://cpaste.com/4078

Read More

Klasa użytkownika oraz filtry Access

Aug 07

Publikacja Vframe 2.0 zbliża się wielkimi krokami, oczywiście jest wiele do zrobienia, ale główny core wydaje się być skończony w wersji pierwszej. W tym wpisie chciałbym przedstawić mniej więcej zasadę działania klasy użytkownika oraz możliwości dostępu ACL do akcji kontrolerów.

Główną nowością w rebuildzie klasy użytkownika i ACL jest możliwość nadawania rang, co znacznie ułatwia pracę nad aplikacjami wymagającymi zaawansowanego dostępu do poszczególnych modułów aplikacji. Przykładowe wykorzystanie klasy użytkownika prezentuje się następująco:

[php]< ?php

$oUser = new Vframe_User;

// log in user
$oUser->Auth(true);
// add some groups with ranks
$oUser->setGroup(‘administrator’, 10);
$oUser->setGroup(‘moderator’, 2);
$oUser->setGroup(‘redactor’, 1);
// and one without rank… rank for this group will be set as 0
$oUser->setGroup(‘user’);
// we can also set only one with theese groups

// will output true
var_dump( $oUser->hasGroup(‘administrator’) );
// will output true, because group “moderator” has group rank 2
var_dump( $oUser->hasRank(2) );
// will output true, because user has greater ranks than 1, it can be rank 1 too…
var_dump( $oUser->isRank(1) );
// first will output true, second false
var_dump( $oUser->isRank(5), $oUser->isRank(11) );
// will output true, user is logged in
var_dump( $oUser->Auth() );

?>[/php]

Kolejnym ważnym elementem jest konfiguracja warstwy dostępu do kontrolera. Przedstawia się ona mniej więcej tak:

[php]< ?php

$aConfig = array
(
'access' => array
(
// allow ranks 1, 2 and group ‘b’
‘allow’ => array(1, 2, ‘b’),
// allow only group ‘a’
‘allow’ => ‘a’,
// allow users with rank 4 or greater
‘allow’ => 4,

// so… forget about above exaple, and…
// let’s create access filter for allow users without banned group
‘allow’ => ‘user’,
‘deny’ => ‘banned’,
),
);

?>[/php]

Konfigurację możemy przedstawić w dowolnym formacie: php array, xml document lub ini configuration.

To na tyle : ) Myślę, że wystarczy wszystkim deweloperom.

Read More

Vframe 2.0 – zapowiedź

Jul 22

Rozpoczynam pracę nad Vframe framework oznaczonym numerkiem 2. Cały silnik jest pisany od samego początku. Nowych możliwości od groma, począwszy od rozwinięcia routera kończąc po stabilizacji dostępu do obiektów z poziomu kontrolera. W przeciwieństwie do wersji 1.x, w nowej odsłonie Vframe będzie obowiązywało nazewnictwo klas a’la Zend Framework, daje to poczucie komfortu programowania oraz możliwości rozbudowy ścieżek. Kilka zasadniczych featurów w wersji 2.0:

  • Zupełnie nowe 3 routery, podstawowy (bazujący na tablicy $_GET), rewrite (separator “/”, “,” lub inny do sprecyzowania, elastyczny na tyle, że nie trzeba mieć modrewrite na serwerze) oraz zaawansowany bazujący na wyrażeniach regularnych adresu. Routery są w pełni konfigurowane, w zasadzie nie ma ograniczeń co do pozycji parametrów i ich imion.
  • Zaawansowana obsługa sesji oferująca dopinanie swoich handlerów z dwoma gotowymi (pliki oraz baza danych). Obsługa sesji implementuje interfejs Countable, dzięki czemu szybko można wyciągnąć i zcacheować ilość osób online. Pełna konfiguracja ciastek wysyłanych na potrzebę implementacji sesji.
  • Obsługa baz danych oparta na PDO, autoukładanie formatowanie zapytań.
  • Modularny Input, dane get, post, files, server są przechwytywane przez pluginy, dzięki czemu można dopinać sobie swoje wtyczki na potrzeby konkretne aplikacji, bądź całego frameworka. Jednym z pluginów jest parsowanie informacji o domyślnym języku użytkownika oraz przeglądarki z danych wejściowych.
  • Klasa użytkownika oprócz przystosowywania grup będzie mogła nadawać im rangi, dzięki czemu nie trzeba sprawdzać dziesięciu grup usera, tylko rangę > 10. Analogicznie do identyfikacji grupy użytkownika hasGroup(), można odwołać się do rang – hasRank().
  • Zaawansowany parser konfiguracji – wykrywa jedno z 3 rozszerzeń oraz dodaje domyślne – php. Dostępne czytniki plików konfiguracyjnych to XML, PHP Array oraz INI. Możliwość odpisania swoich sterowników, które są używane w zależności od rozszerzenia pliku konfiguracyjnego. Nieskończona głębia grup konfiguracyjnych.
  • Cache. Tak jak w przypadku plików konfiguracyjnych występuje tu możliwość nieskończonego zagłębienia cache w grupy. Cache obsługiwane przez 3 podstawowe silniki: pliki, baza danych oraz Memcache.
  • Backend. Podobnie jak w Symfony w Vframe pojawią się 2 dodatkowe aplikcje. Backend oraz system modułów. Backend generuje instalatory do baz danych oraz ma możliwość ustalenia dowolnej ilości dowolnych pól danych. Akcje: dodaj, edytuj, usuń, filtruj, szukaj.

Nie podaję terminu zakończenia prac, jest on niepewny, najważniejsze żeby wszystko było stabilne. Nową wersję piszę ze względu na własne potrzeby, backend na ciągłość powtarzania tych samych operacji.

Read More

Autoload – praktyczne mapowanie

Mar 31

O autoloadzie klas było już głośno, rozpatrywaliśmy wszelkie za i przeciw w wielu miejscach choćby tu, tu i tu.

Mechanizm automatycznego ładowania potrzebnych nam klas jest bardzo dobrym sposobem na zrelaksowanie się poprzez brak przymusu ręcznego ładowania plików potrzebnych do działania aplikacji. Znajdźmy receptę na owe pytanie przedstawiając dwa najpopularniejsze sposoby trzymania klas w np. frameworkach.

  • Zend Framework i Rapide mają dość sztywną, lecz nie wymagającą specjalnego kombinowania technikę umieszczania plików w core. Sposób nazewnictwa jest bardzo prosty: Folder_Subfolder_Klasa – owy zapis odnosi się do ./Folder/Subfolder/Klasa.Class.php.

  • W moim frameworku Vframe zastosowałem technikę, w której pliki leżą sobie „wolność w core, nazewnictwo klas nie tyczy się ich ścieżki, np. NazwaKlasy może odnieść się do ./NazwaKlasy.Class.php lub ./Folder/Subfolder/ NazwaKlasy.Class.php.

Spróbuję opisać drugi – mój – sposób na ładowanie plików z core aplikacji. Potrzebna nam będzie klasa, która jest w stanie przeskanować całe core i zapisać je do tablicy. Aby było łatwiej, skan zostanie zaserializowany do pliku jako mapa folderu. Co jeżeli plik nie będzie istniał w core? Wówczas mapa zostanie stworzona od nowa, jeżeli to nie pomoże – wyrzucimy wyjątek.

Projektujemy naszą klasę, nazwiemy ją przykładowo Autoload, metody:

  • Load($sLibrary, $bRemapped = false) – metoda która będzie odpowiedzialna za załadowanie pliku oraz (jeżeli nie będzie istniała) stworzenie tablicy plików. W wypadku braku pliku zostanie ponownione wywołanie metody tworzenia mapy plików z przymusowym przeskanowaniem folderu klas oraz tym samym odpalenie metody samej siebie z przyjęciem drugiego jej parametru na true – brak ponownego skanowania folderu i wyrzut wyjątku.

  • Map($bUseTemp = true) – metoda odpowiedzialna za stworzenie tablicy z plikami na podstawie pliku mapy poprzez odserializowanie danych w nim zapisanych. Jeżeli parametr otrzyma wartość false lub plik mapy nie będzie możliwy do odczytu, wówczas tworzona zostanie mapa, zapisana do pliku mapy oraz do tablicy klasy.

  • FormatName($sLibrary) – metoda formatująca nazwę klasy: Klasa.Class.php

Wykorzystamy trzy stałe:

  • const _LibDir – określa ścieżkę folderu z klasami

  • const _LibSurfix – surfixy plików (.Class.php)

  • const _LibMap – ścieżka i nazwa pliku mapy

Potrzebna będzie nam jeden statyczny, prywatny parametr klasy, który jest sam w sobie jej singletonem, więc każda instancja klasy będzie z niego korzystała:

private static $_aCoreMap = array();

Ok, teraz wystarczy użyć funkcji __autoload() i wykorzystać naszą klasę:

[php]function __autoload($sLibrary)
{
try
{
Autoload::Load($sLibrary);
}
catch(AutoloadException $oException)
{
// some message to display
die(‘Autoload failed: ‘ . $oException->getMessage());
}
}[/php]

Tworzymy osobisty wyjątek dla autoloadera:

[php]class AutoloadException extends Exception
{

}[/php]

oraz samą klasę:

[php] class Autoload
{
const _LibDir = ‘Core/’;
const _LibSurfix = ‘.Class.php’;
const _LibMap = ‘Map.tmp’;

private static $_aCoreMap = array();

public static function Load($sLibrary, $bRemapped = false)
{
if(!count(self::$_aCoreMap))
self::Map();

$sLibraryFile = self::FormatName($sLibrary);

if(!isset(self::$_aCoreMap[$sLibraryFile]))
{
if($bRemapped)
// if we remapped core and library dosen’t exists – throw an exception
throw new AutoloadException(‘Library “‘ . $sLibrary . ‘” has not been found in directory map!’);
else
{
// ok, let’s go map core again without using map from file
self::Map(false);
// try load class from core directory again…
self::Load($sLibrary, true);
}
}

require_once(self::$_aCoreMap[$sLibraryFile]);
}

public static function Map($bUseTemp = true)
{
// if map is ok and we counld use it, get the map from file…
if($bUseTemp && is_readable(self::_LibMap))
self::$_aCoreMap = unserialize(file_get_contents(self::_LibMap));
// …unless we have to scan core and make map
else
{
// clear array and remamp directory
self::$_aCoreMap = array();

foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator(self::_LibDir)) as $oFile)
{
$sFile = $oFile->getFilename();

if(isset(self::$_aCoreMap[$sFile]))
throw new AutoloadException(‘Core duplication “‘.$sFile.’” found!’);
else
self::$_aCoreMap[$sFile] = $oFile->getPathname();
}

// ok, save map to file
if(!file_put_contents(self::_LibMap, serialize(self::$_aCoreMap)))
throw new VframeException(‘Cannot create core map!’);
}
}

private static function FormatName($sLibrary)
{
return $sLibrary . self::_LibSurfix;
}
}
?>[/php]

Całą paczkę klasy i zastosowań możecie pobrać tutaj.

Read More

Wyróżnienie art.php.pl

Mar 17

W czwartek dowiedziałem się, że zostałem wyróżniony w ogólnopolskim konkursie art.php.pl przez firmę NQ.pl.

NQ.pl było jednym ze sponsorów, ale również obserwatorem konkursowych zmagań. Liczba prac była duża i nie mogliśmy zapoznać się z każdą z nich.

Kilka prac szczególnie przypadło nam do gustu, dlatego też postanowiliśmy dodatkowo wyróżnić dwie prace:
Vframe framework, autor: Piotr `athlan` Pelczar oraz Logger, autor: Mateusz `CyberBoB` Kaczmarek.

Autorzy tych prac otrzymują od nas darmowy pakiet NQ.developer pozwalający na utworzenie pięciu repozytoriów SVN oraz projektów zarządzanych przez Trac.

Nie ukryję, że jestem dumny z mojego projektu. Jednakże ten jest już zamknięty (powstają na nim ostatnie juz aplikacje), gdyż zostałem developerem Rapide framework. Ci, co stanęli na podium oraz wyróżnieni otrzymają dyplomy lub zaświadczenia na wzór tego. Niech to będzie motywacją do wzięcia udziału w konkursie dla tych, którzy nie wystawili swoich prac przed publiczność.

Read More

Przejście do Rapide

Jan 29

Dziś ostatecznie zdecydowałem się w jaką inżynierię oprogramowania wejdę, co postaram się rozbudowywać i poświęcać temu czas. Postanowiłem zostać developerem Rapide Framework, propozycję współpracy dostałem dużo wcześniej, ale myśl o porzuceniu Vframe – nie ukrywam – bolała. Jakie wnioski? Nie ma sensu pisać wielkiego frameworka samemu… lepiej robić to w grupie ludzi, która zna się na rzeczy, zawsze ktoś Cię może poprawić, wesprzeć, doradzić. Rola całkiem często odwraca się, że to właśnie Ty pomagasz i doradzasz. Decyzja zapadła ostatecznie, na Vframe napiszę ostatnią aplikację w ferie. Będę sięgał do jego pojedynczych komponentów jeżeli będzie taka potrzeba, ale to będą wyjątki.

Dlaczego porzuciłem projekt? Poddałem się? Nie. Projektu nie porzucilem, ale nie będę go już rozwijał, nie poddałem się, bo nic nie pójdzie do kosza. Możnaby było zapytać: co ze starymi klasami? Rapide jest gotów przyjąć parę moich rozwiązań, a jeżeli nie będą one dołożone w oficjalnym wydaniu, mogę korzystać z nich jako pomoce (pluginy bądź biblioteki).

Decydującym argumentem jest tutaj niewątpliwie modularność Rapide. Adrian (prph) doskonale przewidział problemy, jakie mogą wystąpić przy dalszym toworzeniu frameworka. Prostym przykładem jest Config, który przyjmuje póki co dane jako tablicę, ale modularność aplikacji pozwala na dołączanie kolejnych możliwości, na przykład obsługe konfiguracji z poziomu plików INI, XML, itp. Drugim argumentem jest to, że pracujemy w grupie. Jak już wspomniałem w drugim akapicie jest to wspaniała sprawa, gdy grupa developerów pomaga sobie nawzajem, pozwala to na dalszy rozwój członka grupy.

Parę moich komponentów jest naprawdę dobrych, chociażby Image. Postaram się wingerować go do Rapide, lecz w sposób modularny, możliwe że ktoś napisze go za mnie, ważne są pomysły. Jeżeli macie jakieś osobiste refleksje dotyczące Rapide, odnoszę na oficjalne forum.

Read More