PHP + Apache + Imagick na Windows 7

Zadanie – zainstalować obsługę Image Magick na maszynie deweloperskiej z Windows7 64-bit. Integracja z PHP 5.3.8 jako moduł Apache 2.2.x.

PHP 5.3.8 musi być w w wersji Thread Safe, bo ona jest przewidziana do integracji jako moduł Apache 2.2 (zawiera bibliotekę php5apache2_2.dll, której jest pozbawiona wersja Non Thread Safe przeznaczona na dostęp CGI). Ponieważ do budowy PHP stosowany jest kompilator VC9, to potrzebne są binaria Apache skompilowane także VC9. Do pobrania z Apache Lounge.

Obsługa rozszerzenia imagick wymaga posiadania zainstalowanego Image Magick. Ściągamy wersję 32-bitową, ponieważ PHP też jest w wersji 32-bit. Najlepiej zastosować się do zaleceń autorów – jeśli nie wiesz co potrzebujesz, to ściągaj wersję Q-16-windows-dll. Podczas instalacji należy zaznaczyć dodanie Image Magick do ścieżki systemowej. Następnie ściągamy php_imagick.dll – nie ma obecnie wersji windows na PECL, więc bierzemy bezpośrednio ze strony autora rozszerzenia (wybieramy wersję Thread Safe). Bibliotekę kopiujemy do podkatalogu ext, zmianiamy nazwę na php_imagick.dll i dodajemy rozszerzenie

extension=php_imagick.dll

I gotowe.

EDIT: Nie do końca gotowe. Jeśli zatrzymamy się w tym punkcie biblioteka będzie się podłączała i zobaczymy ją w phpinfo(), ale każdorazowe wywołanie funkcji Imagick() będzie powodowało restart Apache. Żeby działało poprawnie należy zainstalować wersję Image Magick nie nowszą niż 6.6.4.0. Patrz też: odpowiedź na stackoverflow

Filtrowanie tablicy w javascript

Zadanie:
mamy w javascript tablicę obiektów, przykładowo strukturę jakiejś firmy:

var json = [
{
    "region_id" : "10",
    "obszar_id" : "15",
    "punkt_sprzedazy_id" : 25,
    "nazwa_punktu" : "Punkt 1"
},
{
    "region_id" : "10",
    "obszar_id" : "15",
    "punkt_sprzedazy_id" : 24,
    "nazwa_punktu" : "Punkt 2"
},
{
    "region_id" : "10",
    "obszar_id" : "15",
    "punkt_sprzedazy_id" : 27,
    "nazwa_punktu" : "Punkt 3"
},
{
    "region_id" : "10",
    "obszar_id" : "17",
    "punkt_sprzedazy_id" : 125,
    "nazwa_punktu" : "Punkt 41"
},
{
    "region_id" : "14",
    "obszar_id" : "9",
    "punkt_sprzedazy_id" : 205,
    "nazwa_punktu" : "Punkt 87"
},
{
    "region_id" : "6",
    "obszar_id" : "23",
    "punkt_sprzedazy_id" : 16,
    "nazwa_punktu" : "Punkt 42"
},
...
];

Teraz chcemy wybrać z tej tablicy tylko punkty sprzedaży z jednego obszaru – czyli np. elementy, dla których obszar_id == 15. Można do tego użyć zewnętrznych bibliotek operujących na formacie JSON, np: jOrder, JSONPath, Jaql, czy jLinq, albo wykorzystać obsługę Array.prototype.filter:

function wybierzPunktyZObszaru(obszar_id) {
    var Punkty = json.filter(function(el) {
        return el.obszar_id == obszar_id;
    });
    return Punkty;
}

Dla większej ilości warunków łączymy je:

var Punkty2 = json.filter(function(el) {
    return el.obszar_id == 15
    && el.punkt_sprzedazy_id >= 10;
});

lub

var Punkty3 = json.filter(function(el) {
    return el.obszar_id == 15;
}).filter(function(el) {
    return el.punkt_sprzedazy_id >= 10;
});

Więcej np. na stackoverflow.

