6988157282_d2c10fc165_o

DbInjectionAware formularz w Phalconie

Pisząc pewien projekt w Phalconie, natknąłem się na sytuację gdy formularz musiał mieć validator Uniqueness. Oczywiście taki validator istnieje, ale w Modelach: Phalcon\Mvc\Model\Validator\Uniqueness. Niestety postanowiłem nie korzystać z phalconowych modeli z powodu łamania zasady SOLID.

Pomysł

Wpadłem na pomysł aby stworzyć własny validator który by korzystał z połączenia Db i sprawdzał czy podana wartość już istnieje w bazie. Tutaj jednak pojawiło się pytanie w jaki sposób wstrzyknąć instancje połączenia z bazą danych do validatora?

Pierwszym pomysłem było skorzystać z Dependency Injection w Phalconie jako Service Locator. Jednak uważam że o ile można, to należy omijać Service Locatora. Z tego powodu postawiłem rozwiązać problem trochę okreżną drogą, ale za to łatwo testowalną.

Rozwiązanie

Rozwiązaniem jest połączenie własnego FormManagera oraz Interfejsu DbInjectionAwareInterface.

<?php
namespace My\App\Forms;

class Manager extends \Phalcon\DI\Injectable
{
    private $definitions;

    public function set($name, $definition)
    {
        if (is_string($definition)) {
            $definition = ['className' => $definition];
        }

        $this->definitions[$name] = $definition;
    }

    public function get($name)
    {
        if ($this->has($name)) {
            $className = $this->definitions[$name]['className'];
            $form = new $className();

            if ($form instanceof DbInjectionAwareInterface) {
                $form->setDb($this->getDI()->get('db'));
            }

            if (method_exists($form, 'configure') {
                $form->configure();
            }

            return $form;
        }
    }

    public function has($name)
    {
        return isset($this->definitions[$name]);
    }
}

Moja wersja Form Managera sprawdza przy tworzeniu instancji formularza czy implementuje DbInjectionAwareInterface, jeżeli tak to wstrzykuje db.

Dodatkowo jeżeli formularz posiada metodę configure to jest on odpalany przed zwróceniem obiektu formularza. Jest to spowodowane tym, że wbudowana metoda initialize() jest odpalana podczas konstruktora. W konstruktorze nie ma jeszcze dostępu do wstrzyknietej instancji db. Z tego powodu dodałem obsługę metody configure.

<?php
namespace My\App\Forms;

interface DbInjectionAwareInterface
{
    public function getDb();
    public function setDb($db);
}

Teraz wystarczy tylko odpowiednie zmiany w DI aplikacji

<?php

$di->set('formManager', 'My\App\Forms\Manager');
$formManager = $di->get('formManager');
$formManager->set('register', 'My\Forms\RegisterForm');

Oczywiście aby się nie powtarzać RegisterForm może extendować po klasie która ma zaimplementowany DbInjectionAwareInterface. Jednak ja napisałem do tego traitsa:

<?php
namespace My\App\Di;

trait DbInjectableTrait
{
    private $db;

    public function setDb($db)
    {
        $this->db = $db;
    }

    public function getDb()
    {
        return $this->db;
    }
}
<?php
namespace My\Forms;

use My\App\Di\DbInjectableTrait;
use My\App\Di\DbInjectionAwareInterface;
use Phalcon\Forms\Form;

class RegisterForm extends Form implements DbInjectionAwareInterface
{
    use DbInjectableTrait;

    public function configure()
    {
        //...
    }
}

Autor zdjęcia: Philip Taylor

4773457853_b10fcc8294_b

Automatyczny VirtualHost w Ubuntu

Jeżeli jesteś freelancerem albo developerem i pracujesz nad wieloma projektami webowymi to najprawdopodobniej masz następujący problem przy tworzeniu nowych projektów.

