informatyka cakephp 1 3 programowanie aplikacji receptury mariano iglesias ebook

background image
background image

Tytu

á oryginaáu: CakePHP 1.3 Application Development Cookbook

T

áumaczenie: Przemysáaw Pietraszek (rozdz.1),

Krzysztof Rychlicki-Kicior (wst

Ċp, rozdz. 2 – 11)

ISBN: 978-83-246-3542-9

Copyright © Packt Publishing 2011. First published in the English language under the title
„CakePHP 1.3 Application Development Cookbook”

© Helion 2012
All rights reserved

All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means,
electronic or mechanical, including photocopying, recording or by any information storage retrieval system,
without permission from the Publisher.

Wszelkie prawa zastrze

Īone. Nieautoryzowane rozpowszechnianie caáoĞci lub fragmentu niniejszej

publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metod

ą kserograficzną,

fotograficzn

ą, a takĪe kopiowanie ksiąĪki na noĞniku filmowym, magnetycznym lub innym powoduje

naruszenie praw autorskich niniejszej publikacji.

Wszystkie znaki wyst

Ċpujące w tekĞcie są zastrzeĪonymi znakami firmowymi bądĨ towarowymi ich

w

áaĞcicieli.

Autor oraz Wydawnictwo HELION do

áoĪyli wszelkich staraĔ, by zawarte w tej ksiąĪce informacje byáy

kompletne i rzetelne. Nie bior

ą jednak Īadnej odpowiedzialnoĞci ani za ich wykorzystanie, ani za związane

z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie
ponosz

ą równieĪ Īadnej odpowiedzialnoĞci za ewentualne szkody wynikáe z wykorzystania informacji

zawartych w ksi

ąĪce.

Pliki z przyk

áadami omawianymi w ksiąĪce moĪna znaleĨü pod adresem:

ftp://ftp.helion.pl/przyklady/ caph3r.zip

Wydawnictwo HELION
ul. Ko

Ğciuszki 1c, 44-100 GLIWICE

tel. 32 231 22 19, 32 230 98 63
e-mail: helion@helion.pl
WWW: http://helion.pl (ksi

Ċgarnia internetowa, katalog ksiąĪek)

Drogi Czytelniku!
Je

Īeli chcesz oceniü tĊ ksiąĪkĊ, zajrzyj pod adres

http://helion.pl/user/opinie/caph3r
Mo

Īesz tam wpisaü swoje uwagi, spostrzeĪenia, recenzjĊ.

Printed in Poland.

Kup książkę

Poleć książkę

Oceń książkę

Księgarnia internetowa

Lubię to! » Nasza społeczność

background image

Spis tre!ci

O autorze

9

O recenzentach

11

Przedmowa

13

O czym jest ta ksi"#ka?

13

Oprogramowanie wykorzystywane w ksi"#ce

16

Dla kogo jest ta ksi"#ka?

17

Konwencje typograficzne

17

Materia$y dodatkowe i pomoc

17

Rozdzia$ 1. Uwierzytelnianie

19

Wprowadzenie

19

Konfiguracja prostego systemu uwierzytelniania

20

U#ywanie i konfiguracja komponentu Auth

24

Logowanie za pomoc" nazwy u#ytkownika lub adresu e-mail

28

Zapisywanie informacji o u#ytkowniku po zalogowaniu

31

Pobieranie informacji o zalogowanym u#ytkowniku

33

U#ywanie prefiksów do kontroli dost%pu bazuj"cej na rolach

36

Autoryzacja wykorzystuj"ca warstw% kontroli dost%pu (ACL)

38

Integracja z OpenID

45

Rozdzia$ 2. Wi"zania modeli

49

Wprowadzenie

49

Dodanie zachowania Containable do wszystkich modeli

50

Ograniczanie wi"za& zwracanych przez wyszukiwania

51

Modyfikowanie parametrów wi"za& dla wyszukiwa&

59

Modyfikowanie warunków wi"za& dla wyszukiwa&

63

Zmiana typu z$"czenia dla powi"za& jeden-do-jednego

65

Tworzenie wielu powi"za& z tym samym modelem

66

Dodawanie wi"za& w locie

69

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Spis tre!ci

6

Rozdzia$ 3. Wszystko o pobieraniu danych

73

Wprowadzenie

73

Wykonywanie zapyta& GROUP i COUNT

74

Wykorzystywanie pól wirtualnych

80

Tworzenie zapyta& z wykorzystaniem z$"cze& dora'nych

84

Wyszukiwanie elementów spe$niaj"cych okre!lone kryteria

87

Implementacja w$asnego typu wyszukiwania

89

Stronicowanie wyszukiwa& w$asnych typów

93

Implementacja stronicowania na bazie technologii AJAX

96

Rozdzia$ 4. Walidacja i zachowania

99

Wprowadzenie

99

Dodawanie wielu regu$ walidacji

100

Tworzenie w$asnych regu$ walidacji

104

Wykorzystywanie wywo$a& zwrotnych w zachowaniach

109

Wykorzystywanie zachowa& do dodawania nowych pól

116

Wykorzystywanie zachowania Sluggable

118

Geokodowanie adresów przy u#yciu zachowania Geocodable

122

Rozdzia$ 5. *ród$a danych

127

Wprowadzenie

127

Udoskonalanie dziennika zapyta& 'ród$a danych SQL

127

Parsowanie plików CSV za pomoc" 'róde$ danych

134

Konsumowanie kana$ów RSS za pomoc" 'róde$ danych

138

Tworzenie 'ród$a danych przy u#yciu serwisu Twitter

142

Dodawanie obs$ugi transakcji i blokad w 'ródle danych MySQL

152

Rozdzia$ 6. Magia trasowania

161

Wprowadzenie

161

Wykorzystywanie parametrów named i GET

162

Wykorzystywanie tras z prefiksami

168

Praca z elementami tras

172

Dodawanie tras typu catch-all dla stron profilowych

175

Dodawanie walidacji dla klas typu catch-all

179

Tworzenie w$asnych klas trasowania

182

Rozdzia$ 7. Tworzenie i wykorzystywanie us$ug sieciowych

187

Wprowadzenie

187

Tworzenie kana$u RSS

188

Konsumowanie us$ugi JSON

194

Tworzenie us$ug REST przy u#yciu formatu JSON

199

Dodawanie uwierzytelniania do us$ug REST

208

Implementacja autoryzacji dost%pu do API przy u#yciu tokenu

213

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Spis tre!ci

7

Rozdzia$ 8. Praca z pow$okami

219

Wprowadzenie

219

Tworzenie i uruchamianie pow$oki

220

Parsowanie parametrów wiersza polece&

224

Tworzenie zada& pow$oki wielokrotnego u#ytku

229

Wysy$anie wiadomo!ci e-mail z poziomu pow$oki

239

Tworzenie automatycznych zada& za pomoc" wtyczki Robot

243

Rozdzia$ 9. Internacjonalizacja aplikacji

249

Wprowadzenie

249

Internacjonalizacja tekstów w kontrolerach i widokach

250

Internacjonalizacja komunikatów walidacji w modelach

256

T$umaczenie tekstów zawieraj"cych dynamicznie generowan" tre!+

259

Ekstrakcja i t$umaczenie tekstów

262

T$umaczenie rekordów baz danych za pomoc" zachowania Translate

266

Ustawianie i zapami%tywanie j%zyka

270

Rozdzia$ 10. Testowanie

273

Wprowadzenie

273

Konfiguracja frameworka do testów

274

Tworzenie testowych danych i metod modeli

278

Testowanie akcji kontrolera i ich widoków

286

Wykorzystywanie za!lepek do testowania kontrolerów

290

Uruchamianie testów w konsoli

294

Rozdzia$ 11. Narz%dzia i klasy pomocnicze

297

Wprowadzenie

297

Wykorzystywanie klasy Set

298

Operacje na tek!cie przy u#yciu klasy String

305

Wysy$anie wiadomo!ci e-mail

308

Wykrywanie typów plików za pomoc" MagicDb

314

Rzucanie i obs$uga wyj"tków

319

Skorowidz

325

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

9

Internacjonalizacja

aplikacji

W tym rozdziale omówimy nast%puj!ce zagadnienia:

internacjonalizacj% tekstów w kontrolerach i widokach;

internacjonalizacj% komunikatów walidacji w modelach;