Ważne, żeby dla przeglądarek nieobsługujących Array.prototype.filter dodać lokalną obsługę metody (za dokumentacją):

if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== "function")
      throw new TypeError();

    var res = [];
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in t)
      {
        var val = t[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, t))
          res.push(val);
      }
    }

    return res;
  };
}

Taki fragment dodajemy np. na początku kodu.

Gdyby chcieć skorzystać przykładowo z biblioteki jOrder:

// utwórz obiekt tablicy jOrder i dodaj nieunikalny (grouped: true) indeks 'ix_obszar_id' na polu 'obszar_id'
var jsonTable = jOrder.table(json).index('ix_obszar_id', ['obszar_id'], {grouped : true});
// funkcja filtrująca, która zwraca tylko znalezione rekordy (renumber : true)
function szukajDaneZObszaru(obszar_id) {
    return jsonTable.where([{'obszar_id' : obszar_id}], {indexName : 'ix_obszar_id', renumber : true});
}
// wyszukaj punkty z obszaru 15
var Dane15 = szukajDaneZObszaru(15);

Więcej przykładów zastosowania jOrder na wiki projektu

ZF: Zend_Date a polskie nazwy

Zadanie z użyciem Zend_Date: mając datę przykładowo 2011-01-24 wyświetlić ją jako 24 styczeń 2011 (co jest niepoprawne, ale w tym przypadku zleceniodawca tak sobie zażyczył).

Na początek tworzymy obiekt, który będzie zawierał naszą datę. Żeby wyświetlać polskie nazwy zainicjujemy locale = ‘pl_PL’

$data = new Zend_Date('2011-01-24', 'YMd', 'pl_PL');

Zakładając, że nie wymuszaliśmy formatowania daty jako ‘php’ i wykorzystujemy format ‘iso’ wyświetlamy w wymaganym formacie:

echo $data->get(Zend_Date::DAY) . ' '
     . $data->get(Zend_Date::MONTH_NAME) . ' '
     . $data->get(Zend_Date::YEAR);

Otrzymujemy: 24 stycznia 2011

Czyli niezupełnie to, o co chodziło. Dlaczego tak jest?
Read more of this post

ZF: Długości pól formularza na podstawie bazy

Kiedy tworzymy formularz w Zend Frameworku przesyłamy potem dane z niego do bazy. Czasem się okazuje, że długość wprowadzanych danych przekracza długość pola tabeli i przez to pojawia się błąd w stylu “String data, right truncated: 7 ERROR value too long for type character varying(40)” (PostgreSQL). Żeby temu zapobiec można ustawić dodatkowe walidatory dla pól formularza, które będą bazowały na informacjach z metadanych tabeli. Można to osiągnąć m.in. tak:
Read more of this post

And i &&

W przejętej do utrzymania aplikacji napisanej w PHP zauważyłem, że podczas testowania warunków if() zamiast używania operatorów && i || stosowano and i or. Ponieważ ja zawsze używałem tych pierwszych postanowiłem sprawdzić czym to się różni. Po lekturze dokumentacji i sieci można powiedzieć, że sprawa kręci się wokół dwóch rzeczy: kolejność operatorów (operator precedence) i short-circuit evaluation. To drugie nie wiem jak ładnie przetłumaczyć, ale chodzi o jak najszybsze zakończenie sprawdzania warunków true/false – to znaczy kiedy silnik PHP uzna, że zna już odpowiedź, to nie sprawdza pozostałych warunków.

Ma to miejsce kiedy:

  • pierwsza część warunku and zwraca false – bo od razu wiadomo, że cały warunek zwróci false
  • pierwsza część warunku or zwraca wartość true – bo od razu wiadomo, że cały warunek zwróci true

Read more of this post

Case sensitive REPLACE

Kolejne pytanie: jak wykonać REPLACE w SQL Serverze, ale tak żeby zamieniało będąc wrażliwym na wielkość znaków? Czyli coś w stylu:

REPLACE(kolumna, ‘mars’, ‘Snickers’) – źle
REPLACE(kolumna, ‘Mars’, ‘Snickers’) – dobrze