  • Stworzyć nowy katalog project-name w katalogu www
  • Dopisać nowa domenę do hostów w systemie: project-name.dev 127.0.0.1
  • Dopisać nowy vhost w konfiguracji apacha który powiąże project-name.dev => /www/project-name/public_html 

Każdy programista dąży do automatyzacji prostych zadań. Oto tutorial jak ten proces zautomatyzować.

Podpięcie domen *.dev na 127.0.0.1

Aby zautomatyzowanie podpinania domen pod localhosta potrzebne jest dodatkowo oprogramowanie. Mowa tu Dnsmasq. Instalacja:

sudo apt-get install dnsmasq

Następnie edytujemy plik /etc/dnsmasq/dnsmasq.conf i dodajemy nasŧępujące linijki na samym dole pliku

listen-address=127.0.0.1
address=/.dev/127.0.0.1

Restartujemy Dnsmasq następującym poleceniem

sudo service dnsmasq restart

GOTOWE. Teraz wszystkie adresy *.dev na naszym komputerze będą kierować na 127.0.0.1

VirtualHosty w Apache2

W tym celu potrzebny jest mod_vhost_alias. Podstawowa wersja Apache2 instalowana z paczek ubuntu powinno go już mieć, tak więc wystarczy go aktywować:

sudo a2enmod vhost_alias
sudo service apache2 restart

Konfiguracja VirtualHost

Ostatnim krokiem jest konfigiracja Apache. Edytujemy /etc/apache2/sites-available/default

<VirtualHost *:80>
    VirtualDocumentRoot "/sciezka_do_www/%-2+/public_html"
    ServerName vhosts.dev
    ServerAlias *.dev
    UseCanonicalName Off

