CakePHP: JSON w widokach
Opublikowano 2011-08-27 11:31:13 CakePHP JavaScript
Pomysł jak i klasa do realizacji pomysłu są zaczerpnięte z tego wpisu. Jeżeli mamy akcję, której zadaniem jest zwrócić wynik w JSON; zazwyczaj nie ma potrzeby korzystania z plików widoków i layoutów. Niektórzy pokusiliby się o wyłączenie autorenderowania i następnie wpisali echo json_encode($something);.Bardziej doświadczeni programiście wiedzą, że jest to niezgodne z architekturą MVC. Do tego celu stworzona została klasa JsonView. Poniższy kod ląduje w pliku app/views/json.php.
class JsonView extends View {
var $content = null;
function __construct(&$controller, $register = true) {
if (is_object($controller) && isset($controller->viewVars['json'])) {
$this->content = $controller->viewVars['json'];
}
if ($register) {
ClassRegistry::addObject('view', $this);
}
Configure::write('debug', 0);
}
function render($action = null, $layout = null, $file = null) {
if ($this->content === null) {
$data = '';
} else {
$data = json_encode($this->content);
}
return $data;
}
}
Teraz w naszej akcji, której zadaniem jest wypisać obiekt JSON wystarczy wpisać:
function my_action() {
$this->view='json';
$json = array('myobject'=>true,'mvc'=>'not broken');
$this->set(compact($json));
}
W odpowiedzi akcji powinniśmy otrzymać:
{"myobject":true,"mvc":"not broken"}
Mechanizm bardzo prosty w implementacji, pozwalający znacząco przyspieszyć pisanie kodu z użyciem JSON.
CakePHP: Linki absolutne
Opublikowano 2011-08-26 21:46:20 CakePHP HtmlHelper
Ostatnio napotkałem problem tworzenia linków w mailu wysyłanym z sekcji administratorskiej aplikacji napisanej w CakePHP. Linki tworzyłem za pomocą metody link w HtmlHelper.
echo $this->Html->link('Link'
array(
'controller'=>'contents'
,'action'=>'view'
,'slug'=>'my-custom-slug'
)
);
Tak utworzony link tworzony jest z prefixem 'admin'; jakoże został utworzony z poziomu sekcji admin, która jest uzyskana za pomocą takiego prefixu. Pozbywamy się prefixu podająć w tablicy drugiego parametru element o kluczu takim jak nazwa prefixu, a w wartości prefixu FALSE. Zaleca się aby w każdym tworzonym linku anuluwać nieużywane, a zdefiniowane prefixy. Dla przypomnienia prefixy te zdefiniowane są w pliku app/config/routes.php.
echo $this->Html->link('Link'
array(
'controller'=>'contents'
,'action'=>'view'
,'slug'=>'my-custom-slug'
,'admin'=>FALSE
)
);
Teraz wystarczy tylko uzyskać link absolutny, czyli zaczynający się od http://tomaszmazur.eu/ zamiast standardowego /. W tablicy drugiego parametru tworzymy element o kluczu full_base i wartości TRUE.
echo $this->Html->link('Link'
array(
'controller'=>'contents'
,'action'=>'view'
,'slug'=>'my-custom-slug'
,'admin'=>FALSE
,'full_base'=>TRUE
)
);
CakePHP: Jeden silnik dla wielu aplikacji
Opublikowano 2011-08-22 01:02:28 CakePHP
Jak posiadać jedną kopię framework'a dla wielu aplikacji? Standardowe podejście to jeden silnik dla jednej aplikacji. Zakładając, że na serwerze posiadamy 10 aplikacji, w chwili gdy zechcemy zaktualizować silnik, musimy wgrać nową wersję 10 razy. Dodatkowo posiadamy 10 identycznych kopii źródeł CakePHP. Rozwiązaniem tego problemu jest posiadanie jednego silnika CakePHP wykorzystywanego przez wszystkie 10 aplikacji.
Na moim serwerze struktura katalogów wygląda następująco:
~/domains/domena1.pl/public_html/ ~/domains/domena2.com/public_html/
W każdym z tych katalogów posiadam 2 działające aplikacje CakePHP, zawartość tych katalogów to:
app/ cake/ plugins/ vendors/ .htaccess index.php
W momencie, gdy będę chciał zastosować strategię 'jeden silnik dla wielu aplikacji', zawartość folderu ograniczy się do:
app/ .htaccess index.php
Pozostałe foldery zostaną przeniesione do innej dowolnej lokalizacji. W moim przypadku przenoszę je do ~/cakephp_nr_wersji. Otrzymuję przykładowy efekt:
~/cakephp_1_3_10/cake ~/cakephp_1_3_10/plugins ~/cakephp_1_3_10/vendors/
Aby aplikacje wiedziały, gdy znajduje się silnik CakePHP, musimy dokonać modyfikacji pliku app/webroot/index.php
ustawiając stałą CAKE_CORE_INCLUDE_PATH na ścieżkę do katalogu zawierającego katalogi cake i vendors (u mnie jest to linia #53). W wyżej opisanym przykładzie wyglądałoby to następująco:
define('CAKE_CORE_INCLUDE_PATH', dirname(dirname(dirname(ROOT))).DS.'cakephp1_3_10');
Zmiany musimy oczywiście dokonać w każdej aplikacji z osobna, lecz jest to działanie tylko jednorazowe. Możemy pójść krok dalej i wyrzucić zawartość katalogu app bezpośrednio do public_html, ale o tym w oddzielnym wpisie.
Linux: Kilka przydatnych komend dla programistów
Opublikowano 2011-08-20 17:39:22 SQL Linux
Przedstawię kilka komend linuxowych, które przydają się w codziennej pracy programisty. Niekażdy programista zna linuxa na wylot, w większości przypadków wystarczy znajomość podstaw i kilku, specyficznych dla danej działalności komend. Polecenia są dość jednoznaczne, dlatego nie zamieszczam dokładnego opisu komend.
1. Zrzut/kopia bazy danych
mysqldump -h localhost -u username -p database > file.sql
-p oznacza, że konieczne jest podanie hasła dla użytkownika.
2. Wgranie/import bazy danych
mysql --host localhost --user username -p database < file.sql
-p jak w punkcie 1
3. Policzenie liczby plików/folderów w danym katalogu
ls /my/dir/ -l | wc -l
4. Wylistowanie plików/katalogów zawierających w nazwie określony ciąg znaków
ls /my/dir | grep ".jpg"
Komendy z punktów 3 i 4 można połączyć
ls /my/dir -l | grep ".jpg" | wc -l
Post będzie uzupełniany w miarę potrzeb.
SQL: Przechowywanie IP w bazie danych
Opublikowano 2011-02-12 00:03:43 Optymalizacja SQL PHP
Wpis dotyczy tematu przechowywania adresów IP(dla ścisłości IPv4) w bazie danych MySQL. Najczęściej spotykanym sposobem przechowywania takiego adresu IP jest pole VARCHAR. Jest to zdecydowanie niewłaściwe podejście, wymaga zastosowania pola co najmniej VARCHAR(15), jednak w praktyce można spotkać nawet VARCHAR(100). Polecanym rozwiązaniem jest skorzystanie z pola UNSIGNED INT(4). Aby jednak wcisnąć adres IP do tego pola, potrzebna jest jego pewna obróbka, na szczęście zarówno PHP jak i MySQL posiadają funkcje pozwalające na obustronna konwersje adresów. Przejdźmy do praktyki i utwórzmy nasze pole:
CREATE TABLE IF NOT EXISTS `ips` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `ip` int(4) unsigned NOT NULL, PRIMARY KEY (`id`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Aby wstawić do bazy danych adres IP 127.0.0.1 możemy skorzystać z zapytania:
INSERT INTO `ips` (ip) VALUES(INET_ATON('127.0.0.1'))
W bazie danych pojawi się wpis, który w polu ip będzie zawierał adres IP:
2130706433
Adres ten odczytujemy za pomocą MySQL korzystając ze składni
SELECT INET_NTOA(`ip`) as ip_address FROM `ips`
Co pozwoli nam na odczyt adresu IP w znanej nam formie. Jak wspomniałem, czynności te można również wykonać z poziomu PHP. Służą do tego odpowiednio funkcje ip2long i long2ip
$ip = '127.0.0.1'; $encoded = ip2long($ip); echo $encoded; //wyświetli 2130706433 $ip_2 = long2ip($encoded); echo $ip_2; //wyświetli 127.0.0.1
Jak widać korzystanie z tego sposobu przechowywania adresów IP w bazie danych nie jest takie straszne jak mogłoby się wydawać. Pozatym, że rozwiązanie to jest dużo wydajniesze od zwykłego pola VARCHAR. Należy wspomnieć że udostępnia dodatkową funkcjonalność jak np. wyszukiwanie adresów IP z danego zakresu adresów, sprawdzanie czy adres należy do danej puli itd.