Funkcja REPLACE dokonuje porównania stringów na podstawie parametru COLLATION bazy danych lub kolumny. Aby zmienić to zachowanie najprościej lokalnie wykorzystać COLLATE.
Read more of this post

Dopełnianie zerami

Kolejne zadanie bojowe: do liczby z jakiejś kolumny dodać np. zera – ale albo na początku, albo na końcu. I żeby jeszcze była stała długość tak powstałej wartości, czyli np. dla liczby 12 dopełniać trzema zerami, ale dla 142 już tylko dwoma. Poniżej przykład dla zadanego ciągu 10 znaków.

Na szybko można rozwiązać to tak:
- dla dopełnienia ciągu z lewej strony
SELECT RIGHT(’0000000000′+ CAST(kolumna AS VARCHAR(10)), 10)

Doklejamy na początek 10 zer, po czym bierzemy dziesięć ostatnich znaków.

- dla dopełnienia ciągu z prawej strony
SELECT LEFT(CAST(kolumna AS VARCHAR(10)) + ’0000000000′, 10)

Tak samo – doklejamy 10 zer, tyle że na końcu i bierzemy pierwsze dziesięć znaków.

Połącz wiersze w jeden

Zadanie bojowe: w T-SQLu połączyć wynik kilku wierszy w jeden. Najprościej odpowiada na ten temat np. ASP FAQ, a rozszerza go przywoływany tam post z grupy dyskusyjnej microsoft.public.sqlserver.programming.

Krótko:
- tworzysz długą zmienną (n)varchar
- robisz SELECT z tą zmienną
Read more of this post

data URI

Przeglądając kod plugina Scienta ZF Debug Bar trafiłem na nieznany mi wcześniej sposób osadzania grafik w kodzie HTML. Ikony są tworzone w locie na podstawie zakodowanego przy użyciu base64 ciągu znaków, np.:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEYSURBVBgZBcHPio5hGAfg6/2+R980k6wmJgsJ5U/ZOAqbSc2GnXOwUg7BESgLUeIQ1GSjLFnMwsKGGg1qxJRmPM97/1zXFAAAAEADdlfZzr26miup2svnelq7d2aYgt3rebl585wN6+K3I1/9fJe7O/uIePP2SypJkiRJ0vMhr55FLCA3zgIAOK9uQ4MS361ZOSX+OrTvkgINSjS/HIvhjxNNFGgQsbSmabohKDNoUGLohsls6BaiQIMSs2FYmnXdUsygQYmumy3Nhi6igwalDEOJEjPKP7CA2aFNK8Bkyy3fdNCg7r9/fW3jgpVJbDmy5+PB2IYp4MXFelQ7izPrhkPHB+P5/PjhD5gCgCenx+VR/dODEwD+A3T7nqbxwf1HAAAAAElFTkSuQmCC

Obrazek można zobaczyć wklejając powyższy kod do paska adresu np. w Firefoksie czy Operze

Jak to działa?
Read more of this post

Znajdź ostatnie n znaków

Żona zadała mi pytanie w związku z rozwijanym w firmie systemem pisanym w C# i opartym o SQL Server: jakimi sposobami z ciągu znaków np. “kkk/384/d3/a/332″ można wyciągnąć liczby po ostatnim znaku “/”?

Do głowy przychodzą mi dwa rozwiązania:

  • wyszukać ostatnie pojawienie się znaku “/” i odpowiednio wyciąć string
  • zastosować wyrażenie regularne do znalezienia cyfr na końcu ciągu

W przypadku SQL Servera nie ma wbudowanych bibliotek do wyrażeń regularnych. Można napisać własne funkcje wykorzystujące SQLCLR (dla wersji 2005 i 2008) lub OLE (dla wersji 2000) lub skorzystać z istniejących zewnętrznych bibliotek dll (np. xp_pcre). W tym konkretnym przypadku można jednak osiągnąć zamierzony wynik żonglując standardowymi funkcjami T-SQL. Read more of this post

Follow

Otrzymuj każdy nowy wpis na swoją skrzynkę e-mail.