    <Directory /sciezka_do_www/*>
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        allow from all
    </Directory>
# reszta konfiguracji
</VirtualHost>

Na koniec restart Apache i GOTOWE :)

Autor zdjęcia: Tom Raftery

3762360637_6b851c9478_b

User Settings dla Sublime Text 2

{
  "auto_complete_commit_on_tab": true,
  "color_scheme": "Packages/Tomorrow Color Schemes/Tomorrow-Night-Eighties.tmTheme",
  "draw_minimap_border": true,
  "font_face": "Ubuntu Mono",
  "font_options": ["subpixel_antialias"],
  "font_size": 11,
  "highlight_line": true,
  "ignored_packages": ["Vintage"],
  "line_padding_bottom": 2,
  "line_padding_top": 2,
  "rulers": [120],
  "scroll_past_end": false,
  "tab_size": 4,
  "theme": "Centurion Blue.sublime-theme",
  "translate_tabs_to_spaces": true,
  "trim_trailing_white_space_on_save": true,
  "wombat_color_blue": true,
  "wombat_dirty_bottom_bar_blue": true,
  "word_wrap": true,
  "wrap_width": 120
}

Autor zdjęcia: Eric Miraglia

3711363516_ca2338fbe6_b

Ubuntu 12.04 a polskie znaki

Po instalacji Ubuntu 12.04 nie działały mi polskie znaki: ą,ę etc.

Problem okazał się banalnie prosty, jednak znaleźienie rozwiązania już nie tak bardzo. Z tego powodu też publikuje ten wpis, może komuś się przyda.

  1. Uruchamiamy System Settings > Keyboard.
  2. Na samym dole okienka jest link Layout Settings, klikamy w niego.
  3. Upewniamy się czy mamy dodany layout Polish. 
  4. Następnie klikamy w Options i pojawia się wypunktowana lista z masą opcji.
  5. Rozwijamy element: Key to choose 3rd level i wybieramy  Right Alt.
No i teraz za pomocą prawego alta możemy wpisywać ą,ę itp.
Autor zdjęcia: Nicolás Demarchi
monitors_large

Sublime Text 2 – Pluginy

Sublime Text 2 to genialny edytor tekstu. Od ponad pół roku używam go zamiast Netbeansa czy PHPStorma. Sam edytor tekstu jest super świetny, ale prawdziwa produktywność ma miejsce dopiero po zainstalowaniu paru pluginów.

1. SFTP

Plugin zbawienie przy projektach dla klientów, którzy nie wiedzą co to SSH (lub nie mają dostępu – zwykły hosting).

2. SidebarEnhancements

Sidebar w Sublime Text 2 to poprostu pomyłka, nic się nie da z nim zrobić. Dzięki pluginowi wreszcie sidebar działa normalnie.

3. SublimeLinter

Jeżeli dbasz o jakość kodu to SublimeLinter jest twoim najlepszym przyjacielem.

4. Tag

Doskonały pomocnik przy tworzeniu i refactoringu kodu HTML. Osobiście nieocenione narzędzie przy fixowaniu kodu na potrzeby newsletterów „zepsutego” przez WYSIWYGi.

5. Modific

Jeżeli używasz Svn’a lub Git’a to ten plugin zaznaczy ci linijki które zostały zmienione od ostatniego commita. Czasami prawdziwy „life saver”.

6. DocBlocker

Dobry helper przy tworzeniu komentarzy.

7. Goto Documentation

Jak nie pamiętasz kolejności parametrów w jakieś funkcji, ale co ona zwraca to ten plugin przeniesie Cię na odpowiednią stronę manuala.

8. Theme – Nil

Obecnie mój ulubiony wygląd do ST2. Dopasowuje nie tylko edytor, ale także cały interfejs edytora.

9. Inne

Kiedyś używałem wielu innych pluginów, ale okazało się że wprowadzają tylko szum. W taki sposób oduczyłem się korzystać z kilku narzędzi typowych dla IDE jak np.: autocomplete czy przechodzenie do definicji klasy. Na początku było trudno. Po 2 miesiącach jednak okazało się że nie potrzebuje IDE, a mój kod oraz wiedza o nim się mocno poprawiła. Zwiększyła się także produktywność.

Źródło zdjęcia: http://www.sublimetext.com/blog/articles/anatomy-of-a-next-generation-text-editor

5580657696_bf70c5a0f3_b

Sortowanie tablic po danej wartości indeksu

Czasem mamy dane w tablicach zamiast w bazie danych.

Przykład

Mamy listę użytkowników w kolekcji tablic. Każda tablica składa się z par klucza i wartości

<?php
array(
  'name' => 'Jaś Kowalski',
  'points' => 10
);

Gdy chcemy wyswietlic ranking użytkowników, to chcemy posortować naszą kolekcję tablic z danymi użytkownikach według wartości indeksu ‚points’. 

Rozwiązanie

<?php
$sort = [];

foreach ($collection as $key => $row) {
  $sort[] = $row['points'];
}

array_multisort($sort, SORT_DESC, $collection);

foreach jest w php dość wolny, więc nie polecam tego rozwiązania dla kolekcji danych z 10 000+ elementów. Ale wtedy napewno dane macie już w bazie danych i zrobicie prostego SELECT * FROM users ORDER BY points

4440561067_ff472f723c_b

Jak sortować tablice UTF-8 w PHP

Jeżeli mamy tablicę której kluczami są nazwy miejscowości (zakodowanych w UTF-8) i chcemy ją posortować alfabetycznie po kluczach to mamy problem. Zwykłe ksort( $array ); nie wystarczy :(

Najpierw musimy upewnić się że jest załadowany odpowiedni locale, a następnie użyć metody sortowania za pomocą funkcji użytkownika. A oto pełne rozwiązanie w PHP:

<?php
setlocale( LC_ALL , 'pl_PL.UTF-8' );
uksort( $array , 'strcoll' );

Została tutaj użyta funckja strcoll która porównuje dwa stringi według collate aktualnego locale.

Autor zdjęcia: Jessica Wilson

5267926250_a5c285c0b5_b

Jak Napisać Extension do Google Chrome

Dość prosto. Nawet nie spodziewałem się  jak prosto :) Wystarczą 3 pliki:

  • minifest.json
  • background.html
  • script.js

Manifest jest najważniejszy. To on definiuje do czego mamy dostęp a do czego nie. W manifeście umieszczamy także informacje o samym rozszerzeniu, takie jak nazwa, opis, numer wersji. Oto przykładowy manifest:

{
  "name": "Nasz Extension",
  "description": "Opis",
  "version": "0.1",
  "permissions": ["contextMenus","tabs"],
  "background_page": "background.html"
}

permissions to lista uprawnien do których chcemy mieć dostęp. Listę uprawnień można znaleźć w API.
background_page to strona html która będzie odpalana w tle. W moim przypadku zawiera on tylko kod JS, a dokładnie link do pliku script.js

API jest dość proste. Po prostu używamy obiektu chrome i dodajemy potrzebne nam funkcje :) Np aby dodać dodatkową funkcje w context menu które pojawia się po naciśnięciu prawego przycisku myszy wystarczy:

var properties = {
    title: 'tytuł wyświetlany użytkownikowi',
    contexts: ['link'],
    onclick: function(info, tab) {
        // kod po kliknieciu
    }
};

chrome.contextMenus.create(properties);

Proste jednak jęzeli chcecie się podzielić rozszerzeniem z światem za pomocą Google Web Store to musicie przygotować ikonkę (128×128), screena, video albo pokaz slajdów oraz 5$ za rejestracje developera w Google Web Store.

Autor zdjęcia: Zack Casey

bing

„Nieuczciwy” Bing czyli czarny PR

W ostatnim tygodniu zrobiło się głośno o nieuczciwych praktykach Binga. O co dokładniej chodzi? Osoby używające bing toolbara z włączoną opcją pomocy w poprawie aplikacji poprzez wysyłanie anonimowych informacji do Microsoftu były źródłem problemu. Wydaje się nic wielkiego.

Google także za pomocą swojego toolbaru śledzi co użytkownicy robią i używa tych danych później do polepszenia jakości swoich produktów.

Problem się pojawił gdy się okazało, że duża część użytkowników która ma włączony Bing Toolbar korzysta z wyszukiwarki Google, W ten oto sposób wyniki na zapytania w Google szybko powędrowały do wyszukiwarki Bing. Nic wielkiego, ale gdy Google zauważyło to i przedstawiło całemu światu dowody że Bing kopiuje wyniki od Google to zamiast przyznać się do praktyki panowie od PR Microsoftu postanowili udawać że nic się nie stało i zaprzeczyć wszystkiemu.

Dział PR podał także że wyniki pochodzą z genialnego algorytmu Bingu, który pobiera dane z różnych źródeł. Niestety był to zły pomysł, oto dlaczego:

Oczywiście to wierzchołek góry lodowej.Znacznie więcej i mniej humorystycznych opinii pojawiło się w serwisach newsowych, gdzie ogólnie ing jest obecnie uznawany za tego złego, a Google świeci swoim Don’t be evil.

Wniosek: Jeżeli coś naprawdę zrobiłeś źle to nie ukrywaj tego tylko zaproponuj rozwiązanie problemu bo wszyscy i tak dowiedzą się prawdy a przy okazji wytrą Cię z błotem.

jQuery

jQuery 1.5

Team jQuery wydał nową dużą wersje bblioteki. Tym razem mamy do pobrania jQuery 1.5 A co w nim takiego nowego?

Przepisany od nowa $.ajax

Biblioteka do obsługi AJAXu została całkowicie przepisana. Pierwszą rzeczą która się rzuca w oczy jest zmiana definicji. Od teraz wygląda ona następująco:

$.ajax(url, [settings]);

Według mnie jest to uproszczenie bardzo pożądane. Szczególnie początkującym będzie znacznie łatwiej zrozumieć tak poteżną bibliotekę do obsługi AJAXa. Kolejną zmianą jest enkapsulacja XHR do obiektu jqXHR. Sam obiekt jqXHR jest instancją kolejnej nowości w jQuery 1.5 – Deferred Object. Ten nowy typ obiektu ma tą właściwość że może do dowolnego eventu podpiąć nie jeden callback ale kilka. Na dodatek callbaki są ustawiane w kolejkę i są według tej kolejki uruchamiane. Jednak to nie wszystko :) Kolejne callbacki można dodawać w trakcie lotu :) nawet po wywołaniu eventu. Dodany callback w locie zostaje dodany do kolejki i zostanie wykonany jak tylko kolejka się opróżni.

var jqXHR = $.ajax(url, [settings]);
// kod aplikacji
jqXHR.error(function() { alert('Cos poszlo nie tak') });

Rozszerzono także API, dzięki ktoremu programiści mogą pisać pluginy do biblioteki jQuery.ajax wprowadzają now typy danych, filtry czy transportery.

jQuery.sub()

Nie podoba ci się implementacja jakiejś metody w jQuery? Teraz przy pomocy jQuery.sub() możesz spokojnie nadpisać co tylko sobie chcesz w całej bibliotece jQuery, a jednocześnie zachowując pewność że nie zepsujesz działania żadnego pluginu.

Wydajność

W nowej wersji pod młotek optymalizacji poszły takie metody jak children(), prev() i next(). Ponieważ są to chyba najczęściej używane metody w aplikacji opartych na jQuery więc zysk dla prawdziwych aplikacji będzie naprawdę spory.