t#umaczenie tekstów zawieraj!cych dynamicznie generowan! tre&';

ekstrakcj% i t#umaczenie tekstów;

t#umaczenie rekordów baz danych za pomoc! zachowania

Translate

;

ustawianie i zapami%tywanie j%zyka.

Wprowadzenie

W tym rozdziale zajmiemy si% przyk#adami, które pozwol! na internacjonalizacj% — umi%-
dzynarodowienie — wszystkich elementów aplikacji CakePHP, zarówno statycznych (zawartych
np. w widokach), jak i dynamicznych (np. rekordy baz danych).

W pierwszych dwóch przyk#adach poka$emy, jak udost%pni' elementy widoków, a tak$e ko-
munikaty walidacji modelu do t#umacze". W trzecim przyk#adzie b%dziemy t#umaczy' bardziej
z#o$one wyra$enia. Czwarty przyk#ad to pokaz mo$liwo&ci wbudowanych narz%dzi CakePHP,
które potrafi! wy#uska' statyczn! tre&' aplikacji wymagaj!c! t#umaczenia. Pi!ty przyk#ad
przedstawia mechanizm t#umaczenia rekordów baz danych. Na zako"czenie dowiesz si%, jak
umo$liwi' u$ytkownikowi zmian% aktywnego j%zyka aplikacji.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

250

Internacjonalizacja tekstów

w kontrolerach i widokach

W tym przyk#adzie dowiesz si%, jak zinternacjonalizowa' tekst, który znajduje si% w widokach
naszej aplikacji, a tak$e jak przygotowa' takie teksty do t#umaczenia.

Zanim zaczniesz

Aby wykona' poni$szy przyk#ad, musisz skorzysta' z przyk#adowych danych. Utwórz tabel%

articles

, korzystaj!c z poni$szego zapytania SQL:

CREATE TABLE 'articles'(
'id' INT UNSIGNED AUTO_INCREMENT NOT NULL,
'title' VARCHAR(255) NOT NULL,
'body' TEXT NOT NULL,
'created' DATETIME NOT NULL,
'modified' DATETIME NOT NULL,
PRIMARY KEY('id')
);

Teraz dodaj kilka rekordów, korzystaj!c z poni$szych zapyta" SQL:

INSERT INTO 'articles'('title', 'body', 'created', 'modified') VALUES
('First article', 'The body of the first article.', NOW(), NOW()),
('Second article', 'The body of the second article.', NOW(), NOW()),
('Third article', 'The body of the third article.', NOW(), NOW());

Utwórz plik app/controllers/articles_controller.php i umie&' w nim kontroler o nast%puj!cej
tre&ci:

<?php
class ArticlesController extends AppController {
public function index() {
$this->paginate['limit'] = 2;
$articles = $this->paginate();
$this->set(compact('articles'));
}
public function add() {
if (!empty($this->data)) {
$this->Article->create();
if ($this->Article->save($this->data)) {
$this->Session->setFlash('Article saved!');
$this->redirect(array('action'=>'index'));
} else {
$this->Session->setFlash('Please correct errors!');
}
}

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

251

}
public function view($id) {
$article = $this->Article->find('first', array(
'conditions' => array('Article.id' => $id)
));
if (empty($article)) {
$this->cakeError('error404');
}
$this->set(compact('article'));
}
}
?>

W dalszej kolejno&ci utwórz plik app/models/article.php o nast%puj!cej tre&ci:

<?php
class Article extends AppModel {
public $validate = array(
'title' => 'notEmpty',
'body' => 'notEmpty'
);
}
?>

Utwórz podkatalog app/views/articles, po czym dodaj do niego plik index.ctp o nast%puj!cej
tre&ci:

<h1>Articles</h1>
<p>
<?php echo $this->Paginator->counter(); ?>
&nbsp;-&nbsp;
<?php echo $this->Paginator->prev(); ?>
&nbsp;
<?php echo $this->Paginator->numbers(); ?>
&nbsp;
<?php echo $this->Paginator->next(); ?>
</p>
<p>
<?php echo count($articles) . ' articles: '; ?>
</p>
<ul>
<?php foreach($articles as $article) { ?>
<li><?php echo $this->Html->link(
$article['Article']['title'],
array('action'=>'view', $article['Article']['id'])
); ?></li>
<?php } ?>
</ul>
<p><?php echo $this->Html->link('Create article', array('action'=>'add'));
?></p>

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

252

Do katalogu app/views/articles dodaj plik add.ctp o nast%puj!cej tre&ci:

<?php
echo $this->Form->create();
echo $this->Form->inputs(array(
'legend' => 'Create article',
'title' => array('label' => 'Title'),
'body' => array('label' => 'Body')
));
echo $this->Form->end('Save');
?>

Na zako"czenie dodaj plik app/views/articles/view.ctp o nast%puj!cej tre&ci:

<h1><?php echo $article['Article']['title']; ?></h1>
<?php echo $article['Article']['body']; ?>

Jak to zrobi(

1. Zmodyfikuj tre&' pliku app/controllers/articles_controller.php, uwzgl%dniaj!c

zmiany zaznaczone pogrubion! czcionk! w metodzie

add()

:

public function add() {

if (!empty($this->data)) {

$this->Article->create();
if ($this->Article->save($this->data)) {
$this->Session->setFlash(__('Article saved', true));
$this->redirect(array('action'=>'index'));
} else {
$this->Session->setFlash(__('Please correct the errors', true));
}
}
}

2. Otwórz plik app/views/articles/add.ctp i wprowad= zaznaczone pogrubion!

czcionk! zmiany:

<?php
echo $this->Form->create();
echo $this->Form->inputs(array(
'legend' => __('New Article', true),
'title' => array('label' => __('Title:', true)),
'body' => array('label' => __('Body:', true))
));
echo $this->Form->end(__('Save', true));
?>

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

253

3. Otwórz plik app/views/articles/index.ctp i wprowad= nast%puj!ce zmiany:

<h1><?php __('Articles'); ?></h1>
<p>
<?php echo $this->Paginator->counter(__('Showing records %start%-%end% in
page %page% out of %pages%', true)); ?>
&nbsp;-&nbsp;
<?php echo $this->Paginator->prev(__('<< Previous', true)); ?>
&nbsp;
<?php echo $this->Paginator->numbers(); ?>
&nbsp;
<?php echo $this->Paginator->next(__('Next >>', true)); ?>
</p>
<p>
<?php
$count = count($articles);
echo $count . ' ' . __n('article', 'articles', $count, true) . ': ';
?>
</p>
<ul>
<?php foreach($articles as $article) { ?>
<li><?php echo $this->Html->link(
$article['Article']['title'],
array('action'=>'view', $article['Article']['id'])
); ?></li>
<?php } ?>
</ul>
<p><?php echo $this->Html->link(__('Create article', true),
array('action'=>'add')); ?></p>

Przejd= na stron% http://localhost/articles. Powiniene& otrzyma' stronicowan! list% artyku#ów
podobn! do przedstawionej na poni$szym rysunku.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

254

Jak to dzia a

Dwie najwa$niejsze metody udost%pniane przez CakePHP do t#umaczenia to

__()

i

__n()

.

Nazwy metod mog! wyda' si% nieco dziwne; ich pochodzenie wywodzi si% od implementacji
narz%dzia gettext w j%zyku Perl — narz%dzie to stanowi element Projektu T#umaczenia GNU
(GNU Translation Project).

Metoda

__()

jest u$ywana do t#umaczenia tekstów statycznych i przyjmuje dwa parametry

opisane w poni$szej tabeli.

Parametr

Opis

singular

Tekst, który ma by' przet$umaczony.

return

Je%li ten parametr ma warto%'

true

, przet$umaczony tekst zostanie zwrócony, a nie

przes$any do klienta. Domy%lnie

false

.

Metoda

__n()

równie$ pozwala na t#umaczenie tekstów statycznych, jednak uwzgl%dnia ona

tak$e sytuacje, w których konkretna warto&' mo$e zale$e' od liczby — pojedynczej lub mno-
giej. W zwi!zku z tym przyjmuje ona cztery parametry wymienione w poni$szej tabeli.

Parametr

Opis

singular

Tekst, który zostanie przet$umaczony na aktywny j!zyk, je%li parametr

count otrzyma

warto%'

singular

.

plural

Tekst, który zostanie przet$umaczony na aktywny j!zyk, je%li parametr

count otrzyma

warto%'

plural

.

count

Zmienna lub warto%' liczbowa, która zostanie wykorzystana do okre%lenia liczby dla danego
tekstu (

singular

lub

plural

).

return

Je%li ten parametr ma warto%'

true, przet$umaczony tekst zostanie zwrócony, a nie przes$any

do klienta. Domy%lnie

false

.

Rozpoczynamy od zmiany komunikatów generowanych przez klas%

ArticlesController

, wy-

korzystuj!c funkcj%

__()

. Zastrzegamy, $e teksty maj! by' zwracane, a nie przesy#ane do klienta.

Nast%pnie modyfikujemy plik add.ctp, dzi%ki czemu wszystkie etykiety formularza (wraz z jego
legend!) zostan! przet#umaczone.

W podobny sposób opakowujemy tytu# w widoku index.ctp za pomoc! funkcji t#umaczenia.
Nast%pnie korzystamy z pierwszego parametru metod

counter()

,

next()

i

prev()

(stanowi!-

cych sk#adowe klasy

PaginatorHelper

), aby przekaza' przet#umaczone wersje wszystkich tek-

stowych elementów mechanizmu stronicowania. Na zako"czenie korzystamy z funkcji

__n()

,

by wybra' odpowiedni przet#umaczony tekst przy u$yciu warto&ci zmiennej

count

.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

255

Je%li korzystasz z funkcji

__n(), musisz pami!ta', "e trzecim argumentem w wywo$aniach tej funkcji

powinna by' zawsze zmienna, a nie wyra"enie (np. zawieraj#ce indeksy tablic). Wyra"enia mog# do-
prowadzi' do zwrócenia nieoczekiwanych wyników podczas wywo$ywania pow$oki ekstraktora (por.
przyk$ad „Ekstrakcja i t$umaczenie tekstów”).

Domeny i kategorie

Funkcje t#umacze" wykorzystywane w tym przyk#adzie opakowuj! funkcj%

translate()

nale-

$!c! do klasy

I18n

frameworka CakePHP. Metoda ta pozwala nie tylko na przeprowadzanie

prostych t#umacze"; dzi%ki niej programista mo$e okre&li' domen%, z której s! pozyskiwane
t#umaczone teksty, a tak$e kategori%, do której nale$y tekst do t#umaczenia.

Domeny pozwalaj! na wydzielanie grup t#umaczonych tekstów do osobnych plików. Domy&l-
nie, gdy domena nie jest okre&lona jawnie, CakePHP korzysta z domeny

default

(domy&lnej).

Je&li chcesz okre&li' domen%, w której CakePHP powinien szuka' t#umaczonego tekstu, sko-
rzystaj z funkcji

__d()

lub

__dn()

. Wyszukanie t#umaczonego tekstu w domenie

moja_wtyczka

wygl!da#oby nast%puj!co:

$translated = __d('moja_wtyczka', 'Hello World', true);

Kategorie umo$liwiaj! jeszcze wi%ksz! kontrol% nad zarz!dzaniem t#umaczonymi tekstami.
Pozwalaj! one na grupowanie plików t#umacze" w odr%bnych katalogach; mo$na tak$e po-
wi!za' t#umaczony tekst z dodatkowymi metadanymi. Domy&lnie CakePHP zak#ada, $e t#u-
maczone teksty nale$! do kategorii

LC_MESSAGES

. Je&li chcesz zmieni' kategori%, skorzystaj z funk-

cji t#umaczenia

__dc()

i

__dcn()

, ustawiaj!c przedostatni argument —

return

— na wybran!

kategori%. Mo$e ona przyjmowa' jedn! z okre&lonych poni$ej warto&ci:

LC_ALL

:

0

;

LC_COLLATE

:

1

;

LC_CTYPE

:

2

;

LC_MONETARY

:

3

;

LC_NUMERIC

:

4

;

LC_TIME

:

5

;

LC_MESSAGES

:

6

.

Próba znalezienia nale$!cego do kategorii

LC_MESSAGES

tekstu Hello World w domenie

default

wygl!da nast%puj!co:

$translated = __dc('default', 'Hello World', 6, true);

Korzystaj#c z kategorii, zawsze podawaj warto%ci liczbowe, a nie nazwy sta$ych. Te ostatnie s# bowiem
zale"ne od wykorzystywanej platformy.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

256

Zobacz równie/

„Internacjonalizacja komunikatów walidacji w modelach”;

„Ekstrakcja i t#umaczenie tekstów”.

Internacjonalizacja komunikatów

walidacji w modelach

W tym przyk#adzie wykorzystamy ró$ne sposoby na zrealizowanie tego samego zadania: t#u-
maczenia komunikatów walidacji w modelach.

Zanim zaczniesz

Aby wykona' ten przyk#ad, musimy skorzysta' z podstawowego szkieletu aplikacji. W tym
celu musisz wykona' poprzedni przyk#ad.

Jak to zrobi(

Zmie" tre&' pliku app/models/article.php, wprowadzaj!c zmiany zaznaczone pogrubion!
czcionk! we w#a&ciwo&ci

validate

:

public $validate = array(
'title' => array(
'required' => 'notEmpty'
),
'body' => array(
'required' => 'notEmpty'
)
);

Istniej! dwa sposoby t#umaczenia komunikatów walidacji. Pierwszy z nich wymaga przes#o-
ni%cia konstruktora modelu. Wystarczy doda' jego poni$sz! implementacj% do klasy

Article

w pliku app/models/article.php:

public function __construct($id = false, $table = null, $ds = null) {
foreach($this->validate as $field => $rules) {
if (!is_array($rules)) {
$rules = (array) $rules;
}
foreach($rules as $key => $rule) {

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

257

if (!is_array($rule)) {
$rules[$key] = compact('rule');
}
}
$this->validate[$field] = $rules;
}
$this->validate = Set::merge($this->validate, array(
'title' => array(
'required' => array('message'
=> __('A title must be specified', true))
),
'body' => array(
'required' => array('message'
=> __('You must define the body', true))
)
));
parent::__construct($id, $table, $ds);
}

Inn! metod! t#umaczenia komunikatów walidacji jest przeniesienie komunikatów do widoku.
W ten sposób zamiast przes#ania' konstruktor i deklarowa' w nim komunikaty, wystarczy
wprowadzi' zmiany w pliku app/views/articles/add.ctp:

<?php
echo $this->Form->create();
echo $this->Form->inputs(array(
'title' => array(
'label' => __('Title:', true),
'error' => array(
'required' => __('A title must be specified', true)
)
),
'body' => array(
'label' => __('Body:', true),
'error' => array(
'required' => __('You must define the body', true)
)
)
));
echo $this->Form->end(__('Save', true));
?>

Obie metody doprowadz! do uzyskania takiego samego efektu. Przejd= na stron% http://
localhost/articles/add
i wy&lij formularz bez wprowadzania jakichkolwiek warto&ci. Powiniene&
uzyska' efekt jak na poni$szym rysunku.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

258

Jak to dzia a

Przed utworzeniem komunikatów o b#%dach dla ka$dej z regu# walidacji musimy owe regu#y
nazwa'. W tym celu modyfikujemy model

Article

, dzi%ki czemu ka$da z regu# jest indekso-

wana przy u$yciu nazwy. W naszym przypadku wybieramy nazw%

required

dla regu#y Cake-

PHP o nazwie

notEmpty

.

Pierwsze rozwi!zanie problemu t#umaczenia komunikatów walidacji mo$na okre&li' mianem
scentralizowanego — wszystkie komunikaty s! umieszczone w tym samym miejscu, w kon-
struktorze modelu. Przes#aniamy konstruktor, dzi%ki czemu mo$emy w jego wn%trzu zadekla-
rowa' komunikaty o b#%dach, które powinny by' przet#umaczone. Musieli&my skorzysta'
z konstruktora, poniewa$ w#a&ciwo&ci klas mog! zawiera' tylko statyczne przypisania. Poni$szy
blok kodu spowoduje b#!d sk#adni PHP:

public $validate = array(
'title' => array(
'required' => array(
'rule' => 'notEmpty',
'message' => __('Nothing defined!', true) // B "D SK ADNI

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

259

)
)
);

W implementacji konstruktora rozpoczynamy od sprawdzenia, czy w#a&ciwo&'

validate

sta-

nowi tablic% regu# (indeksowanych przy u$yciu nazw pól). Musimy tak$e sprawdzi', czy ka$-
da regu#a sama w sobie równie$ stanowi tablic% (indeksowan! za pomoc! nazw), której warto-
&ciami s! ponownie tablice, zawieraj!ce przynajmniej ustawienie

rule

.

Po zweryfikowaniu formatu w#a&ciwo&ci

validate

mo$emy po#!czy' komunikaty walidacji dla

ka$dej z regu#, korzystaj!c z funkcji

__()

w celu przet#umaczenia komunikatów. Na zako"-

czenie wywo#ujemy konstruktor klasy bazowej, aby poprawnie zako"czy' proces tworzenia
ca#ego modelu.

Drugie podej&cie do problemu t#umaczenia przedstawione w tym przyk#adzie przesuwa odpo-
wiedzialno&' za obs#ug% t#umacze" na widok, korzystaj!c z ustawienia

error

dost%pnego w meto-

dzie

input()

klasy

FormHelper

. To ustawienie otrzymuje tablic% indeksowan! za pomoc! nazw

regu# walidacji, której warto&ciami s! komunikaty o b#%dach wykorzystywane w razie niespe#-
nienia poszczególnych regu# walidacji.

Zobacz równie/

„Ekstrakcja i t#umaczenie tekstów”.

T$umaczenie tekstów zawieraj"cych

dynamicznie generowan" tre!+

W tym przyk#adzie dowiesz si%, jak t#umaczy' teksty, które zawieraj! elementy dynamiczne
— np. warto&ci zmiennych.

Zanim zaczniesz

Aby wykona' ten przyk#ad, musimy skorzysta' z podstawowego szkieletu aplikacji. W tym
celu musisz wykona' przyk#ad „Internacjonalizacja tekstów w kontrolerach i widokach”.

Jak to zrobi(

1. Otwórz plik app/controllers/articles_controller.php i wprowad= zaznaczone

pogrubion! czcionk! zmiany w metodzie

add()

:

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

260

public function add() {
if (!empty($this->data)) {
$this->Article->create();
if ($this->Article->save($this->data)) {
$this->Session->setFlash(
sprintf(__('Article "%s" saved', true), $this->Article->
field('title'))
);
$this->redirect(array('action'=>'index'));
} else {
$this->Session->setFlash('Prosz7 poprawiy b:7dy!');
}
}
}

2. Otwórz plik app/views/articles/index.ctp i wprowad= w nim zaznaczone pogrubion!

czcionk! zmiany:

<h1><?php __('Articles'); ?></h1>
<p>
<?php echo $this->Paginator->counter(__('Showing records %start%-
%end% in page %page% out of %pages%', true)); ?>
&nbsp;-&nbsp;
<?php echo $this->Paginator->prev(__('<< Previous', true)); ?>
&nbsp;
<?php echo $this->Paginator->numbers(); ?>
&nbsp;
<?php echo $this->Paginator->next(__('Next >>', true)); ?>
</p>
<p>
<?php
$count = count($articles);
printf(__n('%d article', '%d articles', $count, true), $count);
?>
</p>
<ul>
<?php foreach($articles as $article) { ?>
<li><?php echo $this->Html->link(
$article['Article']['title'],
array('action'=>'view', $article['Article']['id'])
); ?></li>
<?php } ?>
</ul>
<p><?php echo $this->Html->link(__('Create article', true),
array('action'=>'add')); ?></p>

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

261

Jak to zrobi(

Gdy podczas tworzenia aplikacji napotyka si% problem t#umaczenia tre&ci zawieraj!cych ele-
menty dynamiczne — np. warto&' zmiennej lub warto&' pola z bazy danych — mo$e si% po-
jawi' pokusa do#!czenia zmiennej do #a"cucha statycznego, a nast%pnie przekazania takiego
wyra$enia do funkcji t#umaczenia:

$translated = __('Hello ' . $name, true); // $LE

To wyra$enie nie jest poprawne, poniewa$ ekstraktor CakePHP (omówiony w przyk#adzie
„Ekstrakcja i t#umaczenie tekstów”) dzia#a poprawnie tylko dla tekstów statycznych. W innych j%-
zykach mo$e na przyk#ad wyst!pi' konieczno&' zmiany kolejno&ci s#ów w zdaniu. W zwi!zku
z tym musimy skorzysta' z innej techniki przetwarzania #a"cuchów. Rozwi!zanie jest proste
i stosunkowo popularne — funkcje PHP

printf()

i

sprintf()

.

Obie funkcje przyjmuj! te same argumenty. Pierwszy z nich jest obowi!zkowy i okre&la #a"-
cuch znaków do sformatowania. Wszystkie kolejne argumenty przekazane do funkcji zostan!
wykorzystane do wygenerowania wynikowego #a"cucha znaków. Jedyna ró$nica pomi%dzy
funkcjami

printf()

a

sprintf()

polega na tym, $e pierwsza z nich wy&wietli efekt swojej pra-

cy, druga za& — zwróci go.

Przejd=my teraz do kodu naszej aplikacji. Rozpoczynamy od zmiany komunikatu zwracanego
przez klas%

ArticlesController

po utworzeniu artyku#u. Korzystamy z funkcji

sprintf()

, ponie-

wa$ efekt jej dzia#ania chcemy przekaza' do metody

setFlash()

komponentu

Session

. W na-

szej sytuacji wyra$enie

%s

pozwala na wstawienie do #a"cucha znaków tytu#u nowo utworzo-

nego artyku#u.

W podobny sposób podstawiamy warto&' zmiennej

count

pod ci!g

%d

. Tym razem korzystamy

z funkcji

printf()

, aby wy&wietli' od razu efekt dzia#ania funkcji.

Zmiana kolejno0ci argumentów

Gdy korzystamy z wyra$e"

%s

lub

%d

w funkcjach

printf()

i

sprintf()

, nie mamy kontroli nad

sposobem pozycjonowania warto&ci; nie mo$emy te$ u$y' dwa razy jednej warto&ci, poniewa$
ka$de z wyra$e" jest dopasowywane do konkretnego, pojedynczego argumentu. Za#ó$my, $e
dysponujemy nast%puj!cym wyra$eniem:

printf('Your name is %s and your country is %s', $name, $country);

Pierwsze wyra$enie

%s

zostanie zast!pione warto&ci! zmiennej

name

, drugie — warto&ci!

zmiennej

country

. Problem pojawi#by si% w sytuacji, w której chcieliby&my zmieni' kolejno&'

argumentów w #a"cuchu znaków, zachowuj!c jednocze&nie kolejno&' argumentów w obr%bie
wywo#ania funkcji

printf()

.

Na szcz%&cie do argumentów funkcji

printf()

mo$emy si% odwo#ywa', korzystaj!c z ich nu-

merów porz!dkowych (okre&laj!cych ich pozycj% w&ród wszystkich argumentów przekaza-
nych w danym wywo#aniu). W poni$szym przyk#adzie

name

jest argumentem

1

, a

country

argumentem

2

:

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

262

printf('You are from %2$s and your name is %1$s', $name, $country);

Takie podej&cie pozwala na ponowne u$ycie argumentu bez konieczno&ci podawania go wie-
lokrotnie w wywo#aniu funkcji

printf()

:

printf('You are from %2$s and your name is %1$s . Welcome %1$s!', $name,
$country);

Zobacz równie/

„Ekstrakcja i t#umaczenie tekstów”.

Ekstrakcja i t$umaczenie tekstów

W tym przyk#adzie nauczymy si% pozyskiwa' wszystkie #a"cuchy znaków, które podlegaj!
t#umaczeniu w naszych aplikacjach CakePHP, a nast%pnie przeprowadzimy proces t#umacze-
nia, korzystaj!c z darmowego oprogramowania.

Zanim zaczniesz

Aby wykona' ten przyk#ad, musimy skorzysta' z podstawowego szkieletu aplikacji. W tym
celu musisz wykona' przyk#ad „Internacjonalizacja tekstów w kontrolerach i widokach”.

Musisz tak$e zainstalowa' aplikacj% Poedit w swoim systemie. Przejd= na stron% http://www.
poedit.net/download.php
, a nast%pnie pobierz plik dla swojego systemu operacyjnego.

Jak to zrobi(

Przejd= do podkatalogu app/ Twojej aplikacji w wierszu polece", a nast%pnie wykonaj poni$sze
polecenie:

je&li pracujesz w systemach GNU Linux/Mac/Unix:

../cake/console/cake i18n extract

je&li jeste& u$ytkownikiem systemu Microsoft Windows:

..\cake\console\cake.bat i18n extract

Powiniene& skorzysta' z ustawie" domy&lnych, jak przedstawiono na kolejnym rysunku.

Po udzieleniu odpowiedzi na ostatnie pytanie pow#oka przeszuka wszystkie pliki Twojej apli-
kacji i na ich podstawie wygeneruje szablon t#umaczenia. Zostanie on umieszczony w pliku
app/locale/default.pot.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

263

Otwórz plik Poedit, a nast%pnie wybierz opcj% Nowy katalog z pliku POT z menu Plik. Pro-
gram wy&wietli okno wyboru pliku. Przejd= do podkatalogu app/locale Twojej aplikacji, za-
znacz plik default.pot i kliknij przycisk Otwórz. Zostanie wy&wietlone okno ustawie" przed-
stawione na poni$szym rysunku.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

264

W oknie Ustawienia wprowad= nazw% projektu i informacje z nim zwi!zane. W polu Formy
liczby mnogiej
powiniene& wprowadzi' wyra$enie, przy u$yciu którego Poedit b%dzie w stanie
rozpozna' t#umaczenia dla liczb mnogich. W wielu j%zykach (np. angielskim, hiszpa"skim,
niemieckim i portugalskim) wystarczy wprowadzi' poni$sze wyra$enie:

nplurals=2; plural=(n != 1);

Wi!cej informacji na temat liczb mnogich i warto%ci, które powinno si! wobec nich stosowa' (w zale"-
no%ci od t$umaczonego j!zyka) znajdziesz na stronie

http://drupal.org/node/17564

.

Po wprowadzeniu wszystkich istotnych informacji kliknij przycisk OK. W tym momencie pro-
gram zapyta, gdzie chcesz zapisa' przet#umaczony plik. Utwórz katalog o nazwie pol i umie&' go
w katalogu app/locale/. Wewn!trz katalogu pol utwórz podkatalog LC_MESSAGES. Nast%pnie
przy u$yciu okna dialogowego programu Poedit wybierz folder app/locale/pol/LC_MESSAGES,
po czym kliknij przycisk Zapisz, nie zmieniaj!c przy tym nazwy pliku — powinna mie' war-
to&' default.po.

Program Poedit zaprezentuje wszystkie oryginalne #a"cuchy znaków. Do ka$dego z nich
mo$na doda' t#umaczenie. Wystarczy wybra' jeden z oryginalnych tekstów, a nast%pnie
wprowadzi' tre&' t#umaczenia w polu umieszczonym w dolnej cz%&ci okna. Po wprowadzeniu
t#umacze" okno programu Poedit powinno wygl!da' tak, jak na kolejnej rysunku.

Wybierz opcj% Zapisz z menu Plik, aby zapisa' przet#umaczony plik. W katalogu app/locale/
pol/LC_MESSAGES
powinny by' dost%pne dwa pliki: default.po i default.mo.

Jak to dzia a

Na samym pocz!tku ekstraktor CakePHP musi otrzyma' &cie$ki do katalogów, które maj! by'
przez niego przetworzone. Nast%pnie mechanizm rekursywnie przegl!da wszystkie katalogi,
próbuj!c znale=' wszystkie wywo#ania funkcji t#umaczenia (

__()

,

__n()

,

__d()

,

__dn()

,

__dcn()

i

__c()

) w plikach PHP i plikach widoków. Dla ka$dego znalezionego wywo#ania ekstraktor

wy#uska z niego tekst do przet#umaczenia (pierwszy argument wywo#a" funkcji

__n()

i

__c()

;

drugi argument wywo#a" funkcji

__d()

i

__dc()

; pierwszy i drugi argument wywo#a" funkcji

__n()

; drugi i trzeci argument wywo#a" funkcji

__dn()

i

__dcn()

).

W argumentach, które s# wy$uskiwane przez ekstraktor, nale"y stosowa' jedynie statyczne $a+cuchy
znaków PHP. Nie mo"na w "adnym przypadku u"ywa' wyra"e+ PHP. Je%li w t$umaczonych tekstach
chcesz stosowa' zmienne lub inne wyra"enia dynamiczne, zapoznaj si! z przyk$adem „T$umaczenie tek-
stów zawieraj#cych dynamicznie generowan# tre%'”.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

265

Po pobraniu wszystkich tekstów do t#umaczenia przez ekstraktor zostan! utworzone odpo-
wiednie szablony plików t#umacze". Je&li w swojej aplikacji korzystasz z funkcji t#umacze",
które maj! zwi!zek z domenami (

__d()

,

__dn()

,

__dc()

i

__dcn()

), mo$esz uwzgl%dni' wszystkie

#a"cuchy w jednym pliku szablonu albo umie&ci' ka$d! domen% w odr%bnym pliku szablonu.
Pliki szablonów maj! rozszerzenie pot; ich nazwy s! za& nazwami domen (np. default.pot jest
domy&lnym (default) plikiem szablonu).

Je&li otworzysz plik default.pot w zwyk#ym edytorze tekstowym, zauwa$ysz, $e rozpoczyna si%
on od nag#ówka zawieraj!cego wiele ró$nych ustawie", po którym nast%puje w#a&ciwa cz%&'
t#umaczenia. Ka$dy #a"cuch do t#umaczenia jest reprezentowany za pomoc! dwóch linijek —
pierwsza z nich zawiera element oznaczony ci!giem

msgid

(#a"cuch do t#umaczenia), w drugiej

za& znajduje si% ci!g

msgstr

— to w#a&nie tam nale$y wstawia' przet#umaczone #a"cuchy znaków.

Program Poedit umo$liwia wygodn! edycj% plików w formacie pot, a tak$e zapisuje pliki do
odpowiedniego katalogu (app/locale/pol/LC_MESSAGES). W katalogu tym znajduj! si% dwa
pliki — default.po i default.pot. Je&li otworzysz plik .po za pomoc! zwyk#ego edytora, powiniene&
natychmiast dostrzec podobie"stwo tego pliku do pliku szablonu. Wyj!tek stanowi! ustawie-

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

266

nia nag#ówka — zawieraj! one warto&ci okre&lone przez nas w programie Poedit — i przede
wszystkim tre&' t#umacze" wprowadzonych przez nas w aplikacji Poedit. Plik default.mo stanowi
binarn! wersj% pliku default.po, tak$e wygenerowanego przez Poedit. Plik default.mo jest
wykorzystywany przez CakePHP w celu szybszego przetwarzania pliku t#umacze".

T$umaczenie rekordów baz danych
za pomoc" zachowania Translate

W tym przyk#adzie nauczymy si% t#umaczy' rekordy z bazy danych za pomoc! zachowania

Translate

.

Zanim zaczniesz

Aby wykona' ten przyk#ad, musimy skorzysta' z podstawowego szkieletu aplikacji. W tym
celu musisz wykona' przyk#ad „Internacjonalizacja tekstów w kontrolerach i widokach”.

Jak to zrobi(

Uruchom wiersz polece", a nast%pnie przejd= do podkatalogu app/ aplikacji i wykonaj poni$sze
polecenie.

je&li pracujesz w systemach GNU Linux/Mac/Unix:

../cake/console/cake i18n initdb

je&li jeste& u$ytkownikiem systemu Microsoft Windows:

..\cake\console\cake.bat i18n initdb

Zaakceptuj domy&lne opcje. Po wybraniu wszystkich opcji pow#oka utworzy tabel%

i18n

, co

przedstawiono na kolejnym rysunku.

Zmodyfikuj tre&' pliku app/models/article.php zgodnie z poni$szym listingiem:

<?php
class Article extends AppModel {
public $validate = array(
'title' => 'notEmpty',
'body' => 'notEmpty'
);
public $actsAs = array(
'Translate' => array('title', 'body')
);
}
?>

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

267

Teraz musimy przenie&' warto&ci pól

title

i

body

z tabeli

articles

do tabeli

i18n

, a nast%pnie

— usun!' oryginalne kolumny z tabeli

articles

. Wykonaj poni$sze zapytania SQL:

INSERT INTO 'i18n'('locale', 'model', 'foreign_key', 'field', 'content')
SELECT 'eng', 'Article', 'articles'.'id', 'title', 'articles'.'title'
FROM 'articles';

INSERT INTO 'i18n'('locale', 'model', 'foreign_key', 'field', 'content')
SELECT 'eng', 'Article', 'articles'.'id', 'body', 'articles'.'body'
FROM 'articles';

ALTER TABLE 'articles'
DROP COLUMN 'title',
DROP COLUMN 'body';

Dodaj polskie t#umaczenia naszych artyku#ów, wykonuj!c poni$sze zapytania SQL:

INSERT INTO 'i18n'('locale', 'model', 'foreign_key', 'field', 'content') VALUES
('pol', 'Article', 1, 'title', 'Pierwszy artyku:'),
('pol', 'Article', 1, 'body', 'Tre]y pierwszego artyku:u'),
('pol', 'Article', 2, 'title', 'Drugi artyku:'),
('pol', 'Article', 2, 'body', 'Tre]y drugiego artyku:u'),
('pol', 'Article', 3, 'title', 'Trzeci artyku:'),
('pol', 'Article', 3, 'body', 'Tre]y trzeciego artyku:u');

Na zako"czenie wstaw poni$sz! instrukcj% na ko"cu pliku app/config/bootstrap.php, tu$ przed
znacznikiem zamykaj!cym PHP:

Configure::write('Config.language', 'eng');

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

268

Przejd= na stron% http://localhost/articles. Powiniene& zobaczy' ten sam wykaz artyku#ów, który
przedstawiono w pierwszym przyk#adzie w tym rozdziale.

Jak to dzia a

Rozpoczynamy od utworzenia tabeli wymaganej przez zachowanie

Translate

, korzystaj!c

z pow#oki

i18n

. Nosi ona tak! sam! nazw% i zawiera (poza kluczem g#ównym) pola opisane

w poni$szej tabeli.

Pole

Opis

locale

J!zyk t$umaczenia danego rekordu.

model

Model, do którego nale"y t$umaczony rekord.

foreign_key

ID (klucz g$ówny) w modelu, który identyfikuje t$umaczony rekord.

field

Nazwa pola, które podlega t$umaczeniu.

content

Przet$umaczona warto%' dla danego pola.

Nast%pnie mo$emy doda' zachowanie

Translate

do modelu

Article

i ustawi' je tak, aby by#y

t#umaczone pola

title

i

body

. Taki zapis sprawi, $e pola te nie b%d! wchodzi#y w sk#ad tabeli

articles

— od tego momentu b%d! one przechowywane w tabeli

i18n

. Korzystaj!c z warto&ci

model

i

foreign_key

w tabeli

i18n

, zachowanie

Translate

pobierze odpowiednie warto&ci dla

danych pól przy ka$dym pobraniu rekordu modelu

Article

(dla aktywnego j%zyka).

Kopiujemy warto&ci pól

title

i

body

do tabeli

i18n

, dzi%ki czemu mo$emy usun!' pola z ta-

beli

articles

. Wywo#anie funkcji

call()

wykorzystywane w klasie

ArticlesController

nie

wymaga $adnych zmian. Co wi%cej, proces tworzenia artyku#ów b%dzie przebiega# bez $ad-
nych modyfikacji, poniewa$ zachowanie

Translate

skorzysta z aktywnego j%zyka podczas za-

pisywania rekordów modelu

Article

.

Na zako"czenie musimy wybra' j%zyk domy&lny. W tym celu korzystamy z ustawienia

Config.language

. Pomini%cie tego kroku spowoduje ustawienie j%zyka na podstawie warto&ci

nag#ówka

HTTP_ACCEPT_LANGUAGE

wysy#anego przez przegl!darki.

Wykorzystywanie odr*bnych tabel t umaczenia

Wszystkie modele, które korzystaj! z zachowania

Translate

, b%d! zapisywa' t#umaczenia

swoich pól domy&lnie do tabeli

i18n

. Takie zachowanie mo$e by' nieco problematyczne, je&li

dysponujemy du$! liczb! rekordów lub du$! liczb! t#umaczonych modeli. Na szcz%&cie za-
chowanie

Translate

pozwala na skonfigurowanie innego modelu t#umaczenia.

W ramach przyk#adu zapiszemy wszystkie t#umaczenia zwi!zane z artyku#ami do tabeli

article_translations

. Utwórz tabel%, a nast%pnie skopiuj rekordy z tabeli

i18n

, korzystaj!c

z poni$szych zapyta" SQL:

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

269

CREATE TABLE 'article_translations'(
'id' INT UNSIGNED AUTO_INCREMENT NOT NULL,
'model' VARCHAR(255) NOT NULL,
'foreign_key' INT UNSIGNED NOT NULL,
'locale' VARCHAR(6) NOT NULL,
'field' VARCHAR(255) NOT NULL,
'content' TEXT default NULL,
KEY 'model__foreign_key'('model', 'foreign_key'),
KEY 'model__foreign_key__locale'('model', 'foreign_key', 'locale'),
PRIMARY KEY('id')
);
INSERT INTO 'article_translations'
SELECT 'id', 'model', 'foreign_key', 'locale', 'field', 'content'
FROM 'i18n';

Utwórz plik app/models/article_translation.php i wstaw do niego poni$szy kod:

<?php
class ArticleTranslation extends AppModel {
public $displayField = 'field';
}
?>

W#a&ciwo&'

displayField

w modelu t#umacze" poinformuje zachowanie

Translate

o tym,

które pole tabeli przechowuje nazw% t#umaczonego pola.

Na zako"czenie wprowad= zaznaczone pogrubion! czcionk! zmiany w pliku app/models/
article.php
:

<?php
class Article extends AppModel {
public $validate = array(
'title' => 'notEmpty',
'body' => 'notEmpty'
);
public $actsAs = array(
'Translate' => array('title', 'body')
);
public $translateModel = 'ArticleTranslation';
}
?>

Zobacz równie/

„Ustawianie i zapami%tywanie j%zyka”.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

270

Ustawianie i zapami%tywanie j%zyka

W tym przyk#adzie dowiesz si%, jak udost%pni' u$ytkownikom mo$liwo&' zmiany j%zyka apli-
kacji, a tak$e jak zapami%ta' ich wybór za pomoc! ciasteczek (ang. cookies).

Zanim zaczniesz

Aby wykona' ten przyk#ad, niezb%dna b%dzie w pe#ni umi%dzynarodowiona aplikacja. W tym celu
musisz wykona' ca#y przyk#ad „T#umaczenie rekordów baz danych za pomoc! zachowania
Translate”.

Musimy tak$e skorzysta' z uk#adu aplikacji, który mo$emy modyfikowa'. Skopiuj plik default.ctp
z katalogu cake/libs/view/layouts do katalogu app/views/layouts.

Jak to zrobi(

1. Dodaj poni$sze instrukcje na ko"cu pliku app/config/bootstrap.php, tu$ przed

znacznikiem zamykaj!cym PHP:

Configure::write('Config.languages', array(
'eng' => __('English', true),
'pol' => __('Polski', true)
));

2. Zmie" uk#ad pliku app/views/layouts/default.ctp, dodaj!c w wybranym przez siebie

miejscu list% j%zyków (np. przed wywo#aniem metody

flash()

w komponencie

Session

):

<div style="float: right">
<?php
$links = array();
$currentLanguage = Configure::read('Config.language');
foreach(Configure::read('Config.languages') as $code => $language)
{
if ($code == $currentLanguage) {
$links[] = $language;
} else {
$links[] = $this->Html->link($language, array('lang' => $code));
}
}
echo implode(' - ', $links);
?>
</div>

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia= 9. • Internacjonalizacja aplikacji

271

Wykorzystywane w kodzie ustawienie

Config.language zosta$o ustawione w pliku

app/config/

bootstrap.php

w ramach przyk$adu „T$umaczenie rekordów baz danych za pomoc# zachowania Translate”.

3. Utwórz plik app/app_controller.php o nast%puj!cej tre&ci:

<?php
class AppController extends Controller {
public $components = array('Language', 'Session');
}
?>

4. Utwórz plik app/controller/components/language.php o nast%puj!cej tre&ci:

<?php
class LanguageComponent extends Object {
public $controller = null;
public $components = array('Cookie');
public $languages = array();
public function initialize($controller) {
$this->controller = $controller;
if (empty($languages)) {
$this->languages = Configure::read('Config.languages');
}
$this->set();
}
public function set($language = null) {
$saveCookie = false;
if (empty($language) && isset($this->controller)) {
if (!empty($this->controller->params['named']['lang'])) {
$language = $this->controller->params['named']['lang'];
} elseif (!empty($this->controller->params['url']['lang'])) {
$language = $this->controller->params['url']['lang'];
}
if (!empty($language)) {
$saveCookie = true;
}
}
if (empty($language)) {
$language = $this->Cookie->read('language');
if (empty($language)) {
$saveCookie = true;
}
}
if (empty($language) && !array_key_exists($language, $this->
languages)) {
$language = Configure::read('Config.language');
}
Configure::write('Config.language', $language);
if ($saveCookie) {

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

CakePHP 1.3. Programowanie aplikacji. Receptury

272

$this->Cookie->write('language', $language, false, '1 year');
}
}
}
?>

Przejd= na stron% http://localhost/articles. Powiniene& zobaczy' list% artyku#ów, a w prawym
górnym rogu powinno si% pojawi' #!cze, które pozwoli na zmian% aktywnego j%zyka na polski.
Klikni%cie #!cza spowoduje wy&wietlenie polskich wersji artyku#ów. Efekt zosta# przedsta-
wiony na poni$szym rysunku.

Jak to dzia a

Zaczynamy od zadeklarowania listy wszystkich dost%pnych j%zyków, dzi%ki czemu mo$emy
bez problemu umie&ci' #!cze do zmiany aktywnego j%zyka. Lista s#u$y nam do stworzenia li-
sty hiper#!czy, która nast%pnie jest umieszczana w pliku uk#adu default.ctp. Jednocze&nie
faktyczne #!cza (a nie teksty) s! generowane dla wszystkich j%zyków poza aktywnym.

Aktywny j%zyk ustawiamy w zmiennej konfiguracyjnej CakePHP o nazwie

Config.language

.

Otrzymuje ona pewn! warto&' — w naszym przypadku eng — w pliku konfiguracyjnym
bootstrap.php. Je&li konieczna jest zmiana j%zyka, warto&' tego ustawienia powinna ulec
zmianie przed pierwszym u$yciem funkcji t#umaczenia.

Aby zachowa' porz!dek w kontrolerze, postanowili&my utworzy' komponent

Language

, który

obs#uguje zmian% j%zyka. Komponent ten przeszuka parametry nazwane, a tak$e te przekaza-
ne w adresie URL, pod k!tem parametru

lang

. Je&li j%zyk nie zosta# okre&lony w ten sposób,

komponent spróbuje znale=' j%zyk, korzystaj!c z ciasteczka.

Je&li nie zosta#o ustawione $adne ciasteczko, a tak$e w sytuacji, gdy nast!pi#o $!danie zmiany
j%zyka, komponent zapisze aktywny j%zyk w ciasteczku

language

, które b%dzie przechowywa-

ne przez okres jednego roku.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Skorowidz

__(), 254
__n(), 254, 255
_authorize(), 151
_checkArgs(), 228
_findMethods, w#a&ciwo&', 92
_help(), 238
_helpCommand(), 238
_importCSV(), 229
_isJSON(), 207
_parseCSV(), 228
_randomPassword(), 223
_restLogin(), 212
_stop(), 223, 318
_usageCommand(), 238

A

Access Control Layer, Patrz

warstwa kontroli dost%pu

ACL, Patrz warstwa kontroli

dost%pu

acl_extras, plugin, 45
add(), 228
afterFind(), 77, 83, 114
AJAX, 96, 98
allow(), 23
allowedActions, parametr, 23
analyze(), 318
AppController, klasa, 24, 26
AppException, klasa, 322, 323
ArticlesController, klasa, 196,

254, 261

ArticlesController::index(), 191
assertEqual(), 283
assertFalse(), 283
assertIsA(), 283
assertNull(), 283

assertPattern(), 283
assertTags(), 284, 289
assertTrue(), 283
Auth, komponent, 23, 24, 26,

30, 33, 212
haszowanie hase#, 224
schemat autoryzacji, 27
u$ywanie i konfiguracja, 24

authorize, parametr, 23
automatyzacja zada", 243
autoryzacja

przy u$yciu tokenu, 213
schemat, 27
wykorzystanie warstwy

kontroli dost%pu, 38

B

backAutoCommit, w#a&ciwo&',

159

beforeFilter(), 23, 26
beforeFind(), 77, 83, 114
beforeRender, wywo#anie

zwrotne, 133

beforeSave, wywo#anie zwrotne,

117, 122

beforeValidate(), 318
bindModel(), 50, 63, 65, 71
blackHole(), 213, 217

C

Cache, klasa, 114
CakePHP, 13, 14, 15, 16

ekstraktor, 261
konwencja nazewnicza, 68

pow#oki, 219
regu#y walidacji, 104
t#umaczenia, 254
trasy domy&lne, 162
wyj!tki, 319
wyszukiwanie, 73, 74

CakeTestCase, klasa, 282, 283
CakeTestFixture, klasa, 281
catch-all, trasy, 175

dodawanie walidacji, 179

ciasteczka, 270
ClassRegistry::init(), 282
cleanInsert(), 306
commands, w#a&ciwo&', 237, 238
comma-separated values, Patrz

CSV

Config.language, 271, 272
Configure, klasa, 292
Configure::listObjects(), 182
ConnectionManager::getDataSo

urce(), 133

contain(), 58
contain, parametr, 58

format, 57

Containable, zachowanie, 50,

51, 53, 55, 56, 57, 59, 63, 65

cookies, Patrz ciasteczka
COUNT, 74, 83
Crookes, Neil, 142
CSV, 136

dynamiczne #adowanie

plików, 137

parsowanie plików, 134

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Skorowidz

326

D

dane testowe, 273, 278, 281
datasources, wtyczka, 134,

136, 139

diff(), 305
Dispatcher, klasa, 294
download(), 317, 318

E

e-mail

wysy#anie, 308
wysy#anie z poziomu

pow#oki, 239

Email, komponent, 239, 308,

311, 312, 313
w#a&ciwo&ci, 242

endCase(), 283
endTest(), 283
error(), 223
execute(), 236, 238
expectAtLeastOnce(), 293
expectException(), 283
expectNever(), 293
expectOnce(), 293
EXPLAIN, 133
extract(), 237, 301

F

fclose(), 228
fgetcsv(), 228
fiksturki, 278, 281, 283, 284
filter(), 305
fixture, zadanie, 284
fixtures, Patrz dane testowe
fopen(), 228
foreignKey, ustawienie, 68

G

Geocodable, 15, 100, 122
Geocode, wtyczka, 122, 124, 126
geokodowanie adresów, 122
GET, parametr, 162, 166
get_class_vars(), 238
getInfo(), 323
getLog(), 134

getMagicDb(), 318
Google Maps, 122, 124, 126
GROUP, 74

H

has#a

hasz, 20
haszowanie, 223, 224
szyfrowanie, 24

help(), 228, 236
HelpTask, klasa, 236, 238
HttpSocket, klasa, 107, 194
HttpSocket::get(), 197
HttpSocketOauth, klasa, 142

I

I18n, klasa, 255
import(), 228, 237
in(), 222, 223
index(), 311
initialize(), 238
INNER JOIN, 66
InnoDb, 152
inputs, metoda, 23
insert(), 306, 307
internacjonalizacja, 249

komunikatów walidacji

w modelach, 256

tekstów w kontrolerach

i widokach, 250

isAuthorized, metoda, 23
isInterfaceSupported(), 133

J

JavaScript Object Notation,

Patrz JSON

j%zyk

ustawianie, 270
zapami%tywanie, 270

JOIN, z#!czenia, 66
jQuery, 96
JSON, 194

konsumowanie us#ugi, 194

json_decode(), 151, 198
json_encode(), 207
JSON-C, 194

K

Kairys, Donatas, 139
konwencja nazewnicza, 68

L

Language, komponent, 272
layout, w#a&ciwo&', 312
LEFT JOIN, 66
LIKE, 87, 88
listSources(), 138
lock(), 159
lockTimeoutErrorCode,

w#a&ciwo&', 159

logException(), 323
login(), 22, 23, 30
logout(), 22, 23
logowanie, 28

pobieranie informacji

o zalogowanym
u$ytkowniku, 33

zapisanie informacji

o u$ytkowniku, 31

<

#a"cuchy znaków, 305
#!cza trwa#e, 118

M

MagicDb, 314, 317, 318
main(), 222, 236
mapowanie obiektowo-

relacyjne, Patrz ORM

merge(), 305
mocks, Patrz za&lepki
Model, klasa, 50
Model-View-Controller,

Patrz MVC

model-widok-kontroler,

Patrz MVC

MVC, 196
MyISAM, 152
MySQL

blokady w =ródle danych, 152
transakcje, 152

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Skorowidz

327

N

named parameters, Patrz

parametry nazwane

named, parametr, 162, 166
numeric(), 305

O

OAuth, 142, 149, 151
OpenAuth, komponent, 46, 47
OpenID, 45

biblioteka, 45
integracja, 45, 46
plugin, 46, 47

options(), 98
optymalizacja dla wyszukiwarek

internetowych, 161

ORM, 298

P

paginate(), 95
Paginator, 98
pami%' podr%czna, 192
parametry nazwane, 164, 166
parsowanie

parametrów wiersza

polece", 224

plików CSV, 134

partial mocks, Patrz za&lepki

cz%&ciowe

permanent links,

Patrz #!cza trwa#e

PHP OAuth, biblioteka, 142
Poedit, 262, 263, 264, 265, 266
pola wirtualne, 80, 82, 83
PostsController, klasa, 193
powi!zania, 49

anulowanie zmian, 58

pow#oki, 219

tworzenie, 220
tworzenie zada"

wielokrotnego u$ytku, 229

uruchamianie, 220, 221, 222
wysy#anie wiadomo&ci

e-mail, 239

prefiksy, 36, 168, 172
printf(), 261, 262

ProfileRoute, klasa, 184
ProfilesController, klasa, 172, 217
przypadki testowe, 273, 282
pushDiff(), 305

Q

QueryLog, komponent, 133

R

read(), 151
readfile(), 318
redirect(), 291, 292
renderException(), 323
Representational State Transfer,

Patrz REST

RequestHandler, komponent,

191, 207

requireLogin(), 212
reset(), 242
resetBindings(), 58
REST, 199, 207

dodawanie uwierzytelniania,

208

reverse(), 305
RIGHT JOIN, 66
Robot, wtyczka, 243, 246
RobotTask, model, 246
Router::connect(), 174
Router::connectNamed(), 167
Router::parseExtensions(), 190
Routing.prefixes, 172
RSS, 138, 188

a pami%' podr%czna, 192
tworzenie kana#u, 188

RssHelper, klasa, 192
RssHelper::item(), 192

S

schedule(), 246
schema(), 82
Search Engine Optimization,

Patrz SEO

Security, komponent, 212,

213, 217

Security.salt, parametr, 24

Security::hash(), 223, 224
send(), 242, 312, 313
SEO, 118, 161
Session, komponent, 261
Set, klasa, 298, 301, 305
Set::combine(), 303
Set::extract(), 301, 302, 303
Set::format(), 304
Set::map(), 304
Set::matches(), 137
setAutoCommit(), 160
setConfig(), 138, 141, 151
setFlash(), 261
setup(), 113
Shell, klasa, 222
SimpleTest, biblioteka, 276, 278
slug, 118, 122
Sluggable, 15, 100, 118, 122
sort(), 305
sprintf(), 261, 304
startCase(), 283
startTest(), 283
startup(), 236
Story, Mark, 45, 294
String, klasa, 305, 306
stronicowanie, 93, 95

AJAX, 96

Syrup, wtyczka, 120
szperacze sieciowe, 192

T

TagsController::view(), 162
tekst, manipulacja, 305
template, w#a&ciwo&', 313
test cases, Patrz przypadki

testowe

test jednostkowy, 282
test_suite, 282
testAction(), 288, 289
testowanie, 273

akcji kontrolera i ich

widoków, 286

konfiguracja frameworka, 274
tworzenie danych testowych,

278

za&lepki, 290

testRedirect, w#a&ciwo&', 292
testsuite, pow#oka, 294

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Czytaj dalej...

Skorowidz

328

testy

jednostkowe, 273
uruchamianie w konsoli, 294

timeline(), 113, 114
t#umaczenie, 254, 262

rekordów baz danych, 266
tekstów zawieraj!cych

dynamicznie generowan!
tre&', 259

token(), 151
tokenize(), 306, 307
tokeny, 213, 217
transakcje, 152
translate(), 255
Translate, zachowanie, 266, 268
trasowanie, 161, 168, 172

odwrotne, 175
tworzenie w#asnych klas, 182

Twitter, rejestracja aplikacji,

143, 144

TwitterAccountBehavior,

klasa, 113

U

unbindModel(), 50, 56, 57
uniwersalnie unikalny

identyfikator, Patrz UUID

unlock(), 159, 160
UploadsController, klasa, 322
User::useToken(), 218
UsersController, klasa, 217
UserShell, klasa, 222, 237, 238
useToken(), 217
us#ugi sieciowe, 187
UUID, 217, 307
uuid(), 307

uwierzytelnianie, 19

konfiguracja prostego

systemu, 20

u$ytkownik

pobieranie informacji, 33
zapisanie informacji po

zalogowaniu, 31

zmiana domy&lnego

modelu, 27

V

validate, w#a&ciwo&', 102, 259
validateTwitter(), 106, 107
Validation, klasa, 104
Video::search(), 198

W

walidacja, 99

dodawanie wielu regu#, 100,

102

tworzenie w#asnych regu#,

104, 107

warstwa kontroli dost%pu, 38
web crawlers, Patrz szperacze

sieciowe

web services, Patrz us#ugi

sieciowe

welcome(), 246
wi!zania modeli, 49

modyfikowanie

parametrów, 59

modyfikowanie warunków, 63
tworzenie wielu powi!za", 66

wiersz polece", parsowanie

parametrów, 224

wirtualne pola, 80, 82, 83
write(), 151
wyj!tki, 319
wyszukiwanie, 73, 74, 87

stronicowanie, 93, 95
w#asne typy, 89, 92, 93

wywo#ania zwrotne, 109

X

Xdebug, 285
XmlHelper, klasa, 192
X-Path 2.0, 301, 302

Z

zachowania, 99

dodawanie nowych pól, 116

zadania, automatyzacja, 243
za&lepki, 290, 292, 293

cz%&ciowe, 293

z#!czenia, 65, 66
z#!czenia dora=ne, 84

*

=ród#a danych, 127

konsumowanie kana#ów RSS,

138

parsowanie plików CSV, 134
tworzenie, 142

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ


Wyszukiwarka

Podobne podstrony:
CakePHP 1 3 Programowanie aplikacji Receptury caph3r
informatyka bezpieczne programowanie aplikacje hakeroodporne jacek ross ebook
CakePHP 1 3 Programowanie aplikacji Receptury
informatyka android flash zaawansowane programowanie aplikacji mobilnych stephen chin ebook
informatyka ajax bezpieczne aplikacje internetowe christopher wells ebook
informatyka access analiza danych receptury ken bluttman ebook
informatyka programowanie aplikacji dla urzadzen mobilnych z systemem windows mobile jacek matulewsk
informatyka testowanie bezpieczenstwa aplikacji internetowych receptury paco hope ebook
informatyka java ee 6 programowanie aplikacji www krzysztof rychlicki kicior ebook
informatyka php5 programowanie z wykorzystaniem symfony cakephp zend framework tomasz skaraczynski e
informatyka tworzenie aplikacji dla ios we flashu receptury christopher caleb ebook
informatyka programowanie aplikacji na iphone 4 poznaj platforme ios sdk3 od podstaw david mark eboo
informatyka programowanie aplikacji na serwisy spolecznosciowe jonathan leblanc ebook
informatyka asp net ajax programowanie w nurcie web 2 0 christian wenz ebook
informatyka php i jquery receptury vijay joshi ebook
informatyka android 3 tworzenie aplikacji satya komatineni ebook
informatyka smarty szablony w aplikacjach php h hayder ebook
informatyka php5 bezpieczne programowanie leksykon kieszonkowy jacek ross ebook
informatyka antywzorce jezyka sql jak unikac pulapek podczas programowania baz danych bill karwin eb

więcej podobnych podstron