You are on page 1of 577

,

4-

4-

-
2015

32.973.26-018.2.75
3-27
681.3.07

""
. .. u

. .-. .. u

" :
info@williamspulishing.com, http://www.williamspulishing.com
, .

3-27

: , , 4- .
".. ", 201 5. - 576 .: . - .

. . - .:

. .

ISBN 978-5-8459-1 922-9 ( .)


32.973.26-018.2.75

.

,
, m .
APress. Berkeley,

Authorized translation from the English language edition puished APress, Copy
right 2013 Matt Zandstra

11 rights reserved. No part of this work may reproduced or transmitted in any form or

means. electronic or mechanical. including photocopying. recording. or any information storage


or retrieval system, without the prior written permission of the copyright owner d the pulisher.
Russian language edition is pulished Williams Pulishing House ac cording to the
Agreement with R&I Enterprises lnternational. Copyright 2015.

-

:

,
4-

.. ..
..
.. ..u
.. u.

23.07.2015 .

70xl00/ 1 6 .

imes.
. . .

46.44.

.-. .

1000 . No

33.
3880.

142300,

". . ",
JSBN
ISBN

978-5-8459-1922-9
978-1-4302-6031-8

127055.

.
r.

. . . .1
. . , .

43.

. l

(.)

"",

(.)

Matt Zandstra.

2013

20 1 5

16

17

18

1.

21

1. :

23

11.

31

2 .
.
4.

33
39
67

5.

115

6.

1 47

111.

1 69

7.

1 71

8.

1 81

9.

1 97

10.

223

11.

245

12.

279

13.

335

IV.

381

14.

383

15. PEAR Pyrus

393

16. phpDocumentor

41 7

17. Git

431

18. PPUnit

451

19. Phing

479

20.

501

V.

527

21. . ,

529

VI.

539

541

545

567

16

D1

17

18

19
20

1.

21

1. :

23

4-

23
25
27
27
28
28
29
30

11.

31

2.

33

-
/FI
3
4
: 5

:

33
33
34
34
36
36
37
38

3.

39



Pulic, Private Protected:

39
39
40
41
43
45
46
47
50
52
52
56
61
62

ShopProduct

63
65

4.

67

,



insteadof




'I}'
: static


-

_clone ()

,

67
71
72
74
76
76
77
78
79
79
81
82
83
83
84
85
88
90
97
98
1 04
1 05
1 08
1 09
114

5.

115









Reflection API


115
116
1 23
1 24
1 28
1 29
1 30
1 31
1 31
1 33
1 33
1 34
1 35
1 35
1 36
1 38



Reflection APl

140
141
142
146

6. r

147

,


.


UML

147
148
152
152
152
153
153
154
156
157
158
158
159
159
159
159
160
166
168

111.

169

7.

171

" "









171
174
174
174
174
175
175
176
176
176
176
177
177
177
178
178
178
179

8. 1,11

181


.


lll
lll
lll
lll.

lll

181
182
182
185
187
188
189
191
192
193
194
194
194
194
194
194
195

9.

197

:
lll Singleton

lll Factory Method

m
lll Astract Factory

m
lll Prototype

197

10. .

223

,
lll Composite


m Composite

223
224
224
226
230
233

201
202
202
204
205
205
207
209
21
21
211
213
215
216
217
219
221

Decorator

Facade

234
234
235
239
240
240
241
242
243

11. mJI

245

Interpreter

Interpreter
Strategy

Observer

Visitor

Visitor
Command

245
245
247
254
254
255
255
259
261
266
267
268
272
273
273
273
278

12.

279



Registry

Front Controller
Application Controller
Page Controller
Thmplate View View Helper

ransaction Script
Domain Model

279
280
280
283
283
294
295
305
317
322
325
325
330
334

11

13.

335

r
Data Mapper

Identity

Unit ofWork

Lazy Load

Domain Object Factory

Identity Object

Selection Factory Update Factory

Data Mapper

335
336
336
336
350
352
352
353
355
356
356
356
360
361
361
361
363
363
364
364
365
366
367
367
372
373
373
373
377
377
379

IV.

381

14.

383

383
384
385
386
388
389
390
391

12

15. PEAR

Pyrus

PEAR
: Pyrus

PEAR

393
394
395
396

PEAR
PEAR
PEAR
package. xml

contents

phprelease


Pirum

398
399
401
404
404
405
406
409
41 1
41 2
41 2
41 2
41 4
41 6

16. phpDocumentor

41 7


DocBlock





41 7
41 8
41 9
421
422
423
424
425
426
428
430

17. Git

431


Git
Git



gi t





431
433
433
433
434
434
435
436
439
439
443
443
443

13

444
444
444
445
449

18. PHPUnit

451



PHPUnit






,
-
-
-
Seleniurn
Seleniurn
PHPUnit Selenium
-

Selenium

452
452
454
455
456
457
458
459
461
464
467
467
469
471
471
472
472
473
473
474
476
478

19. Phing

479

Phing
Phing

condition

480
481
481
482
484
490
491
495
499

20. r

501

m


Phing

501
503
504
505
507

14




Jenkins
Jenkins
Jenkins
Git




508
509
51 1
51 3
515
51 5
51 6
51 7
51 8
520
520
523
524
526

V.

527

21. , ,

529

529
530
530
530
531
531
532
533
533
535
536
536
536
536
537
537
538

VI.

539

541

541
542
542

545

Parser

545
553

567

, :

20 -,

Yahoo! .
.
. 24
(3- ), "" 2007 .
DHTML Unleashed ( SAS Pul!shlng). ,
Linux Magazine, Zend .com, I DeveloperWorks phpl architect
Magazine.

.
(creatlve wrltlng)
-.
, ,
- r,
, .

(Wes Hunt)

(UX lead) 90-
.

Annigent - -
. Scala
- RS-
- () ,
.

CodeMontana. org (
),

MontanaProgrammers. org.

. ,
. ,
.

, ,
5.
. (Andy Budd)
. - (Jessey White-Cinis),
(Martin Streicher)
Apress.
. Apress
. .
.

,
.
(Steven Metsker)
API ,
BuUding Parsers inJava.
,
(John \) , .
, ,
, 6 Music and
Dandelion Radio.

19


, -
.

, . ,
( ) .
( , , ) -. ,

, .
,
API. ,

,
.
.
" ".
,
.
,
,
V- " " ( ,
). , .
, ,
.
,
, , ,
. , , ,

, -
.
, -
-
.
, ,
.
. ,
. -
.
,

Git (
). ,
(agUe),

(codebase). (
) ,
.
.
. ,

20

, . ,

.


, , .
, ,
.
, .
.
-
. ,
, , ,
.
,
, .
.
:
info@williarns pu i shing .
E-mail:
lfN./:

ht t p : //www.wi l l i arnspul i s hi ng .com

:
:

12 7055,

, . , . 43, . 1

03150, ,

/ 152

)/)

@@@
----

/)/

'l

----

5
- .
-.
, 4,
-
.
,
.
( , )
, Java.
, -.
, .

;; .

: -

-.

: , , .


, - .
. -
-,
. (,
) ,
, , -.
. , ,
. ,
, .
, . .
, ,
. , , . ,
. .

24

1.

,
, , , .
, .
.
, ,
, . 20
-.

, .
.
. , ;
, .
. .
, ,
,
. ,
. .
,
. - "", ModRewrite
Apache, .
.
, , 2. .
.
. .
,
. . .
,
.
, .
, . .
m .
. .
.
, ?
, , . "
" . ,
,
. , .
m -.
,
"" .

, . -
, .

, ,
, ,
. ,
. . ,
.

1. :

25

.

.
,
,
. , ,
, , ,
, ,
.
, - .

DVD- . ,
.


,
.
. ,
-. 3
4
-.
,
.
,
.
( )
.
Jv-. ,
, , Java -
. Java ,
,
.

70- .
, .
90- , - .

. , Design
Pattems: Elements of Reusae Object-Oriented Software1, "
", 1 995 ., . ,
, - ,
.
.
API Java ,
90-
. -

1 . . . . -
. mm (. .. . "". 2007).

1 .

26

,
.
, , -
, . "m " (
, ). , ,
,
, .
. -
(eXtreme Programming - ),
(Kent Beck)2. - ,
, -,
.
- ,
. ,
, , m
.
-
( ) . ,
.
, .
,

, - : h Pragmati.c Programmer3 (Andrew Hunt, David
Thomas, 2000 ).
, - ,
-
, .
, -12,
.
80- ,
(Martin Fowler) Refactorig: Improving the Design of Existing Code4,
1 999 , .

.
JUnit,
Jv-.
, est Irifected: Programmers Love Writing Tests (Kent Beck, Erich Gamma) (ht t p : //
j uni t .s ourc e f orge. net/doc /t e s t infe c t ed/t e s t ing.htm),
.
4, ,
.
- .
Zend
(Zeev Suraski) I) (Andi Gutmans),
(Rasmus Lerdorf) .
, , 2

. mi ( . " . "", 2002).


, . -.
( . " . "", 2012).
4 , , , . . .
. ( . " . "-" . 2013).
3

1. :

27

-
.
. ,
. ,
. .
(Leon Atkinson) Zend
2001 , (Harry Fuecks) apecywww.phppatterns.
( ) 2002 .
, BinaryCloud,
.
- 5 2003
- . Zend 2
. ,
, -
-.
5 .
,
. 5
-.


-
: "
". -
( ,
Design Pattems, " ").
,
, r .
,
: , .

II ,
3
5.
,
.
, ,
, .
, 5.

. ,
.
,
, .
.
.
. II -
.

28

1 .


. " " ,
. ( -
). ,
.
, , ,
.

. .

,
.
, .
.
(Unified Modeling Language - UML),
-
.
,
. .
,
.


,
. IV .
,
. ,
IV
. .
. ,
,
.
. IV
.
.
. -
PEAR. ,
.
R-.
PEAR. ,
.
, ,
. . .
- , , ,
, . . ,
, , PHPDo cumentor -,
L-.
API.
-

1 . :

29

, ,
.
- Git,
,
.
, , ,
, . Git
.
. -,
, -
. -,
, .
, . .
PHPUnit, xUnit,
Smalltalk,
, Java. , PHPUnit ,
- , .
PEAR ,
. , ,
.
. ,
, . ,
. Phing
Ant, Jv-. Phing Ant
(build flle)
.
. , Phing
.
- ,
,
.
, .
, , ,
(continuous integration).
.

4-
- . ,
.
,
. . , (traits), fina lly,
, -
.
1 -
PHPUnit. ,
Selenium, API
-
.
. ,
, Git Subversion.

30

1 .

.
3- . ,
. , ,

.
CruiseControl".
Jenkins.
- .


- .
-.

.
.
. . .

.
- .
, .
.
. - ,
. -
. , ,
. ;
. . , .
. .
. .
, .

1 1

/))

@@@
--

)JJ
----

-. ,
"".
.
-
.
.

PHP/FI 2.0: , , .

3: .

4: - .

5: - .

6: .

-
-
, 5,

. .

/FI
, ,
, Perl. ""
"Personal Homepage Tools" (
), "FI" - "Form Interpreter" ( ).
SQL- ,
.
m
"PHP/FI 2.0". ,
, . m ,
. m .

34

11.


. .
. h 3
f. 3 /FI 2.0,
.
.
( . 27 1 997 ).
.
.
.

. ,
( . . ;
). , .
-.
. ,
.
.
.

4
4 .

. Zend .
Zeev Andj. Ze n d

. . -
.
, API
.
Zend ,
-, .
-. Zend ""
, .

4
.
. .

. .
-

$my_obj
$ other

=
=

new User ( ' bob ' ) ;


$my_ob j ;

U s e r ,
U s e r . -
. ,
. , ,
.
,
.

2.

35

. ,
.
, -
, ""
.
.
$other =& $my_obj ;
// $other $my_obj

.
function s etScho o l ( & $ s chool ) {
// $ scho o l ,

.
func t i on & getScho o l ( ) {
// ,
return $ t h i s - > schoo l ;

,
, -
.
, ;
, .

, -
, .
, "
?" .
Zend , -
, , .
,
"" .
- .
DevX.com (ht tp : / /www . devx . com/webdev /Arti c l e / 1 0 0 0 7 /
0 /pag e / l) .


, , .
. -

-.
. .
l . .
,
, [} L
, -

.
, PEAR, -
. -

36

1 1 .

PEAR.
.
, ,
-
. ,
- 60-
, 90- .
Java, " " -
, 1 995 . ++,
, 1 979 .
90- . 1 994 Perl 5.
,
( ,
- Perl ,
).
,
.

: 5
5 -
. , -
(, ) .

, .
, 5
, -.
. , Yahoo! Facebook,
. 5

.
.
, -
. . . ,
, ,
, (hints).
(private) (protected) ,
s t a t i c . , .
, -
, - .
,
,
- .



6 , 5 . 5.
6 20 1 2 r
(http: / /venturebeat.com/20 1 2/ 1 0/ 24/zends-andi-gutmans-on-php-6-being-a
developer-ceo-and-how-apple-is-the-blggest-barrier-to-the-future-of-moblle/).

2.

37

.,
- .
5.5, ,
6,
.
6, ,

6, , ,
5. , 5.3
. ,

.
, ,
.
class megaqui z_uti l_Conf {

}
-
, .
(closures), ,
(late static nding).
.

.
.
.

, .
. ,
.

:
- , , ""
.
, ,
-.
-
,
, "" .
- ,
,
. ,
- .
Perl : "
".
, ,
,
(
" ").

38

1 1 .

- . - ,
, ,
.

- , ,
.
. ,
.


.
- .

.


)/)
'/"------

,
5 .
,
- .
5 -
, , 4, , ,
. - -
, .
.

.: .

:
.

.: .

: .

:
.


-
- .
,
- .
.


. ,
.
-
. ,
.

40

11 .

. - .
. c l a s s
.
. . . ,
r . ,
.
c l a s s ShopProduct
1 1

S ho p P roduct - ,
. .
. .. ,
. .


- , . -
, , .
. - . .
Shop Product
S ho p P r o du c t . new.
.
$product l
$product2

=
=

new ShopProduct ( ) ;
new ShopProduct ( ) ;

new
. ;
ShopProduct.
, ShopProduct
Shop P r o du c t . (.. ), $ p roduct l
$ p r o d uc t 2
,
.
, . ,
- ,
. - .
. , -
. , .
,
. , -.
( , ..
, (..
)). ,
$ p r o d uc t l $ p roduc t 2 .
-

va r_dump ( $product l ) ;
va r_dump ( $product 2 ) ;

.
ob j e c t ( S ho p P roduct ) # l

(0)

}
ob j e ct ( ShopP roduct ) # 2

(0)

3.

41

. 4 5 ( 5.1

) .
, .
5.2 ,
, t o S t r ing ( ) 1
, _tos t r ing ( ) - 4, " ".

v a r_dump ( ) ,
, ,
' # ' .
,
S ho p P r o du c t , ,
(properties).


,
. , - (member
variale), , .
ShopProduct , ,
, .
,
,
, : p u i c ,
prot e c t e d p r i v a t e .
. ( scope) ,

( , ). , ,
, , ,
, - . , ,
. ,
, .
"",
. ,
pu i c, protected pri vate, .


.
pu l i c .
class ShopProduct {
pu i c $ t i t l e
pu i c $pr oducerMai nName
pu i c $producerFirs tName
pu i c $ p r i ce

" " ;
" " ;
" " ;

, ,
. ,
S hopP roduc t , .
pu i c , ,
.
1

. . -

. .

42

11.
pu i c , protected p r i vate, ,
5. 4 . 4
va r , , ,
u i c . , 5
var u i c.

- > ,
.
'

'

$produc t l = new ShopProduct ( ) ;


p r i n t $ p roduct l - > t i t l e ;

.
m

pu l i c ,
, ,
, .
new ShopProduct ( ) ;
$product l
$product2 = new ShopProduct ( ) ;
$product l - > t i t l e= " Coae " ;
$produc t 2 - > t i t le=" Peop " ;

$ t i t l e S h o p P r o du c t , ,
S h o p P roduct
. .
, ,
S h o p P r o du ct .
, $ t i t l e .
, , , ,
. .

.
.
$produc t l - >a r i t ra r yAddi t i on = "nm " ;

,
-
.
- ? ,
. , ( ,
) .
S h o p P r o d u c t $ t i t l e , ,
S h o p P r o d u c t , .
$ t i t l e . .
, .

. .
. . -
.
.

3.
$produc t l

new ShopProduc t ( ) ;

$product l - > t i t l e
$produc t l ->producerMainName
$produc t l - >producerFirstName
$produc t l - >price

" " ;
" " ;
" " ;
5 . 99 ;

43

ShopProduc t ,
, .
, , .
print " : { $produc t l - >produce r F i r s t Name } "
. " { $produc t l - >producerMai nName } \ n " ;

.
:

.
,
, , ,
. ,
$produc t l - >producerMai nName

" " ;

$produc t l - >producerSecondName

" " ;

,
.
, .
- , . "".
, .
. . , ,
. ,
Shop P r o du c t ,
.
. , , .
. -
.
print " :

{ $ produc t l ->p roduce rFirstName } "


. " { $produc t l - >producerMai nName } \n " ;

. .
, ShopProdu c t
.
.


, ,
. (methods) - .
. u ,
. func t i o n .
- - .
.

44

1 1 .

pu i c function myMe thod ( $ a r gument ,


11

$another )

. . .

, .
. ,
. , pu i c ,
p r o t e c t e d p r i v a t e . pu i c ,
.
, ,
pul i c . .
. 4 , , .
pu ic, protected pr ivate .
4 u i c .

,
' - > ' .
, (
).
$my0bj = new MyC l a s s ( ) ;
$myObj - >myMe thod ( " " ,

" " ) ;

ShopProduc t .
c l as s ShopProduct {
pu l i c $ t i t l e
pu i c $producerMai nName
pu i c $producerFi r s tName
pu l i c $price

" " ;
" " ;
" " ;
;

funct ion get Produce r ( )


return
" { $thi s - >produc e r F i r s tName ) "
. " { $ th i s - >produce rMa i nName ) " ;

$ product l = new ShopProduc t ( ) ;


$produc t l - > t i t l e
$produc t l - >producerMainName
$produc t l - >producerFi rstName
$produc t l - >p r i c e
p r i n t " :

" " ;
" " ;
" " ;
5 . 99;

{ $ produc t l - >get Produce r ( ) ) \n " ;

.
:

ge t P rodu c e r ( ) Shop Produ c t .


, ,
. , g e t Produ c e r ( ) pu i c
- .
g e t P rodu c e r ( )
- $ t h i s . .
. ,

3.

45

, $ t hi s "
" .
$this- >producerFi r s tNarne


$produc e r F i r stName

, g e t P roducer ( ) $ p r o duc e r
$ p r oduce rMa i Name , ,
.
, . -
"". ,
ShopProduc t .
. -, ,
ShopP roduc t ,
"". -, , -
Shop Produ c t .
,
.
F i r s t Name


.
, ,
. 5
, . , ShopProduct
ShopProduct ( ) . 5
_ s t rut ( ) . ,
.
-.
ShopProduc t .
class ShopProduct (
pu l i c $ t i t l e
pu i c $producerMai nName
pu i c $p roducerFi rs tName
pu i c $price

" " ;
" " ;
" " ;
;

function _con s t ruct ( $ t i t l e ,


$ f i r stName,
$this->title
$ t h i s - >produc e r F i r s tName
$ t h i s - >producerMa i nName
$ t his ->price

$mainName ,

$price )

$title;
$ f i r s tNarne ;
$mainName ;
$price;

function get Produce r ( ) {


return " { $ t h i s - >producer F i r s tName ) "
. " ( $ th i s - >producerMai nName ) " ;

,
, -

46

1 1 .

. Meo _c o n s t ruct ( ) .
new.
$product l

new ShopProdu c t ( " " ,


" " , " " ,
print " : ( $produ c t l ->get Produce r ( ) } \n " ;
=

5 . 99 ) ;

.
:

...

__
,
1'1'
'
_
_
_
_
_
_,
_
_
_

. ,
,
. . $ t h i s
.
4 cons truct ( ) .
4, ,
. ShopProduct
ShopProduct ( } .

- .
, _cons truct ( ) .

ShopP roduct
.
. .
Shop P roduct . ,
.
-
. ,
. ,
.
,
.


, .
,
,
. ,
- ..
. ,
. S hopP roduct obj e c t ,
S hopProduct.
.
,
. , . ,
, .
,
.
, , ,
, - .

3 .

47


. ,
, . ,
$ num e r
2, " two " ("").
, Java, ,
, , , .
, . ,
, .
. . 3. 1
, ,
. ,
t ru e (""),
.
3. 1 .

i s_bool ( )
i s - i n t e ge r ( )
i s_dou e ( )
i s-s t r i n g ( )
i s_obj e c t ( )
i s_ a r r a y ( )
i s -r e s o u r c e ( )
i s_nul l ( )

: t rue f a l s e ( )
; i s i n t ( ) i s l ong ( )
Dou e
( );
i s_ f l o a t ( )
S t r i ng

Ob j e ct

Array

Resource ,
,
Nu l l

Boolean

Integer

,
.


, .
, ,
.
, L-.
L- < r e s o l vedoma i n s > ,
I- . ,
, . L-.
<settings>
< resolvedoma ins>fa l s e< / res olvedomains>
< / settings>

" f a l s e "
outputAd dr e s s e s ( ) , I-.
outputAddre s s e s ( ) .
class Addres sManager {
private $ addr e s s e s

array ( " 2 0 9 . 1 3 1 . 3 6 . 1 5 9 " ,

func t i on outputAddre s s e s ( $ re s olve

) {

"74 . 125 . 19 . 106" ) ;

48

11.
fo reach ( $thi s - >addr e s s e s as $ address )
print $ addr es s ;
i f ( $ resolve )
print "

( " . gethostbyaddr ( $ address )

") ";

print " \ n " ;

, Addr e s sMana g e r .
, I- .
o u tputAdd r e s s e s ( ) I-
. $ re s o l ve
t ru e , , I-, .
Add re s s
Mana g e r s e t t i n g s L- .
?
$ s e t t i ng s = s implexml_l oad_f i l e ( " s e t t i ng s . xml " ) ;
$manager = new AddressManage r ( ) ;
$manage r- >outputAddres s e s ( ( s t r i n g ) $ s e t t ings- >reso l vedoma i ns ) ;

r e s o l vedoma i n s
SimpleXL API, 5. ,
- " fa l s e " , ,
SimpleXL.
, .
" f a l s e " o u t putAdd r e s s e s ( ) , ,
. ,
t rue () f a l s e ().
" fa l s e " t ru e .
, "fl
t ru e .
i f ( " fa l s e " )

11 . . .

.
i f ( t rue )
// . . .

-. -,
) ,
.
outputAdd re s s e s (

/ / c l a s s Addres sManager . . .
function outputAddres s e s ( $ re s o lve )
i f ( i s _s t r i n g ( $ re s olve ) ) {
$ r e s o lve =

( preg_match ( " / fa l s e l no l o f f / i " ,


f a l s e : t ru e ;

$ reso lve )

)?

3 .

49

11


. ,
,
,
.
.
-, outputAdd r e s s e s ( ) , ,
, $ r e s o l ve
. , , ,
.
/**
* .
* $ res olve ( t rue ) ,
* .
* @param $ resolve Bool e an ?
*/
function outputAddresses ( $ reso lve ) {
// . . .

, , ,
, .
, -, o u t putAdd r e s s e s ( )
$ r s o l v e .
function outputAddresses ( $reso l ve ) {
i f ( ! i s_bool ( $ resolve ) ) {
di e ( " outputAddres s ( ) \ n " ) ;
}
11. "


$ re s o l ve. -
, , , .
,
. ,
, -
.
outputAddre s s e s { ) .

- -
, .

.
. ,
,
. "
" . ,
, .

50

1 1 .

""
.
, ,
,
, (
, ).
, ! ,
, .
, .
,
, . ,
. ,
, .


, -
, ,
. , , . ,
, .
, ShopProdu c t .
c l a s s ShopProductWr i t e r {
pu i c function write ( $ s hopProduct ) {
$ s t r = " { $ shopProduc t - >t i t l e ) : "
. $ shopProduc t - >get Produce r ( )
" ( { $ shopProduc t - >price ) ) \ n " ;
print $ s t r ;

.
$productl
$writer

"
" ,
" " , " " ,
new ShopProductWri t e r ( ) ;
=

new ShopProduct (

5 . 99 ) ;

$ w r i t e r ->wr i t e ( $produc t l ) ;

.
:

( 5 . 99 )

Shop P roduct W r i t e r , w r i t e ( ) . w r i t e ( )
S hopProduc t .
.
-, $ s hop P rodu c t ,
, $ w r i t e ( ) Shop P rodu c t .
. ,
$ w r i te ( )
$ shop P r oduc t .
- ,
Shop P roduc t .

3 .

51

. , , w r i t e ( )
ShopProduct. , , ,

, . : .
ShopProduct , ShopProductWri ter

. , .
-

5 . r
. . w r i t e ( )
.
pu i c function write ( ShopProduct $ s hopProduct )

11 . . .

w r i t e ( ) r $ sh o p P r oduc t ,
S ho p P r oduc t . wri t e ( )
"" .
class Wrong { }
$wr i t e r = new ShopProductWr i t e r ( ) ;
$wr i t e r - >wri te ( new Wrong ( ) ) ;

w r i t e ( ) ,
.

Wrong

Catchae fatal error : Argurnent 1 p a s s e d t o S h o p P roduct W r i t e r : : wr i t e ( )


mus t an i n s t a n c e o f S h op P r oduc t , i n s t an c e o f W r ong g i v e n , . . . 2


. ,
.
w r i t e ( ) .
, r,
.
-
, ,
. , ,
. wr i t e ( )
- ,
, , .
.
r
, .
, i s i n t ( ) .
, .
function s etArray ( array $ s torearray )
$ th i s - > array = $ s torearray;

m 5. 1 .
m
2 : 1. Shop
ProductWrite r : : write ( ) ShopProduct,
Wrong . . .

52

11.

r . , , r
, . .
function setWr i t e r ( Obj ectWr i t e r $ ob j wri t er=nu l l )
$ t h i s - >wri ter = $ ob j wr i t e r ;

, .
. ,
. ,
,
. .

- ,
.
, ,
. ""
"".
. .
(
) . ,
.
,
, .


S hopProdu c t .
.
.
$produc t l = new ShopProduc t ( " " ,
" " , " " ,
$product2

5 . 99 ) ;

new ShopProduc t ( " " ,


" " , "" , 1 . 9 9 ) ;

p r i nt " : "
print " :

. $ p roduc t l - >get Producer ( )


" . $ produc t 2 - >get Producer ( )

" \n " ;
"\n";

.
:
:

,
, -.
(.. , " " " "), ,
" " " " . -
,
ShopProduct .
,
. , , , -

3 .

53

-. , CD
, - . , ,
.
. ?
. -, ShopProduct.
-, ShopProduct .
. ,
- .
class ShopProduct {
pu ic $numPages ;
pu l i c $pl ayLength ;
pu ic $ t i t l e ;
pu i c $producerMainName;
pu i c $produce r Fi rs tName ;
pu ic $ p r i c e ;
function _cons t ruct ( $ t i t l e
, $ f i rstName ,
$mai nName
, $price ,
$numPages=O , $ p l ayLength=O )
$title;
$this->ti tle
$ f i rs tName ;
$this ->producerFirs tName
$mai nName ;
$ t h i s - >producerMai nName
$price;
$thi s - >price
$numPages ;
$ t h i s - >numPages
$pl ayLength ;
$this ->pl ayLength

function getNumerOfPages ( )
return $ t h i s - >numPages ;

function get P l ayLength ( ) {


return $ t h i s - >p l ayLength ;

function getP roduce r ( ) {


return " { $ t h i s - >produce r F i r s tName ) "
. " { $ t h i s ->producerMai nName ) " ;


, $ numPa g e s
$ p l a yLength. ,
, . , CD
.
, CD
, ( ). -
CD. . . ,
, -
, ?
.

54

11 .

, ,

.
.
. , .
,
-. ,
- . ,
. .
. .
func t i on get Summa ryLine ( ) {
$base = " { $ t h i s - > t i t l e } ( { $ t h i s - >producerMainName ) ,
$base . = " { $ t h i s - >produc e r Fi r s tName } } " ;
i f ( $ t h i s - > type = = ' boo k ' ) {
$base . = " : { $ thi s - >numPage s } . " ;
e l s e i f ( $ t h i s - >type == ' cd ' ) (
$base . = " - { $ t h i s - >playLength ) " ;

";

return $ ba s e ;

, $ t yp e ,
$ numP a ge s . S h op P roduct
, .

. , ,
.
S hopProduct " ",
. .
c l a s s CDProduct {
pu i c $pl ayLength ;
pu i c $ t i t l e ;
pu i c $producerMainName ;
pu i c $produce r F i r s tNarne ;
pu i c $ p r i c e ;
function cons t ruct ( $ t i t l e , $ f i r s tNarne ,
$mainName , $ p r i c e ,
$playLength ) {
$this->title
$title;
$ f i rs tName ;
$ t h i s - >produc e r F i r s tNarne
$mai nName ;
$ t h i s - >producerMai nName
$ t h i s - >p r i c e
$price ;
$ t h i s - >playLength
$pl ayLength ;

function getPl ayLength ( ) {


return $ t h i s - >playLengt h ;

funct ion getSummaryLine ( ) {


$base
" { $ t h i s - > t i t l e } ( { $ t h i s - >producerMai nName ) ,
$base
" { $ t h i s - >producerFirs tName } ) " ;

";

3.

55

$base = " : - { $ th i s - >p l ayLength ) " ;


return $ ba s e ;

function get Producer ( ) {


return " { $ t h i s - >produce rFirs tName ) "
. " { $ thi s - >producerMainName } " ;

class BookProduct {
pul ic $ numPage s ;
pu i c $ t i t l e ;
pu l i c $produce rMai nName ;
pu ic $produc e r F i r s tName ;
pu i c $ p r i c e ;
function con s t ruct ( $ t i t l e ,
$mai nName ,
$numPages
$this->title
$ t h i s ->produc e r F i r s tName
$ t h i s - >producerMai nName
$ t h i s - >price
$ t h i s - >numPages

$ f i rstName ,
$price,
) {
$title;
$ f i rs tName ;
$mainName ;
$price;
$ numPages ;

func tion getNumerOf Pages ( )


return $ t h i s - >numPage s ;

function getSummaryLine ( ) (
$base
" { $ t h i s - > t i t l e ) ( ( $ t h i s - >producerMainName } ,
$base . = " { $ t h i s - >produce r F i r s tName } ) " ;
$base . = " : { $ t h i s - >numPages } . " ;
return $ba s e ;

";

func t i on get Producer ( ) (


return " { $ t h i s - >produce r Fi r s tName ) "
. " ( $ t h i s - >producerMainName ) " ;

, -
. g e t S umma r y L i n e ( ) .
.
, .
. g e t P r odu c e r ( )
.
. , .
, g e t P r oducer ( )
. , ,
. .

56

11 .

. .
. . .
ShopProduct W r i t e r ? w r i t e ( )
: S h o p P roduc t . .
. ? .
. w r i t e ( )
. .
c l a s s ShopProduc tWr i ter {
pu i c funct i on w r i t e { $shopProduct ) {
i f ( ! ( $ s hopProduct i ns t anceof CDProduct
&&
! ( $ s hopProduct instanceof BookProduct ) )
die ( " n " ) ;
" { $ shopProduct - > t i t l e ) : "
. $ s hopProduc t - >getProduc e r ( )
" ( { $ shopProduc t - >price ) ) \n " ;
print $ s t r ;
$str

i ns t a n c e o f , .
t rue (),
. .
.
$ s ho p P roduct
w r i t e ( ) , ,
, . , .

wr i t e ( ) , , ShopProduct
.
S ho p P roduc t , ,
, . . .
,
.
. , ,
. .
. .
.


-
,
.
, g e t P l a yL e n g t h ( ) g e t N urn e r O f Pages ( )
. , get
Summa r yL i n e ( ) .
.
c l a s s ShopProduct {
pu i c $nurnPages ;
pu i c $playLength ;
pu i c $ t i t l e ;

3.

57

pu i c $producerMainName;
pu i c $produce rFirs tName;
pul i c $ p r i c e ;
function cons t ruc t ( $ t i t l e , $ f i rstName ,
$mai nName , $ p r i c e ,
$numPages = O , $ p l a yLength=O )
$this->title
$title ;
$ f i r stName ;
$ t h i s - >produce r F i r s tName
$mainName;
$ t h i s - >producerMai nName
$ p r i ce ;
$ t h i s - >price
$numPage s ;
$ t h i s - >numPages
$pl ayLength;
$ t h i s - >p l ayLength

func tion getP roduce r ( ) {


return " { $ t h i s - >producerFi rstName } "
. " { $ th i s - >producerMai nName } " ;

function getSumma ryL i ne ( ) {


$base = " $ t h i s - > t i t l e ( { $ th i s ->producerMainName } ,
$base . = " { $ th i s - >produce r F i r s t Name ) ) " ;
return $ba s e ;

";

c l a s s CDProduct extends ShopProduct


function getPlayLength ( ) {
return $ t h i s - >p l ayLength ;

func t i on getSummaryLine ( ) {
$base
" { $ t h i s - > t i t l e } ( { $ th i s - >producerMainName } ,
$base . = " ( $ th i s - >produc e r F i r s tName } ) " ;
$base . = " : - { $ t h i s ->playLength } " ;
return $ba s e ;

";

c l a s s BookProduct extends ShopProduct


function getNumerOfPages ( ) {
return $ t h i s ->numPages ;

function getSumma ryLine ( ) {


$base
" { $ th i s - > t i t l e } ( { $ t h i s - >produce rMa i nName } ,
$base . = " { $ th i s - >produce r F i r s t Name } ) " ;
$base . = " : { $ th i s - >numPages } . " ;
return $base ;

";

,
e x t e n d s . , B o o k Product
CDProdu c t . S h o p P r o du c t .

58

1 1 .

.

.
pu i c p r o t e c t e d ( p r i vate ) .
, g e t P r oduce r ( )
C DP r oduc t , g e t Pr o d u c e r ( ) ShopProduct.
$product2

new CDProduct ( " " ,


" " , " " ,
1 0 . 9 9 , nul l , 60 . 3 3 ) ;

print " :

{ $ product2- >get Produce r ( ) ) \ n " ;

,
. Book Product .
ShopPr oduct . Boo k P r oduct C D P roduct
w r i t e ( ) ShopP roductWr i t e r , .
,
. C D P r o duct Boo k P r odu c t , get Suuna r yLine ( ) .

. .
g e t S uuna r yL i ne ( )
, .
,
.
,
ShopProduct g e t Suuna r y L i n e ( ) . ,
,
. S h o p P roduct
. g e t S uuna r y L i n e ( )
, C D P roduct B o o k P roduc t . $ t i t l e .
. ,
, ,
, - .
. . $ p roduct 2 - >
g e t P roduc e r ( ) C D Produc t .
,
. ShopProdu c t . ,
$ p roduct 2 - >g e t Suuna r y L i n e ( ) .
g e t S uuna r y L i n e ( ) C D P r o duct .
.
$ t i t l e g e t S uuna r y L i n e ( ) Boo k P r oduct
B o o k P r o d u c t .
, ShopP roduct .
$ t i t l e ,
.
ShopProduct ,
, - ,
. , B o o k Product
$ numPage s .
, C D P roduct
$ p l a yLength. ,
.

3 .

59



.
, .
,
. i
parent.
, ,
" : : " . " - > " . p a rent : : _const ruct ( )
: " eo _ cons t ruct ( ) ".
, ,
.
class ShopProduct (
pu ic $ t i t l e ;
pul ic $producerMainName ;
pu ic $producerFi r s tName ;
pu ic $price ;
function _construct ( $ t i t l e ,
$mainName ,
$this->title
$this ->producerFirs tName
$ thi s - >produce rMainName
$this->price

$ f i rstName ,
$price ) {
$title;
$ f i r s tName ;
$mainNarne ;
$price;

function get Producer ( ) (


return " { $this ->producerFirstName } "
. " { $ this->producerMainName } " ;
function ge tSurnmaryLine ( ) {
$base
" { $this->ti tl e } ( { $ this ->producerMainName } , " ;
$base . = " { $ th i s - >producerFirs tName } ) " ;
return $base ;
=

class CDProduct extends ShopProduct {


pu ic $pl ayLength ;
funct ion _cons truct ( $ t i t l e , $ fi rstName ,
$mainName ,
$price , $playLength ) {
parent : : _cons truct ( $ t i t l e , $ f i r s tName ,
$mainName , $price ) ;
$this ->playLength
$playLength;
=

function getPlayLength ( ) {
return $this->playLength ;
function getSurnma ryLine ( ) {

60

1 1 .
$base
" { $ t h i s - > t i t l e } ( { $thi s - >producerMai nName } , " ;
" { $this ->producerFirstName } ) " ;
$base
" :
{ $ t h i s - >playLength } " ;
$base
return $base ;
-

c l a s s BookProduct extends ShopProduct {


pu i c $numPages ;
function _construc t ( $ t i t l e , $ fi rs tName ,
$mainName ,
$price, $numPages )
parent : : _construc t ( $ t i t l e , $ f i rs tName ,
$mainName , $price ) ;
$thi s - >numPages
$numPages ;

function getNumerOfPage s ( )
return $ th i s - >numPages ;
funct i on getSumma ryLine ( ) {
$base
" $ thi s - > t i t l e ( $ t h i s - >producerMainName , " ;
$base . = " $ this- >producerFirs tName ) " ;
$base . = " : $ t h i s - >numPages . " ;
return $ba s e ;

,
. ""
. - ""
. , .
- "" .
. 5 ,

. _ cons t ruct ( ) .

, parent : : ShopProduct ( ) ;
.

.
- , , "" ,
.
parent : : cons t ruct ( ) ,
, . , , ,
!

1
p a r e n t .
. . ,
, "", . , .
, .
g e t S urnma ryLine ( ) , ,

3.

61

. ,
, ShopProduc t .
1 1 ShopProduct . . .

funct ion getSuuaryLine ( ) (


$base = " { $thi s - > t i t le } ( ( $thi s - >producerMainName } , " ;
$base
" { $ t h i s - >producerFi rs tName } ) " ;
return $base;
. =

1 1 BookProduct . . .

function getSuuaryLine ( )
$base = parent : : getSuuaryLine ( ) ;
$base
" : { $ thi s - >numPages } . " ;
return $bas e ;
. =

g e t Summa ryLine ( )
ShopProdu c t . CDProduct Book
Produc t , ,
.
. , , ,

.

Puli c, Priva te Protec ted:

pu i c (
). . ,
var .
pu i c (). p r i va t e (
) p r o t e c t e d ().

,
.
.


, .
.

? ,
, ,
. .
,
, . ,
, Shop Product .
$di s count s e t D i s count ( ) .
1 1 ShopProduct . . .
pu i c $di scount = ;
11

62

11.
fun c t i on s e t D i s c ount ( $ num
$ t h i s ->dis count=$num;

) {

, get
( ) . .

Price

/ / ShopProduct . . .
function getPrice ( ) {
return ( $ th i s - >price - $ thi s - >d i s count ) ;

.
, g e t P r i c e ( )
$price.
p r i n t " - { $product l ->price } \n " ;

, ,
. .
$ p r i c e . .
g e t P r i c e ( ) . $ p r i c e -
S ho p P r oduct .
.
p r iv a t e - ,
.
. :
. g e t P r i c e ( ) ,
$ p r i ce .
1 1 BookProduct
funct i o n getPrice ( ) {
return $ t h i s ->pr i ce ;

$ p r i c e S ho p P r oduct , B o o k P rodu c t ,
.
, $ p r i c e
(p r o t e c t e d) . .
-
, .
.
,
.
. .
( ) . .
, , . .
, .
.


,
. ,
. .

3 .

63

.
(accessors) (getter) (setter).
, :
,
g e t P r i ce ( ) .
-
. ,
.
. Shop ProductWr i t e r ,
S h o p P r oduct?
. S ho p P roductWr i t e r
S h op P roduct .
class ShopProduc tWr i t e r {
pu ic $products = a rray ( ) ;
pu i c funct ion addProduct ( Shop Product $ shopProduct )
$ th i s - >product s [ ]

= $ shopProduct ;

pu i c funct ion write ( )

$str = " " ;


foreach
$ st r

( $ t h i s - >products a s $ shopProduct )
" { $ shopProduc t - > t i t l e ) : " ;
$ s hopP roduct - >get Producer ( ) ;

$str
$ str

"

( { $ s hopProduct->get Price ( ) } ) \ n " ;

print $ s t r ;

ShopP roduct W r i t e r .
S hop P r oduct .
,
.
addProduct ( ) ,
$ produ c t s .
$ p rodu c t s ,
. ,
$ p rodu c t s .
class ShopProductWr i t er {
private $products

array ( ) ;

11" .

$ p rodu c t s .
addP roduct ( ) , ,
, ,
S ho p P roduc t .

ShopProduct
S h o p P roduct
, .

64

11.

class ShopProduct {
private $ t i t l e ;
private $producerMai nName ;
private $producerFi rstName ;
protected $price;
private $di scount
;
=

pu i c function

construct ( $ t i t l e , $ f i rstName ,
$ma inName , $price ) {
$this->title
$title;
$ t h i s - >producerFi rstName
$ f i r s tName;
$ t h i s -> producerMainName
$mainName ;
$thi s->price
$price;

pu ic funct ion getProduce rFirs tName ( )


return $ t h i s - >producerFirstName ;
pu l i c function getProducerMainName ( )
return $ t h i s - >producerMainName ;
pu ic function setDiscount ( $num ) {
$thi s->di scount=$num;
pu i c function getDiscount ( )
return $ t h i s - >discoun t ;
pulic function getTi t l e ( )
return $thi s - > t i t l e ;
pu ic function get Price ( ) {
return ( $t h i s - >price - $ t h is->di scount ) ;
pu i c function getProducer ( ) {
return " { $ t h i s - >producerFi rs tName } "
. " { $this- >producerMainName J " ;
pu ic function getSummaryLine ( ) {
$base = " { $ t h i s - >t i t l e } ( { $t h i s - >producerMainName } , " ;
$base
" { $ t h i s->producer F i rs tName } ) " ;
return $base;
. =

class CDProduct extends ShopProduct


private $playLength = ;
pu i c function cons t ruct ( $ t i t l e , $ fi rs tName,
$price, $pl ayLength ) {
$mainName ,

3.

65

parent : : construc t ( $ t i t l e , $ f i r s tName ,


$mainName , $ p r i ce ) ;
$ t h i s - >p l a yLength = $pl ayLength ;

pu i c func t i on getPlayLength ( )
return $ t h i s - >pl ayLength;

pu i c function get Summa ryLine ( ) (


$base = parent : : getSumma ryLine ( ) ;
$base . = " : - { $ t h i s ->playLength } " ;
return $ ba s e ;

c l a s s BookProduct extends ShopProduct {


private $numPages = ;
pu i c function cons truc t ( $ t i t l e , $ f i rstName ,
$mainName,
$pri c e , $numPages )
parent : :
cons truct ( $ t i t l e , $ f i r s tName ,
$mainName , $price ) ;
$ t h i s - >numPages = $numPages ;

pu i c function getNumerOfPages ( )
return $ t h i s - >numPage s ;

pu i c function get Summa ryLine ( ) {


$base = parent : : getSumma ryLine ( ) ;
$base . = " : { $ this - >numPage s } . " ;
return $ ba s e ;

pu i c function getPrice ( )
return $ t h i s ->price ;

ShopProduct .
,
, .
.


-
,
.
, .
.
- .

1>


)/)

@@@

'/"

-----


.
.
- .
.

n :
, .

. .

: .

.: .

n : 5 .3.

: .

: .

-: .

-: .

: .

: .

:
.


.
, , -
,
. . -
.
- .

68

1 1 .

. ,
, .
"" s t a t i c.
class Stati cExample {
static pu i c $ aNum

static pu i c funct ion sayHel lo ( )


print " ! " ;

. static 5. 4.

- , .
,
.
. ,
.
,
, , .
, " : : " .
print StaticExampl e : : $aNum;
Stati cExampl e : : s ayHel l o ( ) ;

.
" : : " p a r e n t ,
.
, . .
parent, ,
.
( ),
s e l f. s e l f ,
, $ t h i s - . -
S t a t i c Examp l e $aNum
.
StaticExample : : $ aNum;
S t a t i cExamp l e s e l f .

c l ass Stati cExample {


static pu l i c $ aNum

static pu i c funct ion sayHe l l o ( )


s el f : : $ aNum++ ;
print " ! ( " . sel f : : $ aNum . " ) \n" ;

. parent - ,
.
, " : : "
.
" : : "

4.

69

. , - ;
, . , wri te ( ) ShopProduct
wri ter : ShopProductWri ter : : wri t e ( ) , wri te ( )
. , .


, .
.
$ t h i s
.
?
. -.
( , ). ,
, ,
, . -,
.
,
. , -, ,
,
.
,
ShopProdu c t .
ShopProduct , . SQLi t e
p r odu c t s .
CREATE TABLE products

id
t ype
f i rs tname
mainname
title
p r i ce
numpages
playl ength
d i s count

I NTEGER PRIARY AUTO INCREMENT,


,
,
,
,
float,
int ,
int ,
int

g e t i n s t a n c e ( ) ,
PDO.
,
ShopProdu c t , .
S h o p P roduct. . ,
, , Data jt ( ).
PDO
.
1 1 ShopProduct c l a s s . . .
pr ivate $ i d = 0 ;
//
pu l i c function s e t I D ( $ i d )
$ t h i s - >id = $ i d ;

11
pu i c s t a t i c function g e t i n s tance ( $ i d ,

PDO $pdo )

70

11.

$stmt = $pdo->prepare ( " se lect * from products where id=? " ) ;


$ result = $ stmt->execute ( array ( $id ) ) ;
$ row
if
if

= $stmt- >fetch ( ) ;
empty ( $ row ) ) { return nul l ;

$ row [ ' type ' ] === "book" ) (


$product = new BookProduct (
$row [ ' titl e ' ] ,
$row [ ' firs tname ' ] ,
$row [ ' mainname ' ] ,
$row [ ' price ' ] ,
$row [ ' numpages ' ]
);
else i f ( $row [ ' t ype ' ] === " cd" ) {
$product
new CDProduct (
$row [ ' title ' ] ,
$row [ ' fi rstname ' ] ,
$row [ ' mainname ' ] ,
$ row [ ' price ' ] ,
$row [ ' playlength ' ] ) ;
else {
new ShopProduct (
$product
$ row [ ' ti t l e ' ] ,
$row [ ' firs tname ' ] ,
$ row [ ' mainname ' ] ,
$row [ ' price ' ] ) ;
=

$product->setid ( $ row [ ' id ' ] ) ;


$product->setDi scount ( $row [ ' dis count ' ] ) ;
return $product;
)
11. . .
, g e t i nstance ( ) ShopProduct,
"" , t yp e
.
, . ,
,
D-
. , , D
-, .
-
1 3 , ".
g e t i ns tance ( ) , .
, , ,
ShopProduct.
,
, ,
. , D-.
.

4.

71

$dsn = " s q l i t e : / /home /bo/proj ects /p roducts . db " ;


$pdo = new PDO ( $dsn , nul l , nul l ) ;
$pdo- >setAt t r ibute ( PDO : : ATTR_ERRODE , PDO : : ERRODE_EXCEPT ION) ;
$obj = ShopProduc t : : ge t i n s t a nc e ( 1 , $pdo ) ;

, "", ""
(, , r
) . ,
.
"" .
-
. ShopPr oduc t : : ge t i n s t a n c e ( )

ShopProdu c t , , PDO
. ? -
,
.
9, " ".


. ,
, ,
. ,
.
5 .
, ,
. c o n s t .
,
. ,
, .
class ShopProduct (
cons t
AVAILABLE
cons t OUT OF STOCK

;
1;

11

r ,
. . ,
,
. ,
.
print ShopProduct : : AVAILABLE ;

, ,
.
,

.

72

11 .


5.

- .
.
(. , ) ,
.
abs t ra c t .
S h o p P r oduc t w r i t e r , , ,
.

abst ract c l a s s ShopProduc tWr i ter (


protected $produc t s = array ( ) ;
pu i c func t i o n addProduc t ( ShopProduct $ shopProduct )
$thi s - >products [ J =$ shopProduct ;

, ,
. ,

$writer

new ShopProductWr i t e r ( ) ;

:
F a t a l e r ro r :

C a n n o t i n s t a n t i a t e a b s t r a ct c l a s s Shop P roduct W r i t e r

.1

m1:1=n'1i;!,
.

...,..1u-.


. ,
abs t r a c t .
. , ,
, . w r i t e ( )
S h o p Productw r i t e r .

ab s t ract c l a s s ShopProduc tWr i t e r (


protected $ products = array ( ) ;
pu i c func t i o n addProduct ( ShopProduct $ shopProduct )
$ th i s - >p roduct s [ J =$ shopProduct ;

abstract pu i c func t i on write ( ) ;


, ,
,
.
, , , Shrdutw r i t r .
write ( ) ,

c l a s s ErroredW r i t e r extends ShopProductWr i t e r { ) ,


.

' ShopProductWriter.

.. .

4 .
_._,

"

......

73

.-.;--.

Fat a l e r r o r :

C l a s s E r r o r e dW r i t e r c o n t a i ns 1 a b s t ra c t me t hod a n d
mus t t h e r e f o r e d e c l a re d a bs t r a c t o r imp l em e n t t h e r e ma i n i n g m e t h o d s
( ShopProductWr i t e r : : wr i t e ) i n . . . 2
wus

.,,

....RP?:'1t
...
R.
.

---- ...
"
.
.
"
."
.
"
."
.
"

--

. , ,

.
. .
, ,
.
, .
.
ShopProductwri t e r .

class XmlProductWr i t e r extends ShopProduc tWr i t e r (


pu i c func tion write ( ) (
$writer =new XMLWriter ( ) ;
$writer- >openMemory ( ) ;
$wri ter-> start Document ( ' 1 . ' , ' UTF-8 ' ) ;
$writer->startElement ( 11 p roduct s 11 ) ;
foreach ( $ t h i s - >products as $ shopProduct ) {
$wri ter->s tartEl ement ( 11product11 ) ;
$writer- >wri teAt tribute ( 11t i t l e 11 , $ shopProduct - > ge t T i t l e ( )
$wri t e r - > s t a r t E l ement ( 11 summa ry11 ) ;
$writer->t ext ( $ shopProduct- >get SummaryLine ( ) ) ;
$writer->endE l ement ( ) ; / / summary
$writer- >endEl ement ( ) ; // product
$wri ter- >endEl ement ( ) ;
$wr i t e r - >endDocument ( ) ;
print $writer- > f lush ( ) ;

) ;

// products

class TextProductWriter extends ShopProductWr i t e r {


pu i c func t i on wri t e ( ) {
$ s t r = 11 TOBAPl : \n11 ;
foreach ( $ t h i s - > p roducts as $ s hopProduct ) {
$ s t r . = $ shopProduc t - >get Summa ryLine ( ) . 11 \ n 11 ;
print $ s t r ;

, w r i t e ( ) .
L, - .
, ShopProductwri t e r ,
, , ,
wr i te ( ) . ,
$ p rodu c t s , .
2 ErroredWri t e r
" .
. .
-

74

1 1 .

Sho p P roduct W r i t e r .

4 ,

d i e ( ) .

, .

c l a s s Ab s t ractClass {
function abs t ractFunction ( ) (
d i e ( "Abst ractCl as s : : abs t r a c t Funct i on ( )

- !

\n" ) ;

,
.

,
.


, ,
. ,

. ,
.

i nt e r fa c e . ,
.
.

i n t e r f ace Chargeae {
pul i c funct i on getPrice ( ) ;
, . ,
, . ;
.

i mp l emen t s .
, ,
. .

S h o p P roduct C h a r g e a e .
c l a s s ShopProduct implements Chargea e
// . . .
pu i c funct i o n getPrice ( )
return ( $ t h i s - >price - $ t h i s ->discount ) ;
}
11
S h o p P roduct g e t P r i c e ( ) ,
Cha r g e a e? . ,
, .
, C D P roduct .

CDProduct
ShopProduct
Chargeae

4.

75

. ,
.

puic function CDinfo ( CDProduct $prod )


11

. . .

, $p rod g e t P l a y L e n g t h ( ) ,
, ShopProduct C h a rgea e .
C DP roduct

pu i c function addProduct ( ShopProduct $prod )


11

. .

, $ p r o d ,

Sho p Prod u c t .
g e t P l a yLength ( ) .
, C DProduct

pu i c function addChargea e i t em ( Chargeae $ i tem )

11 . . .
,

ShopProduct CDProduct. ,
$ i t em g e t P r i c e ( ) .
(
),
,
. ,
C h a r g e a e .

class Shipping implements Cha rgea e


pu i c funct i on getPrice ( ) {
11 . . .

S h i pp i n g addCh a r g e a e i t em ( ) ,
. Shop Produc t .
, C h a r g e a l e , ,
g e t P r i ce ( ) .
- ,
. .
,
. e x t e n d s
i mp l ement s . .

class Consultancy extends TimedService implements k , Chargea e {


11 . . .
, C o n s u l t a n c y
. i mp l ement s
.

76

1 1 .
(

), e x t e nd s
.

+ + , ,

Java,

.
, . .
.
.
.
.
.
. ,
?

3
m

5.4

, ,
, . (
). , ,
. , .
i nc lude,
.
, .

,
S h o p P r od u c t ,

c a l c u l a t e a x ( ) .
c l a s s ShopProduct {
private $ t axrate

17;

function calculateTax ( $price ) {


return ( ( $ this ->taxrate / 1 0 0 )

* $price ) ;

$ = new ShopProduct ( ) ;
print $p->calculateTax ( 1 0 0 ) . " \ n " ;
c a l cu l a t e T a x ( ) $ p r i ce .
,
$ t ax r a t e .
, c a l c u l a t eT a x ( )
. ,
? U t i l i t y S e r v i c e ,

S e rv i c e . U t i l i t yS e rv i c e -

3 . trait (. ).
. .

-. - . .

4 .

77

, ,
c a l c u l a t eT a x ( ) , .

abs t ract c l a s s Service {


1 1

class U t i l i t yService extends S e rvice {


private $ t axrate = 1 7 ;
funct ion calculateax ( $ p r i c e ) {
return ( ( $ t h i s - >taxra t e / 1 0 0 )

$ p r i ce ) ;

$u = new U t i l i tyServi ce ( ) ;
print $ u - >cal culateTax ( 1 0 0 ) . " \n " ;


- ,
,
. 1 1 , "
" ,


(strategy class). . , ,
, , , .
,

c a l c u l a t e T a x ( ) , : ShopProduct Ut i l i t y
Service.
trai t PriceU t i l i t i e s {
private $ t axrate = 1 7 ;
funct ion calculateax ( $ p r i c e ) {
return ( ( $ t h i s - >taxrate / 1 0 0 )

1 1

class ShopProduct {
use P r i ceUt i l i t i e s ;

abs t ract c l a s s Service {


11

class Ut i l i tyService extends Service {


use P r i ceUt i l i t i e s ;

$ = new ShopProduct ( ) ;
print $p->calculateTax ( 1 0 0 ) . " \ n " ;

$price ) ;

78

1 1 .

$ u = new Ut i l i tyService ( ) ;
p r i n t $u->calcu l a t eTax ( 1 0 0 ) . " \ n " ;

, P r i ceOt i l i t i e s

t ra i t .

.
(, , ).
P r i ce Ot i l i t i e s
. u s e ,
. , c a l cu l a t eT a x ( ) ,
: S h o p P r o du ct , O t i l i t yS e r v i c e .


.
u s e .
I de n t i t yT r a i t ,
P r i ceOt i l i t i e s .

t r a i t Iden t i t yT r a i t {
pu i c function gene r a t e i d ( )
return uniqid ( ) ;

t r a i t P r i ceUt i l i t i e s {
p r ivate $ t axrate = 1 7 ;
funct i on c a l cul a teTax ( $price ) {
return ( ( $ t h i s - >t axrat e / 1 0 0 )

$price ) ;

1 1
}
c l a s s ShopProduct {
use P r i ceUt i l i t i e s ,

Ident i t yTra i t ;

$ = new ShopProduc t ( ) ;
p r i n t $p->calcu l a t eTax ( 1 0 0 ) . " \ n " ;
p r i n t $p- >gene rat e i d ( ) . " \ n " ;
, P r i c e Ot i l i t i e s I de n t i t yT r a i t ,
u s e , c a l cu l a t e T a x ( ) g e n e r a t e i d ( )

S ho p P r o du c t . , Shop P r odu c t .
. I dent i t yT r a i t gene rateid ( ) . ,

,
. ,
13, " ", I denti ty .
(mocking) 18, "
PHPUit" .

4.

79



, , . ,
Ide n t i t yT r a i t ,
, .
, .
g e ne r a t e i d ( ) , ,
S ho p P r oduct .

inter face I denti tyObj ect {


pu i c func t i o n gene rateid ( ) ;

trait Iden t i t yT r a i t {
pu i c func t i o n gene rateid ( )
return uniqid ( ) ;

t r a i t Pr iceUt i l i t i e s {
pr ivate $ taxrate = 1 7 ;
function calculateTax ( $ p r i c e ) {
return ( ( $ t h i s - > t axrate / 1 0 0 )

$price ) ;

)
1 1

class ShopProduct implements I den t i t yObj ect


use P r i ceUt i l i t i e s , I de n t i t yT r a i t ;
, , S h o p P roduct

I d e n t i t yT r a i t . g e ne r a t e i d ( )
I de n t i t yObj e c t . ,
S h o p P r oduct ,
I d e n t i t yObj e c t ,
.

function s t oreident i tyObj ect ( I de n t i t yOb j ect $ i dobj


//

I dent i tyObj ect

$ = new ShopProduct ( ) ;
store iden t i t yObj ect ( $ ) ;


ins teadof
!
. ,
, c a l c u l a te T a x ( ) ,
?

80

11.

t r a i t TaxTools {
func t i on calculateax ( $ p r i ce )
return 2 2 2 ;

t ra i t P r i ceUt i l i t i es {
private $ t axrate = 1 7 ;
func t i on calculateTax ( $price ) {
return ( ( $ th i s - > t axrate / 1 0 0 )

$price ) ;

}
1 1

abstract c l a s s Service {
1 1

c l a s s U t i l i tyService extends Service


use P r iceUt i l i t i e s , TaxToo l s ;

$ = n e w U t i l i tyService ( ) ;
p r i n t $u->calcula teTax ( 1 0 0 ) . " \ n " ;
,

calculateTax ( )

, .
, .

Fa t a l e r r o r : T r a i t method c a l cu l at eT a x h a s n o t b e e n a pp l i e d , because t h e re
a r e c o l l i s i o n s w i t h o t h e r t ra i t me t ho d s U t i l i t yS e rv i c e i n . . . '
r i n s t e a do f ,
.

t r a i t TaxTool s {
function calcula teTax ( $price )
ret urn 2 2 2 ;

t r a i t P r i ceUt i l i t i e s (
priva t e $ t axrate = 1 7 ;
func t i on calcula teax ( $price ) (
return ( ( $ th i s - >taxrate/ 1 0 0 )
}

$price ) ;

1 1

abstract c l a s s Service {
1 1
4 calculateax -
U t i l ityService . - . .
. .

4.

81

class Ut i l i tyService extends Service (


u s e P r i ceUt i l i t i es , TaxTools (
TaxTools : : cal culateTax i n s teadof P r i ce Ut i l i t i e s ;
}

$u = new Uti l i tyService ( ) ;


print $u->calcul ateTax ( 1 0 0 ) . " \ n " ;
u s e ,
, .
i ns t e a d o f .
. .
,
. i n s t e a d o f
, .
,

Taxool s : : calculateax i n s teadof P r i ceUt i l i t i e s ;


, c a l cu l a t e T a x ( ) T a xT o o l s
P r i ce Ut i l i t i e s .
2 2 2 ,
T a xT o o l s : : c a l cu l a t e T a x ( ) .


, i n s t e a d o f
, .
, ?
a s ,
. i n s t e a d o f ,
as ,
- . c a l cu l a t eTax ( )
P r i ce Ut i l i t i e s b a s i cTax ( ) .

trait TaxTool s (
function calcul ateax ( $ p r i c e )
return 2 2 2 ;

trait PriceU t i l i t i e s (
private $ t axrate = 1 7 ;
function calcul ateTax ( $price ) {
return ( ( $ t h i s -> taxrat e / l 0 0 )
)
1 1

abs t ract c l a s s Servi ce (


/ /

$price ) ;

82

11.

c l a s s U t i l i tyService extends Service {


use PriceUt i l i t i e s , TaxTools {
TaxToo l s : : calculateTax i ns t eadof PriceUt i l i t ies ;
Pri ceUt i l i t i e s : : calcul ateTax as bas i cTax ;

$ = new Ut i l i t yService ( ) ;
print $ u - >calcu l ateax ( 1 0 0 ) . " \ n " ;
print $ u- >basicTax ( 1 0 0 ) . " \ n " ;

222
17
, P r i ceUt i l i t i e s : : c a l cu l a t e T a x ( )

U t i l i t yS e rv i c e ba s i cT a x ( ) .
.
use. ,
, insteado f .
as .
. .
. . . .
,
.


, .
.
. .
P r i c e Ut i l i t i e s : : $ t a x r a t e
P r i ceUt i l i t i e s : : c a l c u l a t eTax ( ) . .

t r a i t PriceUt i l i t i e s {
pri vate s t a t i c $ t axrate = 1 7 ;
s t a t i c funct ion calcu l ateTax ( $ p r i ce ) (
return ( ( s e l f : : $ taxrat e / 1 0 0 ) * $ p r i c e ) ;

/ /
}
abstract c l a s s Se rvice {
1 1
}
c l a s s U t i l i t yService extends Service (
u s e P r i ceU t i l i t i e s ;

$ = new Ut i l i tyService ( ) ;
print $ u : : calcul ateTax ( 1 0 0 ) . " \ n " ;

4 .

83

,
1 7 .



, .
, ,
. ? , -
.

trait PriceUt i l i t i e s {
funct ion calcu l ateTax ( $ p r i ce ) {
/ / ?
return ( ( $ t h i s ->taxrate/ 1 0 0 )

* $pr ice ) ;

1 1
)
abs tract class S e rvice
/ /
}
class U t i l i tyService extends Se rvice {
pu ic $ t axrate = 1 7 ;
use PriceUt i l i t i e s ;

$ = new U t i l i tyService ( ) ;
print $u->calcul ateTax ( 1 0 0 } . " \ n " ;
P r i ceUt i l i t i e s .
. .
. . - !
. ,
, $ t a x r at e

U t i l i t yS e r v i c e . ,
. ( !),
$ t ax r a t e?
, ,
, : "
".
, . ,
.

.
.
. .
.

trait PriceU t i l i t i e s {
function calcul ateax ( $pr ice )

84

1 1 .
1 1 , ,
1 1 getTaxRa t e ( )
return ( ( $ t hi s - >getTaxRate ( ) / 1 0 0 ) * $price ) ;

abs t ract func t i on getTaxRate ( ) ;


1 1
}
abstract c l a s s Service {
/ /

c l a s s U t i l i tyService extends Servi c e (


use Pri ceUt i l i t i e s ;
func t i o n getTaxRate ( )
return 1 7 ;

$ = new Ut i l i t yService ( ) ;
print $ u- >calcul ateTax ( 1 0 0 ) . " \n " ;
g e t T a x Ra t e ( )

P r i ce Ut i l i t i e s ,

U t i l i t yS e rvi c e .

, -
, ,

U t i l i t yS e rv i c e : : c a l cu l a t eT a x ( ) g e tTaxRate ( )
. , .
,
. , ,
,
.


,
( p u l i c ) , ( p r i v a t e } (p r o t e c t e d} .
,
. ,

a s . .
. .
.
,

c a l cu l a t eTax ( ) U t i l i t yS e r v i c e ,
. u s e ,
.

t r a i t PriceUt i l i t ies {
func tion c a l culateTax ( $price ) {
return ( ( $ th i s - > getTaxRate ( ) / 1 0 0
abstract func t i o n getTaxRat e ( ) ;

$price ) ;

4.

85

11
)
abs t ract c l a s s Service {
11
)
class Ut i l i tyService extends S e rvice (
use PriceUti l i t i es {
P r i ceUt i l i t i es : : calcul ateTax as p r i va t e ;
)
pr ivate $ p r i c e ;
function
cons truc t ( $ p r i c e )
$this ->price = $ p r i c e ;

func t i on getTaxRa t e ( )
return 1 7 ;

func t i on getFina l P r ice ( )


return ( $ t h i s - >p r i c e + $ t h i s - > c a l cu l a t eTax ( $ t h i s - >p r i c e )

) ;

$ = new U t i l i t yService ( 1 0 0 ) ;
print $u- >get Fi nal Price ( ) . " \ n " ;
c a l c u l a t eT a x ( ) Ut i l i t y

S e rvi c e , a s u s e p r i v a t e .
g e t Fi n a l r i ( ) .
c a l c u l a t eax ( ) ,
:

$ = new U t i l i t yService ( 1 0 0 ) ;
print $u->calcula teTax ( ) . " \n " ;
:

---Fat a l e r r o r : C a l l t o p r iva t e m e t h o d U t i l i t yS e rv i c e : : c a l cu l a t e T a x ( )
cont ext ' ' i n . . . 5

f rom

:
s tatic
, ,
. ,
,
, .
, ,
.

U t i l it yService : : calculateTax ( ) ' . . . -

. .

86

11.

abs t ra c t c l a s s Dorna inOb j ect

class User extends Dorna i nObj ect (


pu l i c s t a t i c func t i on create ( )
return new Use r ( ) ;

c l a s s Docurnent extends Dorna i nOb j ect (


pu l i c s t a t i c func t i o n create ( ) {
return new Docurnent ( ) ;

Dorna i nObj e c t . ,
,
. : U s e r Docurne n t .
, c r e a t e ( ) .

. -,
new ? 13, " ", ldentity .

ldentity ,
. ,
. - crea te ( )
.

,
- .
, .
, Doma i nObj e c t . ,

c r e a t e ( ) ?
abst ract c l a s s DornainOb j ect {
p u l i c s t a t i c func t i o n create ( )
return new s e l f ( ) ;

c l a s s User extends Dorna i nObj ec t {

c l a s s Docurnent extends Dorna inOb j ect {

Docurnent : : create ( ) ;
,

. !

, , ,

s e l f . s e l f , .
.

$ t h i s . s e l f
.
, .
.

4.
Fat a l e r ro r :

87

C a n n o t i n s t a n t i a t e a b s t r a c t c l a s s Doma i n0bj e c t 6 i n . . . .

. s e l f

Doma i nObj e c t , c r e a t e ( ) , Docume n t ,


.

5.3

, .

5.3 ( late static


bidings) . (

) s t a t i c . s e l f ,
,

, .

, Docume n t : : c r e a t e ( )
Document
Doma i nOb j e c t .
,
.

abstract class Doma inObj ect


pu ic static funct i on create ( )
return new s t a t i c ( ) ;

class User extends Doma inObj ect (

class Document extends Doma i nObj ect (

print r ( Documen t : : c reate ( ) ) ;


.

Document Obj e c t

s t a t i c .
, s e l f p a r e n t ,
. ,
Doma i nOb j e c t .
' de fa u l t ' .
.

abs t ract class Doma inObj ect


private $group;
pu ic funct ion construct ( ) (
$ t h i s ->group = s t at i c : : getGroup ( ) ;

pu ic s t a t i c func tion create ( )


return new s t a t i c ( ) ;

s t a t i c func t i on getGroup ( )

6 .

.. .

88

11 .
return " defau l t " ;

c l a s s User extends Doma i nOb j ect {

c l a s s Document extends Domai nObj ect


s t a t i c func t i o n getGroup ( )
return " document " ;

c l a s s SpreadSheet extends Document {

}
pri nt_r ( User : : create ( ) ) ;
print_r ( SpreadSheet : : create ( ) ) ;

Doma i nObj e c t ,
s t a t i c g e t G roup ( } .
Doma i nOb j e c t , Document .
S p r e a d Sh e e t , Documen t .
.
U s e r Obj e c t
(
[ g roup : Doma i nObj e c t : p r i v at e ]
)
S p r e a d S h e e t Obj e c t
(
[ g roup : Doma i nObj e c t : p r i v a t e ]
)

=> default

=> d o c ument

U s e r
. Doma i nObj e c t g e t G r oup ( ) ,
. .
SpreadSheet g e t G roup ( ) Doma i nObj e c t .
SpreadShe e t , c r e a t e ( )
. SpreadSheet g e t Group ( )
, Document (..
). 5.3
- s e l f ,
g e t G ro u p ( ) Doma i nObj e c t .


. . - ,
. URL-apeca
, L- . .
.
.
.
C o n f , .
L- .

4.

89

class Conf
p r iva te $ f i l e ;
pr ivate $xml ;
p r ivate $ l a s tmatch;
func t i on _construct ( $ f i l e ) {
$ th i s - > f i l e = $ f i l e ;
$ t h i s - >xml = s impl exml_load_f i l e ( $ f i l e ) ;

function wri te ( ) {
f i l e_put_cont ents ( $ t h i s - > f i l e , $ th i s - >xml - >asXML ( )

);

function get ( $ s t r ) {
$matches = $ t h i s - >xml ->xpath ( " / con f / i t em [ @ n ame= \ " $ s t r \ " J " ) ;
i f ( count ( $matches ) ) {
$ t h i s - > l as tmatch = $matches [ O J ;
return ( s t r ing ) $matches [ O J ;
return nul l ;

func t i on s e t ( $ key, $value ) {


i f ( ! i s_nu l l ( $ t h i s - >get ( $ key )
$ t h i s - > l a s tmatch [ O J =$va l ue ;

retu rn;
$conf = $ t h i s - >xml - >con f ;
$ t h i s ->xml-> addChi ld ( ' i t em ' ,

$value ) - >addAt t r i bute (

' name ' ,

$ key ) ;

Conf fl-fl
SimpleXml. L,
.
< ?xml ve r s i on= " l . 0 " ? >
<conf >
< i tem name= "us e r " >bob< / i t em>
< i tem name= "pas s " >newpa s s < / i t em>
< i tem name= "hos t " >localhos t < / i tem>
< / conf>

C o n f ,
s imp l e xml l oa d f i l e ( ) .
S imp l eXml E l eme n t $ xm l . g e t ( )
i t em name x p a t h
S imp l eXml E leme n t .
. s e t ( ) ,
. wr i te ( )
.
_

. , Con f
. , ,
.

90

1 1 .

"". , L-
.
,
, , .
.
l . . ,
. , -
. . _cons t ru c t ( )
w r i t e ( ) , ,
, , .

2.
. ,
- 1 .
,
.
R-
( PEAR Error). .
, .
,
- ,
.
.
. ,
.
,
.
, ,
,
. . !
,
, ""
, . ,
. ,
, , ,
.

5 ,
. - .
Java ++,
. ,
.
- ,
E x c ep t i o n ( ). Except i on
.
E x c ep t i o n :
.
(. 4. 1 ).

4 .

91

4. 1 . Exception

getMe s s a g e ( )

,
( ),
,
,
E x c ep t i on
, ,
, , ,

,

get Code ( )
get F i l e ( )
g e t L i ne ( )
getPrevious ( )
getTrace ( )

getTra ceAs S t r i n g ( )

g e t T r a ce ( )

, Excep t i on
. ,

_to S t r i ng ( )

Excep t i o n
( g e t T ra ce ( ) g e t T r a c e
As S t r i n g ( ) ). E x c ep t i o n P E A R E r r o r ,
.
. .
_


E x c ep t i on t h row.

. eo _con s t ru c t ( ) ,
t h row.
function _construct ( $ f i l e ) {
$this->file = $file;
i f ( ! f i l e_ex i s t s ( $ f i l e ) )
throw new Excep t ion ( " ' $ f i l e ' " ) ;
$ t hi s - >xml

s i mp l exml_load_f i l e ( $ f i l e ) ;

w r i t e ( ) .
function wri te ( ) {
i f ( ! i s_wri t ( $ th i s - > f i l e ) ) {
throw new t i n ( " ' { $ th i s - > f i l e } ' . " ) ;
f i l e_put_cont ents ( $ t h i s - > f i l e ,

$ t h i s - >xml - > asXML ( )

) ;

_ c o n s t ruct ( ) w r i t e ( )
, , .
, ,
.
,
? ,
, t r y. t ry
t r y . t r y -

92

11.

c a t c h ,
. .
t ry
$ conf = new Conf ( di rname (
FILE
p r in t "us e r : " . $ conf- >get ( ' use r ' )
print "hos t : " . $ conf- >get ( ' hos t ' )
$con f - >set ( " pa s s " , " newpa s s " ) ;
$ conf->write ( ) ;
catch ( Exception $ ) (
d i e ( $ e - >_t oString ( ) ) ;

" / con f O l . xml " ) ;


"\n" ;
"\n" ;

, c a t c h .
, c a t ch
. -
Exce p t i on .
,
t r y ,
c a t c h .

Excep tion
, Exce p t i on. .
.
, . -.
. -.
, .
, t r y
c a t c h , . , c a t ch .

. ,
Exce p t i on .
c l a s s Xml Excep t i on extends Except ion {
pr ivate $ e r r o r ;
funct ion
con s t ruct ( L i bXml E r ror $ e r ro r ) {
$ short f i l e = basename ( $ e r r or - > f i l e ) ;
$msg = " [ { $ sho r t f i l e ) , { $ e r r o r - > line ) , " ;
$msg . = " { $ e r ro r ->column ) ] { $ e r ro r - >mes s age ) " ;
$ t h i s - > e r ror = $ e r r o r ;
parent : : _cons t ruct { $ms g , $ e r ror->code ) ;

function getLibXml E r ror { )


return $ t h i s - > e r ror ;

c l a s s Fi l e Exception extends Except i on {


c l a s s Con fException extends Except i on {

}
)

L i bXml E r r o r , SimpleXrnl
L-. me s s a g e code.
Exce p t i o n .
L ibXml E r r o r Xml Ex c e p t i o n . F i l eExcep t i on

4.

93

C o f E x c e p t i o ,
Excep t i o.
,
c o s t ruct ( ) w r i t e ( ) .
/ / f . . .
fuc t i o _co s t ruct ( $ f i l e ) {
$this->file = $ f i l e ;
i f ( ! f i l e_exi s t s ( $ fi l e )
throw w F i l eExcept io ( " ' $ f i l e ' " ) ;
$ t h i s - >xml = s i mpl exml_load_f i l e ( $ f i l e , ul l , L I BXML_NOERROR ) ;
i f ( 1 i s_obj ect ( $ th i s ->xml ) ) {
throw w XmlExceptio ( l ibxml_get l a s t_e rror ( ) ) ;
prit get type ( $ t h i s - >xml ) ;
$matches = $ t h i s - >xml - >xpath ( " /co f " ) ;
i f ( ' cout { $matches ) ) {
throw w CofExcept io ( " f . " ) ;

fuctio w r i t e ( ) {
i f ( ! i s_wri teae ( $ t h i s - > f i l e ) ) {
throw w F i l eExcept io ( " a ' { $ th i s - > f i l e } ' " ) ;
f i l e_put_cotets ( $ th i s - > f i l e ,

$ th i s - >xml ->asXML ( )

) ;

Meo _c o s t ruct ( ) Xml E x c ep t i o , F i l e Except i o n


ConfExcept i on . .
, s i mp l e xm l l o a d f i l e ( ) L I BXML
NOE RROR. -::

Xml E xc e p t i o n . L-, s i mp l e xm l _
l o ad_f i l e ( ) S i mp l e X ML E l eme n t .
Xml Except i o n ,
l i bxml _ge t _l a s t _e r r o r ( ) - .
w r i te ( ) F i l e E x c ep t i on , $ f i l e
, .
. , eo _ co s t ruct ( )
. ?
. Conf ( ) .
class Runer {
s t a t i c fuction ini t ( ) {
try {
" / con f O l . xml " ) ;
$ c onf = w Con f ( di rame (
F I LE
"\n";
p r i nt "user : " . $co f - >get ( ' user ' )
"\n" ;
prit "host : " . $co f - >get ( ' hos t ' )
$ conf->s e t ( "pas s " , "newpas s " ) ;
$con f - >w r i t e ( ) ;
catch ( F i l eExcep t i o $ ) {
/ /
catch ( Xml Except ion $ )

94

1 1 .
1 1 L-
catch ( ConfException $ ) {
1 1 L-
catch ( Except i on $ ) {
1 1 :

c a t ch JI
. , ,
. .
: , c a t ch. ,
c a t ch JI Exce p t i o n JI
Xml Ex cept i o n C o n f E x ce pt i o n ,
. , Excep t i o n
.
c a t ch ( Fi l eE x c ep t i o n ) ,
(
). c a t ch ( Xm l E x c e p t i o n ) ,
L- (. -
). c a t ch ( Co n f E x c ep t i o n ) ,
L- c o n f .
c a t ch ( Ex c e p t i o n ) ,
, . ,
- ,
.
c a t ch ,

. . ,

, .
try {
11 . . .
catch ( F i l eExcep t i on $ )
throw $ ;

, , -
, .
,
, ,
. 1 5.
, ?
,
. ,

. . ,
.

4 .

95

Fa t a l e r ro r : U ncaught e x c ept i o n ' F i l e E x c e p t i o n ' w i t h m e s s a g e


' f i l e ' nonex i s t e nt / n o t t h e r e . xml ' doe s n o t e x i s t ' i n . . . '

, ,
. .
, ,
, . w r i t e ( )
, . ,
. . C o n f
, ,
.

:finally
,
, . ,
t r y
. ,
t r y
c a t c h . ,
,
. .
, Runne r : : i n i t ( )
.
, , ,
- .
. .
class Runner (
s t a t i c funct ion i n i t ( ) {
try
$ fh = fopen ( " . / l o g . txt " , " a " ) ;
fput s ( $ fh , " \ n " ) ;
$ conf = new Con f ( d i rname (
F I LE
) . " / con f . broken . xml " ) ;
print " user : " . $ conf->get ( ' us e r ' ) . " \ n " ;
print " hos t : " . $ c onf->get ( ' ho s t ' ) . " \n " ;
$ conf->set ( "pas s " , "newpas s " ) ;
$ conf->write ( ) ;
fputs ( $ fh , " \ n " ) ;
fclose ( $ fh ) ;
catch ( F i l eException $ )
fput s ( $ fh , " \ n " ) ;

11 . . .
l o g . t x t ,
, .

c a t c h . t r y
. ,
.
7 FileException,
. - .. .

96

11.

c a t ch , t r y .
,
.

.
. .
, ,
, .
,
t ry / ca t ch .
. , catch
.
,
t r y / ca t ch. , c a t ch
.
,
, 5.5
f i n a l l y .
Java, . t ch
,
f i na l l y , ,
t r y .
,
-

f in a l l y .
c l as s Runner {
s t a t i c funct i o n i n i t ( ) {
$ fh = fopen ( " . / l o g . tx t " , " w " ) ;
try
fput s ( $ fh , " \ n " ) ;
$conf = new Conf ( di rnarne (
FILE
) . " / con f . broken . xml " ) ;
print " us e r : " . $ conf->ge t ( ' us e r ' ) . " \n " ;
print " hos t : " . $ conf->ge t ( ' hos t ' ) . " \ n " ;
$ conf->s e t ( "pas s " , " newpas s " ) ;
$ conf->wr i t e ( ) ;
} catch ( F i l eExcep t i o n $ ) {
//
fput s ( $ fh , " \ n " ) ;
throw $ ;
catch ( XmlExcep t i on $ ) {
fputs ( $ fh , " xml \ n " ) ;
1 1 xml
) catch ( ConfException $ ) (
fputs ( $ fh , " \n" ) ;
1 1 n L-
} catch ( Excep t i on $ ) {
fput s ( $ fh , " \ n " ) ;
1 1 :
} finally {
fput s ( $ fh , " \ n " ) ;
f c l o s e ( $ fh ) ;

4.

97

f c l o s e ( )
fina l l y, . ,
Fi leExcep t i o n c a t ch .
Fi leExcep t i o n .

. f ina 1 1 , t ch

return, .
try c a t ch d i e ( ) exi t ( ) ,
fina l l y .



. .
,
, . .
, ,
.
,
, f i na l .
f i n a l . l
. .
.
final class Checkout {
11 . . .

C h e c k ou t .
class I l l egalCheckout extends Checkout {
11
)

.
F at a l e rror : C l a s s I l l e g a l Ch e c kout n o t i nh e r i t f rom
f i n a l c l a s s ( C h e c kout ) i n . . . 8

,
Che c kout , . f i n a l
, p r o t ec t ed s t a t i c .

I l legalCheckout

. .

Checkout. -

1 1 .

98

c l a s s Checkout {
final function t o ta l i z e ( )
1 1

C h e c kou t ,
t o t a l i z e ( ) .
c l a s s I l l egalCheckout extends Checkout {
f i n a l func t i on t o t a l i z e ( ) {
1 1

Fat a l e r ro r : C a n n o t ove r r i d e f i n a l m e t h o d che c kout : : t o t a l i z e ( )

in

-
.
.
, - .
, .
, .
- , .
, ? ,
, ,
, .
, f i n a l .

-
-,
, (.. )
. (overloading),
Java ++ , ,
"" (interception).
5 -.

c o n s t r u c t ( ) ,
. . 4.2.
_get ( ) _ s e t ( ) ,
( ).
_g t ( ) ,
. ,
, .
, _g e t ( ) ,
. .
,

c l a s s Person (
fun c t i on
get ( $property ) {
$method = "get { $property ) " ;
i f ( method_ex i s t s ( $ thi s , $method )
return $ th i s - > $method ( ) ;
9

checkout : : tota l i z e ( ) . - .. .

4.

99

function getName ( )
return " " ;

function getAge ( )
return 4 4 ;

4.2. -0

_get ( $prope r t y )

,

, i s s e t ( )

, unset ( )




set ( $prope r t y ,

$value

i s s e t ( $ prope r t y
_uns e t ( $prope r t y
_cal l ( $method,

$ arg_a r r a y

_cal l S t at i c ( $method,

$ arg_a rr a y

,
_ge t ( ) ,
" ge t " . , ,
method_exi s t s ( )
, .
,
.. , $ n ame
.

$
new Person ( ) ;
print $p- >name ;
=

getName ( ) .
"
"
_.,
.,_
.._
.,..
.,..
,...
._,
._
...,

---_,,
.,.
..,.
,
.
,
..,.,

m
q

...

...,.
,_.
,_.
....,
....,
..,..
,...
_.
.
....,...
.
,_,
..
.
....
=

----...
---

, . ,
, NULL.
_ i s s e t ( ) . _ge t ( ) .
, i s se t ( )
.
Person.

function _isset ( $property ) {


$method
" ge t { $property ) " ;
=

10 :
.
.
-

1 00

11 .
return ( method_ex i s t s ( $ t hi s ,

$method )

) ;

,
.
if

( isset ( $p->name )
print $p- >name ;

_ s e t ( ) .
. :
, . ,
. Per son.
class Person {
private $_name ;
priva t e $_age ;
funct i on s e t ( $prop e r t y , $ va l ue ) {
$method = " s et { $propert y ) " ;
i f ( method_exi s t s ( $ t hi s , $method
return $ t h i s - >$method ( $va l ue ) ;

funct i on s e tName ( $ name ) {


$ t h i s - >_name = $name ;
i f ( ! i s_nu l l ( $name ) )
$ t h i s - >_name
s t r t oupper ( $ t h i s - >_name ) ;

funct i on s e tAge ( $age ) {


$ t h i s - >_age
s t rt ouppe r ( $ a ge ) ;

- (setter),
- (getter).
,
s e t ( )
.
s e t ( ) ,
, , .
.
. , -

, , .
Person : : $ n ame,
, Person.

, Per son,
P e r s on : : $ n ame,
s e t ( ) ,
$name. ,
, . ,
. ,
11 s e t 11 s e tName ( )

4 .

1 01

.
.
setLocale ( LC_ALL,

" ru_RU . C P 1 2 5 1 " ) ;

$ = new Person ( ) ;
$p->name = " " ;
1 1 $_name ' '

,
u n s e t ( )

s e t ( ) . , u n s e t ( )
.
unset ( ) .
.
null
,
set ( ) .
funct i o _unset ( $prope rty ) {
$method = " s e t { $prope rty } " ;
i f ( rnethod_ex i s t s ( $ t h i s , $method )
$ t h i s - > $rnethod ( nul l ) ;

c a l l ( ) , , - -
. , .

c a l l ( ) ,
, . ,

ca l l ( ) , ,
.

c a l l ( ) .

.
- , ,
.
.
- ,
, . ,
. ,
, P e r s o n .
-

c l a s s PersonW r i t e r {
function writeNarne ( Per son $ )
prit $p- >getNarne ( ) . " \ n " ;

func tion writeAge ( Person $ )


print $p->getAge ( ) . " \n " ;

, ,
Person . Per s o n ,
PersonW r i t e r , _ l l ( ) .
class Per son {
p r i vate $ wr i t e r ;

1 02

1 1 .

function
cons t ruct ( Pers onWri t e r $ w r i t e r )
$ t hi s - >wr i t e r = $ wr i t e r ;

function _cal l ( $methodname , $ a rgs ) (


i f ( method_exi s t s ( $ th i s ->wr i t e r , $methodname )
return $ th i s - >writer- >$met hodname ( $ t h i s ) ;

funct ion getName ( ) ( return " " ;


function getAge ( ) ( return 4 4 ; ]

P e r s o n
$ wr i t e r .
_ c a l l ( ) $me t hodname
P e r s o nW r i t e r ,
. ,
P e r s onWr i t e r . m
P e r s o n , $ t h i s . ,
P e r s o n
P e r s onWr i t e r ,

$person = new Person ( new PersonWri t e r ( )


$person - >wri teName ( ) ;

) ;

_ c a l l ( ) . , P e r s o n
W r i t e r w r i teName ( ) , .
, .
func t i on writeName ( ) (
$ t h i s ->write r- >wri teName ( $ t h i s ] ;

, Per s on, ,
Per sonWr i t e r .
,
. ,
,
( )
. ,
,
, . ,
_ca l l ( ) ,
. - ,
. ,
, .
.
-
get ( )
s e t ( J
(composite properties).
.
, Add r e s s
.
,
. ,

4.

1 03

, .
. ,
. ,
Addre s s : : $ s t r e e t a dd r e s s .
c l a s s Addre s s {
pri vate $nurne r ;
pri vate $ s t r ee t ;
funct i on
const ruct ( $maybenurne r , $maybe s t reet=nu l l )
i f ( i s_nu l l ( $maybest reet ) ) {
$ t h i s - > s t r eetaddre s s = $maybenumer ;
else {
$maybenurne r ;
$ t h i s - >numer
$maybe s t r ee t ;
$ t h i s - > s t reet

func t i on _s et ( $prope r t y , $va l ue ) {


i f ( $prope r t y === " s t reetaddre s s " ) {
if ( preg_match ( " / ( \d+ . * ? ) [ \ s , ] + ( . + ) $ / " , $ va l u e , $ ma t ches )
$ t h i s - >numer
$matches [ l ] ;
$ t h i s - > s t reet = $matches [ 2 ] ;
else {
throw new Exception ( " : ' { $ va l ue ) ' " ) ;

func t i on _get ( $prope r t y ) {


i f ( $prope r t y === " s t reetaddre s s " ) {
return $ th i s - >nume r . " " . $ th i s - > s t ree t ;

$address = new Addres s ( " 4 4 1 Bakers S t r e e t " ) ;


print " : { $add res s - > s t reet addre s s ) \ n " ;
$address = new Address ( 1 5 , "Albert Mews " ) ;
print " : { $addre s s - > s t ree taddress ) \ n " ;
$addres s - > s t reetaddre s s = " 3 4 , West 2 4 th Avenue " ;
print " : { $ addre s s - >s tree taddress ) \ n " ;

Add r e s s : : $ s t r e e t a dd r e s s
_ l l ( ) . " s t r e e t
addre s s " , .
$ n umbe r $ s t re e t , ,

. ,
. .
, ,
, - .
,

1 04

1 1 .

$mat ch e s ,
$ n ume r $ s t re e t . .
. , " 4 4 1 B a k e r s
S t re e t " Addre s s : : $ s t r e e t addre s s ,
$ num e r $ s t re e t ,
. p r i nt_r ( ) .
$ address = new Address ( " 4 4 1 Bakers S t reet"
p r i n t_r ( $address ) ;
Addr e s s Ob j e c t
(
[ nume r : Ad d r e s s : p r i va t e ]
[ st re e t : Ad d r e s s : p r i va t e ]

=> 4 4 1
=> B a k e r s S t r e e t

_s e t ( ) _ge t ( ) .
Addre s s : : $ s t re e t a ddre s s _get ( ) .
" s t re e t addre s s " , ,
, ,
$ numer $ s t re e t .


,
eo _co n s t r u c t ( ) . 5 eo _de s t ruct ( ) .
, w", . . ,
, .
, .
, ,
.
de s t ruct ( )
,
. P e r son, .
class Person {
p r i vate $ n ame ;
p r i vate $ a g e ;
p r i vate $ id ;
func t i on
const ruct ( $name ,
$ t h i s - >n ame = $name ;
$ t h i s - >age = $ age ;

function s e t ! d ( $ i d
$this->id = $id;

$ age

) {

funct i o n _des t ruct ( ) {


i f ( ! emp t y ( $ th i s - > i d ) ) {
1 1 Person
print " person \n " ;

4.

1 05

de s t ruct ( ) , P e rson
. _unset ( ) ,
. ,
. , Person,
, , _des t ruct ( ) .
new Perso ( " " , 4 4 ) ;
$person
$person->seti d ( 3 4 3 ) ;
unset ( $person ) ;
1 1 : " perso"
=

,
. -, _ cal l ( ) , _d e s t ruct ( ) ,
. -
"", . , , - .
. . .
, _de s t ruct ( ) ,
. ,
P e r s o :
de s t ruct ( ) . ,
Person, , . eo _de s t ruct ( )
P e r s o n .
,
$ name $ a g e 1 50.
,
.

,
. : .



clone ( )
_
4 -
.
class { )
$first
$second

w ( ) ;

=
=

$ fi rst ;

11 4 $ s econd $ fi rs t L
1 1 5 $ second $ fi rst L

,
"" ,
. ,
, ,
.
(==)

1 06

1 1 .

(===). ,
.
5 . ,
5, $ f i r s t $ s e cond
, .
, , ,
, .
5 c l on e .
.
c l a s s { }
$ f i r s t = new ( ) ;
$ s e cond = clone $ f i r s t ;
1 1 5 $ s econd $ f i r s t
1 1

, , .
P e r s o n , .
P e r s o n ( $ i d) ,

. ,
, , ,
, , . .
.
, c l one
, .
_c l o n e ( ) ( ,
) . _c l o n e ( )
, c l o n e .
_c l o n e ( ) ,
. _c l one ( ) .
.
c l one ( )
Person.
c l a s s Person
pr ivate $m ;
p r i va t e $ ag e ;
priva t e $ i d ;
func t i o n
con s t r uc t ( $narne ,
$ th i s - >narne = $narne ;
$ t h i s - >age = $ age ;

funct i on s e t i d ( $ i d )
$this->id = $id;

$ age

clone ( )
function
$this->id = 0 ;

c l o n e P e r s o n ,
(shallow) . c l o ne ( ) . .

4 .

1 07

,
c l one ( ) ,
. ,
, . , $ i d
.
$person
new Person ( " " , 4 4 ) ;
$person->setid ( 3 4 3 ) ;
$person2 = cl one $person ;
11 $person2 :
/ / name : " "
/ / age : 4 4
11 i d : .
=

,
.
, m . ,
, , . ,
Pe r s o n - Account.
, .
, Pe r s o n m
.
class Account {
pu l i c $balance ;
function construct ( $bal ance )
$this- >balance = $balance;

class Person (
private $name ;
private $age ;
private $ id ;
pu ic $ account ;
function
construct ( $name , $age, Account $ account )
$this->name
$name ;
$this - >age = $age;
$ th i s - >account
$ accoun t ;
=

function setid ( $ i d )
$this->id = $ id ;

function clone ( )
$this->id = ;

$person
new Person ( " " , 4 4 , new Account ( 2 0 0 ) ) ;
$person->setid ( 3 4 3 ) ;
$person2 = clone $person ;
11 $person
$person->account - >balance += 1 0 ;
=

1 08

1 1 .

1 1 $pe rson2
print $person 2 - > accoun t - >balance ;

.
210

$ p e rson,
, Accoun t . ,
, .
, Account,
$ p e rson. .
Account $ p e rson,
$person2.

,
-,
c l one ( ) .
funct i on _clone ( )
$this->id = ;
$ t h i s - >account

{
=

cl one $this ->accoun t ;


, 5 Java,
_

t oS t r i ng ( ) . 5.2

class St ringThing { }
$st
new StringThing ( ) ;
print $ s t ;
=

.
Obj ec t i d # 1

5.2 .
C a t ch a e f a t a l e r r o r : Obj ec t o f c l a s s S t r i ng T h i n g coul d not
conve r t e d t o s t r i ng i n . . . 1 1

_t o S t r i ng ( ) , ,
. _to S t r i n g ( )
. .
p r i n t echo,
. t o S t r i ng ( )
Person.
class Person {
function getName ( )
func t i on getAge ( )
functi on

toStng ( )

return "" ;
return 4 4 ; }
{

1 1 : StringThing
. . . - . .

4.
$desc = $ th i s - >getName ( ) ;
$desc . = " ( " . $ t h i s - >getAge ( )

1 09

" ) " ;

return $de s c ;

P e r s on
$person = new Per son ( ) ;
print $person ;

( 4 4 )

_t o S t r i ng ( )
, ,
- . ,
Excep t i on ,
t o S t r i ng ( ) .

,


- , ,
. , -
. .

.
.
class Product (
pu i c $name ;
pu l i c $ p r i c e ;
function _cons t ruct ( $name,
$ t h i s - >name = $name ;
$ t h i s - >price = $pr ice ;

$ p r i ce )

class Proce s s S a l e {
private $cal lbacks ;
function regi s te rCal lback ( $ c a l lback ) {
if { ! is_cal l a e ( $ c a l l back ) ) {
throw new Except ion ( " - ! " ) ;

$ t h i s - >cal lbacks [ J

$ c a l lback;

funct ion sa l e { $product ) {


print " { $produ c t - >name } : . . .

\n" ;

1 1

1 1 .
foreach ( $ th i s - >c a l lbacks as $ c a l lback }
cal l_us e r_func ( $ c a l lback, $product } ;

.
. P roduct $ name
$ p r i ce . .

. P r o c e s s S a l e . r e g i s t e rC a l lba c k ( )
.
$ ca l l b a c k s .
i s _c a l l a e ( } .
, re g i s t e rC a l l b a c k ( }
, , c a l l_u s e r_func ( }
a r ra y_wa l k ( ) .

s a l e ( ) P r o d u c t .
$ ca l l b a c k .
P r oduct c a l l u s e r f u n c ( ) ,
, , , .
.
?
,

. ,
,
, .
, , -
P r oc e s s S a l e .
, s a l e ( ) .
.
, P r o c e s s S a l e ,
, .
, , s a l e ( ) ,
, .

. .
, . P r o c e s s S a l e
. ,
.
$ l ogger

' $product ' ,


' p rint " . . .
$proce s s o r = new Proces s S a l e ( ) ;
$proce s s o r - > r eg i s t e rCal lback ( $ l ogger ) ;
=

create fun c t i o n (

( { $produc t - > name } ) \ n " ; ' ) ;

$proce s s o r - > s a l e ( new Product ( " " , 6 ) ) ;


print " \n " ;
$proce s s o r - > s a l e ( new Produc t ( " " , 6 } } ;


. , .
, - .
c r e a t e funct i o n ( )

4 .

111

, ,
, .
,
. ,
.
$ l ogge r ,
P r o ce s s S a l e : : r e g i s t e rCa l lb a c k ( ) . ,
, s a l e ( ) . ,
, , , .
( ),
, .
:
( )
:
( )

c r e a t e_ f un c t i on ( ) .
, ?
. ;r
' $ ' ' ? ' ,
. ,
.
, -
. 5.3 !
, , .
- ! ,
.
$logger2

funct i on ( $product ) (
print " ( { $produc t - > name } ) \n " ;
};
$processor = new Proc e s s S a l e ( ) ;
$processor->regis t e rCal lbac k ( $ l ogge r2 ) ;
=

$proce s s o r - > s a l e ( new Product ( " " , 6 ) ) ;


print " \ n" ;
$proce s s o r - > s a l e ( new Produc t ( " " , 6 ) ) ;

,
. , .
f un c t i on
. , ,
,
. ,
,
create _ fun c t i o n ( } .
.
,
.
- .
.

1 12

11.

c l a s s Ma i le r {
func t i on doMa i l ( $ product )

print " n ( { $product- >name ) ) \ n " ;

$processor = new Proce s s S a l e ( ) ;


$ p roce s s o r - >regi s t e rCa l l back ( array ( new Mai l e r ( ) ,

"doMai l " )

);

$proce s s o r - > s a l e ( new Product ( " " , 6 ) ) ;


print " \ n " ;
$process o r - > s a l e ( new Produc t ( " " , 6 ) ) ;

M a i l e r , d oM a i l ( ) .
P roduc t , .
r e g i s t e rCa l l b a c k ( ) ,
, .
M a i l e r . - .
, . , r e g i s t e rC a l l b a c k ( )
i s_ca l l a e ( ) ,
?
.
,
,
. , ,
.
:
( )
:
( )

, ,
.
c l a s s Tot a l i z e r {
s t a t i c funct i on warnAmount ( ) {
return funct i on ( $ p roduct )
i f ( $produc t - >p r i c e > 5 ) {
print " :

{ $p roduct->price ) \n " ;

);

$proce s s o r = new Proc e s s S a l e ( ) ;


$proce s s o r-> regi s terCal lback ( Tota l i z e r : : warnAmount ( )

);

, . warnAmount ( )
.
,
.
(closures).
, . -

4.

11

. , .
.
, m . , ,
Tota l i ze r : : wa rnArnount ( ) . -, ,
m . -, ,
(.. ) .
,
( , ,
).
,
, u s e ,
.
class Tota l i z e r {
static function warnAmount ( $arnt )
$count=O ;
return funct ion ( $product ) use
$arnt , & $count )
$count += $product ->price;
print " : $count\n " ;

i f ( $count > $arnt ) {


print " : { $ count ) \n" ;
);

$processor = new ProcessSale ( ) ;


$processor->regi sterCall back ( Tota l i z e r : : wa rnAmount ( B ) ) ;
$processor->sale ( new Product ( " " , 6 ) ) ;
print "\n" ;
$processor->sal e ( new Product ( " " , 6 ) ) ;

use , T o t a l i
zer : : warnAmount ( ) , . - $ amt ,
, w a r nAmount ( ) . -
$ coun t . warnArnount ( ) ,
. , $ count
use ' & ' . ,
m, .
,
$ amt .
. , .
:
: 6
:
: 1 2
:

12

. $ count
. , $ count $ amt , -

1 14

11.

.
u s e .


-
.
. , ,
.

.
.

/)J
@@@
'l------

, -
, .
, ,
.
,
, m
.
.

: .

. : 5.3
.

.
:

, , .

Rejlection API: ,

.


- ,
.
.
, .
, , . 5.3
.
.
,

.

1 1

1 1 .


, , ,

r.

. ,
, , - .
5.3
,
. , ,
. Shopp i n g Ba s ke t ,
. .
.
, ? , ,
, - .
! ,
.
. .
,
1 1 my . php
requi re_once " u s e fu l /Outputt e r l . php"
class Outputter {
1 1

?
1 1 u s e f u l /Output t e r l . php
c l a s s Outputter {
11
)

, , , ? .
F a t a l e r ro r :
l i ne 3 1

Cannot r e de c l a re c l a s s Output t e r i n . . / u s e fu l / Output t e r l . php

, .
. ,
, .
1 1 my . php
requi re_once " u s e f u l /Outputter2 . php " ;
c l a s s my_Ou tput ter {
1 1
)
1 1 u s e f u l /Outputter2 . php
c l a s s use ful_Outputter {
11
)

.
.
1

Outputter. - . .

5.

1 17

, m
. .
.
,

.
.

5.3.
, , .

. ,
,
m .
? .
.
namespace my;
requi re_once " u s e f u l /Output t er . php " ;
class Outputter {
//
)
1 1 useful /Outputter . php
namespace u s e fu l ;
class Outputter {
11
)

name s p a c e . , ,
, .

. : my use ful.
.
, ,
. . ,
' \ ' ,
.
namespace com\get i n s t ance \ ut i l ;
class Debug {
s t a t i c function hel l oWor ld ( )
print " Debug ! \ n " ;


: g e t i ns t a n c e . .
.
Java,
.
. -

1 18

1 1 .

.
ut i l .
r ? ,
.
, , . .. ,
.
Debug : : he l l oWorld ( ) ;

. ,
com\ g e t i n s t ance\ut i l ,
- . .
.
.
com\getins tance\uti l \ Debug : : he l l oWorld ( ) ;

, ?
namespace mai n ;
com\ getins tance\ut i l \ Debug : : he l loWorld ( ) ;

. .
Fat a l e r ro r : C l a s s

' ma i n \ com\ g e t i n s t an c e \ u t i l \ Debug ' not f ound i n . . . /


l i s t i n g S . 0 4 . php on l in e 1 2 2

,
. ma i n
com\ g e t i n s tance\ut i l . .
. ,
URL.
-, .
namespace mai n ;
\com\get instance\ut i l \ Debug : : hell oWorld ( ) ;


. , .
m
? . Debug
. ""
. . .
use.
, .
namespace mai n ;
u s e com\ge tinstance \ut i l ;
util \Debug : : hel loWorld ( ) ;

com\get i n s tance \ut i l .


ut i l . ,
. ,
use , 2

' ma in \com\getins tance \util \ Debug ' . - . .


.

5.

1 19

.
r . , .

Debug.

namespace ma i n ;
u s e com\ getins tance \ut i l \ Debu g ;
Debug : : he l l oWorld ( ) ;

, rna i n
. .
.
Debug? ,

namespace ma i n ;
u s e com\ getins tance \uti l \ Debug ;
class Debug (
s t a t i c funct ion h e l l oWorld ( ) (
print " ma i n \ Debug " ;

Debug : : he l l oWorld ( ) ;
.
....
...

....
....
.

-.
---
-----------
-----

----------

Fa t a l e r ro r : Cannot d e c l a r e c l a s s rna i n \ Debug b e c a u s e t h e narne i s


a l r e a d y i n u s e i n . . . / l i s t i n g 5 . 0 8 . ph p o n l i n e 1 3 3

--
-

----------
-....

---

. .
. , ,
. .
name space ma i n ;
u s e com\getins tance \ ut i l \ Debug as uDebug ;
c l a s s Debug (
s t a t i c func t i on hel loWo r l d ( ) [
print " , ma in\ Debug" ;

uDebug : : he l l oWorld ( ) ;

a s u s e .
Debug uDebug.

. ( ) .
. h e l l oW o r l d ( )
L i s t e r , .
11 global . php :
c l a s s Lister (
pu l i c s t a t i c funct i on h e l l oWo r l d ( ) (
print " \ n " ;

ma in\ Debug.

. .

".

1 20

1 1 .

, ,
.
namespace com\ getins tance \u t i l ;
requ i re once ' gl obal . php ' ;
class Lister
pu i c s t a t i c func t i on h e l l oWorl d ( ) {
NAESPACE
p r int " " .

. " \n " ;

L i s t e r : : h e l l oWorld ( ) ;
/ /
\ L i s t e r : : hel l oWorld ( ) ; / /

L i s t e r .

. (..
), ,
. .
com\ g e t i n s t an c e \ ut i l

, ,

N AE S PACE
,
.

. ,
.
_

_.

namespace com\ getins tance \ u t i l {


class Debug {
s t a t i c func t i on h e l l oWorl d ( )
p r i nt " Debug\n" ;

namespace main
\ com\ getins tance \ ut i l \ Debug : : h e l l oWorld ( ) ;

,
,
.
.
r e qu i r e_once I
.
.
, .
namespace {
class L i s t e r {
// . . .
)

5 .

1 21

namespace com\ge t i ns tance \ut i l


class Lister {
11 . . .

)
L i s ter : : hel loWorld ( ) ; / /
\Li st er : : he l l oWorld ( ) ; / /

, ame s pa c e
.
. .

- .



, .
, u t i l b u s i n e s s
requi re _once ( ) .
requi re_once ( ' busie s s /Customer . php ' ) ;
requi re_once ( ' ut i l /WebToo l s . php ' ) ;

i n c l ud e_once ( ) .
r e qu i re once ( ) i n clude once ( )
. ,
requ i re once ( ) ,
. ,
i n c l ude once ( ) ,
. r e qu i re ( ) requi re_ once ( )
, i n c l ude ( )
i n c lude_once ( ) .
_

. requ i re ( ) requ i re_ once ( ) - , .

, .
. , , ,
.

. 5. 1 ,
Nautilus.

util

b u s i n e s s

. requi re _once ( ) , -,

.
, .. ,
. ,
.
, ,
requ i re ( ) i n c l ude ( ) .
requi re ( ) requ i r e_once ( ) ,
i ncl ude ( ) i nclude_once ( ) . , , -

1 22

1 1 .

, require ( ) ,
. , , include ( ) ,
,
. , , .
, require_ once ( ) ,
requi re ( ) . ,
require ( ) . , .

. 5. 1 .

, . .
,
.
.
PEAR
, .
. , -
.
" - !"
.
. ,
, .
.
, ,
? .
, PEAR.
PEAR Extension and App/ication Repository (
) . ,
. PEAR ,
. PEAR
http : / /pear . php . net. PEAR 1 5 ,
" PEAR Pyrus".

PEAR , m
. .
.
, PEAR L, RPC.
RPC , S e rve r . php. ,
S e r ve r . php, S e rve r , .
S e rve r , -

5 .

1 23

- PEAR .
. XML_RPC_S e r ve r . ,
. , ,
. .



. .
.
. .
.
( ),
.
. ,
.
requi re_once ( ' bus i ne s s /Use r . php ' ) ;

, b u s i ne s s
. .
, , , r e qu i r e
once ( ) .
requ i r e_once ( ' . . / . . /proj e c t l i /busine s s /Us e r . php ' ) ;

, .
requi re_once ( ' /home / j ohn/pro j e c t l i /bus i nes s / Us e r . php ' ) ;

.
,
.
""
.
r e qu i r e .

.
r e qu i r e ( ) .
.
.
, . b u s i n e s s p ro j e c t l i /
b u s i ne s s?

.
. m
busines s / Us e r . php

. ,
, i n c l ud e p a t h .
i n c l ude_pa t h . p h p . i n i .
, ( U NI-
) ( Windows).
i ncl ude_path = " . : / us r / l ocal / l i / php- l ibrar i e s "

Apache. i nc l u d e _ t h
( h t t pd . c o n f)

1 24

11.

(
. h t a c c e s s ) . .
php_value incl ude_path " . : / u s r / local / l i/php - l ib r a r i e s "
. . h t a c c e s s - -,

.
, fopen ( ) r e qu i r e ( ) ,
, ,
: . fopen ( )
,
. ,
.
, , r e qu i re ( )
.
!:j ,
i n c l ude p a t h . php . i n i .
. Apache,
.
, : php . i n i ,

s e t i n c l ud e_pa t h ( ) . ( .
php . i n i ) . ,
i n c l ude _ th . php . i n i , ,
i n c l ude_p a t h . . .
g e t _ i n c l ude_pa t h ( )
.
.
s e t_include_path ( get_incl ude_path ( )

PATH_SE PARATOR . " / home / j ohn/phpl i / " ) ;

PATH_S E PARATOR -
, . , Unix -
( : ). Windows
( ; ). ,
, _ S E PARATO R
.
-

: ,
.
,
. ,
,
( 1 1 1 2).
,
. . ShopP r oduct
ShopProduct . php. ,
, PEAR. .
ShopProduct b u s i n e s s ,
Shop P ro du c t . php, - b u s i ne s s . -

5.

1 25

, :
bus i n e s s _ Shop P roduct .
,
PEAR. bus i n e s s ,
Shop P r oduct , S h o p P ro du c t . php
bus i n e s s .
,
, 5 .
.
. s p l _a u t o l o a d_r e g i s t e r ( )
. ,
s p l _a u t o l oad ( )
. s p l _a u t o l o a d ( )
, .

( . i nc , . php} .
, ,
.
.
spl_autol oad_regi ster ( ) ;
$writer = new Writer ( ) ;

,

. ,
,
wri t e r . i nc , - w r i t e r . php, .
W r i t e r,
. .

. .
w r i t e r . php (
: } u t i l .
Wri t e r ,

spl_autol oad_regi s t e r ( ) ;
$wri ter = new u t i l \Writer ( ) ;

,
(..
, }? ,
Wri t e r W r i t e r . php,
.
,
, .
s p l_au t o l o ad_r e g i s t e r ( )
.
.
,
.

.
.

1 26

11.

,
.
func tion s t r a i gh t i n c l udeWithCa s e ( $ c l a s s name )
$ fi l e = " { $ c l a s s name ) . php " ;
i f ( f i l e_ex i s t s ( $ f i l e ) ) {
requi r e_once ( $ fi l e ) ;

spl_autol oad_re g i s t e r ( ' s t ra i ghtincludeWithCa s e ' ) ;


$product = new ShopProduct ( ' ' , ' ' ,

' ' ,

1 2 . 99 ) ;

Shop P r oduct
,
, s p l _a u t o l o a d_ r e g i s t e r ( ) .
" Sh o p P r oduc t " .
.
ShopProdu c t . php. , ,
,
. ,
,
PEAR. .
, PEAR, , .
func t i on repl aceUnde r s core s ( $ c l a s sname ) {
$path = s t r_replace ( ' _ ' , DI RECTORY_SE PARATOR,
i f ( f i l e_ex i s t s ( " ( $path } . php" ) ) (
r e qu i r e_once { " { $pat h } . php" ) ;

spl_autol oad_regi s t e r (

' repl aceUnde r s cores '

$ c l a s s name ) ;

) ;

$ = new ShopProduct { ) ;
$ = new busines s_ShopProduc t ( ) ;

, r e p l a ceUnde r s c o r e s ( )
, $ c l a s s name ,
, DI RECTORY S E PARATOR ( ' / ' Unix ' \ '
Windows). bus i ne s s / Shop
P roduc t . php. , ,
, . ,
, ,
,
, .
?
,
. , ,
.

- ,
, .
_

function myName spaceAutol oad ( $path )


i f ( preg_ma tch ( ' / \ \ \ \ / ' , $path )

{
)

5.
$path

s t r_repl ace ( ' \ \ ' ,

D I RECTORY_SE PARATOR,

i f ( fi le_ex i s t s ( " { $path } . php " )


requi re_once ( " { $path } . php" ) ;

1 27

$path ) ;

, ,

.

.
,
, PEAR, ?

,
s p l _a u t o l oad_r e g i s t e r ( ) , .
spl_autol oad_regi s t e r (
spl_au toload_reg i s t e r (
$
$
$z
$

new
new
new
new

' r eplaceUnde rscores ' ) ;


' myNamespaceAutoload ' ) ;

ShopProduct ( ) ;
bus ines s_ShopProduct ( ) ;
bus iness \ S hopProduct2 ( ) ;
\bus i ne s s \ ShopProduc t ( ) ;

,
r e p l a ce Unde r s co r e s ( ) , - myName s pa ce Au t o l o a d ( ) ,
.
,
- .
- ? ,
,
PEAR, .
, ,
,
.
, .

,
s p l_a u t o l o a d_ u n r eg i s t e r ( ) ,
" ".
. 11
_ t o l oad ( ) . ,

, .
, , 11 autoload ( )
. , , autol oad ( )
, ,
spl_autoload_regi s t e r ( ) ' _autoload ' ,
.
spl_aut o l oad_reg i s t e r ( ' _autoload ' ) ;

1 28

1 1 .



. . ? ,
.
,
. , ""
, .

. ,
, .
1 1 Tas k . php
namespace t a s k s ;
class Task {
fun c t ion doSpeak ( )
p r i n t " ! \ n " ;

1 1 Tas kRunner . php


$ c l a s sname = "Tas k " ;
requ i r e_once ( " ta s ks / { $ c l as s name } . php" ) ;
$ c l a s sname = " t a s ks \ \ $ c l a s sname" ;
$my0bj = new $ c l a s sname ( ) ;
$myOb j - >doSpeak ( ) ;

, $ c l a s s name ,
, -,
.
i . ,
.
. ,

, .
, . ,
, , ,
. , ,
, .

, . ,
,
.
, .
, ,
, , .
,
.
- WordPress.

, ,
(plug-lns).

5 .

1 29

,
, , ..
5
Reflectlon API, .

. .


c l a s s e x i s t s ( } , .
t ru e , , f a l s e - .

.
11 Tas kRunne r . php
$clas sname = "Task " ;
$path = " t a s ks / { $ c l a s sname ) . php " ;
i f ( ! f i l e_ex i s t s ( $path ) ) {
throw new Except ion ( " ( $path ) . " } ;

requi re_once ( $path ) ;


$qclassname = " t a s ks \ \ $ c l as s n ame " ;
i f ( ! c l a s s_ex i s t s ( $ qc l as s n ame ) } {
throw new Except i on ( " $ q c l a s s name " } ;

$my0bj = new $ q c l a ss name ( } ;


$myOb j - >doSpea k ( } ;

, ,
.
Reflectlon API,
.
c l a s s _e x i s t s ( } , .
, ,
. .
.
.
,
.
, ,
, .

. ,
g e t_dec l a red_c l a s s e s ( ) .
print_r ( get_decla red_cl a s s e s ( }

} ;


. . ,
.
requ i re ( ) requi re_o n c e ( ) .

1 30

11.


,
. ,
. ,
,
,
.
. ,
ge t _c l a s s ( ) .
, .
$ p roduct = ge t P roduct ( ) ;
i f ( get_cl a s s ( $product ) == ' CDProduc t ' ) {
p r i n t " \ $product -- CDProduc t \ n " ;

- g e t P roduct ( ) .
, C DP r o du c t ,
ge t_c l a s s ( ) .
.

CdProduct BookProduct 3.

get P r oduct ( ) .

function getProduct ( ) {
return new CDProduc t ( " " ,
" " , " " ,
1 0 . 9 9 , 60 . 3 3 ) ;

ge t P roduct ( ) C D P r oduct
. .
get_c l a s s ( ) .
.
, , ShopProdu c t .
, : B o o k P roduct C DProduc t .
i n s t a n c e o f .
. 4 inst anceof . 4
i s_ ( ) , 5.0 . 5.3

i n s t a nc e o f : ,
( i n s t a n c e o f ) ,
. t ru e ,
.
$product = getProduct ( ) ;
i f ( $product i ns tanceof ShopProduct ) {
print " \ $product -- ShopProduc t \ n " ;

5 .

131



,
-
.
, (
!). .

, .
, .
amespace mypackag e ;
u s e u t i l as u ;
u s e u t i l \db \ Que r i e r as q ;
class Local { )
1 1 :
1 1
1 1 u\Wri t e r ;
1 1
11 q;
11
1 1 Local

.
. h ,
. u \ Wr i t e r .
, u

u t i l u t i l ,
. , 5.5 : : c l a s s .
,
c l a s s
, .
-

prit u\Writer : : cl a s s . " \ " ;


prit q : : c lass . " \ " ;
prit Local : : cl a s s . " \ " ;

.
ut i l \ Wr i t e r
ut i l \ db \ Que r i e r
myp a c ka g e \ Lo c a l
------llll!ill!<L

'f
t
*'*
'
...
.
<!1
_..t..,..i'W.4':;.>.,:.;i; '' t.'>".t>-1ii':


,
,
, .
get_c l a s s_me thods ( J .

prit_r ( get_c l a s s_methods (

' CD Produc t '

) ;

1 32

11.

, C D P roduct , .
_
"
"
"
..,
.,.
,
..,
"
._
,
..,..
.,.
..,
,...
_
..,
..,
"
,,.
>':l
a
""
'"'
,.,'
"

""
'l"l

""
"
"
'"
"'
w
-.i::
_
..,
"
,
"
"

..,
,
,_
_
_
_
...,
_
"
"
..,
"
"
_
,
_
1
(!lf8l:
\!llf
1
-.
""
"
""
'
""
"'
_
_
_
-

Array
(
[]
[ 1]
[ 2]
[3]
[4]
[5]
[ 6]
[7]
[8]
[ 9]

=>
=>
=>
=>
=>
=>
=>
=>
=>
=>

construct
g e t P l a yL e n g t h
g e t S umma r y L i n e
g e t P roduc e r F i r s t N ame
g e t P ro du c e rMa i nName
s e t D i s count
g e t D i s count
getTi t l e
g e t P r i ce
g e t P ro du c e r

get_c l a s s_me thods ( )


p r i n t r ( ) .
g e t_c l a s s_me thods ( ) .
.
.
,
.
/ /
$product = getP roduct ( ) ;
$method = " getTi t l e " ;
1 1
print $product - > $method ( ) ; / /

, . ,
? , .
, .
i f ( in_a r ra y ( $method, get_clas s_methods ( $product
print $product->$method ( ) ; / /

, , ,
g e t c l a s s _me thods ( ) .
.
: i s_ c a l l a l e ( ) me t hod_
e x i s t s ( ) . i s_ca l l a e ( ) - .
, .
, i s_ca l l a e ( )
t rue. ,
.
-
. t ru e ,
.
i f ( i s_cal lal e ( array ( $product , $method) ) )
print $produc t - > $method ( ) ; / /

i s_c a l l a e ( ) -
. t ru e . ,
.
.

5.

1 33

me t ho d_e x i s t s ( ) m ( )
, t ru e ,
.
if ( method_ex i s t s ( $product , $method ) ) {
print $product-> $method ( ) ; / /

, , , . method e x i s t s ( )
true (pr ivate ), (protected) (pu i c )
.


, ,
. ge t_c l a s s_va r s ( ) ,
.
, - .
CDProdu c t . : C D Product :
: $ cove r U r l .
print_r ( get_clas s_va rs (

' CDProduct '

) ;

.
Array
(
[ cove rU r l ]

=>

_
. _
_
_
_
_..
_
_
_
_
_
_
_
"

__._..__.



. , g e t _pa r e n t _c l a s s ( )
.
, ,
. , ..
, f a l s e .
print get_parent_c l as s (

' C DProduct '

);

Shop P r o du c t , .
i s_ s ub c l a s s _ o f ( ) ,
.
. t ru e ,
.
$product = getProduc t ( ) ; / /
if ( i s_subc l a s s_of ( $produ c t , ' ShopProduct '

print "CDProduct ShopProduct \ n " ;

i s subc l a s s o f ( )
, , .
_

1 34

11.

i n s t a n c e o f . ,
c l a s s_i mp l eme n t s ( ) , SPL (Standard
Library - ).
. .
if

( in_a r ray ( ' s ome l n t e rface ' , c l a s s _implement s ( $ p roduct ) )


print " CdProduct some l nte r face \n " ;


,
.
$product = getProduct ( ) ;
$method = " get T i t l e " ;
p r i n t $product- >$method ( ) ;

/ /
1 1
/ /

c a l l u s e r_func ( ) .
. . ,
, .
$ ret urnVal

c a l l_use r_func ( " myFunc t i o n " ) ;

.
, - .
$ r eturnVal

c a l l_use r_func ( a r ray ( $my0bj ,

"methodName " )

);


, c a l l _u s e r_func ( ) .
$product = getProduct ( ) ; / /
c a l l_user_func ( a r ray ( $produc t , ' s e t D i s count '

),

20 ) ;

.
$product - >setDi scount ( 20 ) ;



$method = " s etDi scount " ;
$product - > $method ( 2 0 ) ;

c a l l_u s e r_func ( ) .
c a l l _u s e r_ f u n c a r r a y ( ) .
c a l l _u s e r_func ( ) , .
,
c a l l _u s e r_func_a r r a y ( ) .
?
. ,
, . 4,
". -.
. _c a l 1 ( ) .
_

func t i on _cal l ( $method, $ a rgs ) {


i f ( method_ex i s t s ( $ t h i s - > t h i rdpartyShop , $method )
return $ th i s - >thi rdpartyShop-> $method ( ) ;

5.

1 35

, _c a l l ( ) ,
. .
$ t h i r dp a r t yShop.
, $ me t h o d , .
, , ,
. !
_ca l l ( ) ,
$ a r g s . $ a rg s
,
, , , ,
. c a l l u s e r func_a r r a y ( )
.
_

function _ca l l ( $method, $args ) {


i f ( method_ex i s t s ( $ t h i s ->thi rdpartyShop ,
return cal l_use r_func_array (
array ( $ t h i s - >thi rdpar tyShop ,

$method )
$method ) ,

{
$ args ) ;

Reflection API
Reflection API 5
,
j ava . l ang . r e f l e ct Java.
, .
, g e t c l a s s v a r s ( ) .
.
- . . . ,
, .
-


Reflection API
. . Re f l e c t i o n Fun c t i on
, Re f l e c t i o n Ex t e n s i o n

. . 5. 1 Reflection ! .
Reflection API
,
, , .
- Reflection !,
. ,
. ,
, ,
( ),
. ,
. -
Reflection.
-

1 36

11.

5. 1 . Reflection API

e xp o r t ( ) ,

Re f l e c t i o nC l a s s


Re f l e c t i onMe t h o d


Re f l e c t i on Pa rame t e r

Re f l e c t i on P rope r t y

Re f l e c t i o n Funct i on


R e f l e c t i onEx t e n s i o n

Re f l e c t i onExcept i o n

Re f l e c t i on Z e ndEx t e n s i o n Zed
Re f l e c t i o n



. , .
, . R e f l e c t i o nC l a s s
,
, ,
. R e f l e c t i on C l a s s
, .
$ p rod_c l a s s = new ReflectionClas s (
Re f l ection : : expo r t ( $ prod_c l a s s ) ;

' CDProduct '

) ;

Re f l e c t i o n C l a s s ,
Re f l e c t i o n C D P roduct.
Re f l e c t i o n e xp o r t ( ) ,
, R e f l e c t i o n (,
, Re f l e c t o r} . ,
Re f l e c t i o n : : expo r t ( ) .
Class [ <user> c l a s s CdProduct extends ShopProduct ]
@ @ fu l l shop . php 5 3 - 7 3
- Cons tants

[]

- Static prope r t i e s [ 0 ]

- Static methods

[]

- Properties [ 2 ]
Property [ <defaul t > pr ivate $pl ayLength
Property [ <defaul t > protected $ p r i c e ]
)
- Methods [ 1 0 ] {
Method [ < us e r , overw r i t e s ShopProduct , ctor> pu i c method

const ruct ]

5 .
@ @ full shop . php 5 6 - 6 1
- Parameters [ 5 ] {
Parameter # 0 [ <requ i red>
Parameter # 1 [ <requi red>
Parameter # 2 [ <requ i red>
Parameter # 3 [ < requi red>
Parameter # 4 [ <requ i r ed>

1 37

$title ]
$ f i rs t Name
$ma i nName ]
$price ]
$pl ayLength

)
)
Method [ <user> pu i c method ge t P l ayLength ]
@ @ f u l l shop . php 63 - 6 5

)
Method [ <user, overwr i t e s ShopProduct , proto type ShopProduct> pu i c method
getSummaryLine ] {
@ @ ful l s hop . php 67 - 7 1
)
)
)

, Re f l e c t i o n : : e x p o r t { )
.
C D P roduc t , ,
, ,
. . v a r dump ( ) .
,
, v a r_dump ( )
, Re f l e c t i o n : : e x p o r t ( ) .
$cd = new CDProduct ( " " ,
" " , " " ,
1 0 . 9 9 , nu l l , 60 . 3 3 ) ;
va r_dump ( $ cd ) ;

.
obj e c t ( C D P r o du c t ) # 1 ( 8 ) {
[ " p l a yL e n g t h : pr iv at e " ] =>
f loat ( 60 . 3 3 )
[ " coverU r l " ] =>
NULL
[ " t i t l e : p r i va t e " ] =>
s t r i n g ( l 9 ) " "
[ " p roduc e rM a i Name : pr iv a t e " ] = >
s t r i ng ( 3 ) " "
[ " p roduc e r F i r s t Name : p r i v a t e " ] =>
s t r i n g ( 6 ) " "
[ " p r i c e : p r o t e c t e d " ] =>
f l oat ( 1 . 9 9 )
[ " d i s count : p r i vat e " ) =>
int ( O )
[ " i d : p r i v at e " J = >
int ( O )

1 38

1 1 .

va r_dump ( ) "" p r i nt_r ( ) -


.
Reflectlon API .


Re f l e c t i on : : e x p o r t ( )
, Reflection API .
R e f l e c t i o n .
, R e f l e c t i on C l a s s .
$ prod_c l a s s = new Re f l e c t i onCl ass (

' C DProduc t '

);

Re f l e c t i o nC l a s s .
. .
. ,
.
C D P r o du c t

fun c t i on c l a s s Da ta ( Re f l e c t i onClass $ c l a s s ) (
$de t a i l s = 11 11 ;
$name = $ c l a s s - >ge tName ( ) ;
i f ( $ c l a s s - > i sUse rDe f i ned ( ) ) {
$det a i l s . = " $ name -- \ n " ;
if

( $ c l a s s - > i s intern a l ( ) ) {
$ de t a i l s . = " $ name -- \ n " ;

if

( $ c l a s s - > i s i n t e r f ace ( ) )
$de t a i l s = " $ name - - \ n " ;

if

( $ c l a s s - > i s A s t ract ( ) ) {
$det a i l s = " $ name - - \n" ;

if

( $ c l a s s - > i s F i na l ( ) )
$de t a i l s = " $ name - - \ n " ;

if

if

( $ c l a s s - > i s i n s t an t i a e ( ) ) {
$de t a i l s
" $ name
\ n " ;
else {
$de t a i l s
" $ name
\n " ;
( $ c l a s s - > i sCloneae ( )
$de t a i l s

" $ name - - \ n " ;

else {
$det a i l s

" $ name - - \ n " ;

return $det a i l s ;
$ prod_c l a s s = new Re f l e c t i onCla s s (
print c l a s s D at a ( $p rod_c l a s s ) ;

' C DProduct '

);

5.

1 39

Re f l e ct i o nC l a s s $ p rod_
Re f l e c t i on C l a s s ,
' CD P r oduct ' . $ p rod_c l a s s
c l a s s Da t a ( ) , ,
.
. , . -
.
class.

Re f l e c t i o nC l a s s :

Re f l e c t i o n C l a s s : : i sU s e r D e f i ned ( ) ,
-.

Re f l e c t i on C l a s s : : i s i nt e rn a l ( ) ,
.

Re f l e c t i onC l a s s :
.

Re f l e c t i on C l a s s :
.

: g e tName (

) .

: i sA s t r a c t (

: i s i nt e r fa ce (

) ,

) ,

,
( ) , .

Re f l e c t i o n

C l a s s : : i s i n s t a n t i a e

, .
Re f l e ct i o n C l a s s
, .
. Re f l e c t i o n C l a s s
.
class Ref lectionUt i l {
static function getClass Source ( Re f l ec t i onCl a s s $ c l a s s )
$path
$ c l a s s - >getFi l eName ( ) ;
@ f i l e ( $path ) ;
$ l ines
$ c l a s s - >get StartLine ( ) ;
$ f rom
$ c l a s s - >getEndLine ( ) ;
$to
$len
$ t o - $ from+ l ;
return implode ( array_s l i c e ( $ l ines ,

print Re flect i onUt i l : : getC l a s s Sourc e (


new Re f l e c t i onCl a s s ( ' CDProduct '

$ f rom- 1 ,

$ l en ) ) ;

) ;

, Re f l e c t i onUt i l
Re f l e c t ionUt i l : : g e t C l a s s S o u r c e ( ) .
Re f l e c t i on C l a s s .
. Re f l e c t i o nC l a s s : : ge t Fi l eName ( )
,
. f i l e ( ) . Re f l e c
t i onCl a s s : : g e t S t a r t L i ne ( ) ,
Re f l e c t i onC l a s s : : g e t EndL i n e ( ) - .
.
a r r a y_ s l i ce ( ) .
i .
.

1 40

1 1 .


Re f l e c t i onC l a s s ,
.
Re f l e c t i onMe t h o d . -
, Re f l ec t i onMe thod, Re f l e c
t i onC l a s s : : getMe t hods ( ) . -, ,
Re f l e c t i onC l a s s : : g e tMethod ( ) ,
Re f l e c t i onMe thod.
Re f l e c t i on C l a s s : : getMethods ( ) ,
Re f l e c t i onMe t hod.
Re f l e c t i o nM e t h od

$prod_c l a s s = new Re f l ectionC l a s s ( ' C DProduct '


$methods = $prod_c l a s s - >getMethods ( ) ;

) ;

foreach ( $methods a s $method )


print methodData ( $method ) ;
pr int " \n - - - - \n " ;

funct i on methodDat a ( Ref l e c t i onMe thod $method ) {


$deta i l s = " " ;
$ name = $method->ge tName ( ) ;
i f ( $method- > i sUse rDefined ( ) ) {
$de t a i l s . = " $ name -- \n " ;
if

( $method- > i s i nt e rna l ( ) ) {


$de t a i l s . = " $ name -- \n " ;

if

( $method - > i sAb s t ract ( ) ) {


$de t a i l s . = " $ name -- \n" ;

if

( $method- > i s Pu i c ( ) ) {
$det a i l s . = " $ name -- \ n " ;

if

( $method- > i s P rotected ( ) ) {


$detai l s . = " $ name -- \ n " ;

if

( $method- > i s P r i vate ( ) ) {


$det a i l s . = " $ name -- \ n " ;

if

( $method- > i s S t a t i c ( ) ) {
$det a i l s . = " $ name -- \ n " ;

if

( $method- > i s Final ( ) ) (


$deta i l s . = " $ name -- \ n " ;

if

( $method->i sCons t ructor ( ) ) (


$de t a i l s . = " $ name -- \n" ;

if

( $method-> ret urnsRe ference ( ) ) (


$de t a i l s . = " $ name -- ,

\n " ;

5 .

1 41

return $det a i l s ;

r Re f l e c t i onMe thod
Re f l e c t i onC l a s s : : g e tMethods ( ) .
met hodDa ta ( ) ,
Re f l e c t i onMe thod.
, me t h o d D a t a ( ) ,
: , , ,
, , , .
, r
- .
: R e f l e c t i onMe t ho d : : r e t u r n s
Refe rence ( ) ,
( ), 5
. ,
, (
) .
,
, Re f l e c t i o nC l a s s r .
c l a s s Re flect ionUti l {
s t a t i c function getMethodSou rce ( Re f l e c t i onMethod $method )
$path = $method->ge t F i l eName ( ) ;
$ l i nes = @ f i l e ( $path ) ;
$ f rom = $method->getStartLine ( ) ;
$ t o = $method->getEndLine ( ) ;
$ l en = $to-$ from+ l ;
return imp l ode ( a r ray_s l i c e ( $ l i ne s , $ f rom- l , $ len ) ) ;

$class = new Re flect i onClas s ( ' CDProduct ' ) ;


$method = $ c l a s s - >getMethod ( ' getSummaryLine ' ) ;
print Re flectionUti l : : getMethodSource ( $method ) ;

Re f l e c t i onMe t ho d g e t F i l eName ( ) , g e t S t a r t L i ne ( )
g e t EndLi ne ( ) , .


,
,
, . Reflection API
Re f l e c t i o n P a rame t e r .
Re f l e c t i onPa rame t e r , Re f l e c t i onMe thod.
Re f l e c t i onMet hod : : g e t Parame t e r s ( ) Re f l e c t i o n
Parame t e r .

Re f l e c t i o n P a r ame t e r , : ;
(..
) ; ,
r ;
r .
Re f l e c t i o n
Parame t e r .

1 42

11.

$prod_c l as s = new Re f l e c t i onCl a s s ( ' CDProduc t ' ) ;


$method
$prod_c l a s s - > getMethod ( " cons t ru c t " ) ;
$pa rams
$method- >ge t Paramete rs ( ) ;
foreach
$pa rams a s $param )
print argDat a ( $param ) ;

function argData ( Reflecti onParame t e r $ a rg ) {


$ de t a i l s = " " ;
$ de c l aringclass = $ a r g - >getDe c l a ringCl a s s ( ) ;
$name = $arg- >getName ( ) ;
$ c l a s s = $ a rg- >get C l as s ( ) ;
$pos i t i on = $ a rg->getPos i t i on ( ) ;
$ de t a i l s . = " \ $ $ name $pos i t i on \ n " ;
i f ( ! empty ( $ c l a s s ) ) {
$ c l a s sname = $ c l a s s - >get Name ( ) ;
$det a i l s . = " \ $ $name i $ c l a s s name \ n " ;
i f ( $arg- > i s Pas sedByReferenc e ( ) )
$ de t a i l s . = " \ $ $name \ n " ;
if

( $ arg- > i s De faultVa l ueAvai l a l e ( ) ) {


$def = $ a rg->getDefaultValue ( ) ;
$deta i l s . = " \ $ $ name : $ de f \ n " ;

return $ det a i l s ;

Re f l e c t i onC l a s s : : g e tM e t ho d ( ) Re f l e c t i onMe t ho d
( ).
Re f l e c t i onC l a s s : : g e t Pa rame t e r s ( )
R e f l e c t i o n P a r ame t e r , .
a rg D a t a ( ) Re f l e c t i on P a r ame t e r ,
.
- Re f l e c t i o n
P a r amet e r : : g e t Name ( ) . Re f l e c t i o n P a r ame t e r : : g e t C l a s s ( )
Re f l e c t i o nC l a s s , .
i s Pa s s e dB yR e f e re n c e ( ) ,
. i s De f a u l t V a l ueAva i l a e { ) .
.

Reflection API
Reflection API,
.
, ,
Modu l e . ,
, .
, .
, e x e c u t e ( ) Modu l e
, .
Modul e
L- .

5.

1 43

Modu l e ,
execute ( ) .
, Modu l e
( !) ? L-
Modu l e ,
M o du l e -
. ,
-.
Module .
class Person {
pu i c $name ;
function
con s t ruct ( $name )
$ t h i s - >name = $ name ;

interface Module {
function execute ( ) ;

class FtpModul e implements Modu l e {


function setHost ( $host ) {
print " FtpModul e : : s etHo s t ( ) : $ h o s t \ n " ;

funct ion setUser ( $user ) {


print " FtpModul e : : s etUser ( ) : $ u s e r \n " ;

function execute ( )

1 1
)

class PersonModul e implements Module {


function s e t Pe r son ( Person $person )
print "Per sonModul e : : s e t P e r s on ( ) :

function execute ( )

{ $ person- >name ) \n " ;

1 1
)

P e r s onModu l e FtpModu l e
execute ( ) . -,
, , .
, -
: , ,
. P e r s onModu l e : : s e t Pe r s on ( )
P e r s o n ,
P e r s o n .

1 44

11.

P e r s onModu l e FtpModu l e
Modu l e Ru nne r . ,
,
. L-. .
c l a s s ModuleRunner {
private $ confi gData = array (
" Pe rsonModu l e " => a r ra y (
" FtpModu l e " => a r ray (

' pe rson ' => ' ' ) ,


' host ' = > ' examp l e . ' ,
' us e r ' => ' anon ' )

);
p r ivate $modul e s = a r r ay ( ) ;
11

M o du l e Ru n n e r : : $ c o n f i g Da t a
Modu l e .
, . i n i t ( ) Module
Runne r Modu l e ,
.
c l a s s ModuleRunner
// . . .
funct i on i n i t ( )

$ i nterf ace = new Re f l e ct ionClas s ( ' Modul e ' ) ;


foreach ( $ t h i s - >con f i gData as $modu lename => $pa rams )
$modu l e_class = new Ref l e c t i o nC l a s s ( $modu lename ) ;
i f ( ! $module_c l a s s - >i s S ubcl as s0f ( $ i n t e rface ) ) {
throw new Exception ( " n : $modul ename" ) ;
$module = $module_c l a s s - >newlns t ance ( ) ;
foreach ( $modul e_c l a s s - >getMethods ( ) as $method ) {
$ th i s ->handleMethod ( $modu l e , $method , $params ) ;
1 1 handleMethod ( ) !
array_pu s h ( $ t h i s - >modu l e s ,

$modul e ) ;

}
// . . .
}
$ t e s t = new ModuleRunne r ( ) ;
$test->init ( ) ;

i n i t ( ) M o du l e Ru n n e r : : $ co n f i g D a t a
Modu l e
Re f l e c t i o nC l a s s . Re f l e c t i o nC l a s s
Modu l e . .
.
, Modu l e ,
Re f l e c t i o n C l a s s : : i s Subc l a s s O f ( ) .

e x e c u t e ( ) Modu l e ,
. me t ho d : : Re f l ec t i on
C l a s s : : newi n s t a n c e ( ) .
, .

5.

1 45

, .
, .
Modul e ,
.
Re f l e c t i o nC l a s s : : ge tMe t h o d s ( )
Re f l e c t i onMe thod, ..
Modu l eRunne r : : handleMethod ( ) ,
Modu l e , Re f l e c t i onMe t h o d ,
Modul e ,
. handl eMe thod ( ) ,
- Modu l e .
class ModuleRunner (
// . . .
function handleMethod ( Module $modul e , Re f l e c t i onMethod $method,
$method->ge tName ( ) ;
$name
$ a r gs = $method->getPa ramete rs ( ) ;
i f ( count ( $args )
subs t r ( $name ,
return f a l s e ;

!= 1 1 1
, 3 )

!=

" se t " )

$params )

$prope r t y = s t rt o l ower ( sub s t r ( $name , 3 ) ) ;


i f ( ! i s s e t ( $pa rams [ $ prope r t y ] ) ) {
return f a l s e ;

$a rg_class = $ a rgs [ O J - >getCl a s s ( ) ;


i f ( empty ( $a rg_c l a s s ) ) {
$method->invoke ( $modu l e , $params [ $property ] ) ;
else (
$method->invoke ( $modu l e ,
$ a rg_c l a s s ->newi n s t ance ( $params [ $prope r t y ]

) ;

handleMethod ( ) , .
. -
s e tXXXX ( ) .
, ,
-.
" s e t " .
$ p a rams. ,
,
Modu l e . $ p a rams
, f a l s e .
, ,
Modu l e , $ p a r a m s ,
-.
( !) -.
Re f l e c t i o n Pa rame t e r : : g e t C l a s s ( ) . -

1 46

1 1 .

, -
(.. ), - .
-,
Reflection ! Re f l e c t i o nMe t h o d : : i nv o k e ( ) .
( Modu l e ) ,
- Modu l e . Re f l e c t i onMe thod :
: i n v o k e ( ) .
. Re f l e c t i onMe t hod. Re f l e c t i onMe t hod :
: i nvoke ( ) . -
, Re f l e c t i onMe t hod :
: i nvoke ( ) ,
. - ,
.
-.
,
. .
. , Re f l e c t i onCl a s s :
: newi n s t ance ( ) .

Modu l eRunne r : : i n i t ( ) ,
Modu l eRunne r Modul e (
$modu l e s ) , .
Modu l e Ru n n e r ,
Modu l e e x e c u t e ( ) .


,
.
5.3 - . ,

, PEAR
. ,

Reflection !. R e f l e c t i on ,
,
Reflection.

@@@

/))

'/"'

----

.
. .
, .
. .
UL
-
.
.
-

: - .

: . .

: .

: .

.

UL: -
.


:
. . ?
? ?
?
.
. :
.
? - .
. .
. .
. . .
, .

1 48

1 1 .

. , ,
.
. .
.
. ,
.
(.
).
,
. , .
.
,
.
. , .
. ,
.
,
.

-

-
? : "I ,
" . . .
. ,
, .
- - . .
Java, .
-
. .
.
. "
" .
-

.

- ,
. , -
.
. .
. r
.
:

r .
f un c t i on readPa rams ( $ s ourceFi l e )
$params = array ( ) ;
1 1 $ s ourceF i l e

6.

1 49

return $pa rarns ;

func t i on writePa r arns ( $pararns , $ s ource F i l e ) {


/ / $ s ource F i l e

r e a d P a rarns ( ) .
, "-
". .
. w r i t e Pa rarns ( )
.
, "-" .
, .
$file = " . /pararn . txt " ;
"val l " ;
$array [ ' key l ' J
$array [ ' ke y2 ' ] = "va l 2 " ;
$array [ ' ke y3 ' ] = "val " ;
/ !
wr itePararns ( $ a r r a y , $ f i l e ) ;
$output = readPa rarns ( $ f i l e ) ; / /
print_r ( $ output ) ;

, .
w r i t e P a r arns ( ) p a ram . t x t ,
.
keyl : va l l
key2 : va l 2
key : va l

.
, L,
.
<pararns >
<pararn>
< k> < / k>
<vl ></v l >
< /pararn>
< /pararns>

. xml ,
L, .
, ,
. .

. .
fuct ion readParams ( $ s ource ) {
$pararns = array ( ) ;
i f ( preg_match ( " / \ . xml$ / i " , $ s ource ) ) {
! ! XML $ s ource
else {
/ / $ s ou rce
return $pa rarns ;

1 50

11.

funct i on writeParams ( $params , $ source ) {


i f ( preg_match ( " / \ . xml $ / i " , $ s ource ) )
1 1 XML $ s ource
else {
1 1 $ s ource

. .

, , ,
, . ,
,
. ,
.

, . xml .
.
,
, : r e a d P a rams ( ) w r i t e Pa rams ( ) .
.
,
.
abstract c l a s s Paramandl e r {
protected $ s ource ;
protected $pa rams = array ( ) ;
function con s t ruct ( $ s ource )
$ th i s - >s ource = $ source ;

function addPa ram ( $ ke y , $val )


$ t h i s - >params [ $ ke y ] = $ va l ;

function getAl l Pa r ams ( ) {


return $ thi s - >params ;

s t a t i c funct i on getinstance ( $ fi l ename ) {


i f ( p re g_match ( " / \ . xml$ / i " , $ f i l ename ) ) {
return new Xml Paramand l e r ( $ fi l ename ) ;
return new TextPa ramandl e r ( $ f i l ename ) ;

abst ract function w r i t e ( ) ;


abst ract function read ( ) ;

a dd P a r am ( ) ,
$ p a rams, g e tA l l Pa r ams ( ) .
.

6.

1 51

g e t i n s t a n c e ( } ,

. ,
. r e a d ( ) w r i te ( ) , ,
.

- .
,
Paramandler ,
. ,
? ,
Paramand ler, get I ns t ance ( } . ,
(
, ()
, ). 9.

,
.
class Xml Paramandl e r extends Paramandler {
func t i on write ( } {
1 1 XML
1 1 $ t h i s - >params

funct i on read ( ) {
/ / L-
/ / $ t h i s - >params

class TextParamandler extends Paramandl e r {


func t i on write ( ) {
/ /
/ / $ t h i s - >params

function read ( ) {
/ !
1 1 $ t h i s - >pa rams

r e a d ( ) w r i t e ( ) .
.

L- ,
.
$ t est = ParamHandl er : : ge t i n s tance ( " . /params . xml " ) ;
$ t e s t - > addParam ( " ke yl " , "val l " ) ;
$ t es t - >addParam ( " ke y2 " , "va l 2 " ) ;
$ t e s t - > addParam ( " ke y3 " , "va l " } ;
$test ->write ( ) ; / / L-

1 52

1 1 .


.
$ t e s t = Paramandler : : ge t i n s t ance ( " . /params . txt " ) ;
$ t e s t - >read ( ) ; / /

, ?

""
, , . , ,
,
. readPa rams ( ) ,
wri t e Pa rams ( ) ,
( ).
-
g e t i n s t a n c e ( ) ,
. .
, ,
. ,
P a r amHandl e r read ( ) wri t e ( ) .
, -
, .
, .
.


(cohesiDn) - .
. .
.
, , ,
, .
P a r amandl e r
. L-
, ,
, (
, L-). .
Pa ramHand l e r .
, .
L- .


(coupling) ,
,
.
,
.
.
readPa rams ( ) wr i t e Pa rams ( )
, . .

6.

1 53

, 1I ,
. , m
,
. ,
, .
-
.
, ,
g e t i n s t a nce ( ) .

1I



(orthogonality), , , (Andrew Hunt)
(David Thomas) h Pragrtic Programmer (Addison-Wesley Professional, 1 999).
,
, ,
.
, -
. ,
,
. .
.
"" .

. ,
"" .
? ,
.


,
, ,
.
.
- -
, Person, I nvoice Shop.
, -
.
, .
, ,
, ,
,
.
ShopProdu c t ,
3. 1I , ,
ShopProduct
.
?
getT i t l e ( ) g e t P r i c e ( ) . 1I -

1 54

1 1 .

- , ,
, w r i t e ( ) .
,
w r i t e XL ( )
w r i t e XHTML ( ) w r i t e ( ) . w r i t e ( )
,
.
!Ul . S ho p Product
. ,
.
: ? - .
,
. . ,
25
" "".
" , ,
.
. S h o p P roduct - .
,
(.. ) -
. 3,
, . ShopProduct
, S h o p ProductWri t e r
.
.
. . ,

, , ,
, . , , , ,
. ,
.
( ) ,
,
. 12.
; ,
. , .


(polymorphism), , -
- .
.
-
. ,
.
.
3 ShopP roduc t .

6.

1 55

-, .
. .
func tion getSuunaryLine ( ) {
$base = " $ th i s - > t i t l e ( $thi s - >producerMai nName , " ;
$base . = " $ th i s - >produce r F i rs tName ) " ;
i f ( $th i s - >t ype === ' book ' ) {
$base . = " : $ t h i s - >numPages . " ;
e l s e i f ( $ t h i s - > t ype === ' cd ' ) {
$base . = " - $ thi s - >p l a yLength " ;
return $ ba s e ;

C D P r oduct

Boo k Produc t .

, ,
, "" -
. .
.
function readParams ( $ s ource ) {
$pa rams = array ( ) ;
i f ( preg_match ( " / \ . xml $ / i " , $ s ource ) )

1 1 XML $ s ource
else {
/ / $ s ource
return $pa rams ;

function writePa rams ( $params , $ s ource ) {


i f ( preg_match ( " / \ . xml $ / i " , $ s ource ) )
1 1 XML $ s ource
else {
/ / $ s ource

,
: Xml P a r ama nd l e r T e x t Pa ramand l e r .
w r i te ( ) r e a d ( ) P a r aman d l e r .
/ / Xml Paramandl e r Tex t Pa ramand l e r
$ test = Paramandl e r : : getins tance ( $ f i l e ) ;
$ test ->read ( ) ; / / Xml Paramand l e r : : re ad ( )
TextParamand l e r : : read ( )
$ t e s t - >addParam ( " key l " , "val l " ) ;
$ test ->wr i t e ( ) ; / / Xml Paramandl e r : : wr i te ( )
1 1 Text Paramand l e r : : wr i te ( )

,
. P a r amandl e r : : g e t i n s t a nc e ( )
s w i t c h if , .
.

1 56

1 1 .

, 5 ,
. ,
,
, .
.

( ,
). :
, .


. - , .

,

. ,
, .

,
.
,
.
,
.
, .
, , ,
, .
, ,
.
.


.u (encapsulatiDn) -
. -, -
.
,
private pro t e cted. ,

.
.
,
. , ,
, .
,
. , , .
, ,
" " .
- -
. -
. ,

6. R R

1 57

,
.
p r i va t e , p r o t e c t e d pu i c .
- . 4 m
.
.
, -
.
var $_touche zpas ;

, ,
. , , ,
,
.
, 5
, :,
i n s t a n c e o f .
function wo rkWithProduc t s ( ShopProduct $prod )
i f ( $prod i ns tanceof CDP roduct ) {
1 1 C D
e l s e i f ( $prod ins tanceof BookProduct ) {
//

,
.

, , .
,
S hopProdu c t ,
. . ,
C D P roduct B o o k P r o du c t ,
wo r kW i t h P roduc t s ( ) .
. -,
. -, ,
, . - ,
:, .

,
,
. ,
, ,
PEAR. , ,
, .
, .
.
: , ,
. , .
. , ;
, .. ,

1 58

11.

. ,
, .
, ,
, .
,
, . ,
, - .
, "-".
, ,
.
Pa ramandl e r
,
. ,
.
.
, , , ,
L- Paramand l e r , , ,
.
.
( Design Pattems)
: " .
" . ,
.



.

.
, , -
. . - ,
. , ,
. "".
,
.
,
.


- .
"", , ,
.
. ,
. .
- .
? . , ,
.

6.

1 59

,
- -
.
?
.
D ,
. .
,
,
, . ,
.
.
.


?
. ,
.
" " -
.
? ,
? ,
.


,
swi t ch.
.
,
, , , ,
, . ,
,
.
. ,
.
9.

if

UML

,
.
, ,
.

. .
.

1 60

11.

UML "Unified Modeling Language" (


). .
(Martin Fowler) (UL Distilled , Addison-Wesley Professional, 1 999).
UML
- .

- .
, , "" UML .
,
.
.


- UML, , ,
. -
, .

, -
. ,
. 6. 1 .
. , ,
. . ,
, .
. ,
, . 6. 1.
, , .
, .
. 6.2, { abs t ra c t } .
. 6.3. , .
.
{ abs tr act } .
, .
; - ,
.

ShopProduct

UML

. 6 . 1 .

ShopProductWriter

ShopProductWriter

{abstract}

. 6.3.
,

. 6.2.

, . .
(.. UML).
. 6.4.

6.

1 1

. .
, ,
. 6.5.
.
(#) , r, . . 6. 1
.
6. 1 .

.
ShopProduct : : $ p r i c e .
(, , ).
, ,
.

, , ,
. . 6 . 6
ShopProduct.
ShopProduct

interface
Chargeae

. 6.4.

#price : int

ShopProduct

#price : int

. 6.5.

+ setDiscount ( amount : int)


+getT i t l e ( ) : S t r ing
. 6.6.

, ,
. .
. . , ,
. , ,
: .
, .
.
, .


UML .
, .
.
. 6.7 ShopProduct .

1 62

1 1 .

ShopProduct

6
1

CDProduct

BookProduct

. 6.7.

UML . ,
. , ShopProduct
Cha rgea e , , . 6.8.

ShopProduct

1
CDProduct

. 6.8.

-{>

< <interface
Chargeae

1
BookProduct

- -
. , ,
( ) .
. 6.9 . .

Teacher

. 6.9.

. ,
T e a ch e r Pup i l .
.
.
T e a che r Pup i l , ,
, Teacher
Pup i l . , ,
. 6. 1 0 .

6.

1 Teherac 1
. 6 . 1 0 .

1 63

1Teacher1<

. 6. 1 1 .

,
,
. 6. 1 1 .
,
.
. (*),
. . 6. 1 2 ,
Teacher Pupi l .
. 6. 1 3 , Teacher
Pup i l .

Teacher

1 Teacher 11
. 6 . 1 2 .

Pupil

5 .. 1 0

. 6 . 1 3.


.
, m
.
, , m
.

- ( ),
. ,
.
. 6. 1 4 : S choolClass Pup i l . S choolClass
Pupil.
, Pup i l
S choolC l a s s .
, ,
.
.
m -.
-.
, , .
. 6. 1 5.

1 64

11.

SchoolClass

Person

(1
Pupil
. 6 . 1 4.

Social SecurityData

. 6 . 1 5 .

Pe r s on S o c i a l Secur i t yDa t a .

P e r s on .


UML .
, .
.

.
Report . 6. 1 6 ShopProductWri t e r .

; .
.
. . ShopP roductWr i t e r ,
ShopP roduc t .


,
. . 6. 1 6 .
, Repo r t ShopProductWri ter,
. . 6. 1 7 .
.
,
. .
; ,
Rep o r t ShopP roductWr i t e r
. .
. ,
, ,
.

6.

*
-

ShopProductWriter
1

+addProduct ( )

XmlWriter

TextWriter

. 6. 1 6.

ShopProduct

CDProduct

BookProduct

$w rite r - >addProduct s ( $prod u c t s ) ;


$writ e r - >write ( ) ;

ShopProductWriter
+addProduct ( )

1
XmlWriter

. 6 . 1 7.

1
TextWriter

ShopProduct

6
1
CDProduct

BookProduct

1 65

1 66

1 1 .


. .
.
. ,
Report ..
. . 6. 18.

Product Store

ShopProductWriter

ShopProduct

. 6 . 1 8.

.
, ,
: (, productl : ShopProduct).
,
. 6. 1 9.

1 ;1
Re

rt

ProductStore

ShopProductWriter

ShopProduct

. 6 . 1 9.


. .
. 6. 1 9 , ,
. , .
. . 6.20.

6.

Report

ProductStore

ShopProductWriter

1 67

ShopProduct

1
- getProducs() 1

-
1

add Products()
...
write()

*[

Shrc:Jl:juct) getSummaryline()

D
1

. 6.20.

,
(
. -
) .
. . .

.

[ o kToPrint ]
wri te ( )

, w r i t e ( )
. , ,
( ).
* [ ShopProduct ]
wri te ( )

. 6.20 . Repo r t
ShopProduct P roduct S t o r e .
ShopProductW r i t e r ,
( ). S ho p P roduct
Wr i t e r Shop P r oduct : : g e t Summa r yL i n e ( )
Shop P r oduc t , ,
.
, ,
""
.

1 68

11.

. 6 . 1 6 6.20. ,
( , ShopProductWri ter ShopProduct).
, , .
,
.


-
.
, ,
,
- . UL ,
, .

1 1 1

//)

@@@
--

!/)

@@@
-----

.
. - .
,
.
,
.
,
.
, .
. , , ,
(" ")
("" "").
.
.

: ?

: .

: , ?


, - 1

- (Gady Booch), Core Patterns 1


-

- " " (h Gag of Four), Desig Patterns: Eleets


of Rs Object-Orieted Sofiware2

' . . . J2EE.
.. . ". 20 1 3).
2 llla
. . . . -
. m (. . , . "", 2007).
(.

1 72

1 1 1 .

, - ,
,
.
, -
. ?
? ? ?

,
. - .

. , ,
.
"", "" .
- , . ,
( ).
, .
,
, . "
", , .
- .
,
. ,
"". .

.
, , .
, .

, .

(trigger tokens). ,
-, ,
.
, ,
. ,
-
- , .
, .
, : Ma i n P a r s e r , T a g P a r s e r Argume n t P a r s e r .
P a r s e r Fa c t o r y , .
, , , . ,
, , .
-
: OtherTag Pa r s e r , OtherArgume n t P a r s e r ..
:
,
"" . , "
" Abstract Factory
( ): "
".

7.

1 73

!
.
,
9. Abstract Factory.
;
- ,
.
.
. .
,
Abstract Factory. ; -
, , - .
. ,
,
. .
, ,
, (Christopher Alexander),
.
- . Pattem
Langage3 (Oxford University Press. 1 977) .
. ,
,
,
-.

, (
)
. ,
, . ,
.
. - , .
, .
, ,
.

: . (Erich Gamma),
(Richard Helm), (Ralph Johnson)
(John Vlissides) Desig Pattems: Elemets oj Reusae Object-Oieted Sojtware
(Addison-Wesley Professional, 1 995).
- .
.
- .
. , " ", , -

, .. , ,
. ,
(, , ) .
, -
.
3 , , , . m-u

. (.

" . "", 2007).

1 74

111.

" " ,
. ,
, .
.


. : ,
, .

.
;
. .
" " : "
".
: "
, - ,
" (Patterns of Eterprise .(\pplicatio Archi
tecture4, Addison-Wesley Professional, 2002).
Patterns of Eterprise Applicatio Architecture
,
(Deepak Alur). (Dan Malks) : (John Crupi) Core J2EE
Patterns (Prentice Hall. 2003). ,
. .
.
- ( r
). .

, .


(
), - .
, - .
.
.
.
. - ;
. ,
. .
.

.
. , UL- .
.
4

. (. " "". 2009).

7.

1 75

,
" ". ,
, . ,
- , .
, , , . h
, ,
. ( )
( , , ), ,
, ,
, , ..
, , "",
.. .

, ,
. ,
. , ,
,
.

" "
, ,
.
, ,
. , (
), .
,
, ( ),
,
(Portland Pattern Repository) ( ). " "
,
, .
u.

.
.

. , , .

, .
.

,
.
,
.

/ . U L-
,
.

.
,
, .

1 76

111.

. . ,
.
.
- . .
.

.. , (

, ). . ,
,
. ".
_

.
, ,
. .
, - ,
": , - .
.


? , -
, , , .
. , , - .


- ,
? , .
.
, .
- , .


( , ).
,
.
, ,.
.


-
" . ,
. ,
++ Smalltalk Java.

, .
. ,
- ,
( ,
).

7 .

1 77


,
. ,
. Abstract
Factory ,
. .
: Composlte.
: , .
, . . ,
.
.
: ,
.
. ,
.
: ?
, , . , Composite Visltor.
: Visltor .
: .
.
. 1 0
Composite, 1 1
Visltor.
, .
,
. , .
, , .
-


, , ,
,
? .
- .

. -
, .
.
,
. ,
(GUI)
. -
, ,
PDA .


.
.
, . ,
, , .

1 78

111.


,
.



.
. .
,
.


" ".
, ,
, . ,
, - .
, Zend, Code Igniter Symfony.
.
API .


.
.
, .
( ).
, , .
.
. .
.
, .
, Frot Controller
. ,
. . . ,
:
.
, .
, .
,
. ,
(,
, , .
).
-
.
. ,
.
, , .

PEAR. PEAR -

7.

1 79

. - .
, , . PEAR
,
.


,
( " ") ,

.
, - ,
, , . -
.
.
.

/);
@@@
------

,
, , .
- .
,
.
.

: .

: .

: .

: ,


Java. ,
, - .
, .
. ,
. ,
. ,

.

API,
Java. ,
.
-
. ,
, .
, - .

1 82

111.

.
.
,
,
.
Design Patterns' ,
" " (Gang of Four), .
. ,
.
, ,
.
- ?
.
,
. " " : "
".
.
.


(iheritance) -
. ,
.

,
( ).
,
.
. 8. 1 UML.
L e s s o n . 8. 1 .
c o s t ( ) c h a r g eT ype ( ) .

Lesson
+_construction(duration)
+cost()
+chargeType()

imedPriceLesson

+cost ( )
+chargeType()

+cost ( )
+chargeType( )
. 8 . 1 .

FixedPriceLesson

I . , , . mDm
., . "". 2007).

. (.

8.

1 83

, F i x e d P r i ce Le s s o n T imed P r i ceLe s s o n ,
.
r
. , L e s s o n ,
.
. ?
, , .

, .
:
.
. 8.2 " ".

Lesson
+_construction(duration)
+cost()
+chargeType()

Lf

1
1 Seminar 1

1 Lecture 1
1

fi.

FixedPriceLecture

imedPriceLecture

FixedPriceSeminar

imedPriceSeminar

+cost ( )
+chargeType( )

+cost ( )
+chargeType( )

+cost ( )
+chargeType( )

+cost ( )
+chargeType()

. 8.2.

. 8.2 .
, ,
.
L e c t u r e S e mi n a r .

L e s s o n , . ,
, , .
r,
. L e s s o n .
abst ract c l a s s Les s on {
protected $duration;
FI XED = 1 ;
const
cons t
TIMED = 2 ;
$cost t yp e ;
private
function
const ruct ( $dura t i o n ,
$durat ion;
$ t h i s ->dura t i on
$ th i s - >costtype = $cos t t ype ;

$ c o s t t ype=l

1 84

111.

function cost ( ) (
swi t ch ( $ t hi s - >cos t type ) {
CASE s e l f : : T IMED :
re turn ( 5 * $ t h i s - >durat i on ) ;
break ;
CASE s e l f : : FIXED
return 3 0 ;
brea k ;
defaul t :
$ t h i s - >costtype
s e l f : : FI XE D ;
return 3 0 ;

function cha rgeType ( ) {


switch ( $ t hi s - >costtype ) {
CASE s el f : : T I MED :
return " n " ;
brea k ;
CASE s el f : : FIXED :
return " " ;
break ;
defaul t :
$ t h i s ->costtype = s e l f : : FIXED;
return " " ;

1 1 l es s on . . .

c l as s Lecture extends Les son {


1 1 Lecture . . .

c l a s s Seminar extends Les son {


1 1 Seminar . . .

.
$ l ecture = new Lectur e ( 5 , Lesson : : FIXED ) ;
p r i n t " { $ l ecture->cost ( ) } ( { $ l ecture- >chargeType ( ) ) ) \ n " ;
$ s eminar= new Semina r ( 3 , Lesson : : T IMED ) ;
print " { $ seminar- >cost ( ) ) ( { $ s emi n a r - >chargeType ( ) ) ) \n " ;

..
30
15

( )
( )

. 8.3.
, .
- . .

8.

1 85

. , .v
chargeType ( ) c o s t ( ) .

Lesson
+ construction(duration, costtype=1)
+ost ( )
+chargeType( )

Seminar

Lecture
. 8.3.

, .v .


Strategy.
.
, L e s s o n (. 8.4).

Lesson

CostStrategy

+cost(lesson: Lesson)
+chargeType()

+cost()
+chargeType( )
+getDuration ( )

1 Lecture 1

Lf

'f

1 Seminar 1

FixedCostStrategy

+cost (lesson : Lesson)


+chargeType( )

--1

$this->costStrategy- >cost( $this


. 8.4.

imeCostStrategy
-

+cost(lesson : Lesson)
+chargeType ( )

return ($1esson->getDuration( ) *S )

11

C o s t S t r a t e g y ,
c o s t ( ) chargeType ( ) . . cost ( )
L e s s o n , .
C o s t S t r a t e g y. Le s s o n
C o s t S t ra t e g y , ,
,
C o s t S t r a t e g y .
L e s s on .

1 86

1 1 1 .

L e s s o n , . 8.4.
abstract c l a s s Lesson {
p r i vate
$dura t i o n ;
$ co s t S t rategy;
p r i vate
func t i on _con s t ruct ( $ du r a t i o n , CostSt rategy $ s t rategy
$durat ion ;
$ t h i s - >durat i o n
$ t h i s - >costS trategy = $ s t ra t egy ;

funct i o n cost ( ) {
return $ th i s - >costSt rategy->cos t ( $ t h i s ) ;

func t i on chargeType ( ) {
return $ t h i s ->costSt rategy- >chargeType ( ) ;

function getDuration ( ) {
return $ t h i s - >durat i o n ;
1 1 l e s s o n . . .
)
c l a s s Lecture extends Lesson
11 Lecture . . .

c l a s s Serninar extends Lesson {


1 1 Serni nar . . .

L e s s o n C o s t S t r a t e g y ,
. Le s s o n : : c o s t ( ) C o s t S t r a t e g y :
: c o s t ( ) . L e s s o n : : cha r g e T yp e ( ) C o s t S t r a t e g y : : chargeT ype ( ) .

. C o s t S t ra t e g y -
L e s s o n. L e s s o n
C o s t S t ra t e g y.
.
funct i on cost ( ) {
return $ t h i s - >cos t S t rategy->co s t ( $ t h i s ) ;

CostSt rategy

abstract c l a s s Co s t S t rategy {
abst ract func t i on cos t ( Lesson $ l es son ) ;
abs t ract func t i on chargeType ( ) ;

c l a s s TirnedCostSt rategy extends Cos t S t rategy


funct ion cost ( Lesson $ l esson ) {
return ( $ l e s s on - >getDurat i on ( ) * 5 ) ;

8.

1 87

func tion chargeType ( ) {


return " " ;

class FixedCo s t Strategy extends CostSt rategy


function cost ( Lesson $ l e s son ) {
return 3 0 ;

function chargeType { ) {
return " " ;


, L e s s o n ,
Co s t S t r a t e g y . .
.
.
$ l ess ons [ ]
$ l es sons [ J

new Seminar ( 4 , new TimedCostSt rategy ( )


new Lecture ( 4 , new Fi xedC o s t S t rategy ( )

) ;
) ;

foreach ( $ l e s sons as $ l es son ) {


print " { $ l e s son->cost ( ) ) . " ;
print " : ( $ l e s son- >chargeType ( ) } \n " ;

.
2 0 . :
3 0 . :
-----

--

. .
. C o s t S t r a t e g y
, L e s s o n
.
, .

, .
.
, , , ,
, .
.


6 , ", ,
, .
, , . ,

.

1 88

111 .


- -
, - . ,

. ,
, " "
. ,
, .
. 8.2 .
Lecture Semi n a r , T imedP r i ceLec ture

T ime d P r i ceSemi n a r . ,
.
. , ,
c o s t ( ) c h a r g e T ype ( ) .
Strategy, C o s t S t ra t e gy,
.
,
. , ,
, . MySQL.
my s q l i : : que r y ( ) .
,
MySQL, ,
SQLite. ,
.
.
, ,
. , .
-
, -
.
. , ,
,
. -
- .
PEAR PEAR : : MDB2 (
PEAR : : ).
. , PDO,
.
MDB2 connect ( ) ,
, (DSN) .
, , MDB2_D r i v e r_
Common . " my s q l : / / " connect ( )
MDB2 D r i ve r _mys q l , , " s q l 1 t e : / / " ,
MDB2_Dr iver_ s ql i t e .
. 8.5.
, PEAR : : MDB2
. , SQL
o, . MySQL, SQLite,
MSSQL . , ,

8.

1 89

, DSN. , ,
. PEAR : : MDB2
" SQL , ,
PDO.
MDB2

- - - - - ;..

MDB2_Driver_Common

+connect(dsn)

MDB2_Driver_mysql

. 8.5.

PEAR :

MDB2

MDB2_Driver_sqlite

, . 8.5. Abstract
Factory, " "
. , , ,
: , ,
.
MDB2 PDO
.
. ( ) SQL-o
, , -
.
,

SQL-oa .
, ,
.


,

.
.
,
,
.

. ,
-
(SMS). , ,
.
, ,
.
.
Ma i l e r Text e r ,
-

1 90

1 1 1 .

. , .
API.
,
, .
c l a s s Reg i s t r a t i ongr
function regist er ( Lesson $ l e s s on )
1 1 - Lesson
1 1
$noti f i e r = No t i f ie r : : getNot i f ier ( ) ;
$not i f i e r - > i n f o rm ( " : -

( { $ l e s s on->cost ( ) ) ) "

abstract c l a s s Not i f i e r {
s t a t i c function getNot i fi e r ( )
1 1
1 1
if

( rand ( l , 2 ) === 1 ) {
return new Ma i lNot i f i er ( ) ;
else {
return new TextNot i f i e r ( ) ;

abstrac t f unction i n form ( $ me s s age ) ;

c l a s s MailNot i f i e r extends Not i f i e r


func t i on i n form ( $ me s s a ge ) (
print " e-AIL :

{ $me s s age ) \ n " ;

c l a s s TextNot i f i e r extends Not i f i e r


function i n form ( $ me s s age ) {
print " :

{ $message ) \ n " ;

Re g i s t ra t i onMg r ,
N o t i f i e r . Not i f i e r
, g e t N o t i f i e r ( )
N o t i f i e r ( e x t N o t i f i e r M a i l N ot i f i e r)
.
N o t i f i e r - ,
.
. i n f o rm ( ) Ma i lN o t i f i e r TextNot i f i e r
. .
, , .
.
,

8.

1 91

, Not i f i e r : : getNot i fi e r ( )
" Not i fi e r
.
,
Not i f i e r .
, r e g i s t e r ( ) Reg i s t r a
t ionMg r.
$lessonsl
$les sons2

new Seminar ( 4 , new TimedCostSt rategy ( ) ) ;


new Lecture ( 4 , new Fi xedCostStrategy ( ) ) ;

$mgr ; new Regi s trat i onMgr ( ) ;


$rngr ->regi ster ( $ l essonsl ) ;
$rngr ->regi ster ( $ l essons2 ) ;

.
:

(20)

e -AI L :

(30)

- ---------

-- -------

. 8.6 .
RegistrationMgr

Notlflr

+reglster(lesson:Lesson)

+getNotlfier()
+lnform(message)

MallNotlfler
. 8.6.

TextNotifier

Not i fi e r

. , . 8.6,
. PEAR : : MDB2 (. . 8.5).

,

- ,
. 6 ( ),
,
.
, , ,
.
"" , ,
Le s so n : : cos t ( ) L e s s o n : : chargeTyp e ( ) . - ,
. ,

"". , "
".

1 92

111.

.
C o s t S t r a t egy. ..
,
.
.
.
. .
. , .
, - . "",
.
, .
.
.
.
L e s s o n .
function _construc t ( $du ra t i o n , FixedP r i ce S t rategy $ s t rategy )
$du r a t i on ;
$ t h i s - >duration
$ th i s - >costSt rategy = $ s t rategy;

, . .
, L e s s o n ,
.
, Fixed P r i c e S t ra t e g y
.
, Le s s o n
C o s t S t ra t eg y .
funct i on _cons t ruct ( $ du ra t i o n , CostStra tegy $ s t rat egy )
$ t h i s - >duration
$du ra t i on ;
$ t h i s - >c o s t S t rategy = $ s t rategy;

, Le s s o n
. - .
.
,
, . ,
Le s s o n
C o s t S t r a t e g y , "
C o s t S t r a t e g y?"

"
?" "
?"
" ", .


, .
, ?
" " " ".
Le s s o n - .

8.

1 93

I
. . .
, (), I
, . .
, 1U1
, .
, I .
" " 1U1accax
.

, 1U1acc.
1U1accax. .
:

? -
, I
(/, / ),
,
. ,
, - , , .


, ,
.
.
, ,
, , .
(eXtreme Programming - )
, .
- " " (
YAGNI aren't going to need it). .
. .
.
.
. ,
.

-, r .
L- .
. - .
.
.
: " ".

1 94

111 .

, ,
. , ,
" " ,
.
.


- .
, ,
- -.
,
(Martin Fowler) Design Pattems Pattems of Enterprise Application
Architecture2 (Addison-Wesley, 2003) (Deepak Alur) Core J2EE Pattems3
(Prentlce Hall R, 200 1 ) .
,
" ", .


.
, .
,

. .


.
, , .

,
,
.


,
. Pattems of
Enterprise Application Architecture Core J2EE Pattems,
.


,
.

. (. . . "", 2009).

3 . . . J2EE.
. (. . . . "", 2 0 1 3) .

8.

1 95


,
. ,
.
, ,
. -
,
.
.
.

)/)
@@@
""" """

'/

- . -

. ,
(
). , ,
. .
, .

Singleton: ,
.

Factory Method: .

strt Factory: .

Prototype: c l one .

:
- -
. "
, ".
. , ,

. ,
.
, ,
.
abs t ract c l a s s Employee
protected $name ;
funct i on
cons t ruct ( $name )
$ t h i s - >name = $ name ;

abst ract funct ion f i re ( ) ;

1 98

111.

c l a s s Minion extends Empl oyee {


funct ion f i r e ( ) {
print " { $ th i s - >name ) : \ n " ;

c l a s s NastyBoss {
private $ employees

a r ray ( ) ;

funct i on addEmp loyee ( $employeeName ) {


$ t h i s - >empl oyee s [ ] = new Minion ( $ employeeName ) ;

funct ion proj ectFa i l s ( ) {


i f ( count ( $ th i s - >empl oyees ) > ) {
$ emp = a rray_pop ( $ t h i s - > employees ) ;
$ emp - > f i re ( ) ;

$boss = new Nas tyBos s ( ) ;


$boss- >addEmployee ( " " ) ;
$boss- >addEmployee ( " " ) ;
$boss- >addEmployee ( " " ) ;
$bos s - >proj ectFai l s ( ) ;
1 1 :
1 1 :

, Emp l oyee
M i n i o n . , N a s t yB o s s : : a ddEmp l oyee ( )
M i n i o n. , N a s t yB o s s
(- N a s t yBo s s : : pr o j e c t Fa i l s ( ) ,
.. ), M i n i o n , .
M i n i o n N a s t yBo s s ,
. N a s t yB o s s
Emp l oyee,
,
Emp l o y e e . . . 9. 1 ,
.
N a s t yBo s s M i n i o n ,
? ,
,
, .
c l a s s NastyBoss {
private $ employees

arra y ( ) ;

funct i on addEmp l oyee ( Empl oyee $ emp loyee )


$ thi s - >empl oyees [ ] = $emp l oyee ;

function proj ectFai l s ( )

9.
if

1 99

( count ( $ th i s - >emp l oyees ) > ) {


$emp = a rray_pop ( $ t h i s - > employees ) ;
$emp - > f i re ( ) ;

1 1 Employee . . .
class CluedUp extends Empl oyee {
func t i on f i r e ( ) {
print " { $ th i s - >name ) : \n " ;

$boss = new NastyBos s ( ) ;


$bos s - > addEmpl oyee ( new Minion (
"
$boss->addEmploye e ( new Cl uedUp ( " "
$bo s s - >addEmployee ( new Minion (
" "
$bos s - >proj ectFa i l s ( ) ;
$bo s s - >proj ectFai l s ( ) ;
$bo s s - >proj ectFa i l s ( ) ;
11
11
11
11

) ;
) ;
) ;

:
:
:
:

Nasty Boss
+addEmployee(employee : Employee) +projectFails ( )

1
1
1

\-


. 9. 1 .

Minion

+fire( )

Employee
+fire()

WellConnected

+fire ( )

CluedUp

+fire( )

N a s t y B o s s Emp l oyee
,
. - ,
. ,
, .
, : "
". , ,
N a s t yBo s s : : addEmp l o ye e ( ) Emp l o ye e .

200

111.

,
Emp l o ye e .
Emp l oy e e ,
.
abstract c l a s s Emp l oyee (
protected $ n ame ;
private s t a t i c $ t ypes = array (

' Mi n ion ' ,

s t a t i c function recru i t ( $name ) (


$num = rand ( 1 , count ( s e l f : : $ types )
$ c l a s s = s e l f : : $ t ypes [ $num] ;
return new $ c l a s s ( $name ) ;

funct ion
const ruct ( $ n ame )
$ t h i s - >name = $name ;

' C luedUp ' ,

' We l lConne cted '

);

) -1;

abstract fun c t i on f i re ( ) ;
}
/ / Empl oyee . . .
c l a s s We l lConnected extends Employe e
funct ion f i re ( ) (
print " ( $ t h i s ->name } : \ n " ;

, .
Emp l o y e e ,
.
r e c r u i t ( ) Emp l o y e e .
$ b o s s = n e w NastyBo s s ( ) ;
$bos s - >addEmp l oyee ( Empl oyee : : recrui t ( " "
$bos s - >addEmp l oyee ( Emp l oyee : : recru i t ( " "
$bos s - >addEmp l oyee ( Empl oyee : : recrui t ( " "

) ;
) ;
);

4. ,
g e t i n s t a n c e ( ) Shop Produ c t .
g e t i n s t an c e ( ) ShopProduct
, .
ShopProduct . ShopProduct
"" S hopProduc t .
"". - ,
.

1 1 ShopProduct
pu i c s t a t i c func t i on getlnstanc e ( $ i d , PDO $dbh )
$query = " s e lect * from produc t s where id
?";
$ s tmt = $dbh->prepare ( $ query ) ;
if (
1 $ s tmt - >execute ( a r ray ( $ i d ) ) ) (
$ e rror=$dh - >errorinfo ( ) ;
d i e ( " : " . $ e rror [ l ] ) ;

9 .

201

$ row = $ s tmt - > fetch ( ) ;


i f ( empty ( $ row ) ) { return nul l ; }
i f ( $ row [ ' t ype ' ] == "boo k " ) {
1 1 BookProduct
$p roduct=new BookProduc t ( )
e l s e i f ( $ row [ ' t ype ' ] == " c d " ) {
11 CDP roduct
$p roduct=new CDProduc t ( )
else (
1 1 ShopProduct
$product=new ShopProduct ( )
$product ->set i d ( $ row [ ' i d ' J ) ;
$produc t - > s e t D i s count ( $ row [ ' dis count ' J
return $produc t ;

) ;

g e t i n s t a nce ( )
, .
.
, ,
. ,
,
.
. " "
.

Singleton
-
, .
.
. ( 6,
" ", 8. " ").
.
, ,
.

, .
, , .
.
, - . .
, .
. .
. . .
, . .
,
,
.

202

111.

.
. . - .
, .
,
.
, .
.
.



.

. .

, ,
.
P r e fe r e n c e s , ,
.
P r e f e re nc e s . DSN- (.. ,
. ).
URL . .. ,
.
( ).
. .
P r e f e r e n c e s -
. , .
. ,
. .
,
P r e f e r e n c e s . .
- ,
.
.

P r e f e r e n c e s ,
.

P r e f e rence s .
. P r e f e rence s , Z
.
( .
P r e f e r e n c e s ) .

Preferences

,
. ,
. . .
.

9 .
c l a s s Preferences
pr ivate $props

203

a r r ay ( ) ;

private func t i o n _cons t ruct ( )

pu i c funct i on s e t P roper t y ( $ key,


$ t h i s - >props ( $ ke y ] = $ va l ;

pu i c func t i on get Propert y ( $ key )


return $ th i s ->props [ $ ke y ] ;

$val )

. P r e f e re n c e s .
r .
p r i va t e ,
. s e t Prope r t y ( ) g e t P r o p e r t y ( ) .
,
.
c l a s s Pre ferences
pr ivate $props = arra y ( ) ;
private s t a t i c $ i ns tance ;
p r ivate funct ion _cons t ruct ( )

pu i c s t a t i c funct ion get i ns t ance ( )


i f ( empty ( s e l f : : $ i ns t ance ) ) (
s e l f : : $ ins tance = new Prefe rences ( ) ;
return s e l f : : $ i ns tance ;

pu i c func t i on set Prope r t y ( $ ke y ,


$ t h i s - >props [ $ ke y ] = $ va l ;

pu i c func t i on get Prope r t y ( $ key )


return $ t h i s - >props ( $ key] ;

$val )

$ i n s t a n c e - ,
- . ge t i n s t ance ( ) .
g e t i n s t a n c e ( ) - r .
- .
$pref = Prefe rences : : ge t i n s tance ( ) ;
$pre f - > s e t P roperty ( "name " , " " ) ;
unset ( $pref ) ; / /
$pref2 = Preferences : : ge t i ns tance ( ) ;
1 1 ,
print $pref2- >get P rope r t y ( " name " ) . " \n " ;

204

111.

' name ' ,


P r e f e re n c e s ,
.

,
, .
. g e t i ns t a n ce ( ) ,
P r e f e rence s : : $ i n s t a n c e . ,
P r e f e re n c e s .
. g e t i ns t ance ( ) -
P r e f e r e n c e s , P r e f e
r e n c e s , .
. 9.2 Singleton .

'f
Preferences

1
1
1

-instance
construct ( )
+getinstance()
+setProperty(key : String,value: string)
+getProperty(key : String)
-_

if ( empty(self : : $instance ) ) {
self : : $instance
new Preferences ( ) ;
=

return self : : $instance;


. 9.2.

Singleton

, Singleton
? . Singleton,
.
Singleton ,
, .
Singleton , .
. ,
, ,
. , Singleton
, .
Singleton,
. .
Singleton .
, Singleton
,
.

9 .

205

Singleton -
- .
Singleton .
, .
,
.

Factory Method
- .
, .. , .
Factoy Method ,
. ?
.

-.
Appoi ntment (). -
.
, "BloggsCaJ".
, .
,
. ,
App o i ntment BloggsCaJ. Appt
Encod e r . .
, , .
. CommsMana g e r . ,
, Comms M a n a g e r
, App t Encoder
.
. 9.3.
-

CommsMaager

- - - - - ->

+getApptEncoder() : ApptEncoder
. 9 . 3.

ApptEncoder
+encode() : String

App t Encoder?
. App t Encoder CommsManager,
, .
B l o g g sApp t E nc o de r
CommsManager.
abs tract c l a s s ApptEncoder {
abstract funct ion encode ( ) ;

class Bl oggsApptEncoder extends ApptEncoder {


function encode ( )
return " B l oggsCal \ n " ;

206

111.

c l a s s MegaApptEncoder ext ends ApptEncoder {


func t i on encode ( )
return " MegaCal \n " ;

c l a s s CommsManager (
funct ion getApptEncode r ( )
return new Bl oggsApptEncode r ( ) ;

CommsMa n a g e r B l og g sApp t E n code r . ,



MegaCal, CommsManag e r : : getAppt
E n c ode r ( ) . , , .
CommsM a n a g e r ,
: BloggsCal MegaCal.
c l a s s CommsManager
const BLOGGS
MEGA
const
p r ivate $mode

(
l;
2;
l;

func t i on const ruct ( $mode )


$ t h i s - >mode = $mode ;

f unction getApptEncoder ( ) (
swi tch ( $ t h i s - >mode ) (
case ( s e l f : : MEGA ) :
return new MegaApptEncode r ( ) ;
de faul t :
return new BloggsApptEncoder ( ) ;

$ comms = new CommsManager ( CommsManage r : : MEGA ) ;


$apptEncode r = $ comms ->getApptEncode r ( ) ;
p r i n t $ apptEncode r - >encode ( ) ;

, ,
, MEGA BLOGGS . g e t ApptEncoder ( )
s w i t ch , $mode
App t Encode r .
.
,
.
, .
CommsManage r .
.

9 .

207

. .
g e t H e a d e rText ( ) .
class CommsManager
1;
const BLOGGS
2;
MEGA
cons t
1;
private $mode
function
con s t ruct ( $mode )
$ t h i s - >mode = $mode ;

funct ion getHeaderText ( ) {


switch ( $ t h i s - >mode ) (
case ( s e l f : : MEGA ) :
return "MegaCal \ n " ;
defau l t :
return " B loggsCal \n " ;

function getApp tEncoder ( ) {


switch ( $ t h i s - >mode ) {
case ( s e l f : : MEGA ) :
return new MegaApptEncode r ( ) ;
defaul t :
return new B l oggsApptEncode r ( ) ;

.

swi t ch . ,
g e t Fo o t e r T e x t ( ) .
, .

.
( B l oggsAppt E ncode r MegaApp t Encode r } .


(. -
SyncML}.

.
(g e t H e a d e r T e x t ( ) . ge t Fo o t e r T e x t ( ) ) .

. , .
, . Factory Method
,
. ,
CommsMa nage r , g e t App t Encode r ( ) .

Factory Method ,
. - ,

208

111.

-.
, 1U1
. 1U1
.
Counsa n a g e r .
cyeplUlacc ,
, lUl.
. 9.4.

CommsManager

ApptEncoder

+getlleaderText() : String
+getApptEncoder() : ApptEncoder
+getFooterText() : String

+encode() : String

BloggsCommsManager

l--1

- - - - - - ->

+getHeaderText ( ) : String
+getApptEncoder( ) : ApptEncoder
+getFooterText ( ) : String

return new BloggsApptEncoder( ) ;


. 9.4.

BloggsApptEncoder

+encode( ) : String

.
abs t ract c l a s s ApptEncode r {
abs t ract func t i on encode ( ) ;

c l a s s B l oggsApptEncoder extends ApptEncoder {


funct ion encode ( )
return " B l oggsCal \ n " ;

abst ract c l a s s CounsManager {


abs t ract funct i on getHeaderText { ) ;
abs t ract funct ion getApptEncode r ( ) ;
abs t ract function getFooterText ( ) ;

c l a s s Bl oggsCounsManager extends CounsManager {


fun c t i on getHeaderText ( ) {
return " B loggsCal \ n " ;

9 .

209

function getApptEncoder ( ) {
return new BloggsApptEncode r ( ) ;

funct ion getFoote rText ( ) {


return "Bl oggsCal \ n " ;

$mgr = new Blo ggsCommsManage r ( ) ;


prin t $mgr ->getHeaderText ( ) ;
print $mgr ->getApptEncode r ( ) - >encode ( ) ;
print $mgr->getFoo t e rTex t ( ) ;
- --------"'-----.,,

-....----...
-----

B l og g s C a l
B l oggsCa l
B l o g g s C a l

B l o g g s CounsManage r : : g e tApp t Encode r ( ) B l oggs


. g e t App t E n c o d e r ( ) ,
App t Encode r -
. .
, . .
, g e t App t E ncode r ( ) . .
App t Encode r . 5 .

.
Appt Encode r .

MegaCal.

. MegaCal . 9.5.


. -
. .
Factory Method.
.
- Factory Method .
.
Factory Method ( !),
.
,
.
.
"
" "", .
, .
Factory Method Abstract
Factory, .

21

111.

CommsManager
+geteaderText() : String
+getApptEncoder() : ApptEncoder
+getFooterText() : String

- -

Lf

BloggsCommsManager

MegaCommsManager

+getHeaderText ( ) : String
+getApptEncoder ( ) : ApptEncoder
+getFooterText ( ) : String

return new MEGAApptEncoder( ) ;

+getHeaderText ( ) : String
+getApptEncoder( ) : ApptEncoder
+getFooterText ( ) : String

return new BloggsApptEncoder( ) ;

ApptEncoder

+encode() : String

MegaApptEncoder

BloggsApptEncoder

+encode( ) : String
. 9.5.

+encode( ) : String

Abstract Factory
. , ,
. Abstract Factory.


.
, BloggsCal MegaCal.
,
. ,
? .
. 9 . 6 ,
. - (Appt ) , " "' (T t d) (C o n t a c t ) .
, BloggsCal
( ) ,
. l oggs
TtdEncoder, B l ogg s C o n t a c t Encode r .
, , .
Factory Method ( . 9. 7).

9 .

21 1

ApptEncoder
+encode() : String

MegaApptEncoder

BloggsApptEncoder

+encode ( ) : String

+encode( ) : String

TtdEncoder
+encode() : String

MegaTtdEncoder

BloggsTtdEncoder

+encode( ) : String

+encode ( ) : String

ContactEncoder
+encode(): String

MegaContactEncoder

+encode ( ) : String

1
BloggsContactEncoder

+encode ( ) : String

. 9.6.

ApptEncoder
CommsManager

---t
r:===
====::::t- - - , - -> 1-+encode()
: String
+geteaderText() : String
-

+getApptEncoder() : ApptEncoder
+getTtdEncoder() : TtdEncoder
+getContactEncoder() : ContactEncoder
+getFooterText() : String

TtdEncoder

- -?--------<
+encode(): String

1
1

ContactEncoder
- - -?1------1
+encode() : String

. 9. 7.

Commsanage r
( Appt Encoder , TtdEncoder Cont actEncoder).

212

111.

.
.
loggsCal. . 9.8.

CommsManager

ApptEncoder

+geteaderText() : String
+getApptEncoder() : ApptEncoder
+getTtdEncoder() : TtdEncoder
+getContactEncoder() : ContactEncoder
+getFooterText() : String

+encode() : String

i1

-3> BloggsApptEncoder
+encode ( ) : String

BloggsCommsManager

+getHeaderText ( ) : String
+getApptEncoder( ) : ApptEncoder
+getTtdEncoder( ) : TtdEncoder
+getContactEncoder( ) : ContactEncoder
+getFooterText( ) : String

TtdEncoder
+encode(): String

- - - -

L(

::;. BloggstdEncoder
+encode( ) : String

ContactEncoder
+encode() : String

- - ->

L(

BloggsContactEncoder

+encode( ) : String
. 9.8.

CommsMa nage r B l o g g sCommsMa n a g e r .


abs t r act c l a s s CounsManage r {
abst ract
abs t ract
abst ract
abst ract
abst ract

fun c t i on
func t i on
funct i on
funct ion
fun c t i on

getHeaderText ( ) ;
getApptEncode r ( ) ;
getTtdEncoder ( ) ;
getContac tEncode r { ) ;
get FooterText ( ) ;

c l a s s BloggsCounsManager extends CounsManager [


funct i on get Heade rText ( ) {
return "Bl oggsCal \ n " ;

func t i on getApptEncode r ( )

9.

213

return new BloggsApptEncoder ( ) ;

func t i on getTtdEncode r ( ) {
return new BloggsTtdEncode r ( ) ;

func t i on getContactEncoder ( ) {
return new Bl oggsContactEncode r ( ) ;

func t i on getFooterText ( ) {
return " BloggsCal \n " ;

, Factory
Method . g e t C o n t a c t Encode r ( ) C ommsManager
B l o g g s C ommsMana g e r .
, , .
. 9.9 , MegaCal.


Abstract Factory?

-. .

, - .

-,
. B l og g s C ommsManager
, , BloggsCal .

-, .
,
,
. .

Abstract Factory Factory


Method . . . Java
++. ,
, . .

Factory Method, ma ke ( )
, .
abstract c l a s s CommsManage r

1;
const
2;
const
TTD
const CONTACT
3;
abstract function getHeaderText ( ) ;
abstract function make ( $ f l ag_int ) ;
abstract function getFoote rText ( ) ;

...
.

.-

+encode(): String

+encode(): String

<- - -

-1

1- - -.

BloggsContactEncoder

+encode(): String

+l!ncode(): String

BloggsTtdEncoder

Contactfncoder

+encode(): String

+l!ncodl!(): String

MegaTtdEncoder

+encode(): String

tdEncoder

+encode(): String

MegaContactEncoder

- --

1
,

.::-

BloggsApptEncoder

--------------------------------------------

+getHeaderText(): String
+getApptEncoder(): ApptEncoder
+getTtdEncoder(): TtdEncoder
+getContactEncoder(): ContactEncoder
+getFooterText(): String

MegaCommsManager

/;:>.

+l!ncodl!(): String

Apptfncoder

MegaApptEncoder

. 9.9.

+getApptEncoder(): ApptEncoder
+getTtdEncoder(): TtdEncoder
+getContactEncoder(): ContactEncoder
+getFooterText(): String

+getHeaderText(): String

BloggsCommsManager

Lf

+gfi#leodl!rTl!xt(): String
+gl!tApptEncodl!r(): ApptEncodl!r
+gl!tTtdEncodl!r(): TtdEncodl!r
+gl!tContactEncodl!r(): ContactEncodl!r
+gl!tFootl!rTl!xt(): String

sg

:i:
!l:

g'

'

<

....
'

N
....

9.

215

class BloggsCounsManager extends CounsManager {


function getHeaderText ( ) {
return "BloggsCal \ n " ;
function rnake ( $ flag_int )
switch ( $ f lag_ int ) {
case sel f : ::
return new Bl oggsApptEncoder ( ) ;
case sel f : : CONTACT :
return new BloggsContactEncode r ( ) ;
case sel f : : TTD :
return new BloggsTtdEncoder ( ) ;

function get FooterText() {


return "BloggsCal \n " ;

. .
. Factory Method,
.
make ( ) ,
- .
.
-.
. ,
make ( ) .
, .
make ( ) ,
.
.
-
make ( ) .
Astract Factory
.

Prototype
Factory Method
.
.

(, l oggsCal B l oggsCommsManage r) .
, ,
.
-
c l one .
.
Prototype. -

21

111.

. . ,
, .

- "",
. . .
.
, Ter rainFactory ( ).
Sea (). Fores t () Plains ().
,
. Sea - ,
MarsSea EarthSea. Forest Plains
. Abstract Factory.
( Sea, Fores t, Plains ) ,
(Ea rth, Mars ) . . 9. 1 0
, , Abstract Factory Factory
Method .

TerrainFactory
+getsea(): Sea
+getPlains(): Plains
+getForest(): Forest

EarthTerrainfactory +getsea ( ) : Sea


+getPlains ( ) : Plains
+getForest ( ) : Forest

>

EarthSea

MarsSea

- - ,

MarsTerrainfactory
Plains

+getsea ( ) : Sea
+getPlains ( ) : Plains
+getForest ( ) : Forest
1
:;:;:..

1
1 - 3>

MarsPlains

Marsforest

- -i

EarthPlains

Earthforest

<-

________________ ___________

. 9. 1 . Abstract Factory

9 .

21 7

, ,
,

Factory.

,
.
,

Prototype Abstract Factory.

Abstract Factory

Factory Method ,

, . ,
.
, ,
?
,
, . ,

Prototype.

class Sea { )
class EarthSea extends Sea { )
class MarsSea extends Sea { )
class Plains { )
class EarthPlains extends Plains { )
class MarsPlains extends Plains { )
class Forest { )
class EarthFo rest extends Forest { )
class MarsForest extends Forest { )
class TerrainFactory
private $ s e a ;
pr ivate $ forest;
private $plains ;
function
const ruct ( Sea $sea, Plains $plains, Fores t $ forest ) {
$sea;
$this->sea
$this ->pla ins
$plains ;
$this-> forest
$ f ores t ;
function getSea ( ) {
return clone $this->sea;
function getPlains ( ) {
return clone $ this->plains ;
function getForest ( ) {
return clone $this->forest ;

$ factory

new TerrainFactory ( new Ea rthSea ( ) ,

218

1 1 1 .

new EarthPlains ( ) ,
new EarthForest ( ) ) ;
print_r ( $ factory - >getSea ( ) ) ;
pr1nt r ( $ factory->getPlains ( ) ) ;
print r ( $ factory- >getForest ( ) ) ;
E a r thSe a Obj e c t
(
)

E arthP la i n s Obj e c t
(
)
E a rthFor e s t Obj e c t

, Terrain
Factory .
g e t S e a ( ) , S e a ,
. ,
. ,
. , , ?
-
,

$ factory

T e r ra i nFactory.

new TerrainFactory ( new EarthSea ( ) ,


new Mars Plains ( ) ,
new EarthForest ( ) ) ;

. Prototype ,
. .
,
, . ,

Sea
$naviga i l i t y ().
, .

class Sea {
pr ivate $navigab i l i t y

function
const ruct ( $navigabi l i t y ) {
$thi s - >navigab i l i t y = $navigabi l i t y ;

T e r r a i n Fa c t o r y ,
Sea .
S e a , T e r r a i nFac t o r y.

$ factory

new TerrainFactory ( new EarthSea ( -1 ),


new EarthPlains ( ) ,
new EarthFores t ( ) ) ;

, .
, . ,

Sea
Resource (Fi shRe s ou rce. Oi l Re s ource ..).
, Sea

9.

219

FishResource. .
_cl one ( ) .

,
m .

class Contained
class Container
pulic $contained;
function _construct ( )
$this- >contained = new Contained ( ) ;
function _clone ( ) {
11 ,
11 , sel f : : $contained,
11
$thi s->contained = clone $this- >contained;

. 4. cl one
, . , -
, . -
, .
.
-, _clone ( ) .
clone.

. ,

"-" .

. .
Sigleto .
. Abstract Factory
-. .
?

Prototype.
, , ( )
.
. ,
,
. .
(, Apache,

. ht a c c e s s )

- . -
,
"".
r -. ,

220

1 1 1 .

. ,
.

class Sett ings {


static $S

' Bl oggs ' ;

, ( ),
, ,

CounsManager .

Singleton Abstract Factory.


.

require_once ( ' Settings . php ' ) ;


class AppConf i g {
private static $ instance ;
private $commsManager;
private funct ion _construct ( )
11

$this->init ( ) ;
private funct ion init ( ) {
swi tch ( Set tings : : $S ) {
case ' Mega ' :
$this->commsManager = new MegaCommsManager ( ) ;
break;
default :
new BloggsCommsManager ( ) ;
$this- >commsManager

pu i c static funct ion get instance ( )


i f ( empty ( s e l f : : $ ins tance ) ) {
sel f : : $ instance = new sel f ( ) ;
return sel f : : $ i ns tance ;
pu ic function getCommsManager ( )
return $this->commsManager ;

AppC o n f i g - Singleton.

AppCon f i g ,
.

i n i t ( )

S e t t i n g s : : $S,
CounsManager.
CounsMa nager ,

, .

$ commsMgr = AppCon f i g : : getinstance ( ) - >getCommsManager ( ) ;


print $commsMgr- >getApptEncoder ( ) - >encode ( ) ;

9.

221


,
. Singleton,
,
Factory Method,
. Factory Method Abstract Factory
-.
. Prototype ,
.

,,

@@@
'''

)/)

'i


.
, ,
. , ,
" ".
.

Composite: .
, .

Decorator:
.

Facade:
.

,

4 ,
. .
, UL-
,
.
" "?

. ,
,
.
,
. - ,
,

.

224

111 .

Composite
Composite - , ,
, .
, . .
: - .
.
Composite - ,
.
. ,
, . - 1JJ .
, , -
. ,
Composite, . r
.
.
, . ,
, ,
. , (
, ), ,
. ,
. , . , ,
, , .
.
, ,
() ( ). ,
, . Composite
.

,
.
. -1JJ,
, , ,
.
, .
. 1JJ
.
, . ,
- ".
, r.
. ,
, .
().
abst ract class Unit {
abs tract function bomardStrength ( ) ;
class Archer extends Unit {

10.

225

function bomardStrength ( )
return 4;

class LaserCannonUni t extends Unit


function bomardStrength ( )
return 44;

Uni t boma rdSt rength (),


, .

Arche r L a s e rCannonUni t .
,
.
.
-

class Arrny
private $units

array ( ) ;

funct ion addUni t ( Unit $unit ) (


array_push ( $this->un i t s , $unit ) ;
function bomardS trength ( ) {
$ret = ;
foreach ( $this->uni ts as $uni t ) {
$ ret += $unit->bomardStrength ( ) ;
J

return $ r e t ;

Arrny addUn i t ( ) , Uni t .


Uni t $ un i t s .
boma rdS t rength ().
Uni t
bomardSt rength ( ) .
, . ,
? ,
.
.
. ArchDuke
,
.

.
Arrny ,
Arrny. Uni t .
funct ion addArrny ( Arrny $arrny ) {
array_push ( $ this->arrni e s , $arrny ) ;

226

111.

boma rdSt rength ().


Uni t .
function bomardSt rength ( ) {
$ ret = ;
foreach ( $ th i s - >units as $uni t ) {
$ ret += $unit- >bomardSt rength ( ) ;
foreach ( $ th i s ->armies as $army ) {
$ ret += $ a rmy- >bomardSt rength ( ) ;
return $ re t ;
.
, ,
, d e f e n s i veSt rength (),
movement Range ( ) .. .
- ,
,
. ,
, Uni t.
. Army.
( T roopCar r i e r ) ,
Unit. ,
.
, .
bomardSt rength (). ,
, . .
, . ,
, .
. -
, , .
.

Composite ,
.
.
. - bomard
S t rength ( ) .
.
. 1 0. 1 ,
Composite .
, Uni t.
, Uni t
bomardSt rength (). , Army
, Arche r .
Army T roopCa r r i e r
; ,
Uni t . Archer LaserCannon - ,
, Uni t:
-

10.

227

Uni t. "
, ,
. 1 0. 1 ?" , T ro opCa r r i e r Arrny
U n i t , -""
addUni t ( ) . .
U n i t .

Unit
+<1ddUnit(unit:Unit)
+re110vellnit(unit:Unit)
+o.ordStrength(): int

Archer

LaserCannon
TroopCaier :>----'
. 1 0. 1 . Composite

abs tract class Uni t {


addUnit ( Unit $unit ) ;
abs tract functi on
abst ract functi on removeUnit ( Unit $unit ) ;
abstract function bomardSt rength ( ) ;
, Uni t .
, -
.
class Army extends Unit {
private $units = array ( ) ;
funct ion addUni t ( Uni t $uni t ) (
i f ( in_array ( $un i t , $this->uni t s , t rue ) ) {
return;
$this- >units [ J

$uni t ;

function removeUnit ( Uni t $unit ) {


$thi s - >units = array_udi f f ( $thi s - >uni t s , array ( $unit ) ,
function ( $ , $ ) { return ( $ === $ b ) ?O : l ; } ) ;
function bomardStrength ( ) {
$ ret = ;
fo reach ( $this->units a s $unit ) {
$ ret += $unit->boma rdSt rength ( ) ;
return $ re t ;

228

1 1 1 .

addUni t ( ) Uni t
$un i t s . .
$uni t s Uni t . removeUni t ()
, Uni t .
$uni t s .
. removeUni t ( ) .
, $uni ts, .
5.3. ,
c reat e_function ( ) , .
$this->units = array_udi f f ( $this ->units , array ( $unit ) ,
c reate_function ( ' $ , $ ' , ' return ( $ === $) ? 0 : 1; ' ) ) ;
Army Uni t ,
Army, , Archer Laser
CannonUni t. bom
bardSt rength ( ) , Army : : bomardSt rength ( )
Uni t , $un i t s ,
.
Composite -
. add ( ) remove ( )
. ,
. , , ,
-"" .
class Uni tExcept ion extends Exception { )
class Arche r extends Unit {
func t i on addUn i t ( Uni t $uni t ) {
throw new Uni tExcept ion ( get_class ( $ this )

" ' ' " ) ;

function removeUn i t ( Unit $unit ) {


throw new UnitExcept ion ( get_ class ( $thi s )

" ' "' ) ;

function bomardSt rength ( )


return 4;

U n i t Arche r .
addUni t ( ) removeUni t ( ) .
-"". , ,
, addUni t () / removeUni t ()
Uni t , .
abst ract class Unit {
abst ract function bomardSt rength ( ) ;
funct i on addUni t ( Unit $unit ) {
throw new UnitException ( get_class ( $thi s ) . " ' ' " ) ;
func t i on removeUnit ( Unit $unit ) {

10.

throw new Uni tException ( get_class ( $thi s ) . "

229

' "' ) ;

class Archer extends Uni t {


funct i on bomardStrength ( )
return 4 ;

-"".
- Composite
addUnit ( ) removeUnit ().
.
Composite
. ,
.

!U. Composite
, -
"", .

. . Composite.
. .
. -"" (
). Army : : boma rdSt rength ( )
,
,
Arche r : : boma rdS t rength ( ) .

. . Composite
.
.
. Army
Army .
. Uni t ,
Army, .

.
.
.

Visitor.


, .
11


$main_army = new Army ( ) ;

11


$main_army->addUni t ( new Archer ( ) ) ;
$main_army->addUn it ( new LaserCannonUnit ( ) ) ;

11


$sub_army
w Army ( ) ;

230

1 1 1 .

11


$sub_army->addUn i t ( new Arche r ( ) ) ;
$sub_army->addUni t ( new Archer ( ) ) ;
$sub_a rmy->addUni t ( new Archer ( ) ) ;

11


$main_army->addUni t ( $sub_army ) ;

11
print " : { $mai n_army->bomardSt rength ( ) } \n " ;

Army U n i t .
Army, .
Uni t : : bomardSt rength { ) Army,
, , .


- , , Arche r,
. , a ddUni t ()
removeUn i t ( ) -w",
? Uni t .
U n i t , .
addUni t ( ) .
Composite, , ("")
, . ,
- , a ddUni t ()
Uni t , .
/ ,
, Uni t
- , .
addUni t () . - -""
. , ,
.
- Comp o s i t e U n i t .
, / Uni t.

abstract class Unit {


funct ion getCompos i te ( )
return nul l ;
abstract function bomardStrength ( ) ;
getComp o s i t e ().
. ,
addUni t ( ) removeUni t ( ).
.

abst ract class Compos i t eUnit extends Uni t {


private $units = array ( ) ;
funct i on getCompos ite ( )
return $thi s ;

1 0.

231

protected function uni ts ( )


return $this ->uni t s ;
function removeUnit ( Uni t $unit ) (
$ this ->units = array_udi f f ( $this->uni t s , array ( $un i t ),
funct ion ( $, $ ) ( return ( $ === $b ) ? O : l ; } ) ;
function addUni t ( Unit $uni t ) (
i f ( in_a rray ( $uni t , $this ->uni t s , true ) ) {
return ;
$this ->units [ ]

$uni t ;

Compos i teUni t ,
. U n i t
bom a r dS t rength () . Army (
-) Comp o s i teUni t .
, . 1 0.2.

Unit
+otltardStrength(): int

+getComposite(): CompositeUnit

Archer

LaserCannon

CompositeUnit
+addUnit (unit : Unit )
+removeUnit(unit : unit)

TroopCarrier
. 1 0.2. /

/
-"", add
Uni t ( ) - (

Compo s i teUni t).


- getComp o s i t e ( ) .
. Compo s i t e U n i t
Compos i teUni t.
, addUni t ().
.

232

1 1 1 .

class UnitScript {
private $comp;
static function joinExisting ( Unit $newUnit,
Unit $occupyingUnit ) {
if ( ! is null ( $comp = $occupyingUnit->getComposite () ) ) {
$comp->addUnit ( $newUnit );
else {
$comp = new Army ();
$comp->addUnit ( $occupyingUnit );
$comp->addUnit ( $newUnit );
return $comp;

. j oinExisting () Unit. - ,
1U1, - . 1U1
. Unit 1Uiaccy CompositeUnit,
. ,
rm, 1U1 Unit.
, r $occupyingUnit 1Uiacca CompositeUnit.
getComposite () . getComposite ()
,
Unit. Army
.
, , Unit: :get
Composite () Army, Unit.
. (
; - "), Uni t: : addUnit ()
: Army Q Unit.
, , .
Unit. .
, getComposite () add
Unit (), . .
Composite.
, 1U1 1Uiacca.
.
, ,
. , Cavalry ().
,
Composite.
class TroopCarrier extends CompositeUnit
function addUnit ( Unit $unit ) {
if ( $unit instanceof Cavalry )
throw new UnitException (

" " ) ;
super::addUnit ( $unit );

10.

233

function bomardStrength ()
return ;

instanceof,
, addUnit ().
,
. Composite ,
.
, , -
Composite. Army: : bomardStrength () ,
.

. bomardStrength ()
"". , ""
, ?
-
, .
, .
,
- . , ,
.
- . Composite
, .
.
. ,
Composite , ""
. , ,
. ,
, - "
- ", . . .
, .
, Composite
, L.
, L-, ,
.

Composite
, Composite ,
, , , ,
(, ), ,
l\, (, -).
Composite ,
,
. Composite
. (
). Composite .
Composite , .
, -
, .

234

111 .

Composite
, L-.

Decorator
Composite
, Decorator .
. -,
- . -
, .

. . , .


. ,
, . ,
.
. Tile .
abstract class Tile {
abstract function getWealthFactor() ;
class Plains extends Tile {
private $wealthfactor
2;
=

function getWealthFactor()
return $this->wealthfactor;

Tile, .
. .
getWealthFactor{) , .
. .
, Plains 2. , .
.
. .
.
Plains (),

.
, , .
- Plains.
class DiamondPlains extends Plains (
function getWealthFactor{) (
return parent::getWealthFactor() + 2 ;

class PollutedPlains extends Plains (

1 .
function getWealthFactor () (
return parent::getWealthFactor ()

235

4;

.
$tile = new PollutedPlains () ;
print $tile->getWealthFactor ( ) ;
. 10.3.

ile
+getltlealthFactor(): int

Plains
+getWealthFactor( ) : int

DiamondPlains

PollutedPlains

+getWealthFactor( ) : int

+getWealthFactor( ) : int

. 1 0.3.
, .
. .
, ? , ,
PollutedDiamondPlains. .
Forest. .
, .
. ,
.
. -
,
. ,
. ,
- ,
.
. .
ProcessRequest
LogRequest, Structure
Request AuthenticateRequest. . 1 0.4.
,
, ? LogAnd
AuthenticateProcessor? , .


. Decorator

236

111.

. , Decorator
. Decorator
,
( ). ,
Decorator.
D
Authenticate LogReques t?
Authent icateStructureReques t?
StructurelogRequest?

Process Request
+process (req: llequestelper)

.. .n.

+process ( req : RequestHelper)

AuthenticateRequest

LogRequest
-

+process (req : RequestHelper)

StructureRequest
+process(req : RequestHelper)

function process( Requestelper $req ) { L::,


//

parent: : process( $req );

. 1 0.4.
, .

abst ract class T i l e {


abstract function getWeal thFactor ( ) ;
class Plains extends T i l e {
private $wealth factor = 2 ;
function getWeal thFactor ( )
return $ this - >wealth factor;

abstract class T i l eDecorator extends T i l e {


protected $ t i l e ;
functi on
construct ( T i l e $ t i l e ) {
$this->tile = $ t i l e ;

, T i l e P l a i n s , , T i l e
Decorator. getWeal thFactor ( ) ,
. ,
T i l e , $ t i l e .
, .. protected, .
Pollution Di amond.

class Di amondDecorator extends TileDecorator {


funct ion getWealthFactor ( ) {
return $this->tile->getWeal thFactor ( ) +2 ;

1 0 .

237

class Polluti onDecorator extends T i leDecorator


function getWeal thFact or ( ) {
return $this->tile- >getWeal thFacto r ( ) - 4 ;

T i l eDecorator. ,
T i l e . getWe a l thFactor ( ) .
T i l e ,
.
,
.
T i l e , ,
. , getWe a l thFa c t o r ( )
T i le , , " "
.

$tile = new Plains ( ) ;


print $ t i l e- >getWealthFacto r ( ) ; / / 2
P l a i n s ,
2 .

$tile = new DiamondDecorator ( new Pl ains ( ) ) ;


print $ t i le- >getWeal thFactor ( ) ; / / 4
D iamondDe c o r a t o r P l a i n s .
2 getWe a l t h Fa c t o r ( )
P l a i n s .

$tile

new Pol lutionDecorator (


new DiamondDecorato r ( new Plains ( ) ) ) ;
print $ t i l e- >getWeal thFactor ( ) ; / /
P o l l u t i onDe c o r a t o r D i amond
Decor a t o r , - T i l e .
. 1 0.5.
.
Decorator . Decorator,
.
( P l a i n s )
,
. . ,
( P l a ins ) ,

PollutedDi amond P l a i n s .
Decorator ,
. j va . i o Decorator.
, ,
Decorator , , ,
. read ( ). -
.
, Decorator.

238

111.

l
+getllieolthFoctor(); int

Plains

ileDecorator

+getWealthFactor( ) : int

+construct (tile : Tile)

Lf

DiamondDecorator

PollutedDecorator

+getWealthFactor( ) : int

+getWealthFactor( ): int

. 1 0.5. Decorator

class RequestHelper { }
abst ract class ProcessRequest
abs tract function process ( RequestHelper $req ) ;
class MainProce s s extends Proces sRequest {
function process ( RequestHelper $ req ) {
. " : \n" ;
print
CLASS

abstract class DecorateProcess extends ProcessRequest {


protected $process reque s t ;
function cons t ruct ( ProcessRequest $ p r ) {
$ thi s->process request = $pr;

I< . (Proces s Reque st},


(Ma i n P r o c e s s} (Decora t e Process}.
Ma i n P roce s s : : proces s () , ,
. Decora t e P r o c e s s Proces s Reques t
.
.
class LogReques t extends DecorateProcess {
function process ( RequestHelper $ req ) {
print
CLASS
" : \n" ;
$ th i s - >process reques t - >p rocess ( $ req ) ;
.

1 0 .

239

class Authenti cateRequest extends DecorateProcess {


funct ion process ( RequestHelper $ req ) {
print
CLASS . : \ n " ;
$this- >processrequest->process ( $ req ) ;
"

class StructureRequest extends DecorateProcess {


funct ion process ( RequestHelper $ req ) {
print
CLASS . : \n" ;
$this->process request- >process ( $ req ) ;
"

proce s s ( ) ,
proce s s () Proces s Re que s t , .
-
, , ,
.
.

$process

new AuthenticateRequest (
new St ructureRequest (
new LogRequest (
new Mai nProces s ( )
) ));
$process->process ( new RequestHelper ( ) ) ;
.
---

.,...____

_,...
"
"
"
.
_
,
_
_
_

Authen t i ca t e Re que s t :
St ructureReque s t :
LogReque s t :
Ma i n Proce s s :
. , lterceptig Filter.
Core J2EE Pattems .

Composite, Decorator
. , ,
. LogReque s t Proc e s s Re que s t ,
, , Proce s s

Reque s t .
- ,
,
. , -

, . -
, ,
.
,
, . -

240

111.

, , .
,
- ( _cal 1 ( )

). ,
.
T i l e P ro c e s s Requ e s t
,
".

Facade
, - -
. , - -
, , , , .
, . ,
.
Facade -
.

,
, .


. ,
, .
, -
, , , .
,
,
.
, ,
. ,
, - , -
..
, ,
.
, .
,

- .

func t i on getProduct Fi leLi nes ( $ f i l e ) (


return f i l e ( $ fi l e ) ;
func t i on getProductObj ect Fromid ( $ i d , $productname ) {

retur new Product ( $ i d , $productame ) ;

11

1 0 .

241

function getNameFromLine ( $ l ine ) {


i f ( preg_match ( 11 / . * - ( . * ) \ s \d+ / 11 , $ l ine, $array ) ) {
return s t r_replace ( ' ' , ' ' , $array [ l ] ) ;
return
function get IDFromLine ( $ 1 ine ) {
i f ( preg_match ( " / ( \d { l , 3 ) ) - / " , $ l ine, $array ) ) {
return $array [ l ] ;
return - 1 ;
class Product {
pu i c $id;
pu ic $name ;
funct ion
cons t ruct ( $id, $name ) {
$this->id = $ id;
$this->name = $name ;

, ,
, ,
.

234 -_ 5 5
532 -_ 4 4
, (
, ).

$ l ines = getProductFileLines ( ' test . txt ' ) ;


$obj ects = a rray ( ) ;
foreach ( $ l ines as $ l ine )
$id
= get I DFromLine
( $ l ine ) ;
$name = getNameFromLine ( $ l ine ) ;
$objects [ $ id] = get ProductObj ectFromI D ( $ id , $name ) ;
, ,
, " , .
,
.
.

,
, .

class ProductFacade (
private $products = array ( ) ;
function construct ( $ f i le )

242

111 .

$this->file = $file;
$this ->compi le ( ) ;
private function compi l e ( ) {
$ l ines = getProduct FileLines ( $ t h i s - > f i l e ) ;
foreach ( $ l ines as $ l ine ) {
get I DFromLine ( $ l ine ) ;
$id
$name
getNameFromLine ( $ l i ne ) ;
$this->products [ $ i d ] = get ProductObj ect FromI D ( $ i d , $name ) ;
=

function getProducts ( ) {
return $this ->products ;

funct ion getProduct ( $id ) {


i f ( isset ( $ thi s - >products [ $ i d ] ) ) (
return $this->products [ $ i d ] ;
return nul l ;

P roduct
.

$ facade = new ProductFacade ( ' test . txt ' ) ;


$ facade->getProduct ( 2 3 4 ) ;

Facade .
.
,
.
. .
,
,
. Facade .
, ,
.
Facade, .
, . , ,
. ,
. ,
, .
/
, . . ,
Facade.

10.

243



. , ,
, .
Composite Decorator
,
.
,
. , Facade.
, , ,
. Facade
. Facade
-, .

1 1
1

@@@

!))

. .
, -
.

Interpreter: -.
, .

Strategy:
.

Obsever:
.

Visitor: .
Command: ,
.

l nterpreter

( , m ). ,
. , ,
. . .
.
. - ,

- . ,
, .

. ,
, .
, , .

90%

246

111.

(
),
. ,
. 1 0% ,
? , - .
-
( DSL, Domain Specific Language),
.
"".
.

$form_input = $_REQUEST [ ' fo rm_input ' J ;


/ / : "print f i l e_get_contents ( ' / et c/passwd ' ) ; "
eval ( $ fo rm_input ) ;
,
. , .
: .
. -
. , , , .
. ,
, ,
, .
- .
, -
.
.
.
,
,
.
.

?
"" "4" .
-,
.

4 1 $
, , .
, ,
.

$ i nput equal s " 4 " or $ i nput equals ""


, , equa l s
( o r and) . ,
Mar kLogic. ,
.


. . ,

Inter preter.

1 1 .

247

,
. . l l . l , , MarkLogic,
.
1 1 . 1 . MarkLogic


""


VarialeExpre s s i o n
variae
< s t r i ngLi t e r a l > L i t e ra lExpres s i o n
BooleanAndExpress ion
andExpr

""

o rExpr

BooleanOrExpr e s s ion

equalsExpr

EqualsExpre s s ion

NF

$ i nput
" "
$ i nput equa l s
$ o th e r e qua l s
$ i nput e qua l s
$ o the r equa l s
$ i nput e qua l s

' 4 ' and


'6'
' 4 ' or
'6'
4
'

'

. l l . l EBNF. EBNF? - ,
. EBNF
"Extended Backus-Naur For m" - -.
, (productinns).
.
(.. ,
). EBNF.

expr : : = operand ( orExpr 1 andExpr )*


operand : : = ( ' ( ' expr ) ' 1 <stringLi teral>
orExpr : : = ' or ' operand
andExpr : : = ' and ' operand
eqExpr : : = ' equal s ' operand
variae : : = ' $ ' <word>
'

variae ) ( eqExpr

(
). ' * ' " ", ' 1 ' "". . ,
(expr) operand,
orExpr, andExpr. operand
, ( ) ,
eqExpr. ,
. EBNF .
. 1 1 . l .
, BooleanAndExpre s s ion "" Ope rator
Expre s s ion. ,
Expre s s i on. Varial e Expre s s ion LiteralExpre s s i o n
.
Expre s s i on interpret (),
Exp re s s i on . i nt e rpret ( )
I nt erpre t e rContext,
. Exp r e s s i on
I n t e rpret e rCont e x t . I n t e rprete rContext
Expr e s s i on . ,
I nt e rpre t e rCont e x t , Expr e s s i on get
( ) , . .
. Expression.

248

111.

lnterpreterContext

;--

----

Expression

+interpret(context:InterpreterContext)

+getKey() : string

1 LiteralExpression :
1

VariaeExpression

OperatorExpression

BooleanOrExpression

BooleanAndExpression

EqualsExpression \
. 1 1 . 1 . lnterpreter, Marklogic

abstract class Expression {


pri vate static $ keycount=O ;
private $ key;
abstract funct ion interpret ( I nterpreterContext $ context ) ;
funct ion getKey ( )
i f ( ! isset ( $this->ke y ) ) {
sel f : : $ keycount++ ;
$ th i s - >key=sel f : : $ ke ycount ;
return $ this- >key;

class LiteralExpre s s i on extends Express ion {


private $value ;
funct ion const ruct ( $value ) {
$this->value = $value;
function interpret ( I nterpreterContext $context ) (
$context->replace ( $thi s , $this->value ) ;

class InterpreterContext {

1
1

1 1 .

249

private $expres s i ons tore = array ( ) ;


function repl ace ( Express ion $ , $value ) {
$this ->express ionstore ( $exp->getKey ( ) ] = $value ;
function lookup ( Expres s i on $ ) {
return $this->expres s ionstore [ $ exp->getKey ( ) ] ;

$context = new I nterpreterContext ( ) ;


$ l i teral = new LiteralExpres s i on ( ' ' ) ;
$ l itera l - >interpret ( $context ) ;
print $context->lookup ( $ l iteral ) . " \n " ;
.


Inte rpre t e rCont e x t . ,
$ expre s s i on s t o r e .
. replace ( )
, $ e xpre s s i ons t ore.
Expre s s i o n,
. I nt e rp r e t e rContext l o o kup ( )
.
Expr e s s i o n inte rpret ()
g e t Ke y () , ;
. I nt e r
preterContext : : l o o kup() I n t e rp r e t e rContext : : replace ( )
.
Li t e r a l Ex p re s s i o n ,
-. i n t e rp r e t ( ) I n t e rp r e t e r
Cont e x t . replace ( ) .
( Li t e r a l E x p re s s i o n ) $ va l u e .
replace ( ) I n t e rp r e t erContext
g e t Ke y () .
Expr e s s i on .
i nt e rpret ( ) I n t e rp r e t e rConte x t .
.
I nt e r p re t e rContext L i t e r a l E xp re s s i o n (
' ' ) . I n t erpreterContext L i t e r a l
Exp r e s s i o n : : interpret ( ) . i n t e rp r e t ( ) "-"
I n t e rp r e t e rCont e x t , ,
l o o kup ( ) .
. V a r i a l eExpr e s s i on
.

class Varia eExpression extends Expre s s i on {


private $name ;
private $va l ;
function
const ruct ( $name , $val=null ) {
$this->name = $name;

250

1 1 1 .

$ thi s->val

$val ;

function interpret ( InterpreterContext $ context ) {


i f ( ! i s_nul l ( $ t h i s - >va l ) ) {
$ contex t - >replace ( $thi s , $ th i s - >val ) ;
$ th i s - >va l = nul l ;

funct ion setValue ( $value ) (


$thi s->val = $value;
function getKey ( ) {
return $ th i s - >name ;

$ context = new InterpreterContext ( ) ;


$myvar = new Varial eExpres s i on ( ' input ' , ' ' ) ;
$myvar->interpret ( $context ) ;
print $context - > lookup ( $myvar ) . " \n " ;
11 : ' '
$newvar = new VarialeExpression ( ' input ' ) ;
$newvar->interpret ( $context ) ;
print $ context ->lookup ( $newvar ) . " \n " ;
11 : ' '
$myvar->setVal ue ( " " ) ;
$myvar-> interpret ( $context ) ;
print $context - > lookup ( $myvar ) . " \n " ;
11 : ' '
print $context- > lookup ( $newvar ) . " \n " ;
11 : ' '
V a r i a e Expre s s i on (
), . set
Va lue ( ) , .
i n t e rpre t { ) , $ v a l .
$val ,
I n t e rp r e t e rCon t e x t . $val nul l .
, i n t e rpret ( )
, I n t e rp r e t e rCont ext
V a r i a e Expre s s i on.
,
. , ,
Expre s s ion,
. V a r i a l eExpr e s s i o n
. . ,
g e t K e y ( ) , .
.

1 1 .

251


Expre s s i o n . , .
Oper a t orExpre s s ion.

abstract class OperatorExpres si on extends Express i on {


protected $ 1_ ;
protected $ r_op;
funct ion
cons truct ( Expre s s i on $ 1_ , Expression $ r_op ) {
$this->l_op
$ l_op;
$this->r_op
$ r_op;
function interpret ( I nterpreterContext $ context ) {
$this->l_op->interpret ( $context ) ;
$this->r_op- >interpret ( $ context ) ;
$ result_l = $context ->lookup ( $ th i s ->l_op ) ;
$ result_r = $ context ->lookup ( $this->r_op ) ;
$ this->dointerpret ( $ context, $ resul t_l , $result r ) ;
protected abstract function dointerpret ( InterpreterContext $ contex t ,
$ result_l , $ result_r ) ;
Ope ratorExp re s s i o n i n t e rp r e t () ,
d o i nterpret ( ) .
Expre s s i o n
( $ 1_ $ r _ ) , .
i n t e r p r e t ( ) i n t e rp r e t ()
, (
, , , ,
Composite) . i n t e rpret ()
I nt e r p r e t e rContext : : l o o kup ( )
. d o i n t e rp r e t () ,
,
.
. dointerpret ( ) Template Method.

, ,
. ,
,
.

Equal sExpre s s i on ,
Expre s s i on.

class Equal sExpression extends OperatorExpression {


protected function dointerpret ( InterpreterContext $ context ,
$ result_l , $result_r )
$context->repl ace ( $ this , $ result_l
$result_r ) ;

252

111.

Equal s Expre s s ion dointerpret ( ) .


, i nterpret ()
I nt erpre t e rContext.
Expre s s i on ,
B o o l e anOrExpre s s i on BooleanAndExp re s s i on.

class Bool eanOrExpress ion extends OperatorExpress ion {


protected funct ion dointerpret ( Interprete rContext $context ,
$ resul t_l , $result r ) {
$context->replace ( $thi s , $ result_l 1 1 $result_r ) ;

class Bool eanAndExpression extends OperatorExpress ion


protected funct ion dointerpret ( Interprete rContext $context ,
$ resul t_l , $ resul t_r ) {
$context->replace ( $ th i s , $result 1 && $ result_r ) ;

Bool e anOrExpres s i on
"",
I nt erp ret e rContext : : replace ( ) . BooleanAndExp r e s s i on,
, "".
, ,
-, . .

$ i nput equals " 4 " or $ i nput equals " "


Expr e s s ion.

$ context = new InterpreterContext ( ) ;


$ i nput = new Vari a eExpres s i on ( ' input ' ) ;
$ statement = new BooleanOrExpres s i on (
new EqualsExpression ( $ input , new L i teralExpress ion ( ' ' ) ) ,
new Equal sExpression ( $ inpu t , new L i teral Express ion ( ' 4 ' ) )
);
' i nput ' ,
. B o o l eanOrExp r e s s i o n ,
, Equal s Expre s s i on.
Var i a l eExp r e s s ion,
$ input, L i t e ra lExpre s s i o n ,
" " . $ i nput
Li t e ra l Expres s i o n , " 4 " .
, , .
II .

foreach ( array ( " " , " 4 " , " 5 2 " ) as $val ) {


$ input - >setValue ( $val ) ;
print " $val : \n " ;
$ s tatement- >interpret ( $context ) ;
i f ( $context ->lookup ( $statement
) {
print " \n\n " ;
else {
print " \n\n " ;

1 1 .

253

, .
$val " " ,
VariaeExpression, $ input ,
s e tValue ( ) . interpret ( )
Expression ( Boo l eanOrExpress ion,
) . ,
.

$ s t a t eme nt i nt e rp r e t ( ) $ 1
( Equa l sExpr e s s i on ) .

Equal sExpre s s ion interpret ( )


$ 1 _ ( Va riae
Expression, " " ) .

Va ria eExpre s s ion


I n t e rprete rConte x t , Inte rpret e r

Context : : replace ( ) .

Equal sExpre s s ion interpret ( )


$ r_ ( Li t e ra l Expr e s s i o n " " ) .

Li t e ralExpre s s i on

InterpreterContext.

Equal s Express ion $ 1_ ( " " )


$ r_op ( " " ) Interprete rContext.

Equa l sExpression ,
, ( t rue , .. "")
I nt e rprete rContext.

$ s t a t ement ( BooleanOrExpr e s s i on )
interpret ( ) $ r .
( - f a l s e , .. "") ,
$ 1_.

$ s t at ement
I n t e rp r e t e rContext 1 J .
t rue f a l s e , t rue.
I n t e rp r e t e rContex t .

- . .

4:

52 :

, ,
. -
. Expre s s i on
, Expre s s ion
. . .
. 1 1 .2 .

254

111 .

lnterpreterContext
+lookup(key : string) : mixed
+replace( key : string, val : mixed)

Expression

1
1

- - - - +interprn(ctext: InterpreterCtext)
r +getKey( ) : string

--

uteralExpression

#dointerpt (ctext: InterpreterCtext, resul t_l, result_r)

VariaeExpression
+interpret( context : InterpreterContext)

+getKey() : string

OperatorExpression
+interpret ( context : InterpreterContext)

+interpret( context : InterpreterContext)

ooleanOrExpression

1
1 #dolnterpret (context : InterpreterContext , result_ l, result_r) 1
BooleanAndExpression

1
1 #dolnterpret (context : InterpreterContext , result_l, result_r) 1
EqualsExpression

1
1 #dolnterpret ( context : InterpreterContext, result l, result r) 1

. 1 1 .2 . lnterpreter

lnterpreter
Interpreter.
. , . -
, . Interpreter
.
, .
Interpreter ,
, . .
Interpreter,
, ,
. ,
.
.
.

Strategy

. : ,
. ,
.
. ,
.

1 1 .

255

,
.
. Que s t ion mar k ( ) .
,
.
. MarkLogic,
.
. . - ,
(. 1 1 .3).

Question
+mark()

Lf
1

MarkLogicOuestion

MatchOuestion

RegexpQuestion

+mark( )

+mark( )

+mark( )

. 1 1 ..
.
. ,
, .
,
(. 1 1 .4) .
,
.
.
,
( ,
), ,
.

, Strategy . .
(.
). - , ,
,
. .
, Ma rker.
. 1 1 . 5.
" " - " .
"? .
,
.
.

256

111.

Que s t i o n . , Que s t i on . - ,
M a r ke r
ma r k (). - .

Questlon
+mark()
1
TextQuestion

+doTextyThings()

1
AVQQuestion
+doCleverAVhings()

TextarkLogicOuestion

AVarkLogicOuestion
+mark ( )

+mark ( )

TextMatchQuestion

+mark ( )

AVatchQuestion
+mark( )

TextRegexpQuestion

+mark ( )

AVRegexpQuestion
+mark()

. 1 1 .4.

Questlon

::

Marker
+mark()

+mark()
1
Textauestion
+doTextyThings()

!i>

AVQuestion
+doCleverAVhings()

MarkLogicMarker
+mark ( )

,___

MatchMarker
+mark( )

RegexpMarker
+mark ( )

. 1 1 .5.

abst ract c l a s s Que s t i on
protected $promp t ;
protected $ma r ke r ;

Que s t i on,

1 1 .

257

function
construct ( $prompt , Marker $marker ) {
$thi s - >marker=$marker ;
$this- >prompt = $prompt ;
function mark ( $ response ) {
return $this->marker->mark ( $ response ) ;

class TextQuestion extends Question {


11 ,
class AVQuest ion extends Question {
11 ,
11 ( - - )
, TextQue s t i o n AVQues t i on
, .
Que s t i on, , , ,
rk r . Que s t i on : : ma r k ( )
,
Marker.
Mar k e r .
abstract c l a s s Marker
protected $ t e s t ;
function
construct ( $test ) (
$this->test = $test ;
abstract function mar k ( $response ) ;
class MarkLogicMarker extends Marker {
private $engine ;
function construct ( $test ) {
parent : : cons truct ( $test ) ;
11 $this->engine = new Ma rkParse ( $test ) ;
function mark ( $ response ) {
11 return $thi s - >engine->evaluate ( $ response ) ;
11
return true ;

class MatchMarker extends Marker {


function mark ( $response ) {
return ( $this->test == $ response ) ;

258

111.

class RegexpMarker extends Marker {


function mark { $ response ) {
return ( preg_match ( $this ->tes t , $ response ) ) ;

, ( ),
Ma rker. , Ma rkParse
,
. ,
t rue () Ma r kLog i cMa r ke r : : ma r k ( ) .
- r, , .
RegexpMa r k e r MatchMa r ke r , Ques t i on.
, ,
Ma rker.
.
. r .
.

MarkLogic .
: $ input equals ' '
.

/ . /
, .
$markers

array ( new RegexpMarker ( " / . / " ) ,


new MatchMa rker ( " " ) ,
new MarkLogicMarker ( ' $ input equal s " " ' )
);
foreach ( $markers as $marker ) {
print get_class ( $marker ) . " \ n " ;
$question = new TextQuestion ( " ? " , $marker
);
foreach ( array ( " " , " " ) as $ response ) {
print " \ t f 6AA6 : $respons e : " ;
i f ( $ques t i on->mark ( $ response ) )
print " ! \n " ;
else {
print " ! \n" ;

, ,
TextQue s t i on.
TextQue s t i on .
MarkLogicMa r ke r -
, mar k ( ) t rue ().
, -

1 1 .

259

. ,
.
.
----

". ::,,.,.....

t 111

RegexpMar k e r
: : !
: : !
Mat chMa r ke r
: : !
: : !
MarkLog icMa r k e r
: : !
: : !
, Ma r kLogi cMar k e r
t rue (),
.
, (
$ re s ponse) , - mar k ( ) .
, ,
- .
, ,
-, -.
- .

Observer
.
,
.
, ,
,
.
, - , , ,
. m .
.
.
,
.

. ,
.
class Login {
const LOGIN USER UNKNOWN
1;
const LOGIN WRONG PASS
2;
3;
const LOGIN ACCESS
private $ status = array ( ) ;
function handleLogin ( $user, $pass , $ip ) {
$ i sval id = fal s e ;
switch ( rand ( l , 3 ) ) {
case 1 :

260

111.

$this ->setStatus ( s e l f : : LOGIN_ACCES S , $user, $ ip ) ;


$ i sval i d = t rue ;
break;
case 2 :
$this- >setStatus ( se l f : : LOGIN_WRONG_PASS , $user, $ ip ) ;
$ i svalid = f a l s e ;
break;
case 3 :
$ this- >set Status ( sel f : : LOGIN_USER_UNKNOWN , $use r , $ i p ) ;
$ i sval i d = false;
break;
return $ i sva l i d ;
private function setStatus ( $ s tatus , $ user , $ i p )
$this - >status = array ( $ status , $user, $ ip ) ;
function getStatus ( ) {
return $this->status ;

, handleLogin ( )
, - .
rand ( ) .
hand l e Login ( ) .
: LOGIN_ACCES S , LOG I N WRONG_PASS LOGI N_
_
USER UNKNOWN.
Login
"", .
.
. .
I- .
Logge r .
-

funct ion handleLogin ( $user, $ pa s s , $ ip ) {


$ i svalid = false;
switch ( rand ( l , 3) ) {
case 1 :
$thi s- >setStatus ( s el f : : LOGI N_ACCESS , $user, $ip ) ;
$ i sval i d = true ;
break ;
case 2 :
$this- >setStatus ( sel f : : LOGI N_WRONG_PASS , $user, $ip ) ;
$ i sval i d = false;
break ;
case 3 :
$thi s - >setStatus ( s el f : : LOGI N_USER_UNKNOWN , $user, $ ip ) ;
$ i sva l i d = false;
break ;
Logger : : logI P ( $user, $ ip , $this->getStatus ( ) ) ;
return $ i sval id ;

1 1 .

261

,
.
.
if ( ! $ i svalid ) {
Not i f i e r : : mai lWarning ( $user, $ i p , $this- >getStatus ( ) ) ;
-
(ISP) ,
ki-
..
,
. L o g i n
. ,
, .
, ,
. ,
, L o g i n , ,
.
, .
, L og i n?
Observer.

Observer
() () .
, , .
, m
.
,
. L o g i n - a t t a ch ( ) , detach ( )
not i f y ( ) - Obse rva l e .
inter face Observae {
function at tach ( Observer $ observer ) ;
funct ion detach ( Observer $ observer ) ;
funct ion not ify ( ) ;
11

. . . Login
class Login implements Observae
private $observers=array ( ) ;
private $ s torage ;
const LOGIN USER UNKNOWN = 1 ;
const LOGIN_WRONG_PASS = 2 ;
const LOGIN_ACCESS = 3 ;
funct ion _construct ( ) {
$this->observers = array ( ) ;

262

111.

funct ion at tach ( Observer $observer ) {


$ thi s - >observers [ ] = $observe r ;
functi on detach ( Observer $observer ) {
$this->observers = array_f i l ter ( $ th i s ->observers ,
function ( $ ) use ( $observer )
{ return ( ! ( $ === $ observer ) ) ; } ) ;
funct ion noti f y ( ) {
foreach ( $this ->observers as $obs ) {
$ obs->update ( $this ) ;
11 .

}
. .

}
, L o g i n -. r
a tt a ch ( )
detach ( ) . n o t i f y ( ) , ,
- .
, update ( ) .
L og i n n o t i f y ( ) h a ndleLogin ( ) .
function handleLogin ( $user, $pas s , $ ip ) {
switch ( rand ( l , 3 ) ) {
$ isva l i d = false;
case 1 :
$ th i s ->setStatus ( s e l f : : LOGI N_ACCESS , $user, $ ip ) ;
$ i sval i d = true ;
break;
case 2 :
$this->setStatus ( sel f : : LOGIN_WRONG_PASS , $user, $ ip ) ;
$ i sval i d = fal s e ;
break;
case 3 :
$this->setStatus ( s e l f : : LOGIN_USER_UNKNOWN, $user, $ ip ) ;
$ i sva l id = false ;
break ;
$this->noti f y ( ) ;
return $ i svalid;
Obs e rve r .
interf ace Observer {
funct ion update ( Observae $obse rvae ) ;
, , Login
a t tach ( ) . .
class Securi tyMonitor imp lements Observer {
function update ( Observae $observae ) {
$ s tatus
$ observale->getStatus ( ) ;
=

1 1 .

263

i f ( $ s tatus [ 0 ] == Logi : : LOGIN_WRONG_PASS ) {


1 1
prit
CLASS
. " : \ t \ " ;

$logi = new Logi ( ) ;


$ l ogin->attach ( w Securi tyMoni tor ( ) ) ;
, -
Observa e ,
. - ,
. . get
s ta t us ( ) , ,
. .
. Login : : get
S t a t u s ( ) S e cur i t yMoi t o r ,
. Obs e rva e ,
, Logi.
. Obs e rvae
g e t S t a tu s ( ) . , ,
- Obs e rval eLogi. ,
Login.
- Obs e rvae ,
. Obs e rver
.
. Obs e rve r
. ,
. .
abst ract class Logi nObse rver implemets Observer {
private $ l ogin;
functio
cost ruct ( Login $ l ogi ) {
$ this-> logi = $ l ogi;
$ login->attach ( $this ) ;
function update ( Observae $ observae )
i f ( $observa e === $this->login ) {
$this->doUpdate ( $observae ) ;

abstract functio doUpdate ( Login $ logi ) ;


LogiObserver Logi.
Log i n : : a t t a c h ( ) .
updat e ( ) Log i nObse rver ,
Obse rva e . doUpdate ( ) .
LogiOb s e rve r ,
, Logi n ,
, Observae.

264

1 1 1 .

class SecurityMonitor extends LoginObserver


funct ion doUpdate ( Login $ login ) {
$ status = $ login->getStatus ( ) ;
i f ( $ s t atus [ O ] == Login : : LOGI N_WRONG_PASS ) {
1 1
print
CLASS
. " : \t \ n " ;

c l a s s GeneralLogger extends LoginObserver


fucti o doUpdate ( Login $ login ) {
$s tatus = $ login->getStatus ( ) ;
1 1
print
CLASS
. " : \ t \ n " ;

class PartnershipTool extends LoginObserver


function doUpdate ( Login $ login ) {
$s tatus = $ login->getStatus ( ) ;
/ / I -
// ki- ,
print
CLASS
" : \ t ki-, \n" ;

Logi nOb s e rve r


.
$ l ogin = new Login ( ) ;
new Securi tyMonitor ( $ login ) ;
new GeeralLogger ( $ l ogin ) ;
new Partne rshipTool ( $ login ) ;
. -
. . 1 1 .6.
Observer
SPL (Standard Llbrary). SPL
,
-
. , SPL Observer, :
S p l Ob s e rver, S p l Subj ect S p l Obj e c t S t o rage. S p l Obse rver S p l Subj ect

, Obs e rver Obse rvae
. S p l Obj e c t S t o rage

, ,
.
Observer.
-

class Login implements SplSubj ect {


private $ s torage ;
// . . .
funct ion
construct ( )
$this->storage = new SplObj ectStorage ( ) ;

1 1 .

265

function attach ( SplObserver $observer )


$this->s torage->attach ( $observer ) ;
function detach ( SplObserver $ observer )
$this->storage->detach ( $observer ) ;
function notify ( ) {
foreach ( $thi s - >s torage as $ obs ) {
$obs - >update ( $this ) ;
}
//. . .
}
abstract class LoginObserver implements SplObserver {
private $ l ogin;
function
construct ( Login $ login ) {
$this->login = $ login;
$ login->at tach ( $this ) ;
function update ( SplSubj ect $ subj ect )
i f ( $ subj ect === $this- >login ) {
$this- >doUpdate ( $ subj ect ) ;

abstract function doUpdate ( Login $ l ogin ) ;

interface

Observa/e

interface

Observer

+update(observae:Oservale)

+attach(oservale:Oservale)
+detach(observae:Oservae)
+notify()

SecurityMonitor

- -

+update(observae:Observae)

Login
+attach(observale:Observae)
+detach(observale :Observae)
+notify( )
+getStatus ( )

Generallogger
+update(observale :Observae)

PartnershipTool
+update(observae :Observae)
. 1 1 .6. Observer

- - i
1

266

1 1 1 .

S p l Observer S p l Subj e c t ,
Obse rver Observa l e , , , ,

. SplObj e c t Storage
. , , ,
L o g i n : : detach ( )
Obse rval e , $ obse rva e,
-. S p l Ob j e ct S t orage
. a t t ach ( ) de tach ( ) ,
foreach .
. SPL

ht tp : / /www. php . net / spl. , -.


I terator 1 3.

Obse rvae
Obs e rve r , updat e ( )
, Obse rvae .
.
upda te ( ) ,
I- (. , ), Login.
Login
. , -
, updat e ( )
.
, Login
- (, Login
Obse rver).
. a t tach ( ) ; . .
Obs e rvae.
,
. Log i n
.
.

Visitor
,
. .
. . -
Composite. ,
,
.
. ,
.
.
, .
.
,
. , , ,
Visitor.

1 1 .

267

Composite .
,
. . .
- , -
, .
class Army extends Compo s i teUnit
function bomardSt rength ( )
$ strength = ;
foreach ( $this->uni t s ( ) a s $unit ) (
$st rength += $uni t- >bomardSt rength ( ) ;
return $ s t rength ;

class LaserCannonUnit extends Uni t


function bomardSt rength ( ) {
return 4 4 ;


-. .
. .
.
-"". U n i t .
11

Un it
function textDump ( $num=O ) {
$txtout = " " ;
$pad
4 * $num;
$txtout
sprintf ( " % { $pad ) s " , "" ) ;
$txtout . = get clas s ( $thi s )
": ";
$txtout . = " : " . $this->bomardStrength ( ) . " \n " ;
return $ txtout;
Comp o s i teUni t .
11

Compos i teUnit
function text Dump ( $num=O ) {
$txtout = parent : : textDump ( $num ) ;
foreach ( $this->units as $unit ) {
$txtout . = $uni t->textDump ( $num + 1 ) ;
)
return $txtout ;

,
, .
?
.

268

111.

,
.
. -
Composite. , , .
Composite.
.
. .
, "" .

. Uni t
accept ( ) .
abstract class Unit
protected $depth
11 . . .

funct ion accept ( ArmyVi s itor $visitor )


$method = "vi s i t " . get_class ( $this ) ;
$vi s i t o r->$method ( $ th i s ) ;
protected function setDepth ( $depth ) {
$this- >depth=$depth;
funct ion getDepth ( ) {
return $ this ->depth ;

, a ccept ( ) , ArmyVi s i tor.


ArmyVi s i tor,
. , ,

ArmyV i s i to r . , Army,
eo ArmyVi s i tor : : vi s i tArmy ( ) , T roopCa r r i e r ,
ArmyVi s i t o r : : v i s i t T r oo pC a r r i e r ( ) ..
accept ( )
. - g e t Depth ( ) s e t Depth ( ) .
,
. s e t Depth ( ) .
Composi teUni t : : addUni t ( ) .
funct i on addUnit ( Unit $unit ) {
foreach ( $this ->un i t s as $thi sunit ) {
i f ( $unit === $ thisunit ) {
return;

$unit->setDepth ( $ th i s ->depth+ l ) ;
$this ->un i t s [ ] = $uni t ;

1 1 .

269

a ccept ( )
-.
function accept ( ArmyVi sitor $vis i tor ) {
$method = "vi s i t " . get_class ( $this ) ;
$vi s itor->$method ( $this ) ;
foreach ( $this ->units as $thisunit ) (
$thisunit- >accept ( $vi s i tor ) ;

, Uni t : : accept ( ) . .
v i s i t - ArmyVi s i t or
, accept ( ) .
, a ccept ( ) .
.
function accept ( ArmyVi s i t o r $vi s i tor ) {
parent : : accept ( $vi s i tor ) ;
foreach ( $thi s - >uni ts as $thi sunit ) (
$thi sunit->accept ( $visitor ) ;

,
, ,
. accept ( ) :

v i s i t- ;

-
accept ( ) (, - ).

ArmyV i s i t o r.
accept ( ) . -
accept ( ) .
.
v i s i t ( ) .
, ""
Uni t .
abst ract class ArmyVisitor {
abst ract function vi s i t ( Unit $node ) ;
funct ion visitArcher ( Archer $node ) (
$this->vi s i t ( $node ) ;
function vis i tCavalry ( Cava l ry $node ) {
$this->vi s i t ( $node ) ;
funct ion visitLase rCannonUni t ( LaserCannonUni t $node ) {
$this->vi s i t ( $node ) ;
funct ion visitTroopCarrierUnit ( TroopCarrierUnit $node ) (
$this->visit ( $node ) ;

270

1 1 1 .

function v i s i tArrny ( Arrny $node ) {


$this - >vi s i t ( $node ) ;

ArrnyV i s it o r ,
. .
, ArrnyVi s i t o r .
c l a s s TextDurnpArrnyVisitor extends ArrnyVisitor {
private $text= " " ;
funct ion v i s i t ( Unit $node ) {
$ txt
"";
$pad
4 * $node->getDepth ( ) ;
sprint f ( " % { $pad } s " , " " ) ;
$ txt
get_class ( $node ) . " : " ;
Stxt
" : : " . $node->bornardSt rength ( ) . " \n " ;
S txt
$this ->text . = $txt;
function getext ( ) {
return $this- >text ;

, .
Srnain_arrny = new Arrny ( ) ;
$rnain_arrny->addUni t ( new Archer ( ) ) ;
$rnain_arrny- >addUni t ( new LaserCannonUn i t ( ) ) ;
$rnain_arrny->addUni t ( new Caval ry ( ) ) ;
$textdurnp = new TextDurnpArrnyVi s i to r ( ) ;
$rnain_arrny->accept ( $ textdurnp ) ;
print Stextdurnp ->getText ( ) ;
.
Arrny : : 5 0
Archer : : 4
L a s e rCan nonUni t : : 4 4
Cava l r y : : 2
-.!

... 8'JL:WN'f

f'W
'lfil'

J i111WliB8'1 -illl!--!!i'Cl

Arrny. Arrny - , a dd
Uni t ( ) ,
Uni t . T e x t DurnpArrnyVi s i t o r . Arrny :
: a ccept ( ) . a ccept ( ) T e x tDurnpArrny
V i s i t o r : : vi s i tArrny ( ) .
Arrny, vi s i t ( ) .
vi s i t ( ) Arrny. (
getDepth ( ) , , ,
), .
vi s i tArrny ( ) , Arrny : : a ccept ( )
a ccept ( ) , -.
ArrnyVi s i t o r .

1 1 .

271

. ,
-.
.
.
().
. .

-.
class TaxCol lectionVi sitor extends ArmyVisi tor {
private $due=O ;
private $ report= " " ;
function visit ( Unit $node )
$this- >l evy ( $node , 1 ) ;
function visitArcher ( Archer $node ) {
$this->levy ( $node , 2 ) ;
function visitCavalry ( Cava l ry $node ) {
$this->levy ( $node , 3 ) ;
funct ion vis itTroopCarrierUnit (TroopCarri erUnit $ node ) {
$this- >levy ( $node , 5 ) ;
private function
$this->report
$thi s - >report
$thi s->due +=

levy ( Unit $un i t , $amount ) {


. = " " . get_c l a s s ( $un i t ) ;
. = " : $ amount\n" ;
$ amount ;

function getReport ( ) {
return $thi s - >report;
function getTax ( ) {
return $thi s - >due ;

uni t .
v i s i t .
,
Uni t .
.
$main_army = new Army ( ) ;
$main_army->addUnit ( new Arche r ( ) ) ;
$main_army->addUnit ( new Lase rCannonUnit ( ) ) ;
$main_army->addUni t ( new Caval ry ( ) ) ;
$taxco l l ector = new TaxCol l ec t i onVi s itor ( ) ;
$main_army->accept ( $ taxcol lector ) ;

272

111.

print $taxcol l ector- >getReport ( ) . " \n " ;


print " : " ;
print $taxcol lector->getax ( ) . " \n " ;
TaxCo l l e c t i onVi s i t o r accept ( ) Army.
. Army v i s i tArmy ( ) .
accept ( ) .
, .
,
, .
. ArmyV i s i t o r , TaxCol lec
t i onVi s i tor , g e t Re p o r t ( ) getTax ( ) .
, .

Army : 1
A r che r : 2
L a s e rCannonU ni t :
Cava l r y : 3

: 7
. 1 1 . 7 , .
<-

ArmyVisitor
+visit(node: unit)

+visitlaserCannon (node : LaserCannon)


+visitArmy(node : Army)

Unit
+accept(visitor :ArmyVisitor)

.... TextDumpArmyVisitor

LaserCannon

+visit(node: unit)

CompositeUnit
+accept (visitor : ArmyVisitor)

TaxCollectionVisitor
+visit(node: unit)
. 1 1 .7. Visitor

Visitor
Visitor - ,
. .
Visitor
Composite, .
, , ,
"" (.. ).
, ""
, ..
, - . ,
V i s i to r
Uni t .
Text DumpArmyV i s i t o r . Obs e rve r .

1 1 .

273

,
-, . ,
visit ( ) , - , ,
. -
-.
, .
,
.
.

Command
-
.

,
( )
( ). , Command
, .

,
.
. (feedba c k . php) .
, .
" " (
).
, .
,
. .
, , ,
. ,
, - . login . php
feedback . php, ,
, . ,
,
. ,
.
, , ,
, .
.
, , Command.

!
- execute ( ) .
. 1 1 .8 Counand .
. -

274

1 1 1 .

,
.

Command
+execute(context:CO/lllnlQ dContext)
. 1 1 .8. Command

Command : .
; ,
; , .

- -.
, .
Cornrnand .
.
abs tract class Command (
abst ract function execute ( CommandContext $ context ) ;
Cornrnand.
class LoginCommand extends Command (
function execut e ( CommandContext $ context
$rnanager = Reg i s t r y : : getAccessManager ( ) ;
$user = $ context->get ( ' use rnarne ' ) ;
$pass = $ context- >get ( ' pass ' ) ;
$user_obj = $rnanager->login ( $user, $pass ) ;
i f ( i s_nu l l ( $user_obj ) ) (
$context->setError ( $rnanager->getError ( ) ) ;
return false;
$ context- >addPararn ( "use r " , $user_obj ) ;
return t rue ;

Logi nCornrnand Acces sManage r.


Acc e s sManag e r - , -
. ,
Cornrnand : : execute ( ) CornrnandCont ext ( Core J2EE
Patterns Reque s tHelper ) . ,
Cornrnand, -
. ,
, .
Cornrna ndContext - , , -
,
. CornrnandContext .
class CommandContext
private $pararns
a rray ( ) ;
private $error
" "
'

1 1 .

275

function _construct ( ) (
$this- >params = $_REQUEST ;
function addParam ( $ key, $val ) {
$this->params [ $ key] =$va l ;
funct ion get ( $ key ) {
if ( i s set ( $this->params [ $ ke y ) ) ) {
return $this->params [ $ key] ;
return nul l ;
function setError ( $error ) {
$thi s->error = $error;
function getError ( ) {
return $this ->erro r ;

, "" CounandContext , L o g i nC ounand


: .
Reg i s t r y
. a Acces sManager,
LoginCounand. l o g i n ( ) AccessManager
, CounandContex t ,
,
f a l s e (""). . e xe cute { ) L o g inCounand
t rue (""). ,
Counand .
, ,
, .
, "" , ,
, .
, .
, . ,
.
- ,
, - ,
. .
-, - .
.
class CommandNot FoundExcept ion extends Exception { )
class CommandFactory {
private static $dir = ' counands ' ;
static function getCommand ( $action= ' Default ' ) {
if ( preg_match ( ' / \W/ ' , $action ) ) {
throw new tin ( " " ) ;

276

1 1 1.

$class
UCFirst ( s trtolowe r ( $actio ) ) . " Counad" ;
$ fi l e = sel f : : $dir . DIRECTORY_SEPARATOR . " ( $class ) . php" ;
i f ( ! f i l e_exists ( $ f i l e ) ) {
throw w CounadNotFoudExceptio ( " ' $ f i l e ' " ) ;
=

requi re_oce ( $ f il e ) ;
i f ( ! class_exists ( $class ) ) {
throw w CounadNotFoundExceptio ( " ' $ clas s ' " ) ;
$ cmd = w $class ( ) ;
retur $cmd;

C ounadFac t o r y counads
. $ a c t i o Counad
Cotext, , , .
, .
, ,
Counand ,
.
, Command
, .
- .
class Cotrol ler {
private $cotext;
costruct ( )
fuctio
$this->cotext = w CounadCotext ( ) ;
fucti o getCotext ( ) {
retur $this ->cotex t ;
fuctio process ( ) {
$actio
$this->cotext- >get ( ' act i o ' ) ;
$ actio = ( is_u l l ( $ actio ) ) ? "defau l t "
$ cmd = CounadFactory : : getCommad ( $ actio) ) ;
i f ( ! $cmd- >execute ( $this->cotext ) ) {
1 1
else {
1 1
11
=

$ cotro l l er = w Cotroller ( ) ;

$cotext = $cot rol ler- >getCotext ( ) ;
$cotext->addParam ( ' action ' , ' login ' ) ;
$ context- >addParam ( ' username ' , ' ' ) ;
11

$actio;

1 1 .

277

$context- >addParam ( ' pass ' , ' tiddles ' ) ;


$cont rol ler->process ( ) ;
Controlle r : : proc e s s ( ) -,
ComrnandContext , r
. proce s s ( )
' act ion ' , , ' de faul t ' .
proce s s ( ) r ComrnandFa c tory,
execute ( ) .
,
.
Comrnand
.
Comrnand.
.

class FeedbackCommand extends Command (


function execute ( CommandContext $context ) (
$msgSystem = Regi stry : : getMessageSystem ( ) ;
$email
$ context->get ( ' emai l ' ) ;
$msg
$context- >get ( ' ms g ' ) ;
$context- >get ( ' topi c ' ) ;
$topic
$msgSystem->send ( $emai l , $msg , $topic ) ;
$ result
i f ( ! $result ) {
$context->setError ( $msgSystem->getError ( ) ) ;
return f a l s e ;
return true ;

. Commad 1 2,
Command.
, , Front Controller.
-

Feedbac kCommand . php


comrnands
" feedba c k " , ' act i o n ' .
CommandFactory.
. 1 1 .9 Command.

278

111.

Command
+execute(context:COlllnll/Q dC011text): l

LoginCommand

+execute(context : CommandContext) : boolean

FeedbackCommand

+execute(context : CommandContext) : boolean

CommandFactory

1
1

"

+getC011111a nd(action : String) : Corrmand

Controller

1-----1
"

+process ( )
$cmd $commandFactory->getCommand( "login" ) ;
$cmd- >execute( $context ) ;
=

. 1 1 .9.

Cornmand


" ".
- Interpr eter.
Strategy ,

. Obser ver
.
Composite Visitor ,
.
, Command
. "
" ,
.

1 2

@@@

)/)
-----

- , , . -.
5 ,
,
- . Java.

. , . .
, . .
-
. .
. , .
, -
.
. .
.
" ".
.
.
.
.

: .
.

Registry: .

: .
.

:
- .


.
. ,
.

280

1 1 1 .


.
,
. , Command
( 1 1 ) ,
Front Controller Application Controller.

Registry. ,
.
,
.

Font Controller. ,

.

Application Controller.
.

Template View. ,
,
. .

Page Controller. . , Front Controller,


Page Controller . ,
,
, , , .

ransaction Script.
,
. .

Domain Model. 1sti Script.


, .


( !) ,

. , ,
, .
. 1 2 . 1 .
, . 1 2. 1 ,
:
,
, . . 1 2 . l
,
.
.
-

,
.
,
.

1 2.

281

, . ,

.
.

.

n,

ynpell'!.811!!
- -

-----<t:'/

-',r-------'--

n

nl;!!! 1
1-

'

....
,
r-

- - -


...

nn 38118".. - ::::JJ----

nn nn

n

n
',,.-

1
1

_ _ _

_
_
_
_
_
_
_
_
_
__.
..._

. 1 2. 1 .

-.

.


.
, ,
.
, .

?
, .
,

.
(
).
L-, . ,
,
.

. , SOAP RESful API.
, ; ,
L (
,
),
. , , ,

282

1 1 1 .

,
.
, .

.
-
. , - .
L-,
, , . ,
,
, .
, , ,
.
.
( "
" " "). ,
, . .
18.
, ,
.
, .
. ,
. ( , ,
),
. - ,
, .

, ,
. .
, ,
(
, , ?). ,
. .
. .
. (

, ),
Pattems of Enterprise
Application Architecture1 , Core J2EE Patterns2

. ,
.
Enterprise Java Beans, , .
, .
,
. Java, , -
, .

' . (. ., "", 2009).


. . . 4 J2.
(. . . . " , 20 1 3).
2

1 2.

283

,
.
.
.

"Woo".
"What's On Outslde"3.
(. ,
). ( 1 . ) (.
. n ).
, , .
.
, -
, .
. .
,
. , ,
,
. ,
, .
,
, "" .


""
.
,
. . . Registry. . Reglstry -
. .
- . .

Registry
,
. , . , , .
- ,
.
Singleton 9. , Singleton
, . .
Singleton. , Singleton -
" ".
Singleton,
. .
Singleton .
( ) .

. " ".

.. .

284

1 1 1 .

, ,

. .
,
. , -
?
,
App l i ca t i onHel p e r .
11

woo \control ler\Appl icationHelper


class Appl icationHelper {
function getOptions ( ) {
i f ( ! f i le_exi s ts ( "data/woo_options . xrnl " ) ) {
throw new \woo\base\AppExcept ion (
" " ) ;
$options
s irnplexrnl_load_fl l e ( "data /woo opt ions . xrnl " ) ;
$dsn = ( string ) $ options->dsn;
11 ?
11 . . .

,
, ?
, ?
-
: -, ,
,
.
. ,
App l i ca t i onHel p e r Context.
- Context
( ) , .
: ,
Context ,
. ,
.
Registry,
.
(Registry) - ,
( , )
( Singleton).
.
"Registry" Pattems ofEnterprise Application
Architecture, , , .
(David Hunt) (David Thomas) h Pragmatic Programmer
Regi s t r y . .
. ,
, .
Registry "Whiteboard" "Blackboard".

1 2.

285

. 1 2. 2 Reg i s t ry , -
Reques t .
r-

>>
-

'f
Registry
1_

+instance ( ) : Regist
+setRequest ( reques t : Reques t )
+getRequest ( )

. 1 2 .2.

.
class Registry {
private static $ instance ;
private $ reques t ;
private function _construct ( ) { )
static function instance ( ) {
if ( ! isset ( sel f : : $ instance ) ) {
sel f : : $ inst ance = new s e l f ( ) ;
return sel f : : $ instance;
function getReques t ( ) {
i f ( i s_null ( $this ->request ) ) {
$ this- >request=new Reques t ( ) ;

function setReques t ( Request $ request ) {


$this->request = $ request ;

11
class Request ( }

Reque s t
$reg = Registry : : ins tance ( ) ;
$reg- >setReques t ( new Request ( ) ) ;
.
$reg = Reg i s t ry : : instance ( ) ;
print_r ( $ reg->getRequest ( ) ) ;
. Reg i s t ry - ( .
Singleton, 9).
Reg i s t r y i n s tance ( ) .

286

111.

, Requ e s t .
. ,
get Reque s t ( ) . Reque st
- . s e t Request ( ) .

.
class Regis t r y (
private static $ instance = nul l ;
private $values = array ( ) ;
private function

construct ( ) { }

static functi on instance ( ) {


i f ( i s nul l ( self : : $ instance ) ) {
sel f : : $ instance = new s e l f ( ) ;
-

return s e l f : : $ ins tance ;


functi on get ( $ key ) {
if
i s set ( $this->values [ $ key]
return $ this->values [ $ key ] ;

return nul l ;
funct ion set ( $ key, $value ) {
$this ->values [ $ ke y ] = $value ;

,
, .
, , , "
".
:
"-". ,
.
, ,
.

. .
. - .
, ,
.
/ / Reg i s t r y . . .
private $ t reeBui lder = nul l ;
private $ conf = nul l ;
//
function t reeBu i l der ( ) {
i f ( i s_nul l ( $this- >treeBuilde r ) ) {
$this->treeBu i l de r
new TreeBui l der (
=

1 2.

287

$this ->conf ( ) - >get ( ' t reedi r ' ) ) ;


return $thi s - >t reeBui lder ;
function conf ( )
i f ( i s_nul l ( $thi s->conf ) ) {
$thi s - >conf = new Conf ( ) ;
return $this ->con f ;
T reeBuilder C o n f - ,
. ,
T reeBui l d e r . Reg i s t r y : : t re e B u i l d e r ( ) ,
.
, Conf,
.
.
i n s t ance ( )
Regi s t ry, .
i n s t ance ( ) , .
stat ic function tes tMode ( $mode=true ) (
nul l ;
sel f : : $ instance
sel f : : $ testmode = $mode ;
static function i nstance ( ) {
i f ( i s_null ( s e l f : : $ i ns tance ) ) (
i f ( sel f : : $testmode ) {
new MockRegi s t r y ( ) ;
sel f : : $ i nstance
else (
new s e l f ( ) ;
sel f : : $ i nstance

return sel f : : $ i nstance;


,
, .
(, )
( ,
).
Registry : : tes tMode ( ) ;
$mockreg = Registry : : instance ( ) ;
1 8 .
" PHPUnit".

,
(scope)
.
. , -

288

111.

. ,
-.
.
,
.
(ID). ki- ,
.
, .
,
.
, ,
.
, ,
.
, Java Perl ( ModPerl
Apache), . ,
, .
.
,
. ,
,
.
. 1 2 . 3 Regi s t ry,
.

Reglstry
lget(key:Stri.ng):
lset()

Jd.zed

RequestReglstry

SesslonReglstry

AppllcatlonReglstry

+instanc e ( ) : RequestRegistry

+instance ( ) : SessionRegistry

+instance ( ) : Applicat ionRegistry

#get(key : String) : ixed

#get(key : String) : ixed

#get(key: String) : mixed

#set(key: String ,value: mixed)

#set (key: String , value : mixed)

#set(key:String, value : ixed)

- +getAaa( ) :

+getBbb ( ) :

+setBbb(bbb : Bbb)

self : : instanc e ( ) ->set ( ' Aaa ' ,


...
,... ,, , ,,,,

-1

+getCcc ( ) :

+setCcc (ccc : Ccc)

Saa

return self: : instanc e ( ) ->get ( ' Aaa

. 1 2..

(protected) , get ( ) set ( ) .


.
(get) (set).
, i s Empt y ( ) , i s Populated ( )
c l e a r ( ) , .

1 2.

289

. ,

. get ( ) set ( ) ,
getAaa ( ) setAaa ( ) , ,
. . ,
.

.
namespace woo \base ;
abstract class Registry
abstract protected funct ion get ( $ key ) ;
abstract protected funct ion set ( $ key, $val ) ;

. , .

, , ,
,
.

.
Reg i s t r y
.
, - .
namespace woo\base;
11. . .

class RequestRegistry extends Reg i s t ry


private $values = array ( ) ;
private static $ i nstance
nul l ;
=

private function _construct ( ) { )


static function ins tance ( ) {
i f ( i s_nu l l ( sel f : : $ ins tance ) ) {
sel f : : $ instance
new sel f ( ) ;
=

return sel f : : $ instance ;


protected function get ( $ key ) {
if
i s s et ( $this->values [ $ key]
return $this- >values [ $ key] ;

) {

return nul l ;
protected function set ( $ key , $val ) {
$this->values [ $ key ] = $val ;
static funct i on getRequest ( )
$inst = sel f : : ins tance ( ) ;
i f ( i s_nu l l ( $ inst->get ( " request " ) ) ) {
$ i nst->set ( ' request ' , new \woo\control ler\Request ( ) ) ;

290

1 1 1 .

return $inst->get ( " reques t " ) ;


.
namespace woo \ba s e ;
// . . .
class SessionRegistry extends Registry
private static $instance = nu l l ;
private function _construct ( )
s e s s i on_s tart ( ) ;
static functi on instance ( ) {
i f ( i s_nul l ( s e l f : : $ instance ) ) {
s e l f : : $ ins tance = new s e l f ( ) ;
return sel f : : $ inst ance ;
protected function get ( $ key ) {
i f ( i sset ( $_SESS ION [ CLASS
return $ SESS I ON [ CLASS

] [ $ key] ) ) {
] [ $ key] ;

return nul l ;
protected funct ion set ( $ key, $val ) {
$_SESS I ON [ CLASS ] [ $ key] = $val ;
funct i on setDSN ( $dsn ) {
sel f : : instance ( ) ->set ( "dsn " , $dsn ) ;
function getDSN ( ) {
return sel f : : ins tance ( ) ->get ( "dsn " ) ;

,
$_S E S S I ON . ,
s e s s i on_ s t a r t ( ) . ,

.
,
. , , , .
namespace woo \bas e ;
// . . .
class Appl icationRegistry extends Registry
private static $ instance
nul l ;
pr ivate $ f ree zedi r = "data " ;
=

1 2.

array ( ) ;
array ( ) ;

private $values
private $rntirnes

private function _construct ( ) ( }


static functi on instance ( ) {
i f ( i s_nul l ( sel f : : $ i nstance) ) {
sel f : : $ ins tance = new sel f ( ) ;
return sel f : : $ instance ;
protected function get ( $ key ) {
$path = $ this->free zedi r . DIRECTORY_SEPARATOR . $ key;
i f ( f i l e_exists ( $path ) ) {
clearstatcache ( ) ;
$rnt irne= f i l erntirne ( $path ) ;
i f ( ! i s set ( $ this ->rntirnes [ $ key] ) ) {
$this->rntirnes [ $ key] =O ;
i f ( $rntirne > $this - >rntirnes [ $key]
$data
file_get_contents ( $path ) ;
$this ->rntirnes [ $ key] =$rntirne;
return ( $thi s->values [ $ ke y ] =unserial i ze ( $ data ) ) ;
=

if

i s set ( $thi s->values [ $ ke y ] ) ) {


return $this->values [ $ key] ;

return nul l ;
protected functi on set ( $key, $val ) {
$this ->values [ $ key] = $va l ;
$path = $this- >freezedi r . DI RECTORY_SEPARATOR . $ key;
file_put_contents ( $path, serial i ze ( $val ) ) ;
$thi s->rntirnes [ $ key] =t irne ( ) ;
stat i c function getDSN ( ) {
return sel f : : ins tance ( ) ->get ( ' dsn ' ) ;
static function setDSN ( $dsn ) {
return sel f : : instance ( ) ->set ( ' dsn ' , $dsn) ;
static function getRequest ( ) {
$inst = sel f : : instance ( ) ;
i f ( i s_null ( $inst->request ) ) {
$inst->request = new \woo\contr o l l e r \Request ( ) ;
return $ inst->reques t ;

291

292

111.


. get ( )
, .
,
.
,
-
. s e t ( ) ,
$ ke y , , .
$mtime s . ,
. , get ( ) ,
$mt imes , ,
.
, getRequest ( )
Reque s tReg i s t ry, ,
.
s e t Reque s t ( ) .
Requ e s t
. ,
Reque s t .
,
.
.
Reque s t
.
, ,
. , Requ e s t
App l i c a t i onReg i s t r y $ re que s t .
, ,
!
.
.
.
namespace woo\base ;
11 . . .

class MemAppl i ca t i onRegistry extends Regi stry (


pr ivate stat ic $instance = nul l ;
p rivate $values=ar ray ( ) ;
pr ivate $ i d ;
private funct ion _construct ( ) { )
static funct ion ins tance ( ) {
i f ( i s_null ( se l f : : $ instance ) ) (
sel f : : $ instance = new self ( ) ;
return sel f : : $ instance ;
protected function get ( $ key )
return \apc_fetch ( $ key ) ;

1 2.

293

protected function set ( $ key, $val


return \apc_s tore ( $key, $val ) ;
static function getDSN ( ) {
return s e l f : : ins tance ( ) ->get ( " dsn" ) ;
static function setDSN ( $dsn ) {
return s e l f : : instance ( ) ->set ( "dsn " , $dsn ) ;

,
. : ,
. .
. ,

. , http : / /php . net /manual / ru /


apc . insta l l at i o n . php.

S e s s i onReg i s t ry, App l i ca t ionReg i s t r y


, : ,
, m
. S e s s i onReg i s t ry,
. App l i c a t i onReg i s t r y
. ,
, . .
.

l
2
l
2
l
2

, 1 ,
2 .
, App l i c a t ionRe g i s t r y
.
: App l i ca t ionReg i s t r y
" ".
. ,
" ".
,
. ,
. ,
, " ".
, , -
. ,
(, ), -

111.

294

. ,
.
, ?
- , . ,

. !
, Appl i c a t i onRe g i s t r y .
Front Controller,
.
.
,
.
App l i ca t ionRegis t r y ,
.
. - ""

s l eep ( )
wakeup ( ) . s l eep ( ) , -:
.
, , . wa keup ( )
. ,
, , , .
_

,
, .
, .
Reg i s t r y .
, , .
, .
.
Regi s t ry. Reg i s t r y
, .


,
,
.
.
.
. -
( ), -
, .
, Smarty.


, .
.

.
, , ,
" ".

1 2.

295

Front Controller
-
. Front Controller

.
Java.
Core J2EE Pattens,
. ,
- , -
, .
. , , Front
Controller. , ,
, Front Controller,
, .

,
. ,
,
.
. .
,
. .
. ,
. .
, .
-
, ,
.


.
.
.

. Frot Controller
. ,
.
command, Command.
. 1 2 . 4 Front Controller.
. ,
, . .
Cont r o l l e r .
namespace woo \control l e r ;
11 . .
class Cont rol ler (
private $app l i cationHelper ;

296

111.

private function _cons t ruct ( ) ( }


static function run ( ) {
$instance = new Controller ( ) ;
$ instance->init ( ) ;
$ instance->handleReques t ( ) ;
funct ion i n i t ( ) {
$app l i cati onHelper
Appl i cationHelper : : instance ( ) ;
$app l i cationHelper->ini t ( ) ;
funct ion handleRequest ( ) {
\woo \base \App l i cationRegi stry : : getRequest ( ) ;
$ request
$cmd_r
= new woo \command\CommandResolver ( ) ;
$cmd
= $cmd_r->getCommand ( $ request ) ;
$cmd->execute ( $ request ) ;

Controller

Command

-3>

+execute ( request : Request )


#doExecute(request:Request}

+run ( )
+init ( )
+handleRequest ( )

1
DoAhlng
#doExecute ( request : Request )

. 1 2.4.

DoAnotherhl ng
#doExecute ( request : Request )

Contro l l e r

Cont r o l l e r
. .
, .
.
run ( ) ; i n i t ( )
handleReque s t ( ) . ,
m
- run ( ) . i n de x . php,
.
require ( "woo/ cont rol ler/Contro l ler . php" ) ;
\woo \control l e r \Control ler : : run ( ) ;
i n i t ( ) han d l e Re que s t ( )
. i n i t ( )
, hand l e Re que s t ( ) -
.
, i n i t ( )
.

1 2.

297

i n i t ( ) App l i ca t io nHelper.
. i n i t ( )
App l icat i onHe lpe r ,
i n i t ( ) . , , ,
.
hand l e Re ques t ( ) CounandRes ol ve r ,
Counand, , Comrnand : : execute ( ) .
Applica ti onelper
Front Controller.
,
. acca App l i c a t i onHe lper.

namespace woo \cont rol ler ;


11 . .
class ApplicationHelper {
private static $instance
nul l ;
private $config = "data /woo_opt i ons . xml " ;
=

private funct ion construct ( ) { )


static function instance ( ) {
i f ( i s_nul l ( self : : $ i nstance ) )
self : : $ instance = new s e lf ( ) ;
return s e l f : : $ instance ;
function init ( ) {
$dsn = \woo\base\Applicati onReg i s t ry : : getDSN ( ) ;
i f ( ! i s_null ( $dsn ) ) {
return ;
$this->get0pti ons ( ) ;
private function getOptions ( ) {
$this ->ensure ( f i l e_exists ( $this ->config ) ,
" " ) ;
$opt1ons = @ S1mpleXml load_f i l e ( $this->config ) ;
$dsn = ( s t ring) $options->dsn;
$this ->ensure ( $options ins tanceof SimpleXMLElement ,
" " ) ;
$this ->ensure ( $dsn, " DSN " ) ;
\woo\base \Appl icat ionRegi s t ry : : setDSN ( $dsn ) ;
/ /
private function ensure ( $ expr , $message ) (
i f ( ! $expr ) {
throw new \woo\base \AppExcept ion ( $message ) ;

298

111.


. , ,

. : App l i ca t i onHelper
,
. . ,
9.
, Appl i c a t i onHel p e r App l i ca t ionRe g i s t ry.
. ,
App l i ca t i onHel p e r ,
. , ,
, (
App l icat i onRegi s t r y
. ).
!
. i n i t ( ) .
App l i ca t ionRe g i s t ry, , -.
Regi s t r y , i n i t ( )
. ,
.
.
. .
- . ,

(, ),
. .
.
. .
. ( -
, - ,
) , getOpt ions ( ) .
. .
. .
DSN . getOp t i o ns ( ) ,
( $con f i g) .
L-
DSN.
. Appl icat ionRegistry Applicat ionHelper

. ,
.
, PEAR
Phig ( 15 1 9).

, App l i ca t ionHelper
. ""
throw
i f ( ! file_ex ists ( $thi s - >config ) ) (
th row new \woo\base \AppExcept ion ( "a " ) ;

1 2.

299

ensure ( )
throw. . .
(
} .
$this ->ensure ( f i l e_ex i s t s ( $this ->con f i g ) ,
" " ) ;
-, .
.
L. ,
. . -
,

( . ).
. . . .
"-",
parse i n i f 1 l e ( ) . ,
L-,
. App l i ca t i onHelper
.
_

Co:mmandResol ver

. ,
,
. . Con t r o l l e r .
.
r .
Front Controller
Counand ( Command 1 1 ) .

URL (. Apache,
URL ,
Counand}.
: cmd.

.
( }.
. (
).
. .
.
" Application Controller".
, .
. ,
.
namespace woo\command;
11 " .
class CommandResolve r (
private static $base_cmd
nu l l ;
privat e static $default_cmd = nul l ;
=

300

111.

funct ion construct ( )


i f ( i s_nul l ( s e l f : : $base_cmd ) ) {
new \ReflectionClass ( " \ woo\ command\Command" ) ;
s e l f : : $base_cmd
sel f : : $ defaul t_cmd
new DefaultCommand ( ) ;
=

function getCommand ( \woo\controller \Request $request ) {


$ request- >getProperty ( ' cmd ' ) ;
$cmd
$ sep = DIRECTORY_SEPARATOR;
if ( ! $ cmd ) {
return s e l f : : $defaul t_cmd;
$cmd=str_replace ( array ( ' . ' , $ s ep ) , " " , $cmd ) ;
$ f i l epath = "woo { $ sep } command { $ sep } { $ cmd } . php" ;
$clas sname = "woo\ \command\ \ $ cmd" ;
i f ( f i l e_exists ( $ fi lepath ) ) {
@ requi re_once ( $ fi lepath ) ;
i f ( class_exists ( $clas sname ) ) {
$cmd_class = new Reflect ionClas s ( $ cl assname ) ;
i f ( $cmd_cl ass->i sSubCl assOf ( s e l f : : $bas e_cmd ) ) {
return $ cmd_class->newins tance ( ) ;
else {
$ request->addFeedback ( " Command ' $ cmd ' " ) ;

$ request ->addFeedback ( " ' $ cmd ' " ) ;


return clone sel f : : $ default_cmd ;

cmd. ,

. getCommand ( )
..
- , getCommand ( )
C ommand.
, , ,
C ommand, ,
.
i f ( $ cmd_class->isSubClassOf ( s e l f : : $base_cmd ) ) {
return $cmd_class->newinstance ( ) ;
C ommand.
namespace woo\ command;
// . . .
abs tract class Command
final function cons t ruct ( ) { }
function execute ( \woo\control ler\Request $ request ) {
$thi s->doExecute ( $request ) ;

1 2 .

30 1

abstract function doExecute ( \woo\contro l l e r\Request $ request ) ;


f i n a l ,
. Command
.
, ,
, . , ,
" $ cmd" .
, - . . / . . / . . / tmp / DodgyCommand . php.
, .
.
,
. ,
, ,
. - -
: ,
- ,
. -
, . . ,
. ,
, ,
. .

,
. , ,
. Reque s t
CommandRe s o l ve r , - Command.

$ REQUE S T ' $ POST $ GET? , , ,
, .
, . ,
, -,
. ,
,
, m
. Registry,
Reg i s t r y .
Reques t - ,
. Request
.
Reque s t .
namespace woo\control l e r ;
11 . . .
class Request (
private $properties ;
private $ feedback = array ( ) ;
funct ion _const ruct ( )

302

111.

$ th i s - > init ( ) ;
function i n i t ( ) {
i f ( isset ( $_SERVER [ ' REQUEST_METHOD ' ] ) ) {
$thi s->p rope rties
$_REQUEST;
return ;
foreach ( $ SERVER [ ' argv ' J as $arg )
i f ( s t rpos ( $arg, ' = ' ) ) {
l i s t ( $ key, $val ) = explode ( "=" , $arg ) ;
$this ->setProperty ( $key, $val ) ;

function getProperty ( $ key ) {


i f ( isset ( $this->properties [ $ key ] ) ) {
return $this ->properties [ $ key] ;
return nul l ;
function setProperty ( $ key, $val )
$this- >propert i es [ $ key] = $val ;
funct ion addFeedback ( $msg ) {
a r ray_push ( $ th i s ->feedback, $ms g ) ;
function getFeedback ( ) {
return $this- > feedback ;
function getFeedbackString ( $ separator= " \ n " ) {
return implode ( $ separator , $this->feedback ) ;

,
. i n i t ( ) $prope rtie s .
, .
-. ,
.
Requ e s t ,
- g e t Prop e r t y ( ) .
, (
$prope r t i es).
s e t Prope r t y ( ) .
$ feedb a c k . ,
- .

12.

303

Counad, 1 1 Command
, .
,
Counad.
amespace wo o\commad ;

11 . . .
c l a s s De faul tCommad extends Commad {
fuction doExecute ( \wo o \ cotro l l e r \Request $ reque s t )
$ reque s t - >addFeedback (

" Woo ! " ) ;

include ( "woo /vi ew/ma i n . php" ) ;

Counand CounandRe s o l v e r ,
Counand.
, , , Counand
execute ( ) , doEx e c u t e ( ) ,
.
, .
e x e c u t e ( ) Reque s t ,
, , s e t F e e db a c k ( ) .
D e f aul t C ounand
.
,
i n c l ude ( ) . C ounand

,
. " Application
Controller".
mai . php L- g e t Fe e dba c k ( )
Reque s t ,
( ).
, . .
-

<html>
<head>
< t i t l e >Woo !

Woo ! < / t i t l e>

< / h ead>
<body>
<t>
<tr>
<td>
Woo !
< / td>
< /tr>
< / t >
< /body>
< / html >

, , ,
. ,
.

304

111.

. .
Frot Controller. . 1 2. 5
, .
AppllcatlonHelper

CommandResolver

initO
getCommandO
-

1-

. 1 2. 5 .

executeO

Front Controller

, Front Controller App l ication


Helper ( ,
). Cont r o l l e r Command ComrnandRes o l ver.
Command : : e xecute ( ) ,
.
Comrnand
.
.

Front Controller - .
,
. (
Front Controller )
. .
Front Controller . ,
.
,
.
- .
.
. Front Controller
, .

. -
.
. .
, .
.
-, , . -

1 2.

305

.
. ,
,

. , m
App l i c a t i onRegi s t r y ( ).
Front Controller ,
. ,
,
( ).
.
Front Controller .
,
Counand .

. Front Controller ,
( , ),
,
, .
.

Application Controller
,
, . I
,
.
Application Controller ( )
.
,
, .
, -,
. Counand,

(Command) .

.
(Venue) (Space).
AddVenue AddSpace.
, ,
( cmd=AddVenue ) (AddVenue) .
. AddVenue
AddSpace.
, AddVenue
AddSpace. AddSpace
, .

: -
(" , . . . ). ,
,
"

306

111.

Counand ( ,
, ).
,
. ,
AddVenue ,
(,

). ,
,
.
!
,
Counand, ,
.. ,
.

, - . ( ), Frot Controller ,
,
.
. 1 2.6.

Fronteontroller

>

AppController

+handleRequest ( )

+getCommand ( ) : Command

+invokeView()

+getView( ) : St ring

while ( Scoamand

SappController->getCommand( )

!:::.

) {

Sco11111and->execute( Srequest ) ;

Sview

SappController->getView( ) ;

. 1 2 . 6 . Application Controller

, , -
; Front
Cont r o l l e r . .
- . ,
, , ,
, , .
,
.
Fron tCon troller

FrontCont r o l l e r AppCon t ro l l e r (
, ).
namespace woo \cont rol l e r ;
// . . .
function handleRequest ( ) {

1 2.

$ request
$_

307

\woo\base \ApplicationRegi stry : : getReques t ( )


\woo\base \Appl icationRegi s t ry : : appCont roller ( ) ;

whi le ( $cmd = $ app_c->getCommand ( $ reques t ) ) (


$cmd->execute ( $ request ) ;
$this->invokeView ( $app_c->getView ( $ request ) ) ;
function invokeView ( $ ta rget ) {
include ( "woo/view/$target . php" ) ;
exi t ;
, I Front Cont
roller , Command
. AppCont r o l l e r
, . ,
AppCon t r o l l e r ,
Reque s t .
- cmd
- ?

Command, ,
. AddVenue
. ,

. ,
Command, , AddSpace.
Command ,
. ,
(
Command}.
private static $STATUS_STRINGS =
=>
' CMD DEFAULT '
=>
' CMD '
' CMD ERROR '
=>
' CMD INSUFFICIENT DATA ' =>
);

array
,

1,
2,
3

Command,
Reque s t . Command
. Command
, ,
-
- .
r

,
, .
.

308

1 1 1 .

<cont rol>
<view>main< /view>
<view status="CMD OK" >main< /view>
<view status="CMD_ERROR" >error< /view>
<command name= "ListVenues " >
<view> l i s tvenues</vi ew>
< /command>
<command name="QuickAddVenue " >
<classroot name="AddVenue" />
<view>quickadd< /vi ew>
< /command>
<command name= "AddVenue " >
<view>addvenue< /view>
< status value="CMD ">
<forwa rd>AddSpace< / forward>
< / s tatus>
</ command>
<command name="AddSpace " >
<view>addspace< /view>
<st atus value= "CMD ">
<forward>ListVenues</ forward>
< / s t atus>
</ command>
< / control >
L-

Comrnand. cont r o l .
.
. comrnand.
, , view,
, .

( , Command) .
.
Comrnand, .
, , .
_,
"" , ,
.

.
Comrnand ( ),
ComrnandRe s 1 ve r . . cmd
AddVenue, .
" AddVenue " AddVenue . php.
, . ,
cmd Qui c kAddVenue , .

1 2.

309

<cornmand narne="QuickAddVenue ">


<class root narne="AddVenue " />
<view>quickadd< /view>
< /cornmand>
Qui c kAddVenue .
c l a s s ro o t .
AddVenue .
cornrnand .
. , . view
cornrnand, , cornrnand
.
<cornmand narne="AddVenue " >
<view>addvenue</vi ew>
<status value= "CMD " >
< forward>AddSpace < / forward>
</status>
</ cornmand>
, addvenue AddVenue (,
, cmd Reque s t ) .
, addvenue . php
AddVenue. . s t a t u s . AddVenue
CMD_. Cornrnand
.
s tatus .
.
forward.
.


.
.
. App l i ca t i onHelper
.
.
Narnespace woo\cont rol ler;
// . . .
pr ivate function getOpt ions ( ) (
$this->ensure ( f i l e_exists ( $ this ->config ) ,
" " ) ;
$opt1ons = @s1rnplexrnl load_file ( $this ->config ) ;
11 . . . DSN . . .
$map = new Control lerMap ( ) ;
foreach ( $opt ions ->cont rol ->view as $defaul t_view ) {
$stat_s tr = trirn ( $default_view [ ' status ' ] ) ;
$ status = \woo\cornmand\Cornrnand : : statuses ( $ stat_s tr ) ;
$rnap->addView ( ( s tring) $de faul t_view, ' defaul t ' , $ s tatus ) ;

111.

1 1 . . . . .
\woo\base\Appl i cationReg i s t ry : : setControl lerMap ( $rnap ) ;
.

L-,
SimpleXL, - ,
. I, , -
getOp t i on s ( ) ,
- App l i ca t i onReg i s t ry.

, Cont r o l l e rMap. ,
. ,
, Cont r o l l e rMap ,
.
Cont r o l l e rMap.
narnespace woo\control l e r ;
11 . . .
class Control l e rMap {
private $viewMap
private $ forwardMap
private $class rootMap

array ( ) ;
a r ray ( ) ;
array ( ) ;

funct ion addCl assroot ( $ cornrnand, $classroot ) {


$this->clas srootMap [ $ cornrnand] = $classroot ;
funct ion getClassroot ( $ cornrnand ) {
if
i s s et ( $this->cl ass rootMap [ $cornrnand]
return $ th i s - >class rootMap [ $cornrnand ] ;

) {

return nul l ;
function addVi ew ( $view, $ cornrnand= ' default ' , $ status=O ) {
$this->vi ewMap [ $cornrnand ] [ $ status ] =$view;
function getView ( $cornrnand, $ status ) {
if
i s s et ( $this->viewMap [ $cornrnand] [ $ status ]
return $ th i s - >viewMap [ $cornrnand ] [ $ status ] ;

return nul l ;
functi on addForward ( $ cornrnand , $ status=O , $ newCornrnand ) {
$ thi s-> forwardap [ $ cornrnand] ( $ status] =$newCornrnand;
funct ion getForwa rd ( $ cornrnand , $ s tatus ) {
i sset ( $ thi s->forwardap [ $cornrnand] [ $ s tatus ]
if
return $ th i s ->forwardap [ $cornrnand] [ $status ] ;
return nul l ;

1 2.

31 1

$ c l a s s r o otMap - ,
(..
) Command (.. AddVe nue ,
\ wo o \ c omma n d \AddVenue).
, cmd .

addCl a s s ro o t ( ) .
$ fo r w a r dap $ v i e wMap
.
.
< command name="AddVenue " >
<vi ew>addvenue< / v i ew>
< s tatus value= " CMD " >
< fo rward>AddSpace< / fo rward>
< / s tatus>
< / c ommand>


$ v i ewMap .
$map->addView (

' addvenue ' ,

) ;

' AddVenue ' ,


$map - >addForward (

' AddVenue ' ,

1,

' AddSpa ce '

$ fo rwa rdMap.

) ;


.
, AddVenue " CM D_ OK" ( 1 ,
" CM D_ DEFAULT ").
$ fo rw a rdMap
.
, .
$viewMap [ ' AddVenue ' ] [ 1 ] ;

/ / AddVenue CMD_OK [ ]

$vi ewMap [ ' AddVenue ' ] [ 0 ] ;

// AddVenue CMD DEFAULT

$viewMap [ ' de fa u l t ' ] [ 1 ] ;

/ / Defaul tCommand CMD

$viewMap [ ' de f aul t ' ] [ 0 ] ;

/ / De faul tCommand CMD DEFAULT


.
.
name space woo\contr o l l e r ;

11 . . .
c l a s s AppCont r o l l e r

pr ivate s t a t i c $bas e_cmd = nul l ;


p r ivate s t a t i c $defaul t_cmd = nul l ;
p r ivate $cont ro l l erMap ;
private $ i nvoked = a r r ay ( ) ;
function _construct ( Contro l l e rMap $map )

$ th i s - >cont r o l l e rMap = $map;


if

i s_nu l l ( s e l f : : $base_cmd )

se l f : : $base_cmd

= new \ R e f l e c t ionC l a s s (

" \woo \command\Command"

) ;

1 2

111.

sel f : : $defaul t_crnd

new \woo\cornrnand\DefaultCornrnand ( ) ;

funct ion reset ( ) {


$this->invoked = array ( ) ;
functi on getView ( Request $ req ) {
$view = $this->getResource ( $ req, "View" ) ;
return $view;
private function getForward ( Request $ req ) {
$ forward = $this->getResource ( $ req, " Forward" ) ;
i f ( $ fo rward ) {
$ req->setProperty ( ' crnd ' , $ fo rward ) ;
return $ forward;
private function getResource ( Request $ req, $res ) {
1 1
$crnd_s t r = $req->getProperty ( ' crnd ' ) ;
$previous = $ req->getLastCornrnand ( ) ;
$ status
$previous - >getStatus ( ) ;
=

i f ( ! isset ( $ s tatus ) 1 1 ! i s_int ( $ status ) ) ( $ status = ; }


$acquire = "get$res " ;
$ resource
$this->cont r o l l e rMap- >$acqui re ( $ crnd_s t r , $s tatus ) ;
=

11

i f ( i s_nul l ( $resource ) ) {
$ resource = $this->cont rol l e rMap->$acqui re ( $crnd_s t r , ) ;
11

if

11
11

' defau l t '


i s_nul l ( $ resource ) ) {
$ resource = $this->cont r o l l e rMap->$ acqui re ( ' de faul t ' , $ s tatus ) ;

' defaul t ' ,

i f ( i s_nu l l ( $ resource ) ) {
$ resource = $this->contr o l l e rMap->$acqu i re ( ' default ' , ) ;
return $ resource ;
function getCornrnand ( Request $ req ) {
$previous = $ req->getLastCornrnand ( ) ;
i f ( ! $previous ) {
11
$crnd
$ req- >get Property ( ' crnd ' ) ;
i f ( i s_null ( $crnd ) ) {
=

1 2.

31 3

11 ' cmd ' , ' de faul t '


$ req- >setProperty ( ' cmd ' , ' default ' ) ;
retur sel f : : $de faul t_cmd ;

else {
//
$ cmd = $this ->getForward ( $ req ) ;
i f ( i s_nul l ( $cmd ) ) { return nul l ; }
}
/ / $ cmd
/ / Command
$cmd_obj = $ this->reso lveCommand ( $ cmd ) ;
i f ( i s_nul l ( $ cmd_obj ) ) (
throw new \woo\base \AppException (
" ' $cmd ' " ) ;
$cmd_class = get_class ( $cmd_obj ) ;
i f ( i s set ( $ th i s - >invoked [ $ cmd_cl a ss ] ) ) (
throw new \woo\base \AppException ( " " ) ;
$ this-> ivoked [ $ cmd_clas s ] = l ;
/ / Command
return $cmd_obj ;
fuctio resolveCommand ( $cmd ) (
$classroot = $this ->control l erMap->getClassroot ( $ cmd ) ;
$ f i lepath = "woo/commad/$classroot . php" ;
$clas sname = " \woo\command\ $classroot " ;
i f ( f i l e_exists ( $ f i l epath ) ) (
require_once ( " $ fi lepath" ) ;
i f ( class_exi sts ( $classname ) ) (
$cmd_class
new Ref l ectionCl ass ( $classname ) ;
i f ( $cmd_class->i sSubClassOf ( sel f : : $base_cmd ) ) {
return $cmd_class ->newinstance ( ) ;
=

return nul l ;

getResource ( )
. getView ( ) get Forward ( ) .
, -
.
getCommand ( ) ,
. .
cmd,
.
Reque s t . cmd .
Command.
$ cmd r e s o l veCommand ( ) .
Command.

314

1 1 1 .

getCounand ( ) ,
Requ e s t Counand, .
getCounand ( ) , - ,
Command (
g e t Forward ( ) ). get Forward ( ) ,
, Command
.
- getCounand ( ) :
,
. $ invoked,
Counand. ,
. , .
,
. , , .
,
, ; ,
. . 1 2. 7 ,
Front Controller
Command, - .

ApplicatlonRegistry

AppController()

AppController

<E - - - - - getCommand()

<- - - - - - - !
1

execute()
getView()
1

<- - - - - - - - - - - - - - -

. 1 2. 7.


Comrnand

, , AppCon t r o l l e r
, Requ e s t .
Counand.
namespace woo\command;
// . . . .
abstract class Counand
private static $ STATUS STRINGS

a rray (

1 2.

' CMD
' CMD
' CMD
' CMD

DEFAULT '
'
ERROR '
I NSUFFICIENT DATA '
);
private $ status = ;

=>
=>
=>
=>

31 5

1,
2,
3

final function _cons t ruct ( ) { }


function execute ( \woo\ cont r o l l e r \ Request $ request ) {
$ this ->s tatus = $this->doExecute { $ request ) ;
$ request->setCommand { $this ) ;
function getStatus ( ) {
return $this->status ;
static function statuses { $ s tr= ' CMD_DEFAULT ' ) {
i f ( isset ( sel f : : $ STATUS_STRINGS [ $ s t r ] ) ) (
11
return sel f : : $STATUS_STRINGS [ $ s t r ] ;
throw new \w \s \ t i n ( " : $ str " ) ;
abst ract function doExecute ( \woo\ cont rol l e r \Request $request ) ;
Command (
). s t a t u s e s { ) ,
( " CMD_OK")
, g e t S t atus ( ) -
Command. s t a t u s e s ( )
,
. execut e ( )
doExe cut e ( ) ,
Reques t .

AddVenue.
narnespace woo \command;
11 . . . .
class AddVenue extends Command {
function doExecute ( \woo\cont r o l l e r \ Request $ reques t ) {
$name = $ request->getProperty ( "venue_name " ) ;
i f { i s_nul l ( $name ) ) {
$reques t- >addFeedback { " " ) ;
return s e l f : : statuses ( ' CMD_INSUFFICI ENT_DATA ' ) ;
else {
$venue_obj = new \woo \domain \Venue ( nul l , $name ) ;
$ request->set0bj ect ( ' venue ' , $venue_obj ) ;
$ reques t- >addFeedback { " ' $ name ' ( { $venue_obj ->geti d ( ) } ) " ) ;
return s e l f : : statuses ( ' CMD_OK ' ) ;

1 6

111.

.
Venue, .
namespace woo\doma in;
class Venue {
private $ id;
private $name ;
function _const ruct ( $ i d , $name ) {
$ this->name = $name;
$this->id = $ i d ;
function getName ( ) {
return $this->name;
function get id ( ) {
return $this->id;

. h, , - doExecute ( )
,
. , ,
, . ,
L- ,
" CMD_" .
AddSpace. .
" cmd=AddVen ue " .
" cmd=Qui ckAddVenue " . .
qui ckaddvenue.
.
Venue . .

Application Controller
.
. .
. .
, .
. - .
,
. .
- .
.
.
. .
. .

1 2.

1 7


, .
. .
.

Page Controller
Front Controller, -
.
- . .
Page Controller. , , ,
. .

.
, .
.
.
,
,
, Page Controller
.
, ,
Woo .
, Page Controller
. , .
, ;
.
,
, .
-
. , .

Page Controller ,
.
. ,
, ,
(.. .
).
Page Controller.
< ?php
requi re_once ( "woo/doma in /Venue . php" ) ;
try {
$venues = \woo\domain\Venue : : findAll ( ) ;
catch ( Exception $ ) (
incl ude ( ' error . php ' ) ;
exit ( O ) ;
11

1 8

1 1 1 .

?>
<htrnl>
<head>
< t i t l e>aee</title>
< /head>
<body>
<hl>< /hl>
< ?php foreach ( $venues as $venue ) { ?>
< ?php
print $venue->ge tNarne ( ) ; ? > <br / >
< ?php } ? >
</body>
< /htrnl >
L- . -
, -
.
, .
( ,
" ",
" " 1 3). -
Venue ,
$venues .
,
e r ro r . php i n cl ude ( ) ,
e x i t ( ) ,
.
.
,
. i n c l ude ( ) ,
, L- (. 1 2 . 8).

>>
- - - - - -

. 1 2.8. Page Controller,

, Page Controller
, , ,
, .
Page Cotroller .
,
PageCont r o l l e r .
narnespace woo\cont r o l l e r ;
11 . . .
abstract class PageControl l e r
abs tract functi on process ( ) ;

1 2 .

319

function forward ( $resource ) {


include ( $ res ource ) ;
exit ( ) ;
function getRequest ( ) {
return \woo\base\Appl icationRegi stry : : getReques t ( ) ;

, ,
Reque s t App l i ca t i onRe g i s t ry. PageCo n t r o l
l e r - Re que s t
. ,
.

, , .
, , .
PageCont r o l l e r ,
.
namespace woo \contro l l e r ;
11 . . .

class AddVenueControl ler extends PageController {


function process ( ) {
try {
$ request = $ this- >getReques t ( ) ;
$name = $ request->get Property ( ' venue name ' ) ;
i f ( i s_nul l ( $ reques t - >get Property ( ' submi tted ' ) ) )
$ reques t->addFeedback ( "Bepe " ) ;
$this-> forward ( ' add_venue . php ' ) ;
e l se i f ( i s_nul l ( $name ) ) {
$ request->addFeedback ( " " ) ;
$this->forward ( ' add_venue . php ' ) ;
)

1 1 ,
11
$venue = new \woo\domain\Venue ( nul l , $name ) ;
$thi s - >forward ( " L i s tVenues . php " ) ;
catch ( Exception $ ) (
$ this->forward ( ' error . php ' ) ;

$controller = new AddVenueContro l l er ( ) ;


$controller->proces s ( ) ;
AddVenueCont r o l l e r p r o c e s s ( ) ,
.
,
(add_venue . php) , .
, f o rward ( ) ,
Li s tVenu e s .

320

111.

, .
,
, -
.
, AddVenueCont r o l l e r .
< ? php
requi re_once ( "woo/base /Regi s t r y . php" ) ;
$ request = \woo\base\Appl i cationRegistry : : getRequest ( ) ;
?>
<html>
<head>
< t i t l> < / t i t l >
</head>
<body>
<hl > < /hl>
<t>
<tr>
<td>
<?php
print $ request->getFeedbackString ( " < /td></t r><tr><td> " ) ;
?>
< /td>
< / t r>
< / t>
<form acti on="AddVenue . php" method= " get ">
< input type="hidden " name= "submi tted" value=" yes " / >
<input type="text" name= "venue_name " / >
< / form>
</body>
</html>
, ,
.
PageCon t r o l l e r , . :
PageCont rol l e r .
. 1 2.9 Page
Controller.

: ,
-.
.
, " S e rv e r e rr o r " " Page not found"
.
,
Page Controller,
.
, , -
. ( PageCon t r o l l e r)

1 2.

32 1

.
, . , ,
AddVenue ,
.
L i s tVenues. ,
, - .
- ,
.

PageCDntrol/er
+process ()
+forward ( )

AddVenue '- - - ;:>


+process ( )
1

1
UstVenues
+process ( )
1

. 1 2.9. PageControl ler

(PageCont roller)
Command, ,
Front Controller. Front Controller ,
, Page Controller .
,
Command, .
,
Command.
,
.
, ,
. ,
Front Controller, , , ,
.
,
-
( -
). ,

.
Page Controller Front Controller.
, PageCont roller.
, , ,
.
Page Controller .

322

1 1 1 .

,
,
Front Controller.

Template View View Helper


Thmplate View ,
( . L-
, . - -). .
, . . .
.
.
-
. .
!
View Helper (
) ,

. .
.

SQL-
, . "
" , .
-, .
.
.
, ,
.
.
, ,
. ,

. , ,
.
.
,
. .
.
, ,
,
. ,
.
,
,
. .
.
, View Helper
.

1 2.

323

,
. ,
, ,
.
1emplate View .
, ,
.
, ,
. .
Smarty.
, .
- ,
. View
Helper, .
Reque s t - ,
.
View Helper.
namespace woo\view;
11 . . .
class ViewHelper {
static functi on getRequest ( ) {
return \woo\bas e \App l i cationRegi s t ry : : getRequest ( ) ;

, , - Reques t .

. ,
, , View Helper.
View Helper
, .
, View Helper,
Reque s t .
< ?php
require_once ( "woo/view/Vi ewHelper . php" ) ;
$ request = \woo\view\ViewHelpe r : : getRequest ( ) ; / /
$venue = $ request->get0bj ect ( ' venue ' ) ; / /
?>
<html>
<head>
<titl> ' < ?php echo $venue- >getName ( ) ?> ' </title>
</head>
<body>
<hl> ' < ?php print $venue->getName ( ) ?> ' </hl>
<t>
<tr>
<td>
< ?php print $ request->get FeedbackString ( "< /td>< /tr><tr><td> " ) ; ?>

324

111.

< /td>
</tr>
</ t>
<form method="post " >
< input type=" text "
value= " < ?php echo $ request->getProperty ( ' space_name ' ) ?>"
name="space_name " / >
<input type="hidden" name="venue_id"
value="<?php echo $venue->getid ( ) ?>" />
<input type="submi t " value=" submi t " />
< / form>
< /body>
< /html>
( a dd_space . php) Request
V i e wH elper,
L-. , g e t Fe edback ( )
, , getOb j e c t ( )
, - .
g e t P rope r t y ( ) ,
. , Venue Request
. Appl i c a t i onRe g i s t ry
, Reque s t , AddVenue,
, Venue Reque s t .
,
, ,
. p r i n t .
- .
i f .
V i e wHelpe r ,
. , (
, , ,
) 1emplate View. m
, , , .

, ,
. ,
, .
.
: " , ,
, fl. .
, ,
. ,
, , .
,
.

1 2.

325

Reque s t : : ge tObj ect ( ) . . ,


.
, ,
View
Helper - .
Reques t , S e s s i onReg i s t r y
App l i c a t i onRe g i s t r y .
. ,
. .
, .
View Helper.
.
View Helper .
( Facade).
. Facade 10.

Sessio
Facade ( ).
Service Layer,
.



, ,
, . .
"",
. L- .
,
. ,
.
-
. , , ,
. , .
.
.

Transaction Script
. Pattems of Enterprise Application Architec
ture. , . ,
,
. ransaction Script ,
.
. - ,
, .
,
- .

326

111.

- . ,
,
. ,
. ,
, , Facade.
.
( )
. , ,
.
.

.
- ,
. . ransaction
Script ( ,
),
.

, , ,
. , -
, .
.
Transaction Script (
).

.
:

venue, space
eve n t . venue () space () (,

, - ..)
.

CREATE TABLE ' venue ' (


' id '
int ( l l ) NOT NULL auto_increment ,
' name ' tex t ,
PRIARY ( ' id ' )
CREATE TABLE ' space ' (
' id '
i nt ( l l ) NOT NULL auto_increment ,
' venue ' int ( l l ) defaul t NULL ,
' name ' text,
PRIARY ( ' i d ' )
CREATE TABLE ' event ' (
' id '
int ( l l ) NOT NULL auto_increment ,
' space ' int ( l l ) defau l t NULL ,
' start ' mediumtext ,

1 2.

327

' duration ' int ( l l ) default NULL ,


' name ' text ,
PRIARY ( ' id ' )
,
(venue ) , ( event ) . .
(
Command, 1 1 ).
,
. . 1 2 . 1 0 .
\\sss \s
+prepareStatement ( stmt : String)
+doStatement ( stmt : St ring, values : ar ray)

\woo \process \VenueManager


+addVenue ( name : St ring , s pace_array : a rray)
+bookEvent (venue_id : int , name : St ring , time : int , du ration : int )

. 1 2. 1 . Transaction Script n

?
, ,
. ,
-
.
( Layer Supertype),
, .
,
. .
.
PDO.
.
.
namespace woo \proces s ;
11 . . .
abstract class Base (
static $DB;
static $ statements = array ( ) ;
function _construct ( ) (
$dsn = \woo\base \App l i cationRegis t ry : : getDSN ( ) ;
i f ( is_nul l ( $dsn ) ) (
throw new \woo \base \AppExcept ion ( " DSN " ) ;
sel f : : $DB = new \ PDO ( $dsn ) ;
sel f : : $ DB- >setAttribute ( \ PDO : : ATTR_ERRODE, \ PDO : : ERRODE_EXCEPTION ) ;
function prepareStatement ( $statement ) {

328

1 1 1 .

if

i s set ( sel f : : $ statements [ $s tatement }


return sel f : : $ s tatements [ $statement } ;

) {

$ s tmt_handle
s e l f : : $ DB->prepare ( $ statement ) ;
sel f : : $ statements [ $ statement } =$ s tmt_handle;
return $ s tmt handle;
=

pu i c funct ion doStatement ( $ s tatement , a rray $values ) {


$ s th = $ th i s - >p repareStatement ( $ s tatement ) ;
$ s th->closeCurs or ( ) ;
$db_result = $ s th->execute ( $values ) ;
return $ sth;

Appl i ca t i on Re g i s t r y , DSN,
PDO.
preparestatemen t ( ) prepare ( ) PDO,
. , ,
execute ( ) .
$ s t at ement s .
SQL-oepaop.
p r ep a r e S t a t emen t ( )
, , doS t atement ( ) .
SQL-oepaop ( ).
,
. SQL-
prepar e S t atement ( ) , .
PDOSt a tment : : execute ( ) . ,
. ,
. , , - SQL-
.
VenueMa nage r , SQL
.
namespace woo\proces s ;
// . . .
class VenueManager extends Base {
static $add_venue
" I NSERT INO venue
( name )
va lues ( ? ) " ;
" INSERT INO space
static $add_space
( name, venue )
values ( ? , ? ) " ;
static $check_slot
" SELECT id, name
FROM event
WHERE space = ?
AND ( s tart+duration) > ?
AND start < ? " ;
static $add_event
" I NSERT INO event
( name , space, start, durati on
values ( ? , ? , ? , ? ) " ;
// . . .

1 2 .

329

. SQL-
. prepare ( ) PDO.
- ,
execute ( ) .
,
.
function addVenue ( $name , $ space_array )
$venuedata = array ( ) ;
$venuedata [ ' venue ' ]
array ( $name ) ;
$thi s->doStatement ( s e l f : : $add_venue, $venuedata [ ' venue ' ] ) ;
$v_id = se l f : : $DB->lastinsertid ( ) ;
$venuedata [ ' spaces ' ] = array ( ) ;
foreach ( $ space_array as $ space_name ) {
$values
array ( $space_name , $v_id ) ;
$this->doStatement ( s e l f : : $ add_space, $values ) ;
$ s_id
self : : $ DB->l astinsertid ( ) ;
array_unshift ( $values , $s id ) ;
$venuedata [ ' spaces ' ] [ ]
$ values ;
=

return $venuedata;
, addVenue ( )
(space). , (venue) (space).
, ,
(ID) .

. ,
, doSta tement ( ) . , ,
. ,
, doS t atement ( ) (-
) prepa reStatement ( ) , .
, ,
.
venue,
$ space_a r ra y, space .
, space
.
.
.
function bookEvent ( $ space_id, $name , $ time , $duration ) {
$values
array ( $ space_id, $ t ime , ( $t ime+$duration) ) ;
$ s tmt
$this ->doStatement ( s e l f : : $check_s l o t , $va lues , false )
i f ( $ result
$ s tmt- >fetch ( ) ) {
throw new \woo \base\AppException (
" ! " ) ;
=

$thi s->doStatement ( s e l f : : $add_event ,


array ( $ name , $ space_id, $ time, $duration ) ) ;
- event s , .
, SQL-,

330

1 1 1 .

$ check_s l o t , ,
.

'Itansaction Script -
. ,
, , .
, ,
, ,
.
'Itansaction Script
.
, .
, ,
. Domain Model (
). , ,
, .
Transaction Script
, , .
, ,
, , . ,
, .

. , ,
. ,
,
- .

Domain Model
Domain Model - ,
, , .
, . -
, -,
,
.
,
. Domain Model -
. Domain Model
. - .
. Domain Model ,
, , . , - .

'Itansaction Script, , , ,
,
.
( ),
.

1 2 .

33 1

Domai Model
.
,
, Space Eve n t .
: Space : : boo kEvent ( ) .
, , Event : : i n t e r s e c t s ( ) ..
. , Woo, 1ansaction Script
. ,
. . .. Domain Model,
.
.
.

Domai Model .
. ,
" , .. .
Domain Model -
, .
.
- Domain Model
. ,
. .
, Domain Model
,
. , . 1 2 . l l .
Woo .

-t>

OonulnO/tlCf
+getld ( )

Venue

+getName ( ) : String
+getSpaces ( ) : SpaceCollection
+addSpace ( space: Space)

Space
+getNa111e ( ) : String
+bookEvent (event : Event)

Event
+getName ( ) : String
+intersects (event : Event )

. 1 2. 1 1 . Domai Model

. 1 2 . 1 1 ,
1ansaction Script.

332

111.

, ,
, .
. ,
, ,
.
, Domain Model ,
, - .
, ,
,
.
.
Venue .
namespace woo\doma i n ;
abstract c l a s s Domai nObj ect
private $ id;
function
const ruct ( $ i d=nu l l ) {
$this->id = $id;
function getid ( ) {
return $ th i s - >id;
static function getCo l l ection ( $ t ype ) {
return array ( ) ; / /
funct i on col l ection ( ) {
return sel f : : getCol l ect ion ( get _class ( $this ) ) ;

class Venue extends DomainObj ect {


pr ivate $name ;
private $ space s ;
functi on construct ( $ i d=nul l , $name=nul l ) {
$thi s - >name = $name ;
$this- >spaces = sel f : : getCo l l ection ( " \ \woo \ \ doma i n \ \ Space" ) ;
parent : : const ruct ( $ i d ) ;
funct ion setSpaces ( SpaceCol l ection $ spaces ) {
$this- >spaces = $ space s ;
function getSpaces ( ) {
return $this- >space s ;
funct ion addSpace ( Space $space )
$this->spaces->add ( $ space ) ;

1 2.

333

$space->setVenue ( $this ) ;
function setName ( $name_s ) (
$this- >name = $name s ;
$this->ma rkDi rty ( ) ;
function getName ( ) (
return $this- >name ;

, ,
.
SpaceCo l l e c t i on, Space,
Venue. ( , ,
, - , ,
!)
, Space,
. ,
.
$this->spaces

sel f : : getCol lection ( " \ \woo \ \ doma i n \ \ Space " ) ;

,
.
. , venue Space.

.
,
, . , Space
Space, Even t .

$ i d,
. , , $ id
. ,
, ma r k D i r t y ( ) (
, Unit ofWork).

Domain Model -.
. .
.
. .
, .
(Domain Model). - .
. (, ,
) .
.

.
( , .
SQL-). -

334

111.

, Jiacc ,

.


( ).
. Ji .
, , , .
, . ,
, ,
, . ,
, ,
, ,
.
!
,
(mapper), .
, ,
.

1 3

1'


)/J

@@@
----

-
, m.
.
.
238 80-90-
. , ,
-. .
.
.

: ,
.

n: , ,
.

I : . , .

: ,
.

:
Abstract Factory.



. , -
. -
, . ;
. , .
,
r
. .
.

336

111.

. ,
. ,
. , (Clifton Nock),
(Martin Fowler), (Deepak Alur) .

Data Mapper
, " Domain Model" 12
Venue .
. Data Mapper
Core J2EE Pattems' ( Data Access Object)
Pattems of Enterprise Appli.cation Architecture2. Data
Access Object - ,
.
, .
, Data Mapper - ,
.

.
, - ,
. ( )
. ,
.
,
, -
.
,
.

( ).
? - (
), ,
(Domain Model) " "
.

,
Mappe r , .
Mappe r .
.
. 1 3 . 1 Mapper .
. S p a ce
Venue, SpaceMapper Venue
Mapp e r . .
1 . . R. J2.
(. . . . ", 20 1 3).
2

. (. . . "", 2009).

1 3.

337

,
. ,

.
.

Mapper
+find(id : int) : DomainObject
+findll ( ) : Collection
+createObject (fields : array) : DomainObject
+insert (obj : DomainObject)
+update(obj:DollainOject)
#doinsert(oj:DollinOject)
#doCreateOject(fields:array): DollinOject
#selectStllt(): POOState11ent
#selectAllStmt(): POOStatement

f
1

SpaceMapper
+update(obj : DomainOject)
#doinsert(obj : DomainOject)
#doCreateObject (fields : array) : DomainObject
#selectStmt ( ) : PDOStatement
#selectAllStmt( ) : PDOStatement

Eventapper

VenueMapper
+update(obj : DomainObject)
#doinsert(obj : DomainOject)
#doCreateObject(fields : array) : DomainObject
#selectStmt ( ) : PDOStatement
#selectAllStmt ( ) : PDOStatement

+update(obj : DomainObject)
#doinsert (obj :DomainOject)
#doCreateObject(fields : array) : DomainObject
#selectStmt ( ) : PDOStatement
#selectAllStmt ( ) : PDOStatement

. 1 3. 1 . Mapper


, Thmplate Method
( , i n s e r t ( ) , ,
doinsert ( ) ..). , ,
.
Mapper .
namespace woo\mapper ;
// . . .

abs tract class Mapper {


protected static $ PDO ;
construct ( )
function
i f { ! isset ( s e l f : : $ PDO ) ) {

338

111.

$ dsn = \woo \base\Appl icati onRegistry : : getDSN ( ) ;


i f ( i s_nul l ( $dsn ) ) {
t hrow new \woo\base\AppException ( " DSN " ) ;
sel f : : $ PDO = new \PDO ( $dsn ) ;
sel f : : $ PDO- >s etAtt r ibute ( \ PDO : : ATTR_ERRODE , \ PDO : : ERRODE_EXCEPTION ) ;

function f ind ( $ i d ) {
$this->selectStmt ( ) ->execute ( array ( $ i d ) ) ;
$ array = $this->selectStmt ( ) - > fetch ( ) ;
$this->selectStmt ( ) ->closeCursor ( ) ;
i f ( ! is_array ( $array ) )
{ return nul l ;
i f ( ! i s set ( $array [ ' id ' ] ) ) { return nul l ;
$ obj ect = $this- >create0bj ect ( $array ) ;
return $obj ect;
function createObj ect ( $array ) {
$obj = $this- >doCreateObj ect ( $ array ) ;
return $obj ;
function insert ( \woo\domain\ DomainObj ect $obj ) {
$this ->doinsert ( $ obj ) ;
abstract functi on update ( \woo \domain\Doma inObj ect $obj ect ) ;
protected abstract function doCreateObj ect ( array $array ) ;
protected abstract function doinsert ( \woo \domain\DomainObj ect $obj ect ) ;
protected abstract function sel ectS tmt ( ) ;

App l i ca t ionRe g i s t r y
DSN, PDO. ,
,
.
Mappe r , .
Mapper
Reg i st ry.
, Mapper PDO
.
-

namespace woo \mapper;


// . . .

abstract class Mapper


protected $PDO;
function _construct ( \ PDO $pdo ) {
$this->pdo = $pdo;

1 3 .

339

VenueMapper R e g i s t r y
\woo\base \ Reque s t Reg i st r y : : getVenueMappe r ( ) .
Mapper, PDO.
Mapper.
, Reg i s t ry
, .
Mappe r ,
( ).
.
i n s e rt ( ) ,
doinse rt ( ) . i n s e r t ( ) ,
, .
find ( ) (
) .
, c r e a t eObj e c t ( ) . ,
,
doCreateObj ect ( ) . ,
createObj ect ( ) ,
. ,
1emplate Method .

(.
Space, Venue ) .
.
namespace woo\mapper ;
11 . . .
class VenueMapper extends Mapper
funct ion construct ( )
parent : : construct ( ) ;
$this->selectStmt = sel f : : $ PDO->prepare (
" SELECT * FROM venue WHERE id=? " ) ;
$this->updateStmt = sel f : : $ PDO->prepa re (
"UPDATE venue SET name= ? , i d= ? WHERE id=? " ) ;
$this->insertStmt = sel f : : $ PDO->prepare (
" INSERT into venue ( name ) values ( ? ) " ) ;
funct ion getCol l ection ( array $ raw )
return new SpaceCol lection ( $ raw, $this ) ;
protected funct ion doCreateObj ect ( array $ array )
$obj = new \woo\domain\Venue ( $ array [ ' id ' ] ) ;
$obj ->setName ( $ array [ ' name ' ] ) ;
return $obj ;
protected function doinsert ( \woo\doma i n \ DomainObj ect $ object ) {
$values = array ( $ obj ect->getName ( ) ) ;
$this->insertStmt->execute ( $values ) ;

340

111.

$ id = s el f : : $ PDO->lastinsert i d ( ) ;
$object->set id ( $ i d ) ;
function update ( \woo\domain\DomainObj ect $obj ect ) {
$values

array ( $obj ect->getName ( ) ,


$obj ect->get i d ( ) , $obj ect->get i d ( ) ) ;
$this ->updateStmt->execute ( $values ) ;
=

function selectStmt ( ) {
return $this->select Stmt ;

.
. SQL-
.
VenueMappe r , ,
Mapp e r Regi s t ry.
.
Mapp e r find ( ) , s e l ec t S tmt ( ) ,
SELECT . , ,
Mapper VenueMappe r : : doCreateOb j ect ( ) .
Venue.
, - .
$mapper = new \woo \mapper\VenueMapper ( ) ;
$ venue = $mapper->find ( 12 ) ;
print_r ( $venue ) ;
r i n t r ( ) , f i nd ( )
. ( venue
ID 1 2 ) .
woo \ doma i n\ V e nue Obj e ct
(
[ name : w o o \domai n\ Ve nue : pr ivat e ] = > The Eyeb a l l I n n
[ sp a c e s : woo \ doma i n \ Ve nue : pr ivat e ] = >
[ id : woo\doma i n \ Domai nOb j e c t : p r i va te ] = > 1 2

d o i n s e r t ( ) update ( ) f i nd ( ) .
Doma inOb j e c t , ,
,
P DOStatement : : execute ( ) . , do i n s e r t ( )
I D . ,
,
.
, d o i n s e r t ( ) update ( )
. Doma i nObj ect
. i ns tanceof
Except i on, .
.

1 3.

341

, , ,
.
$venue = new \woo \domain\Venue ( ) ;
$venue->setName ( "The Likey Lounge-yy" ) ;
1 1
$mapper->insert ( $venue ) ;
1 1 - , !
$venue = $mapper->find ( $venue->getid ( ) ) ;
print_r ( $venue ) ;
1 1
$venue->setName ( "The i Beer Likey Lounge-yy" ) ;
1 1
$mapper->update ( $venue ) ;
1 1 , ,
$venue = $mapper- >find ( $venue->get id ( ) ) ;
print_r ( $venue ) ;


find ( ) ,
. , ?
, - . ,
.
,
. 1 ,
. -
.
, Mappe r .
, , (..
). I te r a t o r .
I t e r a t o r .
. ,
foreach , . ,
I te r a t o r , ,
. !
I t e ra t o r .
. 1 3 . 1 , I te ra t or .
1 3. 1 . , I t era t o r

rewind ( )
current ( )
key ( )
next ( )


,
(.. )
, ,

,

val id ( )

342

111.

I te ra t o r ,
, . ,
, , .
I t e r a t o r , .
Mappe r.
.
namespace woo\mapper ;
// . . .
abstract class Coll ection implements \ I terator {
protected $mapper ;
protected $total = ;
protected $ raw = array ( ) ;
private $ resul t ;
private $pointer
private $ obj ects

;
array ( ) ;

funct ion
const ruct ( ar ray $ raw=nul l , Mapper $mappe r=nul l ) {
i f ( ! is_nul l ( $ raw ) && ! i s_nul l { $mapper ) ) {
$this- >raw = $ raw;
$this->total = count { $ raw ) ;
$this->mapper

$mapper ;

function add ( \woo\doma i n \ DomainObj ect $ obj ect ) {


$class = $this->targetC lass ( ) ;
i f ( ! ( $ obj ect instanceof $ c l as s )
throw new Except ion ( " o { $class ) " ) ;
$ this->noti fyAccess ( ) ;
$thi s - >objects [ $this->total ]
$this->total++;

$ ob j ect ;

abstract function targetClass ( ) ;


protected function noti fyAccess ( )
/ / n !
private function getRow ( $ num )
$thi s - >noti fyAccess ( ) ;
i f ( $num >= $ this->total 1 1 $num < ) {
return nul l ;
i f ( i sset ( $this ->obj ects [ $num] ) ) {
return $ th is ->ob j ects [ $num] ;
i f ( isset ( $ this ->raw [ $num] ) ) {
$this ->obj ects [ $num ] =$this->mapper->create0bj ect ( $this->raw [ $num] ) ;
return $this->objects [ $num] ;

1 3.

343

pu ic function rewind ( )
$this ->pointer = ;
pu ic function current ( ) {
return $thi s - >getRow ( $this ->pointer ) ;
pu ic function key ( ) {
return $this->pointer;
pulic function next ( ) {
$ row = $this- >getRow ( $this->pointer ) ;
i f ( $ row ) { $this->pointer++ ;
return $ row;
pu ic function va lid ( ) {
return ( ! is _nul l ( $this->current ( ) ) ) ;

,
( ,
, Mappe r).
, $ r a w ( Mapper).
.
. Mappe r.
.
,
(.. ) . , add ( )
.
: $ obj e c t s $ raw.
, g e t Row ( )
$obj e c t s , , . ,
. $ raw
. $ ra w . Mapp e r
,
Mapper : : createObj ect ( ) . .
DomainObj e c t , $obj ects
. Doma i nObj ect .
- $ p o i n t e r
g e t Row ( ) . , not i fyAcces s ( ) ,
. Lazy Load.
. . C o l l e c t i o n
.
.
.

namespace woo \mapper ;


11 . . .
class VenueCol lection extends Collection {

344

111.

function targetClass ( ) {
return " \woo\domain\Venue " ;

VenueCol le c t i o n Co l l e c t i on ,
t a rgetC l a s s ( ) . , add { )
, , Venue r .
,
.
, VenueMapper.
,
Domain Model.
, Event Space.
, VenueCol lect i o n
\woo \ doma i n\VenueCol l e c t i on.
(Separated Interface), . ,
, doma i n ,
Co l l ec t i o n , mappe r .
Domai nObj ect \ woo\doma in\Venue
C o l l e c t i on, \ woo\mapp e r\VenueCol lec t i on.
mapper.
, doma i n
.
\ woo \ domai n \ VenueCol l ct i on
.
namespace woo\ domain;
inter face VenueColl ection extends \ I terator
funct ion add ( DomainObj ect $venue ) ;
interface SpaceCol lection extends \ I terator
funct ion add ( DomainObj ect $ space ) ;
interface EventCol l ection extends \ I terator
funct ion add ( DomainObj ect $event ) ;
Collec t i on . 1 3. 2 .
Domain Model Collec
t i on - (
), - Domain
Model Co l l e c t i on .
VenueColl e c t i on.
require_once ( "woo/domain/HelperFactory . php " ) ;
use woo\domain as dom;
$collect ion = \woo\domain\HelperFactory: : getCollection ( dom\Venue : : class ) ;
, .
$col lection- >add ( new \woo\domain\Venue ( nul l , " Loud and Thumping" ) ) ;
$collection- >add ( new \woo\domain\Venue ( nul l , " Eeezy" ) ) ;

1 3 .

345

$collection->add ( new \woo\domain \Venue ( nul l , " Duck and Badger" ) ) ;


foreach ( $col lection as $venue )
print $venue->getName ( ) . " \n " ;

Collection

->

+_construct(raw : array=null,mapper : Mappernull)


+add{obj : DomainObject)

+createObj ect ( row: array ) : DomainObject

+t11r9etCl11ss() : Strjng

+rewind{}
+current( ) : DomainOject
+key( ) : int
+next ( ) : DomainOject
+valid { } : Boolean

VenueCollection

SpaceCollection

EventCollection

+targetClass ( ) : String

+targetClass () : String

+targetClass( ) : String

. 1 3.2.

, ,
, e lementAt ( ) , deleteAt ( ) , count ( )
. . (
!)
, : : c l a s s ,
, .
5.5.
!

I te r t r
, I t e r a t o r
. 5 . 5 (
) ,
wn (generator). , - ,
, . return
y i e l d .
y i e l d, Gene ra t o r .
,
. , ,
y i e l d ,
, Gene r a t o r
next ( ) . ,
.

,
yield.

-
, -

346

1 1 1 .

yield.
, Gene r a t o r .

Gen e r a to r
, ( , foreach) .

foreach Generator
.

,
C o l l e c t i on? ( - )
Gene r a t o r , C o l l e c t i o n
.
, .
abstract class Collection
protected $mappe r ;
protected $ t o t a l = ;
protected $ raw = array ( ) ;
private $ resul t ;
private $obj ects = array ( ) ;
funct ion
construct ( array $raw=nul l , Mapper $mapper=null ) {
i f ( ! i s_nul l ( $ raw ) & & ! i s_nul l ( $mapper ) ) {
$ th i s ->raw = $raw ;
$this->total = count ( $ raw ) ;
$this ->mapper = $mappe r ;
function add ( \woo\domain\DomainObj ect $ obj ect ) {
$class = $this->targetClass ( ) ;
i f ( ' ( $ obj ect instanceof $class ) ) {
throw new Exception ( "o { $ class } " ) ;
$this->noti fyAccess ( ) ;
$this ->obj ects [ $this->total ]
$this ->total++ ;

$obj ect ;

function getGenerator ( ) {
for ( $
; $x< $ th i s - >tota l ; $ ++ ) {
yield ( $this->getRow ( $x ) ) ;

abs tract function targetClass ( ) ;


protected function not i f yAcces s ( )
1 1 !

pr ivate function getRow ( $num ) {

1 3.

$ this->noti fyAccess ( ) ;
i f ( $num >= $ this ->total
return nul l ;

1 1

347

$num < ) {

i f ( i sset ( $this->obj ects [ $num] ) ) {


return $this->obj ects [ $num] ;
i f ( isset ( $this->raw [ $num] ) )
$this ->ob j ects [ $num] =
$this->mapper->create0bj ect ( $this->raw [ $num] ) ;
return $ this->obj ects [ $num] ;

, .
current ( ) , r e s e t ( )
. , C o l l e c t i o n
.
getGene r a t o r ( )
y i e l d Gene ra t o r , .
$gen = $col lecti on->getGenerat or ( ) ;
foreach ( $ gen as $wrapper ) {
print_r ( $wrapper ) ;

.

. .

.

C o l l e c t ion
Domai nObj ect - ,
.
namespace woo\domain;
11
11

DomainObj ect
function coll ection ( )
return s e l f : : getCol lect i on ( get_class ( $this ) ) ;
static funct ion getCo l lect i on ( $ t ype=nul l ) {
i f ( i s_nul l ( $ t ype ) ) {
return HelperFactory : : getCollection ( get_ca l l ed_class { ) ) ;
return HelperFactory : : getCol l ection ( $ t ype ) ;

Col l ec t i on:
.
HelperFacto r y : : getCo l l e ct i on ( ) . 1 2

348

1 1 1 .

, getCo l l e c t i o n ( )
Domain Model. (late static indings)
get_c a l l e d_c l a s s ( ) , 5.3, ge tCollection ( )
DomainObj ect (
, ). , get_
c a l led_c l a s s ( ) ,
, , .
$ col lection = \woo \domain\Venue : : getCol lection ( ) ;

. 1 3.3 Helpe r Factory.


, , Mappe r.
domain

Dom ainObject
+e1Qllc:!;iQ(1JlP:
n
S1rio)
+i1Fi:!r(1JlP:S1xi:)

- - - ->

Helperfactory
+e:tCQllec:!;iQO(1)lpe: S:!;rin)
+etfinder(t)lpe: Stxioi:)
1

. 1 3.3. -

, . 1 3.3,
doma i n Mapper C o l l e c t i on, , ,
Mapper. ,
mappe r ( ,
He lperFa ct ory, ) . ,
Separated Interface , , ,
mapp e r .
Separated Interface, g e t Fi nder ( )
Finde r , Mapper .

. get Fi nde r ( ) Mappe r.
Venue
Space.
Space SpaceC o l l e ct i on
SpaceCo l l e c t i on.

1 3.

349

1 !Venue
namespace woo\domain;
11 . . .

function setSpaces ( SpaceCol lection $ spaces ) {


$thi s - >spaces = $ space s ;
function getSpaces ( ) {
i f ( is _null ( $this->spaces ) ) (
$this- >spaces = sel f : : getCo l l ection ( Space : : class ) ;
return $this- >spaces ;
function addSpace ( Space $ space ) {
$this->get Spaces ( ) ->add ( $ space ) ;
$ space->s etVenue ( $this ) ;

setSpaces ( ) 1U1
VenueMappe r Venue. , Space
Venue.
. .
, $ sp a c e s ,
getSpaces ( ) . , "
" , .
VenueMappe r SpaceC o l le c t i o n
Venue.
11

VenueMapper

namespace woo \mapper ;


11 . . .

protected funct ion doCreateObj ect ( array $array ) {


$obj
new \woo\domain\Venue ( $array [ ' id ' J ) ;
$obj ->setName ( $ array [ ' name ' J ) ;
$ space_mapper
new SpaceMapper ( ) ;
$ space_collection = $space_mapper - > f i ndByVenue ( $array [ ' id ' J ) ;
$obj - >setSpaces ( $space_collection ) ;
return $obj ;
=

VenueMapp e r : : doCreateObj e c t ( ) SpaceMapper


SpaceCo l l ec t i on . , SpaceMapper
fi ndByVenue ( ) . ,
. Mappe r : : f i ndAl l ( )
woo \mapper\Mapp e r . .
11

Mapper

namespace woo \mapper ;


11 . . .

function findAll ( ) {
$this->selectAll S tmt ( ) ->execute ( array ( ) ) ;

350

111.

return $ this->getCol lection (


$this->selectA1 1 S tmt ( ) ->fetchAl l ( PDO : : FETCH_AS SOC ) ) ;

s e l e ctAl l S tmt ( ) . s e l e c t S tmt ( ) ,


SQL,
. PDOS t a t emen t , SpaceMappe r .
1 1 SpaceMapper : = construct ( )
$this->selectAl l S tmt = s e l f : : $ PDO->prepare ( " SELECT * FROM space " ) ;

// . . .
$thi s - > findByVenueStmt

sel f : : $ PDO->prepare (
" SELECT * FROM space where venue=? " ) ;

, $ f i ndByVenueS tmt ,
Space, Venue.
f i ndA l l ( ) , getCol l e c t ion ( ) ,
. SpaceMappe r : : getCol le c t i on ( ) .
function getCol lection ( array $ raw )
return new SpaceCollection ( $ raw, $this ) ;

Mapper g e t C o l l e c t i on ( ) s e l ectAll
S tmt ( ) , Mapper
, .
Space, Venue,
. ;
SpaceMappe r : : fi ndByVenue ( ) , .
function findByVenue ( $vid ) (
$ th i s - > findByVenueStmt ->execute ( array ( $vid ) ) ;
return new SpaceCo l lect ion (
$this->findByVenueStmt - >fetchAl l ( ) , $this ) ;

f indByVenue ( ) f i ndAl l ( ) , SQL


oepaopa. VenueMappe r
Venue Venue : : setSpaces ( ) .
Venue ,
Space .
, .
. 1 3.4 ,
SpaceCo l le c t ion, , SpaceCo l l e c t i on
SpaceMapper : : createObj ect ( ) ,
.

, Space
Venue, , u .
, , .
, Ve nue : : doCr e a t e Ob j e c t ( )
Spaceco l l e ct ion Venue : : get
Spaces ( ) ,
. .

1 3.

\ 1
Cli nt

SpaceCollection

findByVenue() 1

SpaceMapper
1
-

35 1

1
<- - - - - -, 1
next() _ 1

---_

. 1 3.4. SpaceC o l lection

Space
11

Venue

namespace woo\domain;
11 . . .

function getSpaces ( ) (
i f ( is_nul l ( $this- >spaces ) ) (
$ finder = sel f : : getFinder ( Space : : class ) ;
$this->spaces = $ finder->findByVenue ( $this->getid ( ) ) ;
return $this->spaces ;

,
SpaceMappe r
JOI N SQL-apoca.
. ,
!
, Mappe r .
,
Mapper .
-
. Mapp e r " "
.
, -
Mappe r.
, .
Mapp e r - .
, -
- (, )
Mapp e r , .
Mappe r , .
Mapp e r ,
.

352

111.

I te r a t o r . C o l l e c t i o n
, ( Space) ,
Venue .
" " ,
.
. Mapper,
, Mappe r
.
Mapper
. , , ,
,
.
,
,
( , ). SQL-,
, - ;
- . ( )
-
, , ,
.

ldentity

4? , , ,
, , ,
? , .

, Data
Mapper.
require_once ( "woo /domain/Venue . php" ) ;
$venue = new \woo\domain\Venue ( ) ;
$mapper = $venue- >finder ( ) ;
$venue->setName ( "The Likey Lounge " ) ;
$mapper->insert ( $venue ) ;
$venue = $mapper->find ( $venue->getid ( ) ) ;
print_r ( $venue ) ;
$venue - >s etName ( "The i Beer Likey Lounge" ) ;
$mapper->update ( $venue ) ;
$venue = $mapper->find ( $venue->geti d ( ) ) ;
print_r ( $venue ) ;

- , ,
, Mapp e r ,
.. , ,
! , Venue .
, .

1 3 .

353


. ,
, (,
C o l l e c t i on ) ?
- , .
- ,
, , .
, .

(Identity ) - ,
- , ,
, .
Identity -
. ,
. Identity .
namespace woo\domain ;
//. . .
class Obj ectWatcher {
private $all
array ( ) ;
private static $ ins tance=nul l ;
=

private function _construct ( ) { }


static function instance ( ) {
if ( i s_null ( self : : $ instance ) ) {
sel f : : $ instance = new Obj e ctWatcher ( ) ;
return sel f : : $ ins tance ;
function globalKey ( DomainObj ect $ obj ) {
$ key = get_class ( $ obj ) . " . " . $ ob j - >getid ( ) ;
return $ key;
static function add ( DomainObj ect $ obj )
$inst
sel f : : inst ance ( ) ;
$ i nst->al l [ $ inst->globalKey ( $obj ) ]
=

$ obj ;

static function exists ( $classname , $ i d ) {


$inst
self : : inst ance ( ) ;
$ key = " { $clas sname } . { $ id ) " ;
i f ( isset ( $inst->all [ $key]
) {
return $ i nst->al l [ $ key] ;
=

return nul l ;

354

111.

. 1 3. 5 , Identity
, .

+createObject (row: array) : DomainObject


+insert($obj : Domain0bject)
1

ObjectWatcher
1

+add{obj: DomainObject)
+exists (classname: String, id : int) : DomainObject
+globalKey(obj : DomainObject)

Dom ainObject
+getid ( ) : id

. 1 3.5. ldentity

h Identity - , ,
() . ,
- . .
, , ,
, ID II .
,
. , ,
, .
, .
, .
.
woo \ doma i n \ Event 4 , woo\
doma i n \ Event . 4 II .
g l obalKey ( ) .
add ( ) II .
$ a l l .
e x i s t s ( ) $ i d , .
, , !
, ,
$ a l l . , ,
.
, Obj e ctWat cher
Identity . Mappe r 11
, .
1 1 Mapper
namespace woo \mapper ;
// . . .

private funct ion get Fromap ( $ id ) {


return \woo\domain\Obj ectWatche r : : ex i s t s (
$thi s ->targetC l as s ( ) , $ id ) ;
private function addToMap ( \woo\domain\DomainObj ect $ obj ) {
return \woo\domain\Obj ectWatche r : : add ( $obj ) ;

1 3 .

355

function f ind ( $ id ) {
$old
$this->get Fromap ( $ i d ) ;
if

is _nul l ( $old ) ) { return $ o l d ; )

11 db
return $obj ;

funct ion createObj ect ( $ array ) {


$old
$this ->get Fromap ( $array [ ' id ' ] ) ;
i f ( ! i s nul l ( $old ) ) { return $old; )
_

1 1
$this->addToMap ( $obj ) ;
return $obj ;

function insert ( \woo\domain\Doma inObj ect $ obj ) {


1 1 . $ obj
$this->addToMap ( $obj ) ;

: addToMap ( ) get Fromap { ) .


Obj e ctWatche r .
, , (VenueMapper ..),
,
.
t a r ge t C l a s s ( ) , ,
Mapper. ,
Mapper. t a rgetCl a s s ( )
SpaceMapper.
protected function t argetClas s ( ) {
return \woo\domain\Space : : cl as s ;

find ( ) , createOb j ect ( ) , ,


get Fromap ( ) . ,
, .
, .
createOb j ect ( ) addToMap ( ) ,
.
, g e t Fromap ( )
f i nd ( ) , createObj ect ( ) ? C o ll e c t ion.
, , createOb j ect ( ) .
, , C o l l ect i on , ,
, .


Identity ,
,
.

356

111.

, .

.
() . ,
.

Memc a ched. Memc ached
h t tp : / /memca c he d . org / , - h t tp : / /www . php . ne t /

memcache.

Unit of Work
? Unit
of Work ( Pattems of Enterprise
Application Architecture),
. .
Unit of Work ,
.

SQL-
. ,
. . ..
, .
.
, .
,
Jdentity . ;
.
, .

, ,
, . ,
, , - .
,
(, , ).
. ! ?
Obj e c tWatche r , .

1 1 Obj ectWatcher
namespace woo\doma i n ;

// . . .
private
private
private
private
private
// . . .

$all
array ( ) ;
$dirty
array ( ) ;
$new
array ( ) ;
array ( ) ; / /
$ delete
s ta t i c $ instance ;

1 3 .

357

stati c function addDe lete ( DomainObj ect $obj ) (


$ s e l f = sel f : : instance ( ) ;
$sel f->delete [ $sel f->globalKe y ( $ obj ) ] = $obj ;
stati c function addDi rt y ( DomainObj ect $obj
$inst = self : : instance ( ) ;
i f ( ! in_array ( $ obj , $ ins t->new, true
$ inst->dirty [ $ inst->globalKey ( $ obj ) ]

$obj ;

static function addNew ( DomainObj ect $obj ) {


$ inst = sel f : : instance ( ) ;
1 1 i d
$ inst->new [ ] = $obj ;
static function addClean ( DomainObj ect $obj ) {
$ s e l f = self : : instance ( ) ;
unset ( $sel f->delete [ $ se l f - >globalKey ( $obj ) ] ) ;
unset ( $sel f->dirty [ $ se l f - >globalKey ( $obj ) ] ) ;
$self->new
array_f i l ter ( $ s el f->new,
funct ion ( $ ) use ( $ obj ) { return ! ( $
);
=

$obj ) ; }

function performOperations ( ) {
foreach ( $this->dirty as $ key=>$ obj ) {
$obj -> finder ( ) - >update ( $obj ) ;
foreach ( $thi s - >new as $ key=>$obj ) {
$obj -> finder ( ) - >insert ( $obj ) ;
$this - >dirty
$this ->new

array ( ) ;
array ( ) ;

Obj e ctWa tcher - Idetity



$ a l l .
.
Unit of Work Obj ectWatcher . 1 3.6.

ObjectWatcher
+addDelete{obj : DomainObject )
+addDirty{obj : DomainObject)
+addNew{obj : DomainObject)
+addClean {obj : DomainObject)
+performOperations()

: DomainObject 1
1

1
- - - - - - -

. 1 3.6. Unit of Work

358

111.

".
. $ d i r t y
( addDi r t y ( ) ) .
.
, . ,
( addCl e an ( ) ).
,
$new ( addNew ( ) ).
. ,
.
addD i r t y ( ) a ddNew ( )
. addC l e a n ( )
$ d i r t y , .
. , ,
, p e r f o rmOpe r a t i on s ( ) (,
).
$ d i r t y $new, .
Obj e ctWa t cher
. Obj ect
Watcher.
, , .
, Domai nObj ect.
.
.

1 1 DomainObj ect
namespace woo\domain;
11 . . .

abs tract class DomainObj ect


private $ id = - 1 ;
function
const ruct ( $ i d=null ) {
i f ( i s_nu l l ( $ i d ) ) {
$ this->markNew ( ) ;
else {
$ th i s - > i d = $ i d ;

funct ion markNew ( ) {


ObjectWatche r : : addNew ( $this ) ;
funct ion markDeleted ( ) {
ObjectWatche r : : addDelete ( $ th i s ) ;
funct i on markDirty ( ) {
ObjectWatche r : : addDi rty ( $this ) ;
function markClean ( ) {
ObjectWatcher : : addClean ( $this ) ;

1 3.

359

function setid ( $ i d ) {
$this->id = $ id;
function getid ( ) {
return $this->id;
function f inder ( ) (
return s e l f : : getFinder ( get_class ( $this ) ) ;
static function getFinder ( $ t ype=null ) {
i f ( is_null ( $ t ype ) ) {
return HelperFactory : : getF1nder ( get_called_cl ass ( ) ) ;
return HelperFactory: : getFinder ( $ t ype ) ;
}// . . .

Unit of Work. ,
Doma i n f i nde r ( ) get F inde r ( ) . ,
collect i o n ( ) getC o l l ect i o n ( ) , , Helper
Factory, Mappe r , .
. 13.3.
, (
ma r kNew ( ) ). $ id. ,
.
-
. ,
,
. .
. , ?
, , ,
! - , -
. . -
, .
Mappe r .
11

Mapper
function createObj ect ( $a rray ) {
$this- >get Fromap ( $ array [ ' id ' J ) ;
$old
i f ( ! i s_nul l ( $old ) ) { return $old; }
$obj
$this ->doCreateObj ect ( $array ) ;
$this ->addToMap ( $obj ) ;
$obj - >markClean ( ) ;
return $obj ;
=


Obj e ctWa tche r : : addNew ( ) ,
mar kClean ( ) , , ,
, , .

360

1 1 1 .

, , - ma r k D i r t y ( )
Domain Model. : - ,
. ,
Domain Model. , ,
, ,
. , (
) .
Space, ma r k D i r t y ( ) .
namespace woo \dornain;
// . . .
class Space extends DomainObj ect
11 . . .
funct ion setName ( $name s ) (
$ th i s ->name = $name_s ;
$ th i s - >rnarkDi rty ( ) ;
function setVenue (Venue $venue ) (
$ th i s - >venue = $venue;
$this ->markDi rt y ( ) ;

Venue Space ,
Cornrnand.
require once ( "woo/dornain/Venue . php " ) ;
require_once ( "woo/domain/Space . php" ) ;
$venue
new \woo\domain\Venue ( nul l , "The Green Trees " ) ;
$venue->addSpace (
new \woo\ domain\ Space ( nul l , ' The Space Upsta i rs ' ) ) ;
$venue->addSpace (
new \woo\dornain\Space ( nul l , ' The Bar Stage ' ) ) ;
/ / .
/ / ,
// \woo \domain\ObjectWatcher .
\woo\dornain\Ob j ectWatcher : : instance ( ) ->performOperat i ons ( ) ;
=

Obj e ctWatcher, ,
.
inserting The Green Trees
inserting The Space Ups tairs
inserting The Bar Stage

- perforrn
Operat ions ( ) , , , -
, Unit of Work (Obj ectWatcher)
.

, ,
. ,
.
, .

1 3 .

361

. .
. . ,
- ,
.

Lazy Load
Lazy Load - , -
. -
, , .. ,
.

, ,
Venue, Space Eve n t . Venue,
SpaceCo l l e c t ion.
Space Venue, ,
Even t , Space.
Event C o l l e c t ion. ,
.
Venue, - Space,
Space Event ,
.
,
.
SpaceMapp e r , Eve n t .
protected function doCreateObject ( array $array )
new \woo\domain\Space ( $array [ ' id ' ] ) ;
$obj
$obj ->setName ( $a rray [ ' name ' ] ) ;
$ven_mapper = new VenueMapper ( ) ;
$venue = $ven_mapper-> find ( $ array [ ' venue ' ] ) ;
$obj ->setVenue ( $venue ) ;
$event_mapper = new EventMapper ( ) ;
$event_col lection = $event_mappe r->findBySpace i d ( $array [ ' id ' J ) ;
$obj ->setEvents ( $event_collection ) ;
return $ obj ;
=

doCreateOb j e c t ( ) Venue,
Space. ,
Obj ectWat che r. EventMapp e r : : fi nd
B ySpa c e i d ( ) . .

, , , Lazy Load -
, .
, -
. Space.

362

111.

1 1 Space
funct ion getEvents ( ) {
i f ( i s_nul l ( $this->events ) ) {
$this - >events =
sel f : : getFinder ( Event : : class ) -> f i ndBySpaceid ( $this ->geti d ( ) ) ;

return $ this ->events ;

. $ events .
, (.. Mapper )
$ i d EventCo l l ect i on ,
. ,
, S pa ceMappe r ,
EventC o l l e c t ion,
!
, .
?
,
C o l l e c t i o n . (,

). ,
.
, EventCo l l e c t i on ,
, .
, (, Space, )
, C o l l e c t i on .
, Event C o l l e c t i on.
De f e r redEventCol l e c t i on.
namespace woo \mapper ;
// . . .
class Def erredEventCol lection
extends EventCo l l ection
private $ s tmt ;
private $valueArray;
private $ run=fal s e ;
function construct ( Mapper $mapper, \ PDOStatement $ s tmt_handle,
array $valueArray ) {
parent : : construct ( nul l , $mapper ) ;
$this- >s tmt = $s tmt_handl e ;
$this - >valueArray = $valueArray;
function notifyAccess ( ) {
i f ( ! $ this->run ) {
$ this->stmt ->execute ( $ t h i s->valueArray ) ;
$this ->raw = $thi s->stmt -> fetchAl l ( ) ;
$this->total = count ( $this - >raw ) ;
$this->run=true ;

1 3 .

363

, EventCo l l e c t i on.
EventMappe r PDOS ta t ement ,
.
, .
.
. C o l l e c t i o n n o t i f y
Access ( ) , " Data Mapper".
, .
De f e r redEvent C o l l e c t i o n . .
- C o l l e c t i on, ,
- . ,
PDOS t a t ement : : execute ( ) . PDOSt a t ement : : f e t ch ( )
, Mapp e r : : c r e a t eObj e c t ( ) .
EventMapp e r , D e f e rredEvent C o l l e c t i o n .
1 1 EventMapper
namespace woo \mappe r ;
11 " .

function findBySpace id ( $ s id ) {
return new DeferredEventCo l l ection (
$thi s ,
$thi s - >selectBySpaceStmt , array ( $ s_id ) ) ;


"" - ,
, .
,
. - ,
"" , .

Domain Object Factory


Data Mapper . .
, Mapper . SQL-,
. , .
. Mapp e r
. .
. Mapper

Mapper. Data Mapper,
.
, Data
Mapper, ( !)
. (Clifton Nok) Data Access
Patterns (Addison Wesley 2003) . ,
.
- .

364

111.


, Mapper
. , c r e a t eObj ect ( ) Mapper
. C o l l e c ti o n
. Mapper
C o l l e c t i on. , (
Vi s i to r , Obse rve r ) ,
.
Mappe r C o l l e c t i o n .
Domain Object Factory Data Access Pattems.

Mapp e r , ,
. Domain Object Factory
, createOb j ect ( ) Mapper
.
. 1 3 . 7.

Collection

>

Dom ainObjectFactory
+createObject(row:array)

SpaceDomainObjectfactory
+createOject (row: array)

VenueDomainObjectFactory
+createOject ( row: )

EventDomainObjectfactory
+createOiect (row: )

. 1 3. 7. Domain Object Factory

Domain Object Factory ,


.
namespace woo \mapper ;
11 " .
abstract class DomainObj ectFactory
abst ract function createObj ect ( array $array ) ;

.
namespace woo \mapper ;
11" .
c l ass VenueObj ectFactory extends DomainOb j ectFactory
function createObj ect ( array $array ) {

1 3.

365

$obj = new \woo\domain\Venue ( $array [ ' id ' ] ) ;


$obj ->s etName ( $array [ ' name ' J ) ;
return $obj ;

,
, ,
Mapper. addToMap ( ) g e t Fromap ( )
Obj ectWatche r createObj ect ( )
. :
, !
.

Domain Object Factory ,


, .
createObj e c t ( ) .
, - .
Mapper ,
. , C o l l e c t i on.
namespace woo\mapper ;
11. "
abstract class Coll ection
protected $dofact ;
protected $total = ;
protected $ raw = array ( ) ;
// . . .
function
construct ( array $ raw=nu l l ,
\woo \mapper \DomainObj ectFactory $dofact=nul l ) {
i f ( ! is_nul l ( $ raw ) && ! i s_nu l l ( $dofact ) ) {
$this- >raw = $ raw;
$this- >total = count ( $ raw ) ;
$this->dofact

$dofact ;

11

DomainObj ect Fac t o r y


.
if ( isset ( $this->raw [ $num] ) ) {
$this ->obj ects [ $num] =$this - >do fact->create0bj ect ( $this- >raw [ $num] ) ;
return $this ->ob j ects [ $num] ;

Doma inOb j e c t Fa c t o r y ,
. , .
DomainOb j e c t Factory, Collect ion.
, Mapp e r (
- . 1 8) .
-
.
. -

366

111.

,
, .
, - .
Data Mapper. Mapper : : getCo l l e c t ion ( ) ,
, -, C o l l ection
, ,
. . : C o l l e c t i o n
Domai n Obj e c t Factory. ,
, , Venue
C o l l e c t i o n Venue Doma inOb j e ctFactory SpaceCo l l ec t i o n SpaceDoma i nObj ect
Fa ctory. , Abstract
Factory. . 1 3.8 Pe r s i s tenceFactory.
,
.

PersistenceFactory
+getCollection(raw:array): Collection
+getDo8ainOjectFactory() : Do8ainO/ljectFactory

+getFactor(tees tr : string)

VenuePersistenceFactory

SpacePersistenceFactory
+getCollection ( raw: array) : Collection
+getDomainObjectFactory( ) : DomainObjectFactory

+getCollection(raw: array ) : Collection


+getDomainObjectFactory( ) : DomainObjectFactory

Dom ainObjectFactory

:;:....

SpaceDomainObjectFactory

VenueDomainObjectFactory

<- - - -

1
- -1

Collection

:.--

SpaceCollection

VenueCollection

<- -

1
1

- - - - - - - - - - J

. 1 3.8. Abstract Factory

ldentity Object
Mapp e r , ,
, .
- .
. - , -

1 3.

367

(
EventMapp e r : : f i ndBySpace i d ( ) ) .
Identity Object ( Data 1ransfer
Object) ,
.
-

,
. ,
.
, Map p e r .
, ,
,
Mapp e r , Mapper .
Identity Object
,
. , Person,
Identity Object, 30
40 1 80 . ,
(.
). Identity Object
.
, i n come , ,
. . , .

Identity Object ,
. ,
, SQL-oepaopa.
. 1 3.9 I dent i t yObj e c t .

ldentityObject
+setid ( id : int)
+getid ( ) : st ring
+setName ( name : st ring )
+getName ( ) : st ring

li>

1 VenueldentityObject 1 1 SpaceldentityObject 1

EventldentityObject
+setMinimumStart (minstart : int)
+getMinimumSta rt () : int
+setStart ( start : int )
+getSta rt ( ) : int

. 1 .9. ldentity Object

, ,
, .
, , , . 1 3 .9.

368

111.

namespace woo \mapper ;


// . . .
class Identi t yObj ect {
private $name = nul l ;
function setName ( $name ) {
$this->name=$name ;
function getName ( ) {
return $ thi s - >name ;

class Eventi dentityObj ect


extends IdentityObj ect
private $ s tart = nul l ;
private $minstart = nul l ;
function setMinimumStart ( $mins tart ) {
$ thi s - >mi nstart = $minstart;
function getMinimumStart ( )
return $this->minstart;
function setStart ( $ s tart ) {
$this ->start = $start ;
function getStart ( ) {
return $thi s- >start ;

.
. ,
Spacei denti t yOb j e c t WHERE .
$idobj = new Event i dent ityObj ect ( ) ;
$ idobj ->s etMinimumStart ( t ime ( ) ) ;
$ idobj ->setName ( " Fine Show" ) ;
$comps = array ( ) ;
$name = $ idob j - >getName ( ) ;
i f ( ! is_nul l ( $name ) ) {
$comps [ J = " name = ' { $name } ' " ;
$minstart = $ idobj ->getMinimumStart ( ) ;
i f ( ! is_nul l ( $minstart ) ) {
$comps [ J
" start > { $minstart } " ;
=

$ s tart = $idobj ->getStart ( ) ;


i f ( ! is_nu l l ( $ s tart ) ) {
$comps [ ] = " st art = ' { $start } "' ;

1 3.

369

$clause = " WHERE " . implode ( " d " , $ comps ) ;

,
. -
-, , . ,
,
WHERE. (
s etMaximumS t a r t ( ) ).
ldentity Object .
, ,
SQL-oa. , ,
.
: , ,
.
. SQL-
, . ,
- ,
.
(fluent interface). ,
.
, .
. . ,
.
\woo \mapper\Field,
, WHERE.
amespace woo\mappe r ;
class Field {
protected $ame=ul l ;
protected $ operator=u l l ;
protected $comps=array ( ) ;
protected $ icomplete=false;
1 1 , age
fuctio _cos truct ( $m ) {
$this- >ame = $m ;
1 1
11 ( > 4 0 , ) $comps
fuctio addTest ( $operator, $value ) {
$this->comps [ ] = array ( ' m ' = > $ t hi s- >ame ,
' operator ' => $operato r ,
' value ' => $value ) ;
1 1 $comps - ,

11
fuctio getComps ( ) { retur $ th i s - >comps ; }
1 1 $comps , ,
11
11

370

111.

fuctio i s i complete ( ) ( retur empty ( $this->comps ) ; }

, .
a ddT e s t ( )
. .
I de t i t yObj ect.
amespace woo \mapper ;
class Ideti tyObj ect (
protected $curret field
protected
$ fi elds
private
$d
private
$ef o rce

ul l ;
array ( ) ;
ul l ;
array ( ) ;

11
11

ideti t y obj ect



costruct ( $ fi eld=u l l , array $ eforce=ull } (
fuc t i o
i f ( ! i s_ul l ( $eforce ) ) (
$this - >eforce = $eforce ;
i f ( ! i s_ul l ( $ field ) )
$ this->field ( $ field ) ;

1 1 ,
fuctio getObj ectFields ( )
retur $this ->eforce;

11
11
11

.
,
( . . age , age > 4 0 ) .
11
1 1
fuctio fiel d ( $ fieldame ) (
i f ( 1 $this->isVoid ( ) & & $this->curretfield- > i s i complete ( ) ) {
throw w \t i ( " " ) ;
$ th i s ->eforceField ( $ fi eldame ) ;
i f ( i s set ( $this->f ields [ $ f i eldame ] ) ) {
$ t h i s - >curret fi eld=$thi s - > fields [ $ fieldame ] ;
else {
$ t h i s - >curretfield = w Field ( $ f i e ldame ) ;
$this->fields [ $ fieldame ] =$thi s - >curretfield;
retur $thi s ;
11

ideti t y obj ect


fuctio i sVoid ( ) {
retur empty ( $this->fields ) ;

1 3 .

371

// ?
function enforceField ( $ f i eldname ) {
&&
i f ( ! in_array ( $ f ie ldname , $this- >enforce
! empty ( $this ->enforce ) ) {
$ forcel i s t = implode ( ' , ' , $this->enforce ) ;
throw new \Exception ( " { $ fieldname )
( $ forcel i s t ) " ) ;
}
/ /
1 1 . . ' age ' age=4 0 .
/ / ( operator ( ) )
function eq ( $value ) {
return $ th i s ->operator ( "-" $value ) ;
/ /
function lt ( $value ) {
return $this ->operator ( " < " , $value ) ;
1 1
function gt ( $value ) {
return $this->operator ( " > " , $value ) ;
1 1 operato r .
/ /
/ /
private function operator ( $ symol , $value ) {
i f ( $this->i sVoid ( ) ) {
throw new \Exception ( " oe " ) ;

$this->current fiel d->addTes t ( $ s ymol , $value ) ;


return $thi s ;
1 1 ,
function getComps ( ) {
$compari sons = array ( ) ;
foreach ( $this->f ields as $ key => $ f i eld ) {
$comparisons = array_merge ( $ ret , $ field->getComps ( ) ) ;

return $comparisons ;

, , -
.
namespace woo\mapper ;
requi re_once ( "woo/mapper/Identi tyObj ect . php " ) ;
$ idobj = new Ident i t yObj ect ( ) ;
$ idobj ->field ( "name " ) ->eq ( " The Good Show" )

372

111.

->field ( " start " ) ->gt ( time ( ) )


->lt ( t ime ( ) + ( 2 4 * 60 * 6 0 ) ) ;

I dent i t yOb j e c t . add ( )


F i e l d $ current f i e ld.
, add ( ) I dent i t y
Obj e c t .
add ( ) . eq ( ) , gt ( )
operator ( ) . , F i e l d,
, , ,
. , eq ( ) ,
add ( ) , .
,
: " name " " The Good Show " . " s t a r t " , ,
, .
, .
. $ enforce.
.
namespace woo\mapper;
class Eventident i t yObj ect extends IdentityObj ect
function _cons truct ( $ field=nu l l ) {
parent : : _cons truct ( $ field,
array ( ' name ' , ' id ' , ' start ' , ' duration ' , ' space ' ) ) ;

Eventident i t yObj e c t .
, .
----- ,.._.,.__,_>10'111! --------

F a t a l e rr o r : Uncaught excep t i o n ' Except i o n ' w i t h me s sage ' banana not


l e g a l f i e l d ( name , i d , s t a r t , durat i o n , space ) ' . . .


Identity Object
.

, .
Identity Object -
. ,
, ,
, .
.
.
,
, Abstract Factory (,
P e r s i s t enceFactory, ),
, .
, ,
.

1 3.

373

Selection Factory Update Factory


Mapper.
Mappe r .
Identity Object,
f ind ( ) . -
.

, .
. ,
. , , ,
" "
. - ,
,
. .

, Data Mapper.

. ldentity Object. ,
, ,
.
. 1 3 . 1 0 Selection Factory Update Factory.
Selection Factory Update Factory, -,
, (,
Identity Object).
Pe r s i s t enceFactory - Abstract Factory,
" "
.
Update Factory.
namespace woo\mapper ;
abst ract c l a s s UpdateFactory
abstract function newUpdate ( \woo\domain\ DomainObj ect $obj ) ;
protected function buildStatement ( $t , array $ fields ,
array $condit ions=null ) {
$terms = array ( ) ;
i f ( ! is_null ( $conditions ) ) {
"UPDATE { $t ) SET " ;
$query
?";
implode ( " = ? , " , array_ keys ( $ fi elds ) ) . "
$query
$terms
ar ray_values ( $ fields ) ;
$cond
array ( ) ;
$query
" WHERE " ;
foreach ( $ condi tions a s $ key=>$val ) {
$cond [ J = " $ key = ? " ;
$terms [ J =$val ;
$query . = implode ( " AND " , $ cond ) ;

374

111.

else {
$ query
" INSERT INTO { $tal e ) { " ;
implode ( " , " , array_keys ( $ f ields ) ) ;
$query
" ) VALUES ( " ;
$ query
foreach ( $ fields as $ name => $ value ) {
$ t e rms [ ] =$value ;
$qs [ ] = ' ? ' ;
$query
$ query

implode (
") ;

11

"

$qs ) ;

return a rray ( $ query, $terms ) ;

SelectionFactory
+newSelectjo (jdobj : ldentityObject) : errey

VenueSelectionFactory
+newSelection ( idobj : IdentityObject ) : a r ray

EventSelectionFactory
+newSelection ( idobj : IdentityObj ect ) : array

SpaceSelectionFactory
+newSelection ( idobj : IdentityObj ect ) : array

UpdateFactory
+nettUpdete(idobj : ldentityObject) : errey

VenueUpdateFactory

+new\Jpdate ( idobj : IdentityObj ect ) : array

r----J

SpaceUpdateFactory
+new\Jpdate (idobj : IdentityObj ect ) : array

EventUpdateFactory
+new\Jpdate(idobj : IdentityObject ) : a r ray

. 1 . 1 . Selection Factory Update Factory

, , -
newUpdate ( ) . , ,
, . buildStatemen t ( )
, , -

1 3 .

375

, . b u i l d S t at ement ( )
,
.
. Upda t e Factory.
namespace woo\mapper;
class VenueUpdateFactory extends UpdateFactory (
function newUpdate ( \woo\domain\ DomainObj ect $obj ) (
11
$ id = $ ob j - >get id ( ) ;
$cond = nul l ;
$values [ ' name ' J = $ obj ->getName ( ) ;
i f ( $ id > - 1 ) {
$cond [ ' id ' J
$id;
=

return $this->buildStatement ( "venue " , $value s , $cond ) ;

Doma i nObj e c t .
,
, Identity Object ,
. $ cond,
i d .
newUpdat e ( ) , .
,
.
: n ewUpda t e ( )
Doma i nOb j ect. , Upda t e Fa c t o ry
. ,
, .
,
VenueUpdat e facto ry.
namespace woo\mappe r;
requi re_once ( "woo/mapper /VenueUpdateFactory . php" ) ;
requi re_once ( "woo/domain /Venue . php " ) ;
$vuf = new VenueUpdateFactory ( ) ;
print r ( $vuf->newUpdate ( new \woo \domain\Venue ( 3 3 4 , "The Hairband" ) )
);
Array
(
[ 0 ] = > U P DATE venue S E T name
[ 1 ] => A r r a y

? WHERE i d

[ 0 ] = > The H a i rband


[ 1 ] => 3 3 4

376

111.

1U1 S e l e c t i on Factory.
1U1acc.
namespace woo\mapper;
abst ract class SelectionFactory
abstract function newSelection ( IdentityObj ect $obj ) ;
function buildWhere ( Identi tyObj ect $obj ) {
i f ( $obj - > i sVoid ( ) ) {
return array ( " " , array ( ) ) ;
$comps t r ings
array ( ) ;
$values
array ( ) ;
foreach ( $obj - >getComps ( ) as $ comp ) {
$compstrings [ ]
11 { $ comp [ ' name ' J ) { $comp [ ' operator ' ] ) ? 11 ;
$values [ J
$comp [ ' value ' ] ;
=

$where
11WHERE 11
implode (
AND 11 , $ compstrings ) ;
return array ( $ where, $ values ) ;
=

11

1U1acce
1U1acca. newS e l e c t i o n ( ) Identi t yObj ect. I denti t y
Obj e c t , , - b u i l d
Where ( ) . I dent i t yObj ect : : getComps ( ) ,
, WHERE,
, , .
IUlacc S e l e c t i onFactory.
namespace woo\mapper;
// . .
class VenueSelectionFactory extends Select ionFactory {
funct ion newSelect ion ( IdentityObj ect $obj ) {
$ fie lds
implode ( ' , ' , $obj - > getObj ectFields ( ) ) ;
$core = " SELECT $ f ields FROM venue 11 ;
l i s t ( $where , $ values )
$ this->buildWhere ( $obj ) ;
return array ( $ core . " 11 . $where , $values ) ;
=

SQL-oepaopa, bui l dWhe re ( ) ,


. ,
S e l e c t i on F a c t o r y . -
. ,
, 1U1 1U1acc
S e l e c t ionFactory, Pe r s i s tenceFactory.
1U1 .
namespace woo\mapper;
require once ( 11woo/mapper/VenueSelectionFactory . php11 ) ;
requi re_once ( 11woo/mapper /Venueident i t yObj ect . php11 ) ;
require once ( 11woo/domain /Venue . php11 ) ;
$vio

new Venue i dent ityObj ect ( ) ;

1 3.

377

$vio->field ( "name " ) - >eq ( "The Hai rband " ) ;


$vs f = new VenueSelectionFactory ( ) ;
pri nt_r ( $vs f - >newSelect ion ( $vio ) ) ;
Array
(
[ ] => S E LECT name , id FROM venue WHERE name
[ 1 ] => A r r a y

[ 0 ] => T h e H a i rband
-....
...
-..w

_
_
_
..,
,
_
__
_
....
_
..
_
_
_
_
_
_...
1
"
_
""'....

..._,
:d
i!I
_
_
_
_
_
_
_
_
_
_


Identity Object
SelectionFactory .
Identity Object, -
-, , , S e l e c t i o n
Factory .
Query Factory Identity jt
, .
. " ",
, . ,
Identity Object,
, .
.
,
, - , , . ,
,
. .
Mappe r, ,
,
API.
,
- ,
.
, -
, ,
.

Data Mapper
, Data Mapper ,
, . ? .
Data Mapper . - ,
.

( ).
.

378

111.

.
namespace woo \mapper ;
// . .
class DomainObj ectAs semer
protected static $ PDO;
funct ion cons t ruct ( Persi stenceFactory $ factory ) {
$this - >factory = $ factory;
i f ( ! i s s et ( se l f : : $ PDO) ) {
$dsn = \woo\base\ApplicationRegis t r y : : getDSN ( ) ;
i f ( i s_null ( $dsn ) ) {
throw new \woo\base \AppException ( " DSN " ) ;
s e l f : : $ PDO = new PDO ( $dsn ) ;
se l f : : $ PDO->setAttribute ( \ PDO : : ATTR_ERRODE , \ PDO : : ERRODE_EXCEPTION) ;

funct ion getStatement ( $ s t r ) (


if ( ! isset ( $this->statements [ $ s t r ] ) ) (
$ this ->statements [ $ s t r ] = s e l f : : $ PDO->prepare ( $str ) ;
return $this->statements [ $ s t r ] ;
funct ion findOne ( I dentityObj ect $ i dobj )
$ col lection = $this->find ( $ i dobj ) ;
return $ co l lecti on->next ( ) ;
funct ion find ( I denti tyObj ect $ i dobj ) {
$sel fact = $this->factory->getSelecti onFactory ( ) ;
l i s t ( $ selection, $values ) = $ s el fact->newSelect ion ( $idobj ) ;
$ s tmt = $this->getStatement ( $ s el ection ) ;
$ s tmt- >execute ( $values ) ;
$ raw = $ stmt ->fetchAl l ( ) ;
return $this - > factory->getCol l ection ( $ raw ) ;
function insert ( \woo\domain\DomainObj ect $obj ) {
$upfact = $this->factory->getUpdateFactory ( ) ;
l i s t ( $update, $values )
$upfact- >newUpdate ( $ obj ) ;
$ s tmt = $thi s->getSta tement ( $update ) ;
$ s tmt- >execute ( $values ) ;
i f ( $obj - >getid ( ) < ) {
$ obj ->set i d ( sel f : : $ PDO- >lastinsert i d ( ) ) ;
=

$obj ->markClean ( ) ;

, .
, Pe r s i s t enceFactory,
, .

1 3 .

379

. 1 3. 1 1 , ,
Mapp e r .

DomainOiectAssemer
+findOne (idobj : IdentityObject ) : DouinObject
+find ( idobj : IdentityObj ect } : Cottection
+insert (obj :DouinOject)

PersistenceFactory

- -r

t====================:j

1
1

+QetDouinObj ectFactory ( ) : OOtNinObj ectfactoy

getcottection ( ) : Collection
+getSe\ectionFactory ( ) : Se\ecttonFactory
+getUpdteFactory ( ) : UpdateFactory

'------ -----+------

1
1
1
1_ _ _ _ _ _ _
1
1
1
1
1- - - - - - -

,_

_ _ _ _ _

DomainObjectFactory
+crt.Object(row:erry)

->

Collection
+_construct ( raw: 11rr11y-=nul \ , obj creator: DONinObjectFactory.:i:::nu\

\}

SelectionFactory
UpdatFactory
+wflpdate(idoj :IllentityObject) : rry

. 1 3 . 1 1 . ,

,
S e l e c t i o nFactory UpdateFactory.
Se lectionFactory C o l l e c t i on,
DomainObj ectFactory, .
, Doma i nObj ectFactory .
Per s i s t enceFa c t o ry .
$ factory = \woo\mapper\PersistenceFactory : : getFactory ( ' woo\ \domai n\ \Venue ' ) ;
$ finder = new \woo\mapper\DomainObj ectAssem er ( $ factory ) ;
. , get Finde r ( ) Pe r s i s
tenceFacto r y , .
=

$ finder

\woo \mapper\PersistenceFacto r y : : getFinder ( "woo \ \ domain\ \Venue " ) ;

.

Venue.
$idobj

$ factory->get identi t y0bj ect ( ) - >field ( ' name ' )


- >eq ( ' The Eyeball Inn ' ) ;
$collection = $ f inder->find ( $ idobj ) ;
foreach ( $col lection as $venue )
( print $venue->getName ( ) . " \n " ) ;


, . Data
Mapper, ldentity Object.
, ,
. ,

380

111.

. ,
SQL-apoc ,
. ,
, , -
, .
- ,
, .
, , . . !
.
.
Data Mapper.


Domain Model .

ldentity . ,
.

Unit oj Work. ,
, ,
, - .

Lazy Load. .
.

Domain Object Factory. .

ldentity Object.
.

Query (Selection Update) Factory. SQL

Domain Object Assemer. .


.

,
, .

lV


@@@

/))

1 4
!''

)/)

@@@
''

'/'

,
.
. ,
,
, .

, .
.

: .

: .

: .

: . ,
.

:
.

:

, .



, , -.
, , :
?
? ?
? ?
, , , ,

.
, Perl Java, , .
, , ,

384

IV.


. - , ,
. ,
. , . -
, , , .
. , ,
. ,
, .

, .


, (,

} ,
.
. ,
,
.
, .
,

. , .
, , , - ,
! - , , .
, , .
-: , , , .
, ,
, ,
, .
: ,
? , .
?
?
.
- ,
. ,
- "", -
. ,
. " "
, , .
,
, , ,
.
,
, .
, ( } RSS-;

,

1 4.

385

.
.
, - PEAR h t t p : / /pear . php .
net . PEAR ( Extension and Application Repository -
) - ,
.
. PEAR ,
, PEAR
. ,
PEAR, , PEAR.
Cache_L i t e .

Benchma rk.

MDB2 .

. htacces s Apache File_HtAcce s s .

XML_RSS.

Mai l_Mime.

Config.

Auth.

- PEAR ,
. , ,
.
, , ,
.
, ,
, .
, ,
.
, , .
Ma i l PEAR.
mai l ( ) , .
,
RFC822
, . , PEAR
.
, ,
, .
,
.

, .
. ,
, , .
Perl - w ".


- "
. w

386

IV.

,
.
,
.
,
. ,
.
, .
, ,
,
.
. ,
. ,
.
, , .
Git, Subversion ,
.

, .
, .
,
, .
.
, .
.
,
.

.
,
.
, ,
. , .
Git 1 7.


- , ,
? ,
. ,
,
. -
.
, .
,
,
. .

14.

387

.
.
,
. , ,
,
. .
. ,
,
.
,
, ,
.
,
- .
, ,
.
,
, .
- .
,
. .
, ,
.
, 2 Amazon,
.
,
.
, "
" .
. ,
PEAR - .
PEAR
PEAR. PEAR,
. PEAR

.
, ,
" ". PEAR
1 5 .
, ,
, . 1 9
Phing.
Ant,
Java Java. Phing
. Ant L-
1.
PEAR
, Phing , ,
, .
Phing ,
XSLT, , -

388

IV.

. Phing -
5,
.
, PEAR Phing
. Phing
. Phing ,
, ,
PEAR, Phlng.
Phing , PEAR
.


, .
. ,
. .
, . .
.
,
.
: ,
, , .
,
, .
.
- -.
pu i c func t i on s e tName (

$name_s t r ,

$age_int

// . . .
}
, .
. , -
,
. ,
,
.
, -
. ,
, ,
. ,
. ,
? ,
, .
, , ,
, .
h t tp : / /www . bash . org.
< @ Logan > : .
< @ Logan > : : , , ?"
:
, ,
( - }.

1 4 .

389

, , , . ,
, .
, .

.
:
.
? . , , "",
Java. phpDocumentor (h t t : 11www . phpdoc . org /)
JavaDoc, ,
Java SD. .
,
. phpDocumentor
. ,
, ,
. ,
( )
.
phpDocumentor 1 6.


, . ,
.
, ,
, .
, ,
? . , .
, ; ,
? , .
, .
, , ,
, .
. ,
? ,
, . ,
, ,
. ,
, , -
,
. ,
, , , " " .
,
.
, .
, .
.
,
, .
, ( -

390

IV.

).
, , .
- ,
.
,
. - ,
. ,
, .
- ,
. ,
.


- ,
? -
. ,
.
. , .
, - .
, . ,
, .
, .
.

.
, .

. .
, , . ,
. .
, .
. ,
, !
- , -
. ,
. , ,
,
.
, ""
. - , ,
. ,
"".
,
. ,
, .
,
,
"" .

1 4 .

391

. - ! - !
.
.
() (Cotinuous Itegratio, CI).
.
. , , .
,
.
. ,
, - .
20.
.
,

Review Board (ht t p : / /www . reviewboard . org) Gerrit

(http : / /code . googl e . com/p/ge rri t / ) . ,


, .


- .
- , .
PEAR (
). ,
:
. ,
, Phing, - Ant,
Java. .
,
.

1 5

PEAR Pyrus

'

/);
-----

,
. - .

,
. , , ,
. ,
,
.
,
. ,
?
.
, ,
?
PEAR ( Extension and Application Repository) .
PEAR - - ,
. -
,
.
.

PEAR: ?

PEAR: !

Pyrus: PEAR.

PEAR :
.

pa cka ge . xml :

:
.

394

IV.

PEAR
PEAR ,
, , L. PEAR
, , PEAR,
.
htt p : / /pear . php . net.
,
PEAR, . - .
PEAR ( ,
). ,
( PEAR
--wi thout-pe a r) .
( Unix Linux , , /usr/
l o ca l / share /pear) .
pea r .
$ pear config-get php_dir

/ us r / l ocal /share /pear

( PEAR Fundation Classes)


- ,
.
. Uix
. ,

PEAR Fedora 18, .

sudo yum install php


sudo yum install php-pear

Uix, .

pear .
PEAR.
PEAR. p e a r .
con f i g- g e t ,
. config- s how
.
$ pear config-show

C on f i gu r a t i on ( channe l pea r . php . net ) :


Aut o - d i s c ove r new Channe l s
Default Channel
P roxy S e rver Addr e s s
PEAR s e rv e r [ DE PRECAT E D ]
D e f a u l t Channel M i r r o r
Remote C o n f i gu r a t i o n F i l e
PEAR execut a e s d i re ct ory

auto d i s cove r
d e f a u l t channe l
h t t p_proxy
ma s t e r s e rver
p r e f e rr e d_m i r r o r
remo t e_c o n f i g
bin dir

<not s e t >
pea r . php . net
<not s e t >
pea r . php . net
p e a r . php . net
<not s e t >
/ us r / l oc a l / i n

1 5. PEAR Pyrus

395

: Pyrus
,
PEAR. Pyrus - ,
PEAR2 (.. PEAR).
PEAR PEAR2.
.
. Pyrus
.
"Pyrus" ,
(pear tree) 1 .
(.. "pear tree") - "Pyrus". Pyrus
http: / /pear2 . php . net. phar ( Ar
chlve). Java, , .
- j ar. , phar
h-, zi-.
. Pyrus .
php pyrus . phar

Pyrus version 2 . 0 . 4 S HA- 1 : 7 2 2 7 1 D92 C3AA1 FA9 6DF9 6 0 6CD5 3 8 8 6 8 5 4 4 6 0 9A52


Pyrus : No user configurat ion f i l e detected
I t appears you have not used Pyrus be fore , wel come 1 Ini t i a l i ze i n s t a l l ?

, Pyrus
. .
, , . .
Pyrus (
5.3. 1 ). PEAR
- ,
. ,
PEAR, Pyrus.
, Pyrus .. .
.
Pyrus.
PEAR. Pyrus.
, . Pyrus get,
con f i g- show PEAR.
$ php pyrus . phar get
_
_
_
.
...
.
...
"
.
..
.
..
.
..
.
"
...

.
__,,.
.

._
.._...

Pyrus version 2 . 0 . 4 S HA- 1 : 7 2 2 7 1 D92CAA1FA9 6DF9 6 0 6CD5 3 8 8 6 8 5 4 4 6 0 9A52


Using PEAR instal l a t ion found at /usr/ loca l / s hare /pyrus
System paths :
php_d i r => / u s r / l oca l / share/pyru s / php
ext dir => / u s r / l oca l / l i/php / 2 0 1 3 1 2 2 6- z t s
cfg_dir = > /usr/ loca l / share /pyru s / cfg
--------"--. -.--....
..

....,

. . . .

"
....'"'
... ""
"":tokiitA'

.. .

396

IV.

. Pyrus " " ,

Liux Pyrus.
: phar, simplexml, l ibxml2, spl pcre. , Pyrus Fedora 18,
.

yum install php-xml


Uix . ,
Pyrus 5.3.1 .

PEAR, Pyrus . ,
, . ,
pear inst a l l PEAR.


,
. Log , ,
.
$ pear install pear/Log
. (root ) ,

, PEAR,
, .
, . " PEAR"
, .
, .

. PEAR
, Log .
.
WARN I N G : "pea r / DB " i s deprecated in favor of "pea r /MDB2 "
Did t dowl oad opt iona l dependec ie s : pear / DB , pear /MDB2 , pear/Ma i l , use
- - a l ldeps t o dow load automat i ca l ly
pear/Log opt i oa l l y use package " pe a r / DB " ( ve r s io > = 1 . 3 )
pear/Log opt i ona l l y use package "pear /MDB2 " ( vers io > = 2 . 0 . 0RC l )
pear/Log opt ioa l ly use package "pear/Mai l "
pear/Log opt i oa l l y use extesion " sq l i t e "
down loadig Log - 1 . 1 2 . 8 . tgz . . .
St art i g to dowl oad Log - 1 . 1 2 . 8 . t g z ( 4 6 , 7 2 5 bytes )
. . . . . . . . . . . . . d : 4 6 , 7 2 5 byt e s
i sta l l ok : chae l : / /pear . php . et / Log- 1 . 1 2 . 8
----

Log ,
. ,
. :
PEAR , Log pear . php . net .
pea r / Log. Log.
.
Log Pyrus.
php . /pyrus . phar install pear/Log

1 5. PEAR Pyrus

397

Pyrus ve r s i o n 2 . 0 . 4 SHA- 1 : 7 2 2 7 1 D9 2 C AA1FA9 6DF9 6 0 6CD5 3 8 8 6 8 5 4 4 6 0 9A52


U s ing PEAR i n s t a l l at ion found at / u s r / l o ca l / s h a r e /pyrus
I n s t a l l e d pea r . php . net /Lo g - 1 . 1 2 . 8 am
Opt i onal depende n c i e s that w i l l not i n s t a l l e d , u s e - -opt i onaldeps :
================================> ] 1 0 0 % ( 4 5 / 4 5 kb )
pear . php . net / DB depended on p e a r . php . net / Log
pea r . php . net /MDB2 depended on p ea r . php . n e t / Log
pea r . php . net /Ma i l depended o n p ea r . php . net / Log

PEAR Pyrus,
.
, .
,
.
pea r /d i a l e kt requ i r e s package " p e a r / Fandan g o " ( v e r s i on
No va l id package s f ound

>=

10 . 5 .0)

,
. pear i n s t a l l - .
pear install

dialekt

- , PEAR
. PEAR
, , -.
, - .
. Pyrus .

, .
-

PEAR ,
. ,
R- .
tar gzip.
PEAR , .
$ pear install - http : //www . example . com/dialekt-l . 2 . l . tgz

downl oading d i a l e k t - 1 . 2 . 1 . tg z . . .
Start ing t o down l oad d i a l e k t - 1 . 2 . 1 . tg z ( 1 , 7 8 3 byt e s )
. . . . done : 1 , 7 8 3 byte s
i n s t a l l o k : channe l : / / pe a r . php . net / d i a l e kt - 1 . 2 . 1

.
Unlx wge t , di a l e kt
.
$ wget -nv http : //127 . 0 . 1 . 2 : 8080/dialekt-1 . 2 . 1 . tgz

2 0 : 2 1 : 4 0 URL : ht tp : / / 1 2 7 . 0 . 1 . 2 : 8 0 8 0 /d i a l e k t - 1 . 2 . 1 . t g z [ 1 7 8 3 / 1 7 8 3 )
- > " di a l e k t - 1 . 2 . 1 . tg z . 1 " [ 1 ]
$ pear install dialekt-1 . 2 . 1 . tgz

i n st a l l o k : channe l : / /p e a r . examp l e . com/ D i a l e kt - 1 . 2 . 1

--------

398

IV.

PEAR, L
( , p a c ka ge . xml ) ,
, .
$ pear install package . xml

i n s t a l l o k : channe l : / /pea r . example . com/ D i a l e kt - 1 . 2 . l

PEAR
PEAR 1 .4.
, pea r . php . net ,
. ,
, . PEAR
.
,
,
.
PHPUnit
(Sebastian Bergman). , , PEAR
, .
$ pear channel-discover pear . phpunit . de2

Add i ng Channe l " pe a r . phpun i t . de " s ucceeded


D i s covery of channel " pe a r . phpunit . de " succeeded

chann e l - d i s cover,
, ,
phpuni t / . phpuni t

pea r . phpuni t . de. ,
channe l -i nf o .
-

$ pear channel-info pear . phpunit . de


_
__
..,.
_,
_,
....,
..,
....,.
"
. .,.
..
..,
.
....,.. "
.

"
.
"
"
..,
"
,
.
"
_
"
co
,_,
...,
"

"
,
,..
11
r

..,.
..,.
..,
. _
....,

_,
....,
_
..,.
...
...
W'!Wnil!t

c-r
Wllit
l
....
.__
..,
,

Chann e l p ea r . phpun i t . de I n f o rmat i o n :


Name and Server
Al i a s
Summary

p ea r . phpuni t . de
phpuni t
P H PUni t channe l s erver

. , Pyrus channel-inf .

PHPUnlt PEAR,
.
$ pear channel-discover pear . symfony . com

Adding Channe l " pe a r . s ymfony . com" succeeded


D i s covery of channel " pea r . s ymfon y . com " s ucceeded
2 pear . phpuni t. \ 31 20 1 4 .
PHPUnit PEAR, .
. .
-

pear ins t a l l

PHPUnit

1 5. PEAR Pyrus

399

, PHPUit.
$ pear install

PHPUnit

WARN I NG : " p e a r / PHPUn i t " i s deprecated in f av o r o f " channel : / / p ea r . phpun i t .


de / PHPUn i t "
down loading P H PUni t - 1 . 3 . 2 . tg z . . .
S t a r t i ng t o down load PHPUn i t - 1 . 3 . 2 . t g z ( 2 0 , 9 1 3 byt e s )
. . . . . . . . done : 2 0 , 9 1 3 byt e s
downloading PH P_Compa t - 1 . 5 . 0 . t g z . . .
S t a rt i ng t o download P H P_Compat - 1 . 5 . 0 . tg z ( 4 4 , 1 3 3 byt e s )
. . . done : 4 4 , 1 3 3 byt e s
i n st a l l o k : channel : / / pea r . php . ne t / PHPUni t - 1 . 3 . 2
i n s t a l l o k : channel : / /p e a r . php . net / PH P_Compa t - 1 . 5 . 0

"

....

...._
-...--
,
_.
_..

,
.

-,

';l:;"f
"
"
"
_
_
_
_

PEAR

PEAR
PEAR,
. PEAR i n cl ude .
PEAR_Conf i g , .
$ pear install

Config
.....___,

w
_
_
_
,.,.
11
-.
.

"
_
....,
_
...,.
,_
.

WARN ING : " p e a r /XML_P a r s e r " i s dep r ecat ed i n favor o f " p e a r / XML_P a r s e r 2 "
downloading Con f i g - 1 . 1 0 . 1 2 . t g z . . .
S t a r t i ng t o downl oad Con f i g- 1 . 1 0 . 1 2 . t g z ( 3 2 , 2 9 1 byt e s )
. . . . . . . . . done : 3 2 , 2 9 1 byte s
down loading XML_Pa r s e r- 1 . 3 . 4 . t g z . . .
S t a r t i ng t o downl oad XML_ P a r s e r - 1 . 3 . 4 . t g z ( 1 6 , 0 4 0 byt e s )
. . . done : 1 6 , 0 4 0 byt e s
i n st a l l o k : chan ne l : / / p e a r . php . net /Con f i g- 1 . 1 0 . 1 2
i n s t a l l o k : channe l : / / pea r . php . net /XML_Par s e r - 1 . 3 . 4

.
requi re_once ( "Con f i g . php" ) ;
class MyConfig (
private $ root0bj ;
function
construct ( $ f i lename=nul l , $ t ype= ' xml ' ) {
$this->type=$ type ;
$conf = new Config ( ) ;
i f ( 1 i s_nul l ( $ f i l ename ) ) {
$this->root0bj
$conf->parseConfig ( $ f i l ename , $ t ype ) ;
else {
$ th i s - > root0bj
new Conf1g Conta1ner ( ' section ' , ' conf i g ' ) ;
$ conf->setroot ( $ this->rootObj ) ;

function set ( $s ecname , $key, $val ) {

400

IV.
$ s ect ion=$ t h i s - >getOrCreate ( $ t h i s - >root0b j ,
$ d i rective=$ t h i s - >getOrCreate ( $ se c t i o n ,

$ s ecname ) ;

$ ke y ,

$val ) ;

$di rect i ve - > s e t Content ( $val ) ;

private function getOrCreat e ( Config_Container $ cont ,

$name,

$value=nu l l )

$ i t emtype=i s_nu l l ( $ va l ue ) ? ' s e c t i on ' : ' di rective ' ;


if

( $ c h i l d = $ cont - > s earchPath ( a rray ( $name )

) {

return $ chi l d ;
return $con t - >crea t e i t em ( $ i temtype ,

funct i on

toSt ring ( )

$name ,

nu l l ) ;

return $ t h i s - >rootOb j - >toStri ng ( $ t h i s - >type ) ;

Con f i g . php. PEAR



. r e qu i r e .
,
C o n f i g , - C o n f i g C o n f i g_C o n t a i ne r . Con f i g
.
MyCo n f i g C on f i g
.
.
$myconf = new MyConfig ( ) ;
$myconf->set ( "di recto r i e s " ,

"pre f s "

$mycon f - > s e t ( "di recto ries " ,


$myconf->set ( "gene ra l "
,

" s cratch " ,

" / tmp/myapp /pre f s " ) ;


" / tmp / " ) ;

"ve r s i on " ,

" 1 . 0" ) ;

echo $mycon f ;

L-.
< c on f i g >
<di r e ct o r i e s >
< p re f s > / tmp /myapp / p r e f s < / p r e f s >
< s c r a t c h > / tmp / < / s c ra t ch >
< / d i re c t o r i e s >
< g e ne r a l >
<ve r s i on > l . 0 < / v e r s i o n >
< / g e n e ra l >
< / co n f i g >

, -
,
.
PEAR. Con f i g .

(, , I N I , ).
. Co n f i g .
PEAR API -
h t t p : / /p e a r . php . ne t / . ,
.

1 5. PEAR Pyrus

40 1

PEAR
.
!.
. , PEAR, ,

,
. PEAR, conf i g
, - ,
.
, php . ini error_report ing , .

error_repo r t i ng

ALL

& -

DEPRECATED

PEAR
PEAR
ll PEAR E r r o r .
, - . ,

_

PEAR : : i s E r r o r ( ) .
$ th i s - > root0bj ; @ $ conf- >parseCon f ig ( $ f i l ename ,
if

( PEAR : : i s Error ( $ t h i s - > root0bj


print " :
print " :

".

".

$ t ype ) ;

) {

$ th i s - > rootObj - >getMessage ( )

$ t h i s - > rootOb j - >getCode ( )

. "\n";

. " \n \ n " ;

print " : \ n " ;


foreach ( $ t h i s ->rootObj ->getBackt race ( )

as $ ca l l e r )

print $ cal ler [ ' c l a s s ' ] . $ c a l l e r [ ' type ' ] ;


print $ cal l e r [ ' funct i on ' J . " ( )

";

print " " . $ c a l l e r [ ' l i ne ' ] . " \ n " ;


die;

,
PEAR : : isErro r ( $ th i s ->root0b j

Con f i g : : pa r s e C o n f i g ( ) .

.
$ t h i s - >root0bj ins tanceof PEAR_Error

, , $ thi s - > r o o t Ob j PEAR_E r r o r , C o n f i g_Co n t a i n e r .


, PEAR_E r r o r ,
.
: getMe s s a g e ( ) , ; g e t C ode ( ) , ( ,
, , );
getBa c k t r a c e { ) , .

, . , g e t Ba c kt r a c e ( )
, , .
. 1 5. 1 .

402

IV.

1 5. 1 . , PEAR Error : : getacktrace ( )


_

file

-
,
( )

, ( : : - > )

args
class
func t i o n
t yp e
l i ne

, PEAR E r r o r .
5. , ,
4 , PEAR_E r r o r .
PEAR_E r r o r , ,
,
PEAR_Ex c e p t i o n . C o n f i g , ,
XML_Fe e d_P a r s e r ,
.
_

$ s ource= " notthere " ;


try

{
$myfeed = new XML_Feed_Pa rser ( $ source ) ;

catch ( XML_Feed_Parser_Excep t i on $
print
print
print
print
print
print

" : "
" : "
" : "
" : "
" : "
" : " ;

print_r (

) {
" \ n" ;

$ e - >getMessage ( )
$ e - >getCode ( )

" \n" ;

$ e - >getErrorClass ( )

"\n" ;

$ e - >getEr rorMethod ( )

" \n ;

$ e - >getT raceAs S t r ing ( )

" \n" ;

$ e - > getErrorDa t a ( )

) ;

PEAR , PEAR_Ex c e p t i o n .

, ,
c a t ch .
PEAR_Exce p t i on . , Except i on.
, 4.
. . g e t E r r o r
C l a s s ( ) g e t E r r o r M e t hod ( ) .
. g e t E r r o r D a t a ( )
,
. PEAR_ Excep t i o n
Exce p t i o n.
PEAR Excep t i o n .
PEAR :
: g e t C a u s e ( ) . - E x c ep t i o n , .
, n u l l , .
PEAR Ex c e p t i on Observer.
.
. - .
_

1 5 . PEAR Pyrus

403

class MyPearException extends PEAR_Exception


class MyFeedThing {
function acqui re ( $ source ) {
try {
$myfeed = @new XML_Feed_Parse r ( $ source ) ;
return $rnyf eed;
catch ( XML_Feed_Parser_Exception $ )
throw new MyPearExcept ion ( " " , $ ) ;

PEAR_Except i on .
XML_Feed_Pa r s e r . XML_Feed_Pa r s e r
, MyPearExcep t i on ,
.
. .
.
class MyFeedCl ient {
function
construct ( ) {
PEAR_Exception : : addObserver ( a rray ( $thi s , "notifyError" ) ) ;
function proces s ( ) {
try {
$feedt = new MyFeedThing ( ) ;
$parser = $ feedt ->acquire ( ' wrong . xml ' ) ;
catch ( Exception $ ) {
print " . . \ n " ;

function notifyError ( PEAR_Exception $ ) {


print get_class ( $ )
" : ";
print $e->getMessage ( ) . " \n " ;
$cause
$ e - >getCause ( ) ;
i f ( i s_obj ect ( $ cause ) ) {
print " [ ] " . get_clas s ( $ cause ) . " " '
print $ cause- >getMessage ( ) . " \n " ;
else i f ( is_array ( $ cause ) ) {
foreach ( $cause as $ sub_e ) {
print " [ ] " . get_class ( $ sub_e ) .
print $ s ub_e->getMes sage ( ) . " \n " ;
=

" "
.

'

print " - - - - ------------ - - - - - - \n " ;

$client = new MyFeedCl i ent ( ) ;


$cl ient->process ( ) ;

, ,
. .

404

IV.

, . ,
. PEAR_Except i o n : : addOb s e rv e r ( ) -
. ,
, , .

PEAR_Excep t i o n. MyFeedC l i ent ,
.
p r o c e s s ( ) MyFe edThi ng :
: acqu i re ( ) , XML _ Feed_ Pa r s e r .
.
. not i fy E r r o r ( ) - ,
MyFeedCl i en t . ,
PEAR_Excep t i on.
, .
, .
PEAR Except i o n : : getCause ( ) .
Except ion, . "
" , .
_

XML_Feed_ Pa rs e r_Except i on : I nva l i d i nput : t h i s i s not v a l i d XML


MyPearExcep t i on :
[ ] XML_Feed_Pa r s e r_Except i on : I nva l id i nput : t h i s i s not va l i d XML

----------

- ,
( XML_ Feed_ Pa r s e r , - MyFeedThing ) . XML_ Feed_
Parser_Excep t i on ,
MyPea rExcep t i o n .

PEAR
PEAR
. ?
PEAR.

package . xml
package . xml
PEAR.
,
, . PEAR package . xml
, , URL,
t a r g z i p .
,
, , .
, ,
package . xml .
-

$ pear install baddialek t . tgz

could not ext ract t he p a c kage . xml f i l e f rom " badd i a l e kt . t g z "
Cannot i n i t i a l i ze ' badd i a l e kt . tg z ' , i nval id o r m i s s ing package f i le

1 5. PEAR Pyrus

405

Package "baddi a l e kt . t g z " i s not va l i d


i n st a l l f a i l ed

PEAR ,
package . xrnl .
. pac kage . xrnl , ?


package . xml L.
package.
< ?xml versio=" l . 0 " ecodig=" UT F- 8 " ? >
<package packagerversio=" l . 4 . 1 1 " version=" 2 . 0 "
xmls="http : / /pear . php . net /dtd/package-2 . 0 "
xmls : tasks="http : / /pear . php . et /dtd/tasks - l . 0 "
xmls : xsi="http : / /www . w . org / 2 0 0 1 /XMLSchema-istace "
xsi : schemaLocat i o=" http : / /pear . php . et /dtd/tasks-l . O
http : / /pear . php . et /dtd/tasks - l . O . xsd
http : / /pear . php . et/dtd/package-2 . 0
http : / /pear . php . et /dtd/package-2 . 0 . xsd">
< ! -- - - >
< /package>

. PEAR
. . .

ll

<ame>Dialekt</ame>
<chael>pear . example . com< /chael>
<summary>ae , -
ooco< /summa ry>
<descriptio>yc ,

!
< /descriptio>
< ! - - -->

.
m ,
. surnma r y .
des c r i p t i o .
, channe l .
, uri.
URI, .
<uri >ht tp : / /www . example . com/proj ects /Dialekt- l . 2 . l< /uri>

, .
. t g z .
"
. l ead.
.

<l ead>
<ame>Matt Zads tra< /ame>
<use r>mattz< /user>

406

IV.

<ema i l >ma tt@getinstance . com< /ema i l >


< a c t i ve>yes < / a c t i ve >
< / lead>

.
l ea d deve l o p e r , c o n t r i b u t o r h e l pe r.
, R-,
R-. u s e r ,
PEAR.
,
, , .
,
, .
<date>2 0 1 0 - 0 2 - 1 3 < /date>
< t i me > l 8 : 0 1 : 4 4 < / t ime>
<ve rs i on>
< r e l ease> l . 2 . 1 < / release>
<api > l . 2 . 1 < / api>
< / vers ion>
< s tai l i ty>
< re l ease>be t a < / release>
<ap i >beta</api>
< / stab i l i t y>
< l icense u r i = " h t tp : / /www . php . net / l icens e " > PHP Li cense< / l i cense>
<notes >i n i t i a l work< /notes>

,
. , ve r s i o n ,
r e l e a s e . PEAR
. ,
Dialekt 1 .0.0, , m ,
0.2. l . PEAR
, ,
. , api
. .
s t a i l i t y r e l e a s e a p i .
: s n a p s h o t , deve l , a lp h a , b e t a s t a e :
, .

(, GPL GNU, ),
l i cens e .
s umma r y de s c r i p t i on, no t e s
.

con ten ts
, .
con t e n t s , (
, t a r
g z i p) . , d i r
file.
.

1 5 . P EA R Pyrus

407

<contents>
<di r name= " / " >
<dir name="data ">
< f i l e name= " a l i g . txt" role="data" / >
< f i l e name="da l e k . txt" role= "data " / >
</dir> < ! - - /data - - >
<di r name= "Dialekt " >
< f i l e name= "Al i G . php" role= "php " />
< f i l e name= " Dal e k . php" role="php" />
</dir>
</dir>
</contents>
PEAR , (
r) . . 1 5.2.
1 5.2.

php
-
test

script

data

doc

PEAR

php_d i r
test dir
in dir

/ us r / l o ca l / s h a re / p e a r
/us r / l o ca l / s h a re /pea r / t e s t s / < a e>
/us r / l o c a l / i n

data di r
doc d i r

/us r / l o c a l / s h a r e / p e a r / da t a / <ae>
/us r / l o c a l / s h a r e / d o c / pe a r / <ae>

, doc, data t e s t
. doc_d i r ,
data_d i r t e s t_d i r ,
.
PEAR , .

,
pear.
$
$
$
$
$

pear
pear
pear
pear
pear

config-set
config-set
config-set
config-set
config-set

php_dir
data_dir
bin_dir
doc_dir
test_dir

/php/li/
/php/li/data/
/php/in/
/php/li/doc/
/php/li/test/

. Pyrus conf i g- set s et.

PEAR , ,
. 1 5.2. l ib i n c l ude:
php . i n i . ht ac c e s s i n i_s e t ( )
. , i n .
.
Dia l e k t .
.
. /package . xml
. /data

408

IV.

. /data/dia lek . txt


. /data/al i g . txt
. / script
. / script /dialekt . sh
. / script /dialekt . bat
. / c l i -dialekt . php
. / Dialekt . php
. / Dialekt
. / Dialekt /A l i G . php
. / Dialekt / Dal e k . php

, PEAR
. , data s c r i p t .
-. PEAR (
/us r / l o c al / share/pear) . D i a l e kt . php ,

.
D i a l e kt .
requi re_once ( " Dialekt . php " ) ;

- (Da l e k . php Al i G . php}


D i a l e k t , PEAR (
-
). D i a l e k t . php.
Dialekt ,
, PEAR.
Dialekt ,
. PEAR.
conten t s .
<contents>
<dir name= " / " >
<dir name="dat a " >
< fi l e name=" a l i g . txt" role="data" / >
< f i l e name="dal e k . txt" role="da t a " / >
< / di r> < 1 -- /data -->
<dir name= " D i alekt " >
< f i l e name="Al i G . php " role= " php" / >
< f i l e name="Dalek . php " role="php" / >
< / di r> < ! - - /Di alekt - - >
<dir name= " s cript " >
< f i l e name= "dialekt . bat" role=" script " >
<tasks : repl ace from=" @php_dir@ " to="php_d i r "
<tasks : repl ace from=" @in_di r@ " to="in d i r "
<tasks : replace from=" @php_in@ " to="php_in"
< / fi le>
<file name="dialekt . sh " role= " s cript " >
<tasks : replace from= " @php_dir@ " to="php_d i r "
<tasks : replace from= " @in_dir@ " to="i n d i r "
<tasks : replace from=" @php_in@ " to="php_in"
< / fi le>
</dir> < ! - - /script -->
<file name= " c l i -dialekt . php" role= "php" / >
<file name=" Dialekt . php " ro le="php " >

type= "pear-config" / >


type="pear-config" / >
type="pear-config" / >

type="pear-config" / >
type="pear-config" / >
t ype="pear-config" / >

1 5. PEAR Pyrus

409

<tas ks : repl ace f rom= " @bin_di r@ " to="in dir" type="pear -con f i g " / >
</ fi le>
< /dir> < ! - - / -->
</contents>

. t a s ks : replace
PEAR -, from,
p e a r - con f i g t o . D i a l e kt . php,
, .
< ?php
/*
* n -, CLI
* @bin_dir@ /dialekt
*/
class Dialekt {
const DIALEKT ALI G= l ;
const DIALEKT DALEK=2 ;
11" .
)


.
/*
* -, CLI
* /home/mattz /php/in/dialekt
*/

- ,
. .
, ,
, , .
depende n c i e s - ,
PEAR.
<dependencies>
<required>
<php>
<min>S . 3 . 0< /min>
</php>
<pearinstaller>
<min>l . 4 . 1< /min>
</pearinsta l l er>
< ! -- - - >
< / requi red>
< /dependencies>

php. pea r i n s t a l l e r min, max exclude.


exclude , ,
, . pea r i n s t a l l e r
,
.

41

IV.

required .
PEAR .
, - (, zlib GD) .
, Dialekt Fandango
1 0.5.0 .
<package>
<name>Fandango</name>
<channel >pea r . example . com< /channel >
<min>l 0 . 5 . 0</min>
< /package>

channe l ; , pear
, - ( ,
). channe l , uri. uri
.
<package>
<name>Fandango</name>
<uri>http : / /www . exampl e . com/packages/ fandango-1 0 . 5 . 0 . tgz</uri>
< /package>

p a ckage ,
p e a r i n s t a l l e r , c on f l i c t s , ,
.
p a c kage, extension, o s arch.
. 1 5.3.
1 5.3. package . xml

php
p a c kage
exten s i o n

-
PEAR
- ( , ,
zlib GD)

a r ch
os

.
r e qui r e s opt i o na l .
. PEAR
, , , , .
o p t i o n a l ,
.
p e a r i n s t a l l -
pear install - package . xml

PEAR (
, - Pyrus ,
). -
, ,
.

1 5. PEAR Pyrus

41 1

phprelease
content s ,
phpre l e a s e , ,
.
php r e l e a s e .
<phprelease>
<instal lconditions>
<os>
<name>unix</name>
< /os>
< / i ns tallconditions>
< fi le l i st>
<install as="dialekt" name=" script/dialekt . sh" />
<install as= "dal ek" name=" data/da l e k . txt" / >
<install as= " a l i g " name= "dat a / a l i g . txt " / >
<i gnore name= " script/dia lekt . ba t " / >
< / filelist>
< /phprelease>
<phprelease>
<installcondit ions>
<os>
<name>windows< /name>
< /os>
< / instal lcondit ions>
< fi le l i st>
<install as= "dialekt " name= " s cript/dialekt . ba t " / >
<install as="dalek" name="data/dalek . txt " / >
<install as="alig" name="dat a/al i g . txt " / >
<ignore name=" script /dialekt . sh" />
< / f i lelist>
< /phprelease>

i n s t a l l condi t i o n s .
phpre l e a s e , . -
o s , extens i on, a r c h php. , ""
. , php r e l e a s e . i n s t a l l
condi t i on s , ,
. .
u n i x phpre l ea s e . i n s t a l l .
d i a l ekt . sh d i a l e k t .
,
txt. d i a l e kt

d a t a . ,
as i n s t a l l ,
cont e n t s . ,
<data d i r > / d i a l e k t / d a l e k <data d i r > / d i a l e kt / a l i g .
: U n ix
d i a l ekt . b a t . i gnore. ,
.
.

41 2

IV.


, package . xml ,
, .
PEAR. ,
, .
$ pear package package . xml

Ana lyzing Dialekt/Al i G . php


Analyz ing Dialekt/Da l e k . php
Analyz ing c l i -dialekt . php
Analyz ing Dialekt . php
Package Dialekt- 1 . 2 . l . tgz done

t a r g z i p (
, , package . xml ) ,
. .
, URI
u r i .
, , ,
.


? .
PEAR
.

URL .
,
, .
.
.
,

root -,
;

- (, Apache)
(, pea r . yourserve r . com) .

. ,
,
Github (h t tp s : / /g i t hub . com/ ) . ,
, .

Pirum
Pirum - ,
PEAR .
h t t p : / /pi rum . sensiolabs . org/. Pirum
PEAR. /us r / l o c a l /www/pea r / htdoc s ,
URL, .

1 5 . PEAR Pyrus

41 3

http : / /pea r . l . / . ,
PEAR.
$ pear channel-discover pear . pirum-project . org

Adding Channe l " pe a r . p i rum-p ro j e c t . or g " s u c ceeded


D i s covery of channel " pe a r . pi rum-p ro j e ct . or g " s u c ceeded

-------

------
--

....

$ pear install pirum/Pirum

down loading P i ru- 1 . 1 . 5 . t g z


S t a r t i ng t o downl oad P i r um- 1 . 1 . 5 . t g z
. . . . . . done : 1 5 , 6 5 8 byte s

( 1 5 , 658

byt e s )

-------

Pirum r p i rum . xl
PEAR. ,
URL, .
<server>
<name>pear . example . com< /name>
<summary>pep PEAR< /summary>
< a l ias>getinstance</alias>
<url>http : / /pear . example . com/ < /url >
< / server>
.
$ pirum uild /usr/local/www/ pear/htdocs

Runn ing the bui l d command :


I NFO
P a r s i n g package
INFO
Bui l d i ng channel .
I NFO
Bui lding a i n t a i ne r s .
INFO
Bu i lding catego r i e s .
I NFO
Bu i l ding package s .
I NFO
Bu i l ding cop o s e r repos i t o r y .
I NFO
Bu i l ding r e l e a se s .
I NFO
B u i l ding i ndex .
INFO
Bu i l ding feed .
I NFO
Updat i ng PEAR s e rv e r f i l e s .
I NFO
Command bu i l d run s u c c e s s fu l l y .
! PEAR! ,
. ,
.
$ pear channel-discover pear . example . com
----
-._
....
_.
.
....
._
_.
....
.....
....
....

....
....
.
_...
.
_
_,
*
S
S
__
_.
__
._.
....
....
.
, __
._
._
._
_.
._
.

,
_.
J

INFO Updat i ng PEAR s erve r f i l e s .


Addi ng Channe l " pea r . exap l e . com" succeeded
D i scovery o f channe l " r . l . " succeeded
, .
, -,
Pium http : / /pear . l . (. 1 5. 1 ) .

41 4

IV.

. 1 5 . 1 . PEAR



PEAR. .
$ pirum add /usr/local/www/pear/htdocs Dialekt-1 . 2 . 1 . tgz

Runn i n g the add command :


INFO Pa r s i ng package D i a lekt 1 . 2 . 1
INFO Bui l d i ng channe l .
INFO Bui l d i n g ma i nt a i ne r s .
INFO Bui l d i n g catego r i e s .
INFO Bui ld i n g package s .
INFO Bui ld i n g package D i a l e k t .
INFO Bui ld i n g comp o s e r repos i t o r y .
INFO Bui l d i n g re l e a s e s .
INFO Bui l d i n g r e l e a s e s f o r D i a l e kt .
INFO Bui l d i n g r e l e a s e 1 . 2 . 1
INFO Bui l d i n g i ndex .
INFO Bui ld i ng feed .
INFO Updat i n g PEAR s e rv e r f i l e s .
INFO Command add run succe s s fu l l y .
! PEAR.
. chann e l - d i s cover
r . examp l e . ,
d i a l e kt , .

1 5. PEAR Pyrus

41 5

$ pear install getinstance/dialekt


---------;\ -1111)1f'""'---

down l o a d i ng D i a l e kt - 1 . 2 . 1 . t g z

. . .

S t a rt i n g t o down l o a d D i a l e kt - 1 . 2 . 1 . t g z
. . . . done :

1,

inst a l l o k :

780

( 1 , 780

byt e s )

byt e s

channe l : / / p e a r . l oc a l ho s t / D i a l e kt - 1 . 2 . 1

, Dialekt
, .
(. 1 5.2).

. 1 5.2.
. PEAR,

, OpenPear (ht t p : / / openpear . org / )

41

IV.


PEAR ,
. .
PEAR,
. p a c kage . xml PEAR (
Pyrus)
. ,
,

.
PEAR
.
.
Phlng - .

1 6
,,

1>


phpDocumentor

/);
-

@@@

'/'

.
. , , ?
, ? , ? -
, ,
. ,
.
,
, .
.
; .

phpDocumentor: phpDocumentor
.

:
DocBlock.

: DocBlock
, .

: -
.

-
.
. . , , , .
. (
- ).
. , - .
, , ,
. , ,
. .
. ,
. . -

418

IV.

( )
. .
, .
,
, .
.
,
. ,
. "
, . ,
,
, ,
. .
, , ,
.
. ,
. .
, .
, ,
. , , ,
- ,
.
,
, , .
,
. ,
.

-. .
phpDocumentor , Java
avaDoc".
,
(API) ,
.


phpDocumentor -
PEAR.
$ pear channe l - di scover pear . phpdoc . org
$ pear install phpdoc/phpdocumentor
. PEAR Uix,
pear root.
h t tp : / /pea r .
phpdo c . o r g phpDocu
mentor .

1 6 . R phpDocumetor

41 9

phpDocumentor phar ( php)


h t t p : / /phpdoc . o rg /phpDocume n t o r . pha r . phpDocumentor
.
$

php phpDocumen tor . phar - h



. phpDocumentor ,
. -
.

"megaquiz". , couna nd qu i z t o o l s ,
. . phpDocumentor

. ,
,
. phpDocumentor - phpdoc .
. .
$

phpdoc - -di rectory=megaqu i z / \


- - t a rget=docs/megaqu i z / \
- - t i t le= ' Mega Qui z '

- - templ ate=abstract

- - d i re c t o r y ,
. - - d i r e c t o r y
-d . - - t a rg e t
( - t ) (.. ,
). - - t i t l e
( - t i ) . PhpDocumentor ,
.
- - t emp l a t e .
Abstract,
.
h t t p : / /www . phpdoc . o r g / t emp l a t e s .

Clean, . PhpDocu
mentor - - t e mp l a t e .
$

phpdoc - -d i rectory=megaqu i z / \
- -target=docs/megaqu i z / \
- - t i t l e= ' Mega Qu i z '

,
.
. 1 6. 1 .
, ,
, .
. . 1 6.2
Counand, 1 1 , "
".

420

IV.

. 1 6 . 1 . , phpDocumentor

. 1 6.2. Command

1 6. phpDocumentor

421

phpDocumentor , , Cornmand

. :
e xecute ( ) .
,
,
, .
, .
-

DocBlock
DocBlock ,
.
-
.
/**
* DocBlock
*/
phpDocumentor DocBlock,
.
, (
- , , ).
, . @
.
DocBlock, , phpDocumentor ,
.
/**
* @package command
*/
(
, ), phpDocumentor
. Clean
,
. , Abstract,
,
. Abstract.
$

phpdoc --di rect ory=megaqui z / \

--target=docs/megaqu i z /
- - t i tle= ' Mega Qui z ' \
- - template=abst ract

. 1 6.3 phpDocumentor, .
: . 1 6 . 3 , c ornmand, q u i z o b j e c t s
qui z t o o l s ,
.
.
command c omma nd. . ,
Cornmand,
command, . , @package
. -

422

IV.

, .
.

. 1 6.. , er @package


,
DocBlock. ,
.
Command.
/**
*
*
*

Defines core functiona l i ty for commads .


Commad classes perform spec i f i c tasks i s ystem via
the execute ( ) method .

*
*
*
*

.
Commad
execute ( ) .

*
*
*
*

@package commad
@ author Clarrie Grundie
@ copyright 2 0 1 5 Amridge Technologies Ltd

*/

abstract c l a s s Command {
abs tract function execute ( CommandContext $ context ) ;

1 6. phpDocumentor

423

DocBlock . -
(). .
. .
.
,
. . . , ,
.
@author @copyright, .
. 1 6.4.

. 1 6.4.
, phpDocumentor,
, , - phpDocumentor
, , .
. DocBlock .
phpDocumentor ,
, DocBlock, ,
.
Command - .


, ,

.
.

424

IV.

DocBlock
. @ p a c kage
. , DocBlock
,
.
.
.
Doclock
,
. )], @ l i cense. @ l i cense
URL, .
/**
* @ l i cense http : / /www . exampl e . com/ l i c . html Borsetshire Open Li cense
* @package command
*/
URL

@ l i cense phpDocumentor.


, ..
. ,
, ,
. phpDocumentor
@var.
, CommandContext.
class CommandContext {
/**
* The app l i ca t i on name .
* Used various cl ients for error mes sages, etc .
*
* .
* . .
*
* @ var st ring
*/
pu ic $appl icati onName ;
/**
* Encapsulated Keys /values .
* This class i s essent i a l l y wrapper for thi s array.
*
* "-" .
* , ,
* @var array
*/
a rray ( ) ;
private $params
/**
* An error mes sage .
* .
* @var s t ring

1 6 . phpDocumentor

425

*/
private $ e rror

"";

11 . . .

,
- . @va r ,
. . 1 6.5.

. 1 6.5.


. , - ,
. . ,
, .
Doclock ,
:
.
@param. @ p a r am ,
, .
5 ,
, .
@ r e t u r n . @ r e t u r n ,
.
.

426

IV.

/**
* Perform the key operatio ecapsulated the clas s .
* Commad classes ecapsulate s igle operatio. They
* are easy to add to d remove f rom pro j e c t ,
* sto red after istatiat io d execute ( ) ivoked at
* leisure .
* @param $cotext CommadCotext Shared cotextual data
* @ retur bool false failure, t rue success
*/
/**
* .
* Commad .
* ,
* execute ( )
* .
*
* @param $cotext CommadCotext
* @ retur bool false , t rue
*/

abstract fuct i o execute ( CommadCotext $ cotext ) ;


, ,
. ,
, ,
. " ",

. .
.
. 1 6. 6.


, 5 . 3
, ,
- @package.
. ,
, , phpDocumentor ,
.
"megaquiz" .
. Command
, ,
.
amespace megaquiz \commad;
abstract class Commad (
abst ract fuctio execute ( megaqu i z \commad\CommadCotext $cotext ) ;
. 1 6. 7 ,
.

1 6 . phpDocumetor

. 1 6.6.

. 1 6 . 7.

427

428

IV.


phpDocumentor .

, .
:
(inline tag).
DocBlock , ,
(} , .
,
@ s e e . .
c l as s
c l as s : : method ( )

c l as s : : $property
.
DocBlock CommandContext
, Command :
: execute ( ) .
namespace megaqu i z \command;
/**
* Encapsulates data for pass ing t o , from and between Commands .
* Commands require disparate data according to context . The
* CommandContext obj ect i s pas sed to the Command : : execute ( )
* method and contains data i n key/value format . The class
* automatical l y extracts the contents of the $_REQUEST
* superglobal .
*
* , Command,
* .
* Command .
* CommandContext Command : : execute ( )
* " -" .
* $_REQUEST .
*
* @package command
* @ author Clarrie Grundie
* @copyright 2 0 1 5 Amridge Technologies Ltd
* @ see \megaqui z \command\Command : : execute ( ) the execute ( ) method
*/
class CommandContext
11
. @ see @ l ink
phpDocumetor. ,
. ,
phpDocumetor.
. 1 6.8, @ se e . ,
execute ( ) .

1 6. phpDocumetor

429

. 1 6.8. @see

. phpDocumetor @ see
.
{ @ see class : : method ( ) )
, , ,
phpDocumetor.

l - @ l ik.
URL , .
@ l ik http : / /www . exampl e . com . . .

URL - , -
, .
. Counad
CounadCotex t , Counad : : execute ( )
Couna dCotext .
. - @ l i k @ see. @uses
.
/**
* Perform the key operat io ecapsulated the class .
*
* @param $cotext Shared cotextual data
* @ retur bool
false fai lure, t rue success
* @ l ik http : / /www . exarnpl e . com More ifo
* @uses \megaqui z \cornrnad\CornrnadCotext
*/
abst ract fuctio execute ( CornrnadCotext $cotext ) ;

430

IV.

phpDocumentor @ us e s ,
Comman d : : execute ( ) " U s e s : CommandContex t " .
CommandCont e x t : " Used Command : : execute ( ) " .
. @uses .
, phpDocumetor.
@ l in k @ u s e s . 1 6.9.

. 1 6.9. , @ l ink @uses


phpDocumentor.
DocBlock ,
, ,
. ,

. ,
.
,
, phpDocumentor,
h t tp : / / www . phpdoc . org.

1 7

Git

)/)
@@@
-----

,
- . -
?
? , , "
" , - (, ,
, ,
). ,
.
, , ,
, - .
,
. "" , .
? Git -
, .
.
:

Git.

: .

: .

: .

: .


, (
, ).
.
? ,
? ,
"" ,
. ,
. , . .
, - "" , . ,

432

IV.

.
. ,
-. ,
? , ?
Git
. Git
, . ,
,
.
,
.
Git . ,


.
. ,
, ,
, ,
.

.
,
, ,
.
,
. ,
,
. ,
, .
!
. , ,
. , 2
. , 1 . ? , .
.
2 ,
? Git .
,
1 . .
2 (.. ),
1 . .
. Git - .
Subversio1 (http : / /subversion . apache . org/) Mercurial (http : / /mercurial . selenic . /).
, . ,
Git, Pro Git (Apress, 2009).
http : / / gi t - scm. com/book.

Subversion .

. .

1 7. Git

433

Git
Unix (, Linux FreeBSD),
Git- .
.
$ git help

, r,
. Git,
.
, Yum Apt. Git
http : / / g i t - s cm . com/downloads .
. , , .
$ .

Git
G i t
. -, - Git
, ,
. -, , Git
,
.
,
.
Git
, ,
.
, ,
Git.
, root Uni-.


Git
. SSH
, root .
/var/g i t .
root ,
.
$ mkdir - /var/git/megaquiz
$ cd /var/git/megaquiz /

/var/git,
- megaqui z .
.
$ sudo git ini t --r

I ni t ial i z ed empty G i t repository i n /va r / g i t /megaqu i z /

434

IV.

- -bare Git
, GIT_D I R
. , Git
.
roo t / va r / g i t ,
, .
g i t g i t .
$ adduser git
$ chown -R git : git /var/git


,
,
. ,
.

. .
$ chmod -R g+rws /var/git

g i t /var/git
,
g i t .
g i t,
. ,
g i t .
gi t,
.
$ usermod -aG git

g i t .



gi t . , SSH,
.
. ,
. ,
Git .
,
.

SSH .
, -
SSH. . , UNI- .
, . ssh
id_ rsa . pub. ,
. UNI-
ssh- keygen ,
.

435

1 7. Git
$ ssh-keygen
$ cat . ssh/id_rsa . pu


.
SSH g i t .
. s sh /
authori zed_keys . . s sh,
. (
g i t . )
.

$ mkdir . ssh
$ chmod 0700 . ssh

authori zed_ keys


vi, .
$ vi . ssh/authorized_keys

. , SSH - ,
. s sh .
.
(Michael Stahke) OpenSSH (Apress, 2005)
SSH.


gi t
, ,
. .
Git.
UNIX ,
. / e t c /pas swd.
, gi t .
git : x : l 0 0 1 : 1 0 0 1 : : /home/gi t : /bin/bash
Git , g i t - s he l l .

Git.
/ e t c /pas swd, 2.
git : x : l 0 0 1 : 1 0 0 1 : : /home/gi t : /usr/bin/git-shell
gi t-s hel l ,
g i t - she l l -commands
(
g i t ) .

-

2 pas swd UN!X.


. . SD-

pw usermod g i t -s /us r /bin/g i t - shel l .
Linux
usermod -s /usr/bin/git-she l l g i t .
.
. .
-

436

IV.

, SSH.

no- interact ive-login, g i t -she l l -commands ,
.
$ su -s /in/ash - git
$ mkdir git-shell -commands
$ echo ' echo " Sorry . No interactive access . " ; '

> git-shell-commands/no
interactive-login
$ chmod 755 git-shell-commands/no-interactive-login

g i t.
, su
bash gi t ,
. gi t- shel l - commands
, .
.

,
.
$ ssh git@my-git-server

Enter pas sphrase for key ' /home /matt z / . s s h / id_rsa ' :
Last log i n : Mon Oct 2 1 1 9 : 0 3 : 5 8 2 0 1 3 from some- remote-server
Sorry . No interact ive acces s .
Conne ction t o my- g i t - s e rver c losed .


Git

/var/gi t /megaqui z .
,
, . . ,
,
, phpDocumentor, ,
..
. , ,
. gi tignore . UNIX
man gi tignore. , ,
lk- , ,
.
http : / /git -scm . com/docs/giti gnore.
,
Git. ,
.
$ git config --global user . name "matt z "
$ git config --global user . email "matt@ getins tance . com"

1 7 . Git

437

,
.
.
$ cd megaquiz
$ git init

I n i t i a l i zed emp t y G i t repo s it o ry i n / home /ma t t z /work/megaqu i z / . gi t /


:
$ gi t add .

Git ,
megaqu i z .
: (unmodified),
(modified) (staged) .
.
$ git status

branch ma s t e r
I n i t i a l commit
Changes t o commi t t e d :
( use " g i t rm - - cached < f i l e > . . . " t o uns t a g e )
new
new
new
new
new
new
new

file :
f i le :
f i le :
file :
file :
file :
f i le :

command/Command . php
command/CommandContext . php
command/ Feedbac kCommand . php
command/Logi nCommand . php
ma i n . php
qu i zob j e c t s / U s e r . php
qu i z tool s /Acce s sManage r . php

, git add
.
, .
$ gi t commi t -m ' my first commit '

[ma s t e r ( root - commit ) f 4 4 5 4 a f ] my f i r s t commit


7 f i l e s change d , 2 1 4 i ns e rt i on s ( + ) , de l e t i on s ( - )
create mode 1 0 0 7 5 5 command/Command . php
create mode 1 0 0 7 5 5 c ommand/CommandContext . php
create mode 1 0 0 7 5 5 command/ Feedbac kCommand . php
create mode 1 0 0 7 5 5 comma nd / Logi nCommand . php
create mode 1 0 0 7 5 5 ma i n . php
creat e mode 1 0 0 7 5 5 q u i z obj ect s /U se r . php
create mode 1 0 0 7 5 5 qui z t oo l s /Acc e s sManage r . php
-m .
, Git
.
, CVS
Subversion, , .

438

IV.

,
, ,
, ,
.
, Git
.
,
. Git
ma s t e r . ,
.
$ qi t branch

* ma s t e r
- Git,
, , (
). ,
mas t e r .
, , -
. .
$ qit remote add --track master oriqin qit@myqitserver : /var/qi t/meqaquiz

,
, , . , "
" Git: " o r i g i n .
,
ma s t e r o r i g i n" .
, G i t o r i g i n ,
.
$ qit remote -v

o r i g i n g i t @mygi t s e rve r : / va r / g i t /megaqu i z ( fe t c h )


o r i g i n g i t @myg i t s e rve r : / va r / g i t /meg a qu i z ( push )

'L

!Oi-11:.81('
1

lil'

--
,

"

"

...
W
-

Git.
.
$ qit push oriqin master

Ente r p a s s phrase f o r key ' /home/mat t z / . s sh / i d_rsa ' :


Count i ng obj ect s : 1 2 , done .
De l t a comp re s s io n u s ing up t o 2 threads .
Comp r e s s ing obj e ct s : 1 0 0 % ( 9 / 9 ) , done .
W r i t ing obj ect s : 1 0 0 % ( 1 2 / 1 2 ) , 2 . 65 K i B , done .
Tot a l 1 2 ( d e l t a 1 ) , reused ( de l t a 0 )
g i t @myg i t se rve r : / v a r / g i t /megaqu i z
* [ new branch ] mas t e r - > mas t e r
g i t branch ,
mas t e r .
$ qit branch

1 7. Git
*

439

ma s t e r
remot e s / o r i g i n /mas t e r

. ,
(trackig brach) . , ,
. Git , , ( push)
, mas t r, r i g i n /ma s t r,
. ( clone ) Git
.



"", MegaQuiz. ,
.
Git.
.
,
.
$ git clone git@mygitserver : /var/git/megaquiz
.._.
_
_
_
_
__
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_

Cloning i n t o ' me g a qu i z ' . . .


E n t e r p a s s ph r a s e f o r key ' /home /bo / . s sh / i d_ r s a ' :
remote : Coun t i ng obj e ct s : 1 2 , done .
remote : Comp re s s i n g obj e ct s : 1 0 0 % ( 9 / 9 ) , done .
remot e : T o t a l 1 2 ( de l t a 1 ) , reused ( de lt a 0 )
Receiving obj e ct s : 1 0 0 % ( 1 2 / 1 2 ) , done .
Resolving de l t a s : 1 0 0 % ( 1 / 1 ) , done .
Now both a nd I c a n deve l op l oc a l l y and, when we ' re ready , s h a r e our
code with one anothe r .

. ,
.


, - .
:
, - .
.
. ,
, . - :
, . , .
. , ,
.
qui zobj e c t s / U s e r . php. .
.

440

IV.

< ?php
class User { }
?>
. ,
.
.
< ?php
/**
* @ l icense http : / /www . example . com Borsetshire Open Li cense
* @package qui zobj ects
*/
class User { }
?>
, .
: (unmodified). (modified)
(staged) ? , U se r . php
. ,
.
$ git status

On b r anch mas t e r
Change s not s t aged f o r commit :
( us e " gi t add < f i l e > . . . " t o upda t e what w i l l comm i t t e d )
( us e " g i t checkout - - < f i l e> . . . " t o d i s c a r d changes i n w o r k i ng d i re c t o r y )
modi f i ed : qui zobj e c t s / Us e r . php
no changes added to comm i t ( us e " g i t add" a n d / o r " g i t commit
----W-: ".-.noq

-" )
-."8il
l
------

, Use r . php ..
. g i t add,
.
$ git add quizobjects/User . php
$ git status

On branch ma s t e r
Changes t o comm i t t e d :
( us e " gi t r e s e t HEAD < fi l e > . . . " t o u n s t a ge )
mod i f i ed : qui zobj e c t s / U se r . php
.
$ git counit -m ' added documentation ' quizobjects/User . php

[ ma s t e r 2 3 0 2 dd8 ] added docume n t a t i on


f i l e s cha n g e d , 5 i n s e r t i on s ( + ) , de l e t i on s ( - )

....
"
. ...

._..,.
"
...
..
"
,
_
_
_

g i t c ommi t
. .
, .
$ git push

1 7. Git

441

Enter p a s sphr a s e f o r key ' /home /ma t t z / . s s h / i d r sa ' :


Count i ng obj ect s : 7 , done .
D e l t a comp r e s s i on u s i ng up t o 2 t h reads .
Comp re s s ing obj ect s : 1 0 0 % ( 3 / 3 ) , done .
W r i t ing obj e ct s : 1 0 0 % ( 4 / 4 ) , 4 0 9 byt e s , done .
Tot a l 4 ( de l t a 1 ) , reused ( de l t a 0 )
g i t @myg i t serve r : / va r / g i t /megaqu i z
f 4 4 5 4 a f . . 2 3 02dd8 ma s t e r - > ma s t e r

, ".
.
< ?php
/**
* @package quiz obj ects
*/
class User { )
?>
.
.
, Git
.
$ git commi t - -m 'my great documentation '

[ma s t e r 2 d8 8 0 ] my g r e a t document a t i on
1 f i l e s change d , 3 i n s e rt i on s ( + ) , d e l e t i o n s ( - )

- -- ......

-il'111

U se r . php.
- , , -
. .
. ,
?
$ git push

E nt e r p a s sph r a s e f o r key ' / home /bo / . s s h / i d r sa ' :


g i t @myg i t s e r ve r : / va r/ g i t /megaqu i z
! [ re j e c t e d ] mas t e r - > ma s t e r ( no n - f a s t - forwa r d )
e rr o r : f a i l ed t o push s ome r e f s t o ' g i t @myg i t s e rve r : / va r / g i t /megaqu i z '
p revent you f r om l o s i ng h i s t o r y , non- f a s t - f o rw a rd upd a t e s we re r e j e c t e d
M e r g e the remote change s ( e . g . ' gi t pul l ' ) b e f o r e pushi ng a ga i n . S e e t h e
' Note about f a s t - forwards ' s e c t i o n o f ' g i t p u s h - -he l p ' f o r det ai l s .

li"/'I.
Jllo
-'l'l
....,.
._...,M

, Git push.
,
. U s e r . php
.
$ git pull

E nt e r p a s sphrase f o r key ' / home /bo / . s s h / id r sa ' :


remot e : Coun t i ng obj ect s : 7 , done .
remote : Comp re s s ing obj e ct s : 1 0 0 % ( 3 / 3 ) , done .
remot e : Tot a l 4 ( de lt a 1 ) , reused ( de l t a 0 )

442

IV.

U np a c k i n g obj e ct s : 1 0 0 % ( 4 / 4 ) , done .
From mygi t se r ve r : / va r / g i t /meg a qu i z
f 4 4 5 4 a f . . 2 3 0 2 dd8 mas t e r - > o r i g in /ma s t e r
Aut o-me r g i n g qui z obj e ct s / U se r . php
CONFL I C T ( co n t e nt ) : Merge con f l i ct i n qui zobj e c t s / U s e r . php
Automa t i c merge f a i l e d ; f i x c o n f l i c t s and then commit the r e s ul t .
"11 u

'

...

,._.,.

:n

,..... "!t"'<

Git
, . Git
, .
, ? .
?
? ? Git
,
.
, .
< ?php
/**
<<<<<<< HEAD
* @package qui zobj ects
*/
* @ l icense http : / /www . example . com Borsetshire Open License
* @ package qui zobj ects
*/
>>>>>>> 2 3 02dd80ad0da8 69997 lbd7 0 e 4 9 f 4 3b fd4 3 1 5 1 8
class User { }
?>

Git . ,
, , .
.
" ", . ' HEAD ' . ,
, -
" ".
,
.
< ?php
/**
* @ l i cense http : / /www . example . com Bors etshire Open License
* @package qui z obj ects
*/
/**
* @package qui zobj ects
*/
class User { }
?>


.
$ git add quizobjects/User . php

$ git commit -m ' documentation merged '

1 7. Git

443

[ ma s t e r 4 0 7 6 92 ] documentat i o n merged


.
$ git push


.
, ,
.


git add.
megaqu i z ,
- . g i t add
Git
.
Que s t ion . php.
$ touch quizobjects/Ques tion . php
$ git add quizobjects/Question . php

, ,
Que s t i on . php.
t ouch.
commi t , .
$ git comm.i t -m ' ini tial checkin '

"

....
-
-

."..._
.
"

[ ma s t e r 9 6da 1 0 8 ] i n i t i a l che c k i n
f i l es changed , i n s e rt i o n s ( + ) , de l e t i on s ( - )
create mode 1 0 0 6 4 4 qu i zobj e c t s / Que s t i o n . php
-

Que s t ion . php .


,
, rm.
$ git

quizobjects/Ques tion . php

rm ' qui zobj ect s /Qu e s t i o n . php '

commi t .
, , g i t s t a t u s .
$ git status

On branch m a s t e r
Changes t o commi t t ed :
( us e " g i t reset HEAD < f i l e > . . . " t o u n s t a g e )
de l eted : q u i z ob j ect s /Que s t i on . php

444

IV.

$ qit commit -m ' removed Question '

[ m a s t e r O d5 7 lb2 ] removed Que s t i on


f i l e s changed, i n s e r t i o n s ( + ) , d e l e t i o n s ( - )
d e l e t e mode 1 00 6 4 4 qui z ob j ec t s / Que s t i on . php


add rm .
. .
$ mkdir resources
$ touch resources/ah . qif
$ qit add resources/
$ qit status

----....
....
....
.
....
.
._.
..._
_,.
,._

-----

jH
..,.,_
W. ,
--

O n b r anch ma s t e r
Changes t o commit t e d :
( us e " g i t r e s e t HEAD < f i le > . . . " t o unstage )
new f i l e : r e sources / l a h . g i f
, r e s ources
.
.


,
rm. ,
rm - r . ,
r e s ource s .
$ qit

rm

- r resources/

rm ' re source s / ah . gi f '


, - r .
, commi t .


. ,
.
,

. , (tag)
g i t tag.
$ qit taq

' versionl . 0 ' - m ' release 1 . 0 '

, , , gi t
t a g .

17. Git

445

$ git tag

ve rs ionl . O
.
, gi t push,
--tags.
$ git push --tags

Ent e r pa ssphrase for key ' /home /mat t z / . s sh/ i d_rsa ' :
Count ing obj ect s : 1 , done .
Writ ing obj e ct s : 1 00 % ( 1 / 1 ) , 1 60 byt e s , done .
Tota l 1 ( de l t a 0 ) , reused ( delta 0 )
g i t @mygi t s e rve r : /va r / g i t /megaqu i z
* [ new tag ] ve rs ionl . O > ve r s i onl . 0
-

.
,
.
, -, Git !


, , , -
, ? , ,
, ,
!

. ,
1 .2.0 .
?

. ,
, .
, -
. . ,
, ,
. .
. . , ,

( 3),
.
.
.
g i t
checkout . ,
.
$ git ranch -

* ma ster
remot e s / o r i g in/mas t e r
3 . trunk - "" , "" . - . .

446

IV.

, rna ster
.
.
$ git checkout - megaquiz -branchl . O

Swit ched t o

new branch ' rnegaqu i z -branch l . 0 '

,
, cornrnand/ FeedbackCornrnand . php. ,
.
,
. . ,
.
11" .

$result
$msgSystem->dispatch ( $emai l , $msg, $ topic ) ;
i f ( ! $user ) {
$this->context ->setError ( $msgSystem->getError ( ) ) ;
// . . .
=

. $ result, $user.
.
11" .

$result = $msgSystem- >dispatch ( $emai l , $msg, $ topic ) ;


if ( ! $result ) {
$this- >context- >setError ( $rnsgSystern->getError ( ) ) ;
11" .

rnegaqu i z -branchl . ,
.
$ git ac:\d command/FeedackCommand . php
$ git commit -m ' bugfix '

[megaqui z-branch l . O 5 9 6 3 ] bug fix


1 files changed , 1 insert i on s ( + ) , 1 de l e t ions ( - )

,________,
....,.
...,
...,
"
.. .
.,..,
.
....
-.-..
w
.
.

_
.
........,.,...._....,,...,_,__._,.......,_,,.,_.. _.,_,..._.,_...,._.....,_..

._
..,
__
__
__

,
g i t push.
$ git push -u origin megaquiz -branchl . O

Enter passphrase for key ' /horne/rnat t z / . s sh / i d_rsa ' :


Count ing o b j e c t s : 7 , done .
De l t a cornp r e s s ion u s i ng up t o 2 t hreads .
Cornpress ing obj e ct s : 1 00 % ( 4 / 4 ) , done .
Writ i ng obj ect s : 1 0 0 % ( 4 / 4 ) , 4 3 1 b yt e s , done .
Total 4 ( de l t a 2 ) , reused ( delta 0 )
g i t @rnyg i t s e rve r : / va r / g i t /rnegaqu i z
* [ new b ranch ] rnegaqui z - branch l . O - > megaqu i z -branch l . O
Branch rnegaqu i z-branch l . 0 set up t o t rack remote branch megaqu i z -branchl . O
f rom o r i gi n .

--------r.....,_,....,.-.....,--R---..,.--as:c..,_,.,_,-uu...,.._._,,._..--=-----

,
origin. -u
-

1 7 . Git

447

. g i t push .

.
$ git branch --set-upstream megaquiz -branchl . 0 origin/megaquiz-branchl . O

.
. g i t pul l ,
.
$ git pull
-----....
-----._..
"
..,
.

...
--...

Ent e r pas sphrase for key ' /home /bo/ . s sh/id_rsa ' :
remote : Counting object s : 7 , done .
remote : Compre s s i ng obj e ct s : 1 00 % ( 4 / 4 ) , done .
remote : Tot a l 4 ( de l t a 2 ) , reused ( de l t a 0 )
Unpacking obj e ct s : 1 0 0 % ( 4 / 4 ) , done .
From myg i t server : /var/ g i t /megaqu i z
* [ new branch ] megaqui z -branch l . O - > origi n/megaqu i z -branchl . 0
Al ready up-to-date .

.
$ git checkout - megaquiz-branchl . 0 origin/megaquiz -branchl . O

Branch megaqu i z-branch l . O set up t o t rack remote branch megaqu i z -branchl . O


from origi n .
Swit ched t o new branch ' megaqu i z -branchl . 0 '
.
.
g i t push.
.
.. .
.
$ git branch

ma ster
* megaquiz -branchl . O
remot e s / origin/mas t e r
gi t
checkout, - .
$ git checkout master

Swit ched to branch ' mast er '

_
_
_
_
__
_
..__
,
,.....

command/ FeedbackCommand . php,


. !
, megaqu i z -branch l . .
ma ster.
!
.

448

IV.

class FeedbackCornmand extends Cornmand {


function execute { CornmandContext $context ) {
/ /
11
$msgSystem
ReceiverFactory : : getMes sageSys tem ( ) ;
$ema i l
$context->get ( ' email ' ) ;
$msg = $ context->get ( ' pass ' ) ;
$context - >get ( ' topic ' ) ;
$ topic
$ result
$msgSystem->di spatch ( $ema i l , $ms g, $ topic ) ;
i f ( ' $user ) (
$this- >context ->setError ( $ms gSys tem->getError ( ) ) ;
return false ;
=

$context->addParam ( "user" , $user ) ;


return true;

,
.
, . ,
megaqu i z -branchl .
. , Git
merge.
$ git checkout master
.......,
..
.,...
..,.

.,_

--
--

..-.
....

.._

....

...,.
,,_
"
....
,_.
.,
_...
..,..
....,.
_.,

Swit ched t o b r a n ch ' ma s t e r '

$ git merge megaquiz -branchl . O

Upda t i ng 1 0 2 9 6 6 . . 5 9 6
Fas t - forward
command/ FeedbackCommand . php 1 2 +1 f i l e s changed, 1 i n s e r t i on s ( + ) , 1 de l e t i on s ( - )
. ? , . ,
,

. . , ,
,
.
" ".

, Feedac kCommand ,
, m .
function execute ( CornmandContext $context ) {
11
1 1
$ms gSys tem
ReceiverFactory : : getMessageSys tem ( ) ;
$email
$ context- >get ( ' email ' ) ;
$msg
$ context->get ( ' pass ' ) ;
$ topic
$context- >get ( ' topic ' ) ;
$ result = $msgSys tem->dispatch ( $ema i l , $ms g, $ topic ) ;
=

1 7. Git
if ( ! $result )

449

$this ->context->setError ( $msgSystem->getError ( ) ) ;


return fa l s e ;
$context ->addParam ( "user " , $ u s e r ) ;
return true;
execute ( )
11
11

:
if ( ! $ result ) {
""
MegaQu iz. .
. . .
. . . .
.
.
. .
. .
$ git checkout - new-versionl . 0-branch versionl . O

Swit ched t o

new branch ' new-ve r s i on l . 0 -b r a n ch '

. ,
. .


Glt
.
. .
, , ,
Git - , .
Glt.
. .
.
, .
.
, . ,

. ,
. ,
.
.
.
.

1 8

PH PUnit

,.
'
1;1

//)
@@@

,,, ,,,

-:,....


.
.
, , .
, . .
" ,
, , .
,
. ,
,
. , ,
, .
. ,
, ,
.
, -,
PHPUit, ,
.
PPUit.

: PEAR PHPUnit.

:
(assertlon methods).

: .

: .

: .

.: .

-.:
.

452

IV.

I .
, .
.
, ,
.
.
. ,
.
.
, ,
, .
"
" -
, .
, (
) .
, I
. ,
, , , ,
. ,
.
, .

-.
.
-
. .
" ". ,
, .
, ,
. -
.
. ,
I . ,
, .


. I
. . I .
. ,
.
, I .
,
. . .
U s e r , .

1 8 . PHPUnit

453

class UserStore {
private $users = array ( ) ;
function addUser ( $name , $ma i l , $pass ) {
i f ( i s set ( $this->users ( $mai l ] ) ) {
throw new Except ion (
" { $mai l } . " ) ;
i f ( st rlen ( $pass ) < 5 ) {
throw new Exception (
" 5 . " ) ;
$this->users [ $mai l ]

array ( ' pass ' => $pa s s ,


' ma i l ' = > $mai l ,
' name ' => $name ) ;

return true ;
function not i f yPasswordFai lure ( $ma i l ) {
i f ( i s set ( $ th i s - >users [ $mai l ] ) ) {
$thi s->users [ $mai l ] [ ' failed ' ] =t ime ( ) ;

function getUs er ( $ma i l ) {


return ( $this->users [ $mai l ] ) ;

addU s e r ( ) .
getUs e r ( ) .
. ,
, ,
, . .
$store=new UserStore ( ) ;
$ store- >addUser ( " w i l l iams " ,
"bob@example . com" ,
" 12345" ) ;
$user = $ store- >getUser ( "bob@exampl e . com" ) ;
print_r ( $user ) ;

,
. ,
; , ,
UserStore : : getUser ( ) , ,
. .
, UserStore
,
.
class Val idator {
private $store;
pu ic function

cons truct ( UserStore $ s tore ) {

454

IV.

$this->store

$ s tore;

pu i c function val idateUser ( $ma i l , $pas s ) {


i f ( ' i s_array ( $user = $this->store->getUse r ( $ma i l ) ) ) {
return f a l s e ;
i f ( $user [ ' pass ' ]
return true;

$pass ) {

$this->store->noti fyPasswordFai lure ( $mai l ) ;


return false;

U s e r S t o r e ,
$ s tore.
val i da t e U s e r ( ) , -, , ,
, , -,
r.
, . -,
.
$ s tore
new UserStore ( ) ;
$ s tore->addUser ( " wil l i ams " , "bob@exampl e . com" ,
=

$val idator
new Val i dator ( $ store ) ;
i f ( $va l i dator->vali dateUser ( "bob@example . com" ,
print ", ! \n" ;

"1234 5 " )

"12345"

) ) {

U s e r Store,
Val i da t o r .
.
, .
.
. ,
, - PPUnit.

PHPUnit
PHPUnit - xUnit.
- SUnit, , (Kent Beck)
, Smalltalk. xUnit,
, Java, j Unit
, (Extreme
Programming, ) Scrum,
.
"" PHPUnit
(Sebastian Bergmann), PHPUnit2 (
) 2007 pea r . php . net

1 8. PHPUit

455

pea r . phpuni t . de 1
pear. .
$ pear config-set auto_discover 1
$ pear install --alldeps phpunit

. , , ,
.


, PHPUnit. I O s e r
S t o r e . I
. PHPOni t_Framework_T e s t C a s e . ,
PHPUnit.
.
requi re_once ' PHPUn i t / Framework/Tes tCase . php ' ;
class Use rStoreTest extends PHPUni t Framework TestCase
pu ic function setUp ( ) {
)

pu ic function tearDown ( ) {
)

11 . . .
)

O s e r S to reTe s t . ,
,
.
,
. ,
, ,
.
, , !
.
s etup ( J I ,
I
. tearDown ( J .
,
. . ,
s et up ( J tea r Down ( ) , (fixture) .
Os erSt o re, .
setup ( ) .
.
requi re_once ( ' UserStore . php ' ) ;
requi re_once ( ' PHPUn i t / Framework/TestCase . php ' ) ;
class UserStoreTest extends PH PUni t Framework TestCase
' pear . phpuni t. de 31 20 14 .
PHPUn.it PEAR. ,
https : / /phpuni t . de/ phar. - . .

456

IV.

private $ store ;
pulic function setUp ( ) (
$this- >store
new UserStore ( ) ;
=

puic function tearDown ( ) (


}
pu i c function testGetUser ( J (
$this->s tore->addUser ( " wi l l iams " , " a @ b . com" , " 12 3 4 5 " ) ;
$user
$this->store- >getUser ( " a@ b . com" ) ;
$this->assertEquals ( $user [ ' mai l ' ] , "@ . " ) ;
$this->asse rtEquals ( $user [ ' name ' ] , " w i l l iams " ) ;
$this->assertEquals ( $user [ ' pass ' ] , " 12 3 4 5 " ) ;
=

,
" t e s t " . ,
.
. n n 5.

, ,
, (. . .
" te s t " ) .
.
U s e rS tore ,
s e tUp ( J . s e t Up ( J ,
$ st o r e .
t e stGetUser ( ) UserStore : : add
User ( ) ,
.


(assertion) - .
.
,
$ cheese i s " u " $ p i e i s " appl e " . ,
. -
.
(inline) .
( - Java). PHPUnit
.
a s s ert
Equa l s ( ) .
. ,
. PHPUni t_Framewo r k_TestCase,
. . 1 8 . 1 .

1 8 . PHPUit

457

1 8. 1 . PHPUni t Fram.ework Tes tCase


_

asse rtEqua l s ( $va l l ,


$va l 2 , $del t a , $me s sage )
a s s e rt Fa l se ( $expre s s ion,
$me s sage )
a s s e r t T rue ( $expre s s i o n ,
$me s sage )
a s s ertNotNul l ( $ va l , $me ssage )
a s s e rtNul l ( $ va l , $me s s age )
a s s e rtSame ( $ va l l , $va l 2 ,
$me s sage )

, $va l l
$va l 2 ( $del t a )
$expre s si on.
, ""
$expre s s ion.
, ""
, $val -
, $val
, $val 1 $va l 2
,
a s s e r tNotS ame ( $val 1 , $va l 2 ,
, $va l l $va l 2
$me s sage )
,
a s s e r t RegExp ( $ regexp ,
, $val
$va l , $me s sage )
$ regexp
a s s e rtType ( $ type s t r i n g ,
, $val ,
$va l , $me s sage )
$ t ype st r i n g
asse rtAt t ribut eSame ( $val ,
, $val
$att ribut e , $ c l a s s name , $me s s age ) , $ c l a s s name : : $ t t r ibute
fai l ( )


,
. . .
. .
. . . .
.
? . ?
? . . ,
, ?
, . .
PHPUnit.
, U s e r S tore,
.
11 " .
pu ic function tes tAddUser_ShortPass ( ) {
try {
$this->store->addUser ( " wi ll iams " , "bob@exampl e . com" , " ff " ) ;
$this- > fai l ( "Oaoc - n . " ) ;
) catch ( Exception $ ) {
)

11 . . .

U s e r S tore : : addUs e r ( ) . .
, .
.

458

IV.

t ry. ,
c a t ch . addU s e r ( )
, t ch ,
, f a i l ( ) .
, , -
PHPUnit, PHPUnit_Extens i on s_Except ion
T e s t C a s e . s e t
E x p e c t edExcept i on ( ) , ,
( E x c ep t i on . ).
, , .
.
requi re_once ( ' PHPUn i t / Framewo rk /TestCas e . php ' ) ;
requi re_once ( ' UserStore . php ' ) ;
class UserStoreTest extends PHPUni t Framewo rk TestCase
private $ store;
pu ic function setUp ( ) {
$ this->sto re = new UserStore ( ) ;
pu i c function testAddUser_ShortPass ( ) {
$this->setExpectedException ( ' Except i on ' ) ;
$this->store->addUse r ( " w i l li ams " , "bob@ example . com" , " f f " ) ;


U s e r S t o r e ,
V a l i d a t o r . V a l i da to r T e s t .

Val i d a t o r : : va l ida t e U s e r ( ) .
requi re_once ( ' UserStore . php ' ) ;
requi re_once ( ' Val idator . php ' ) ;
requi re_once ( ' PHPUnit/ Framewo rk/TestCase . php ' ) ;
class Va l i datorTest extends PHPUnit Framework TestCase
pr ivate $va l i dator;
pu i c function setUp ( )
$store = new UserStore ( ) ;
$ s tore->addUser ( " will iams " , "bob@exampl e . com" , " 1 2 3 4 5 " ) ;
$ this->val i dator = new Validato r ( $ store ) ;
pu ic funct ion tearDown ( ) {
}
pu ic funct i on testValidate_CorrectPass ( ) (
$this- >assertT rue (
$this->val idator- >val idateUser ( "bob@ example . com" , " 1 2 3 4 5 " ) ,
" . "

1 8. PHPUnit

459

. . ,
?
t e s t . , PHPUnit
, .

$ phpuni t test/
PHPUnit 3 . 7 . 2 4 Seba s t i an B e r grnann .
T irne : 1 0 4 rns , Merno r y : 3 . 7 5
( 5 t e st s , 1 0 a s s e r t i ons )

. , .
.
.



.
eoa A s s e r t T rue ( ) . PHPUnit .O PHPUn i t Framewo r k
_
_
TestCase ,
PHPUni t Framework Con s t ra i n t .
_
_
Uni t Framework TestCase : : As se r t That ( ) ,
_
.
. UserStore
. ,
.
class UserSto reTest extends PHPUnit Frarnework TestCase
private $store;
pulic function setUp ( ) {
$ this->store
new UserStore ( ) ;
=

// . . . .
pulic function tes tAddUser_dupl icate ( ) (
try {
$ ret = $this ->s tore->addUser ( " wi l l iarns " , " a@b . com" , " 1 2 3 4 5 6 " ) ;
$ret = $this->s tore->addUser ( " stevens " , "a@b . com" , " 1 2 3 4 5 6 " ) ;
sel f : : fa i l ( " . " ) ;
catch ( Except ion $ ) {
$ const

$this->logica lAnd (
$this-> logicalNot ( $this ->contains ( "bob stevens " ) ) ,
$this-> isType ( ' array ' )
);

460

IV.

self : : As sertThat ( $this->store- >getUser ( " a@b . com" ) , $const ) ;

U s e r S t ore,
.
, addUs e r ( ) . catch
.
P H PUni t _ Framewo r k_Cons t r a i n t .
.
$this- >conta ins ( "bob stevens " )

PHPUni t Framework_Cons t r a i nt _T raversaeContains.


A s s e rtThat , ,
, (" stevens " ) .
, :
PHPUnit_Framewo r k_Co n s t r a i nt_Not. ,
Te stCase ( A s s e r t ) .
$this- >logica1Not ( $this ->contains ( "bob stevens " ) )

A s s e rtThat ,
( ) ,
" s t evens " .
. : "
,
" s t even s '"' .
. ,
, A s sertThat ( ) .
,
, . -,
( I
). -,
. .
.
.
$ const

$thi s - >logica1And (
$a_complex_constraint ,
$another_complex cons traint ) ;

. 1 8. 2 ,
T e s tC a s e .
1 8.2. TestCase

greate rThan ( $ num)


conta i n s ( $val )

, S num
() ,
$val
- ,
$ va l , , ,

$ num
S num

ident i ca lTo ( $val )

greate rThanOrEqua l ( $ num)


l e s sThan ( $ num)

1 8 . PHPUnit

461

. 1 8. 2

equa 1To ( $ va l u e , $de l t a= O ,


$depth= l 0 )

$val. $del ta,


,
, $depth

s t ringCont a ins ( $ s t r ,
$ s t r.
$cas e s e n s i t ive=t rue )

mat chesRegularExp re s s i on ( $pa t t e r n )
, $pattern
logicalAnd ( PHPUni t_Framewo r k_

Con s t ra i nt $con s t , [ , $const . . ] )
logicalOr ( PHPUni t Framework_

Con s t raint $con s t , [ , $const . . ] )

logicalNot ( PHPUnit Framework_

Con s t ra i n t $const )


-
.
.
.
.
. s e tUp ( ) t e a r
Down ( ) , ..
, ,
, ..
- .
, , .
,
.
(
),
.
. , ""
, (stubs). ,
, ,
.
.
-
, .
""
, (mock) (stub).
,
,
. , .
PHPUit .
" " . PHPUit ,
, , , -

462

IV.

. ,
,
.
. U s e r S t o r e n o t i fyPas sword
Failure ( ) , .
V a l i d a t o r
. U s e r S t o r e ,
Val i d a t o r , n o t i fyPas s wordFa i lure ( )
, .
class Val idatorTest extends PHPUni t Framewor k Tes tCase
// . . .
pu ic funct ion tes tVal idate_Fal sePas s ( ) {
$ s tore = $this- >getMoc k ( "UserStore " ) ;
$this ->validator = new Val idator ( $store ) ;
$ s tore->expects ( $ th i s - >once ( ) )
- >method ( ' noti fyPasswordFai lure ' )
- >wi th ( $ this->equal To ( ' bob@example . com ' ) ) ;
$ store->expects ( $this ->any ( ) )
- >method ( "getUser" )
->wil l ( $ t h i s - >returnValue ( array ( "name"=> "bob@example . com" ,
"pass "=>" right " ) ) ) ;
$this ->validator->val i dateUser ( "bob@ examp l e . com" , "wrong" ) ;

(flent interjace), ..
. , .
, ,

( ). ,
.
PHPUnit_Framewor k_T e stCase : : getMock ( ) ,
" Us e rS t ore " , , .
.
$ s t ore Val idator.
, UserStore.
V a l i d a t o r , "".
, PHPUnit, expec t s ( ) .
(
PHPUnit_Framework_MockOb j ect_Ma t ch e r_ I nvoca t i o n , ;
T e s t C a s e ,
) . , ..
.
. 1 8. 3 ,
TestCase.
1 8..
TestCase

any ( )

(
-, , )

1 8 . PHPUit

463

. 1 8.3

TestCase

neve r ( )
a t LeastOnce ( )
once ( )
exa c t l y ( $num
at ( $num )




$ num
$ num (
)

. .
. . expects ( ) (PHPUni t _ Framewor k_Moc kObj ect _
Builder_Invocati onMocker, ), method ( ) .
. .
$store = $this->getMock ( " UserStore " ) ;
$store->expects ( $this->once ( ) )
->method ( ' not i fyPas swordFa i l ure ' ) ;

, not i fyPas sword


Fa i lure ( ) . I nvocat i onMocke r : : method ( ) ,
. I nvoca t i onMocker w i t h ( ) ,
.
, ..
. ,
not i fyPas swordFa i l ure ( ) .
$store- >expects ( $ this->once ( ) )
->method ( ' not i fyPasswordFa i l ure ' )
->with ( $ this->equa lTo ( ' bob@ example . com ' ) ) ;

, .
: " $ s tore
, not i fy Pa s swordFa i l u r e ( )
bob@examp l e . " .
. wi th ( ) .
- .
.
$s tore->expects ( $thi s - >once ( ) )
->rnethod ( ' noti fyPasswordFai lure ' )
->with ( ' bob@exarnpl e . ' ) ;

PHPUit ,
.. . , .
I nvoca t i onMoc ke r : : wi l l ( ) method ( ) .
wi l l ( ) ( ,
), .
, TestCase : : returnVal ue ( ) ,
TestCa s e : : onConsecut i veCa l l s ( ) . .
. .
UserStore .
$store->expects ( $this->any ( ) )
->rnethod ( "getUser " )
->wi l l ( $this->returnVal ue (

464

IV.

array ( " name "=> "bob w i l l iams " ,


"ma i l "=> "bob@example . com " ,
"pass " => " right " ) ) ) ;
U s e r S t o r e ,
g e t U s e r ( ) , -
, . w i l l ( )
Tes tCase : : r e turnValue ( ) , ( ,
PHPUni t Framewor k MockOb j e c t Stub Return,
, ).
: T e s t
Case : : onCons e cu t i veCal l s ( ) w i l l ( ) .
,
.

,
. - .
,
. ,
.
U s e r S t o r e ,
, U s e r ,
. .
class UserStore {
private $users

array ( ) ;

function addUs er ( $name , $mai l , $pass ) {


i f ( isset ( $ th i s ->users [ $mai l ] ) ) {
throw new Except ion (
" { $mail ) . " ) ;
$this ->users [ $mai l ] = new User ( $name , $mai l , $pass ) ;
return t rue ;
function notifyPasswordFai l ure ( $ma i l ) {
i f ( i sset ( $this ->users [ $ma i l ] ) ) {
$ t h i s - >users [ $ma i l ] - > fa i l ed ( t ime ( ) ) ;

functi on getUser ( $mail ) {


i f ( i s set ( $ th i s ->users [ $ma i l ] ) )
return ( $this ->users [ $mail ] ) ;
return nul l ;

U s e r .
class User
private $name ;
private $ma i l ;

1 8. PHPUnit

465

private $pass ;
private $ fa i l ed ;
fuctio
costruct ( $, $mai l , $pass ) {
i f ( strle ( $pass ) < 5 ) {
throw w Exceptio (
" 5 . " ) ;
$this- >ame
$this->mai l
$this->pass

$m ;
$mai l ;
$pas s ;

fuctio getName ( ) {
retur $this ->ame ;
fuctio getMai l ( ) {
retur $this->ma i l ;
fuct io getPas s ( ) {
retur $this ->pas s ;
fuctio fai l ed ( $t ime ) {
$this->failed = $ t ime ;

, U s e r S t o reTes t
.
pulic fuctio testGetUser ( ) {
$this->store->addUser ( " wi l l iams " , " a@b . com" , " 1 2 3 4 5 " ) ;
$user
$ this->store- >getUser ( " a@b . com" ) ;
$this>assertEqua l s ( $user [ ' mai l ' J , "a@b . com" ) ;
11 " .
=

, .
pu ic fuctio testGetUser ( ) {
$this ->store->addUser ( "bob w i l l iams " , "a@b . com" , " 1 2 3 4 5 " ) ;
$user
$this ->store- >getUse r ( " a@b . com" ) ;
$this - >as sertEqua l s ( $user->getMai l ( ) , "a@b . com" ) ;
11
=

, ,
.
$ phpunit test/

'

....
.
-

PHPU i t 3 . 7 . 2 4 S e ba s t i a B ergmann .
. . . . FF
T ime : 3 5 9 m s , Memor y : 3 . 7 5
The r e were 2 f a i l u r e s :
1 ) Va l ida t o re s t : : t e st V a l i d a t e C o r r e c t P a s s

466

IV.

Expe c t i ng s u c ce s s fu l v a l idat i o n
Fa i le d a s s e rt in g t h a t f a l s e i s t rue .
/ . . . / t e st /Va l idat o re s t . php : 2 2
2 ) Va l i da t o r T e s t : : t e s t Va l i da t e_ Fa l s e P a s s
Exp e c t a t i o n fa i l ed f o r method name i s e qu a l t o
< s t r i ng : not i f y P a s swordFa i l u r e > when i nvoked 1 t ime ( s } .
Method was expec t ed t o c a l l e d 1 t ime s , a c t ua l l y c a l l ed t imes .
FAI LURES !
T e st s : 6 , A s s e r t i on s : 5 , Fa i lure s : 2 .

V a l idatorTe s t .
Valida t o r : : val idateUser ( ) .
pu i c function va lidateUser ( $mail , $pass } {
i f ( ! i s_array ( $ user
$this->store->getUse r ( $mail } } } {
return fal s e ;
=

i f ( $user [ ' pass ' J


return true;

$pass } {

$this->store->noti fyPas swordFailure ( $mail } ;


return false;

g e t U s e r ( ) . getUser ( } ,
, . getUse r ( )
( ) nul l (
),
i s_ a rray ( ) . , , getUser ( )
, va l idat e U s e r ( ) "".
Va l idat o r
, .
,
.
, , :
" ? !"
- , ,
- .
. ,
. ,
.
,
.
.
. , ,
, , -
. ,
, ,
. ,
, .
.

1 8. PHPUit

467

, 400 ,
t e s t_97 3 8 9 2 . php. ,
?

-
- ,
, API, -. 12
, . ,
- Reque s t ,

, .
.
,
, . , ,
, ,
, .
, , ,
. 1 2
Registy, .
, - ,
, ,
-
.
,

. ,
. ,
WOO, 1 2 1 3, .

-
WOO ,
.
Frot Controller, API.
, Runner . php.
requi re_once ( "woo/control l er /Control ler . php " ) ;
\woo\ controller\Cont rol l er : : run ( ) ;
, ?
?
Reque s t .
/ / \woo\cont rol ler\Request
function ini t ( ) {
if ( isset ( $_SERVER [ ' REQUEST_METHOD ' ] ) ) {
$this ->prope rties
$_REQUEST;
return ;
foreach ( $_SERVER [ ' argv ' ] as $arg ) {

468

IV.

if ( s t rpos ( $arg, ' = ' ) ) {


l i s t ( $ key, $val )
explode (
$this->setProperty ( $ ke y , $val ) ;
=

"

"

$arg ) ;

i n i t ( ) , (
),
$proper t i e s ( ,
s e t P rope r t y ( ) ).
. ,
$ php

runne r . php

cmd=AddVenue venue_name=o

...
.

....

_
_
_
_
-
--"
,._.. "
,
_
_

<html >
<head>
< t i t l e>Add Space for venue bob< / t it le >
< / head>
<body>
< h l >Add Space for Venue ' bob ' < / h l >
<t>
< t r>
< t d>
' ' added ( 5 ) < / td > < / t r > < t r > <td>pl e a s e add n ame f o r the spa c e < / td>
< / t r>
< /t >
[ add space ]
< fo rm method= " p o s t " >
< i nput t yp e = " t ex t " v a l ue = " " name = " space name " / >
< input t yp e = " h idde n " name = " cmd" value="AddSpac e " / >
< i nput t yp e = " h idden " name = " venue i d " v a l ue= " S " / >
< i nput t yp e = " s ubmi t " value=" submit " / >
< / f o rm>
< / body>
< /html>

,
.
r , run ( )
$ a rgv. ,
.
, - , ,
, .
.
, .
hand l e Re quest ( ) .
/ / \woo \control l e r \Controller
function handleRequest ( ) {
$ request = \woo\base\ApplicationRegi s t ry : : getRequest ( ) ;
$_ = \woo\base \Applicat ionRegi stry : : appController ( ) ;

1 8 . PHPUnit

469

whi l e ( $cmd = $app_c->getCommand ( $ request ) ) {


$ cmd->execute ( $ reques t ) ;
\woo\domain \Obj ectWatche r : : instance ( ) - >pe rformOperati ons ( ) ;
$this->invokeView ( $app_c- >getView ( $ request ) ) ;
run ( ) .
. Reque s t ,
App l i ca t i onRe g i s t ry.
Requ e s t ,
, ,
.
-. Reque s t
. -,
. Reque s t ,
. . - -.
,
, .
-
Appl i ca t i onRe g i s t r y : : i ns t ance ( ) ,
. .
ll ,
.
!

Request .

-
.
WOO.

class AddVenueTest extends PHPUnit_Framework_TestCase


function tes tAddVenueVani l l a ( ) {
$this-> runCommand ( "AddVenue " , array ( "venue_name "=>"bob " ) ) ;
function runCommand ( $command=nul l , a rray $a rgs=nul l ) {
$ request
\woo\base \App l i cationRegi stry : : getRequest ( ) ;
i f ( ! is_nul l ( $args ) ) {
foreach ( $args as $ key=>$val ) {
$ request->setPropert y ( $ key, $val ) ;
=

i f ( ! is_nul l ( $ command ) ) {
$ request->setProperty ( ' cmd ' , $command ) ;
woo \controlle r \Cont rol l e r : : run ( ) ;

470

IV.

, ,
, .
runCommand ( ) . .
App l i ca t i onRe g i s t ry Reques t ,
, .
Contro l l e r
R e que s t , ,
.
, ! ,
. ,
.
, .

class AddVenueTest extends PHPUnit Framework TestCase


function testAddVenueVani l l a ( ) (
$output = $ this - > runCommand ( "AddVenue " , array ( "venue_name "=> "bob" ) ) ;
self : : Assert:Regexp ( "/added/ " , $ output ) ;

function runCommand ( $ command=nul l , array $ args=nul l ) (


ob_start ( ) ;

$ request = \woo\base\ApplicationRegi stry : : getRequest ( ) ;


i f ( ! i s_nu l l ( $ args ) ) (
foreach ( $ args as $ key=>$val ) (
$request ->setP roperty ( $key, $val ) ;
}
i f ( ! i s_nu l l ( $command ) ) (
$ request->setProperty ( ' cmd ' , $ command ) ;
woo\cont rol ler\Controller : : run ( ) ;
$ret
ob_get_contents ( ) ;
ob_end_clean ( ) ;
return $ ret;
=

, run
Command ( ) . ,
.
.
$ phpunit test/AddVenueTest . php

PH PUni t 3 . 7 . 2 4 S e ba s t i a n Be rgma nn .
T ime : 2 1 5 ms , Memo r y : . 2 5
( 1 t e s t , 1 a s s e r t i o n )

, -
runCommand ( ) .

1 8. PHPUnit

471

,
. ,
. ,
,
.
.
, , DSN,
Reg i s t ry. ,
"".
s e t Up ( ) . Appl i c a t i on Re g i s t ry
MockReque st Reg i s t ry, ,
.

-.
. .
JavaScript, Ajax
. , .
. - .
, !

Selenium
Selenium (h t tp : / / s e l eniumhq . or g / ) (
). -.
. !
.
.
WOO,
1 2 . Selenium Server API,
- (php-webdriver).

Selenium
Selenium - : h t t p : / /
seleniumhq . o r g / downl oad / . , Se
lenium Server.
s e l e n i um-serve r - s t a n
dalone - 2 . 4 5 . . j ar (
). - .
. Java.
. Selenium Server.
/usr /
loca l / l i b .
$ server-s tandalone-2 . 4 5 . 0 . j ar /us r / l oca l / l i b
$ java - j ar /us r/ loca l / l i / s erver-standa lone-2 . 4 5 . 0 . j ar

1 3 : 1 5 : 08 . 32 3
1 3 : 1 5 : 08 . 4 59
1 3 : 1 5 : 0 8 . 4 60
1 3 : 1 5 : 0 8 . 4 90
1 3 : 1 5 : 08 . 631

I NFO
I NFO
I NFO
I NFO
I NFO

Launching s t andalone s e rv e r
Java : O r a c l e Corpo r a t i o n 2 5 . 4 0 - 2 5
OS : FreeBSD 1 1 . 0 -CURRENT amd 6 4
v2 . 4 5 . 0 , w i t h C o r e v 2 . 4 5 . 0 . Bui l t f rom revi s i o n 5 0 1 7 8
De fault d r i v e r o rg . openqa . se le n i um .

472

IV.

ie . InternetExplorerDriver reg i s t rat ion i s s k ipped : reg i s t rat ion


capab i l i t ies Capab i l it ie s [ { ensure C l eanSes sion=t rue , browserName=int ernet
explore r , ve rs ion= , plat form=WINDOWS } ] does not match with current
plat form : UNIX
1 3 : 1 5 : 08 . 67 6 INFO - Remot eWebDrive r i nstances should connect t o :
http : / / 1 2 7 . 0 . 0 . 1 : 4 4 4 4 /wd/hub
1 3 : 1 5 : 0 8 . 67 7 INFO - Version Jet t y/ 5 . l . x
1 3 : 1 5 : 08 . 67 8 INFO - Started Ht tpContext [ / s e l enium- serve r , / s e lenium- s erve r ]
1 3 : 1 5 : 08 . 8 5 2 INFO - Started org . openqa . j e t t y . j et t y . servlet .
ServletHandl e r @ 2 a l 8 f 2 3c
1 3 : 1 5 : 08 . 8 5 2 INFO - Started Ht tpContext [ /wd, /wd]
1 3 : 1 5 : 08 . 8 5 2 INFO - Started HttpCont ext [ / s e l enium- s e rver/drive r , / s e l enium
s e rver/drive r ]
1 3 : 1 5 : 08 . 8 52 INFO - Started HttpCont ext [ / , / ]
1 3 : 1 5 : 08 . 8 68 INFO - Started SocketLi s t ener on 0 . 0 . 0 . 0 : 4 4 4 4
1 3 : 1 5 : 08 . 8 6 8 INFO - Started org . openqa . j et t y . j et t y . S e rver@lbc7ed
, URL.
. URL
.
/I .

PHPUnit Selenium
PHPUit API /I Selenium.
.
, Selenium 1 .
, , , Selenium Server
2.45. , PHPUnlt
Sele
nium Server.
PHPUnit /I WebDrlver API (
Selenium 2) PHPUnit_Ext ens ions_
Selenium2Te stCase.
Linux.
(
), Llnux.
,
Selenlum, PHPUnit,
,
.

-
- (WebDriver) , Sele
nium 2, Selenium .
Selenium API - /I , Java, Python #.
, ll API. /I
- php-webdriver,
Facebook.
API.
- php-webdriver GitHub.
, .

1 8 . PHPUnit

473

$ git clone git@ githu . com : faceook/php-wedriver . git


php-webd r i ve r .
. .


WOO,
URL h t t p : / / localhost / webwoo.
.
requi re_once ( ' PHPUnit/ Framework/TestCase . php ' ) ;
requi re_once ( "php-webdriver/l i/_init_ . php" ) ;
class seleniumtest extends PHPUni t_Framework_TestCase
protected function setUp ( ) {
}
pu ic function tes tAddVenue ( ) {
}
PHPUni t Framewo r k / T e s tCase . php .
php-webdrive r / l ib / _ i ni t_ . php, , ,
API . ,
.
$ phpunit seleniumtest . php

PHPU n i t 3 . 7 . 2 4 Seba s t i a n Be rgman n .


T ime : 7 ms , Memory : . 5 0
( 1 t e s t , a s se r t i on s }
, ,
- .

Selenium
, Selenium URL,
.
URL (capabllities array)

RemoteWebDri ve r.
requi re_once ( ' PHPUnit/ Framework/TestCase . php ' ) ;
requi re_once ( "php-webdriver / l i / _init_ . php" ) ;
class sel eniumtest extends PHPUnit_Framework_TestCase
protected function setUp ( ) {
$host
"http : / / 1 2 7 . 0 . 0 . 1 : 4 4 4 4 /wd/hub " ;
$capabi l i ties
array ( WebDriverCapab i l i t yType : : BROWSER_NAE => ' fi refox ' ) ;
$this- >driver
new RemoteWebDrive r ( $hos t , $capab i l it ies ) ;
=

pu ic function testAddVenue ( ) {
}

474

IV.

remote /
Remo t eWeb D r i verCapa i t yT ype . php.
. $ ho s t , URL
. $ capai l i t i e s
RemoteWebDriver. $ d r iver.
, Selenium
.


,
. AddVenue ,
- .
- .
.
pu ic funct ion tes tAddVenue ( ) {
$this- >driver->get ( "http : / / l ocalhost /webwoo/?cmd=AddVenue " ) ;
$venel = $this->drive r - > findEl ement ( WebDriverBy: : name ( "venue_name " ) ) ;
$venel->sendKeys ( "my_test_venue " ) ;
$vene l->submi t ( ) ;
$tdel
$ this ->driver->findElement ( WebDriverBy : : xpath ( " / / td ( l ] " ) ) ;
$this->asse rtRegexp ( " / ' my_test_venue ' added/ " , $tdel->getText ( ) ) ;
=

$spacel = $ this ->drive r - > findElement ( WebDriverBy : : name ( " space_name " ) ) ;
$spacel->sendKeys ( "my_test_space" ) ;
$space l - >submit ( ) ;
$el
$this - >driver->f indEl ement ( WebDriverBy : : xpath ( " / /td ( l ] " ) ) ;
$this ->assertRegexp ( " / ' my_test_space ' added/ " , $ e l ->getText ( ) ) ;
=

:
$ phpunit seleniumtest . php

P H PUn i t 3 . 7 . 2 4 Seba s t i an Bergma n n .


T ime : 8 . 7 5 second s , Memo r y : . 7 5
( 1 t e s t , 2 a s s e r t i on s )
, , . Selenium
.
, !
.
WebDri ver : : get ( ) , .
, URL
.
, Selenium . Selenium
, . 1 8 . 1 .
WebDriver API .
RemoteWeb
D r i ver : : fi ndEl ement ( ) . Web
D r i ve rBy. WebD r i ve rBy -,

1 8 . PHPUit

475

WebDriverBy,
. -
, name "venue_name " .
WebD r i ve rBy :
: name ( ) find
Element ( ) . . 1 8.4 -.

. 1 8. 1 . AddVenue, Seleium

1 8.4. - WeDrivery

c l a s sName ( )
c s s S e l e c to r ( )
id ( )
name ( )
l i n kText ( )
part i a lLinkText ( )
t agName ( )
xpath ( )

CSS
CSS
id HTML
name HTML
,
,
HTML
, Xpath

RemoteWebEleme n t ,
" ve nue_name " , send
Keys ( ) . , sendKey s ( )
. .
.
JavaScript.
.

. ! . s ubmi t ( )
Selenium
-.
. - -
. , , .
WebDri ve r : : f i ndElemen t ( ) .
WebDri verBy.
Xpath. , f i ndElement ( )
RemoteWebEl ement . ,
, . .
,
RemoteWebEl ement : : getText ( ) .

476

IV.

. 1 8.2. AddSpace
-
-, , . 1 8.2.
,
. ,
.
, Seleium .
, , ,
. Selenium
http : / / s e l e n i umhq . o r g / doc s / i ndex . html .
Seleniu m .
PHPUnit https : / /phpu n i t . de /manu a l / cu r r e n t / e n / s e l e n i um . html .


.
, PHPUnit .
, , .
, , .
. ,
,
, ,
. , ,
.
,
. ,
. ,
, , .
- ,
, cron. ,
.
.
, , -
.
, , , -

1 8. PHPUit

477

. . ,
. ,
, .
-
, .
- ,
. 30
.
. . .
.
, . ,
.

. ,
. ,
, .
, ,
. ,
"" , .
- ,
, ,
. , ,
, .
. .
. ,
" " , . ,
.
-, ,
. ,
, . r
- . .
.
, ,
. ,
: , ,
. - .
,
. . ,
. , PDO.
, PDO .

class DBFace {
private $pdo ;
function
const ruct ( $dsn , $user=nul l , $pass=nu l l ) {
$this ->pdo = new PDO ( $dsn, $user, $pass ) ;
$this->pdo->setAttribute ( PDO : : ATTR_ERRODE , PDO : : ERRODE_EXCEPTION ) ;
function query ( $query ) {
$ s tmt = $this->pdo->query ( $ query ) ;

478

IV.
return $strnt ;

DBFace -,
, SQLite,
.

pu ic function setUp ( ) {
$ face
new DBFace ( " sql ite : : memo r y : " ) ;
$ face- >query ( " create t user ( id INTEGER PRIARY , name ) " ) ;
$ face- >que ry ( " insert into user ( name ) val ues ( ' bob ' ) " ) ;
$ face- >query ( " insert into user ( name ) values ( ' harry ' ) " ) ;
$this->rnapper = new Too lMapper ( $ face ) ;
=

, , , , .

"", ,
,
(fixtures) , "
" (Object Mothers). - ,
.
- .
,
, ,
.
, :

( );

( );

, ,

, ;

, ,
.


,
, .
PHPUnit,
,
! .
.
,
. ,
,
-, PHPUnit,
- Selenium. ,
, .

1 9


Phing

@@@

/)/
------

- ,
- .
.
,
. ,
- / u s r / l o ca l / ap ache / h t do c s , -
/ home / i b e / pu i c_html .
, .
.

-
.

PEAR.
. .
. .
PEAR
. -. PEAR
,
, . ,
-
.
.
PEAR.
Phing, ,
. .

Phig: ?

: .

: .

: .
.

: , .

480

IV.

Phing
Phing - - .
( ) Jv- Ant.
Ant ( "") , ,
. Phing. Ant L- (
bui l d . xml ) , ,
- .
-
.
. ma ke ,
Unix,
, ++ Perl. ma ke
, . -
,
Unix Linux. . ma ke
,
. ,
Unix. make ,
.
make, . ,
. ma ke f i 1 ( , ma ke ) .
Phing ma ke : Phing
"Phing Is Not Gnu make" (Phing - o GNU ma ke).
(, GNU "Gnu is Not Unix" (GNU Unix).
Phing - "" -,
L-, .

, Phing - . Phing
, , .
-. PEAR, ,
t a r / g z ip.
Phing , ,
.
Phing - -, ,
. - . Phing -
-, - - ,
, , .
, PEAR . PEAR
. PEAR
. PEAR
?
. PEAR .
,
.
, .
Phing PEAR
Phing.

1 9. Phig

48 1

Phing
, . - !
, , 5 ( ,
!). Phlng.
Phing .
$ pear channel-discover pear . phing . info
$ pear install phing/phing
Phing PEAR.
PEAR. Unix
Linux , ,
root.
- ,
Phing http : / /phing . in f o / t ra c / w i ki /
Use r s / Downl oad. .


Phing! .
$ phing -v

Phing ve rsion 2 . 1 0 . 1
-v phing
. , ,
. , ,
.
phi ng .
$ phing

Bui ldf i l e : build . xml does not exist !

, Phlng .
b u i l d . xml . ,
.
< ?xml ve rsion= " l . 0 " ? >
< ! - - bui ld xml -->
<proj ect name="megaqui z " de faul t="ma i n " >
<target name="ma i n " / >
< /proj ect>
, .
bui l d . xml phing,
.
$ phing

Bui ldfile : / home/bo/working/megaqu i z /bui l d . xml


Warning : target ' mai n ' has no tasks or dependencies
megaqui z > mai n :
BUILD FINI SHED
Total time : 0 . 1023 seconds

482

IV.

: , !
, Phig ,
. - !
. L, L. ,
, , L .

< ! -- , , - - >
, ,
. ,
, ,
.
.
- p ro j e c t ,
. name default
. name , d e f a u l t - ,
, .
d e s c r i p t i on .
b a s e d i r
. ,
. phi ngVe r s i o n
Phing, .
. 1 9. l .

1 9. 1 . proj ect

name
description
de faul t
phi ngVer s i on

basedir




Phig,

,

( . )

proj e c t , , de faul t .

. -
, ,
.
.

<target name="main " / >


, name .
proj e c t .
ma i n, phing
. .

megaqui z > main :


, .
, Phing,

1 9. Phig

483

, , .
.

< ?xml version= " l . 0 " ? >


< 1 - - build xml -->
<proj ect name="megaqui z "
defaul t="main"
>
<target name= " runfi r s t " / >
<target name=" runsecond" depends= " runfirs t " / >
< target name="main" depends= " runsecond " / >
</proj ect>
. t a rg e t . depends
Phlng, , ,
. . ,
, ,
. : runsecond,
ma i n , run f i r s t , runs e cond.
. . Phing
.
$ phing

Bui ldf i l e : /home /bo/working/megaqu i z /bui ld . xml


Warning : target ' runfirst ' has no t a s ks or dependenc ies
megaquiz > runfi rst :
megaquiz > runsecond :
megaqui z > main :
BUILD FINI SHED
Total t ime : 0 . 1022 seconds
. . Phing mai n ,
runse cond. run s econd
, Phlng run f i r s t .
, Phing runsecond.
ma i n . depends .
, ,
.
. ,
d e f au l t .
$ phing runsecond

Bui ldf i l e : / home /bo/working/megaqu i z /bui l d . xml


Warning : target ' runfi rst ' has no tasks or dependencies
megaquiz > run f i rs t :
megaqui z > runsecond :
BUILD FINI SHED
Total time : 0 . 2 6 7 1 seconds

484

IV.

, d e f au l t .
, . ,
. ,
.
t a r g e t description,
.

< ? xml version=" l . O " encoding="wi ndows - 1 2 5 1 " ?>


< ! - - bui l d xml -->
<proj ect name= "megaqui z "
defaul t="main"
descript ion= "o ">
<target name= "run f i r s t "
description= " epoe " />
<target name= "runsecond"
depends = " runfirst"
description=" Bopoe " />
<target name= "main"
depends=" runsecond"
description="Ocooe " / >
< /project>

. Phig -proj ecthelp,
.
$ phing -projecthelp

Buildfi le : /home/bob/working /megaqu i z /bui l d . xml


Warning : target ' run f i rst ' has tasks or dependencies

Default target :
main

Main targets :
main

runfirst
runsecond
, d e s c r i p t i on
p r o j e c t . ,
, hidden.
,
.

< target name= "housekeeping " hidden= " t rue" />


< ! -- , -->
< / target>

Phing property.
. .
. , "

1 9. Phig

485

" . ,
.

< ? xml version=" l . 0 " ? >


< 1 -- build xml -->
<pro j ect name="megaqu i z "
default="main"
>
<prope rty name="dbname " value="megaqu i z " />
<prope rty name="dbpas s " value="de faul t " / >
<prope rty name= "dbho s t " value=" l ocalhos t " />
<target name="ma i n " >
<echo>database : $ { dbname ) < /echo>
<echo>pas s : $ { dbpas s ) < / echo>
<echo>hos t : $ { dbhos t ) < /echo>
< / target>
< /proj ect>
, p rope r t y , name
() value (). .
main . e cho - .
. . e cho
, , - .
, . -
, Phing,
.

$ { propert yname )
, , -
. .
$ phing

Bui ldfile : /home /bo/working/megaqui z /bui l d . xml


megaquiz > ma i n :
[ echo J databas e : megaquiz
default
( echo ] pas s :
l ocalhost
[ echo ] hos t :
BUILD FINI SHED
Total time : 0 . 1 0 6 5 seconds
, .
. t a rget : i f
unl e s s . . i f
. ,
. ,
. dbp a s s ,
ma i n i f .

<property name= "dbname" value="megaqui z " / >


< 1 --<property name= "dbpass" value="defaul t " />-->

486

IV.

<prope rty name="dbhost " val ue=" localhost" / >


< target name="main" i f="dbpas s " >
<echo>database : $ ( dname } < /echo>
$ { dbpass } < /echo>
<echo>pass :
$ ( dhost } < /echo>
<echo>hos t :
< / target>
phing.
$ phing

Bui ldf i l e : /home/bo/working/megaqui z /bui l d . xml


megaqu i z > main :
BUILD FINI SHED
Total t ime : 0 . 1 0 6 4 seconds
, , mai n .
? .
. Phing -.
. . .
- Dname=value
, dp a s s
. .
$ phing -Ddpass=userset

Buildf i l e : /home /bo/working/megaqui z/bu i l d . xml


megaquiz > main :
[ echo ] database : megaqui z
userset
[ echo ] pass :
[ echo ] host :
localhost
BUILD FINI SHED
Total time : 0 . 1 0 4 7 seconds
i f ma i n , dbpa s s
.
, u n l e s s
i f .
u n l e s s ,
. ,
.
mai n ..
-

<target name="main" unless="suppressma i n " >


mai n ,
supp r e s sma i n.
$ phing -Dsuppressmain=yes
t a r g e t ,
. 1 9. 2 .

1 9. Phig

487

1 9.2. r target

name
depends
if
unl e s s
hidden
de s c r ipt ion


,
,
,

,
. ,
. , .
.
. ove r r i de p rope r t y .
.

< ?xml version=" l . O " ? >


< ! - - build xrnl - - >
<proj ect narne="rnegaqui z "
default= "rnain"
>
<property narne=" dbpas s " value= "defaul t " / >
< target narne="rnain">
<prope rty narne="dbpas s " override = " yes " value=" spec i f i c " / >
<echo>pas s : $ { dbpas s } < / echo>
< / target>
</pro j ect>
dbpa s s . " de faul t " .
ma i n , ove rr i de ,
" ye s " , .
.
$ phing

Buildf i l e : /home/bo/working/rnegaqui z /bui l d . xrnl


rnegaqui z > rnain :
[ echo ] pas s : speci fic
BUILD FINI SHED
Total t irne : 0 . 3802 seconds
ove r r i de p rope r t y .
" de faul t " . ,
- : .
.
. , , ,
,
.

488

IV.

. . Phing
. ,
, . .

< ? xml ve rsion= " l . 0 " ?>


< ! - - bui l d xml - - >
<proj ect name="megaqu i z "
defau l t= "main"
>
<target name="main " >
<echo>name :
$ { phing . proj ect . name } < / echo>
<echo>base :
$ { proj ect . basedi r J < / echo>
<echo>home :
$ { user . home ) < /echo>
<echo>pass :
$ { env . DBPASS ) < / echo>
< / target>
< /proj ect>
Phing.

phing . p r o j e c t . n arne , name


p r o j e c t ; p r o j e c t . b a s e d i r ; u se r .
home
(
-

).
e nv
. . $ { env . DBPAS S } .
DBPASS . Phing .
$ phing

Buildfi l e : / home /bo/working/megaqui z /bui l d . xrnl


megaquiz > mai n :
[ echo ]
[ echo ]
[ echo ]
[ echo ]

name :
base :
home :
pass :

megaquiz
/home /bo/working /megaquiz
/home/bob
$ { env . DBPASS )

BUILD FINISHED
Total time : 0 . 1 1 2 0 seconds
, .
. , - ,
. .
DBPASS phing . .
$ export DBPASS=wooshpoppow
$ phing

Bui l df i l e : / home /bo/working/megaquiz /bui l d . xml


megaquiz > mai n :
[ echo ] pass :

whooshpoppow

BUILD FINI SHED


Total time : 0 . 2 8 5 2 seconds

1 9. Phig

489

. :

prope rty, .
. .
.
.
.

< ?xml version=" l . 0 " ? >


< ! - - bui ld xml - - >
<proj ect name="megaqui z "
default="ma i n " >
<target name="ma i n " >
<echo>database : $ { dbname } < /echo>
$ { dbpass } < /echo>
<echo>pas s :
<echo>host :
$ { dbhost } < / echo>
</targe t>
< /proj ect>
,
, .
-. , .
phing .

$ phing
[ e cho ] database : $ { dbname }
$ { dbpa s s }
[ e cho ] p a s s :
$ { dbhos t }
[ e cho ] hos t :
.

megaqu i z . p rope r t i e s .
dbname=fi ledb
dbpass=fi lepass
dbhos t=fi lehost

-prope r t y f i l e phing.
$ phing -propertyfile megaquiz . properties

[ echo ] databa s e : f i l edb


f i l ep a s s
[ echo ] p a s s :
f i l ehost
[ echo ] host :
,
.
!
, .
. . dbpas s . ,
dbp a s s (
). -

490

IV.

, . ,
.

< ? xml vers ion= " l . 0 " ? >


< ! - - bui l d xml - - >
<proj ect name="megaqu i z "
default= "main"
>
<target name= " setenvpass " i f= " env . DBPASS " unless="dbpas s " >
<property name="dbpas s " override= " yes " value= " $ ( env . DBPASS } " / >
< / target>
<target name="setpas s " unl ess="dbpas s " depends=" setenvpas s " >
<property name="dbpa s s " overr ide= " yes " value= "defaul t " / >
< / target>
<target name= "main" depends= "s etpas s " >
<echo>pass :
$ ( dbpas s } < / echo>
< / target>
< /proj ect>
. , ma i n .
, Phlng s e t pa s s . setpa s s
s et e nvp a s s . . s e t envp a s s
, , dbp a s s
env . DBPAS S . ,
dbp a s s p rope rty.
dbpas s ,
. ,
. s e t p a s s ,
dbpa s s .
: " de f ul t " .


condi tion

. ,
. cond i ti on,
.
.
< ?xml ve rsion= " l . 0 " ? >
< ! - - build xml - - >
<proj ect name="megaqui z "
default="ma i n " >
<condi tion property= " dbpas s " value="default " >
<not>
<i sset property= " dpas s " / >
< /not>
< / condit ion>
<target name="ma i n " >

1 9 . Phig

49 1

<echo>pass : $ ( dbpass } < /echo>


< /target>
</proj ect>
condi t ion property. .
v a l ue ,
. .
va lue . true.
,
, . . n o t ,
. i s s e t .
t rue. .
dbp a s s , ,
i s s e t , not.
. ,
, condi t i o n
, .

if ( ! i s set ( $dbname ) ) (
$dbname = "de faul t " ;

. Phig
https : / /www . phing . info/docs /guide/sta e / ch0 5 s 0 8 . html


. . . , .
Phing - ,
n , .

fi leset
:
. . ,
. -
, .
f i l e s e t ,
. .
,
Windows. f i l e s e t
.

< f i leset dir=" src/ l ib" / >


, d i r , ,
. id.
f i l e s e t .

< f i l eset dir=" src/ l ib" id= " s r c l i b " >


f i l e s e t ,
. ,
, .
e x c l udes.

492

IV.

< f i leset dir=" s r c / l i b " id= " s rclib"


excludes= " * * / * test . php * * / *Test . php " / >
, excl udes .
s r c / l i b .
. , ,
, _t e s t . php T e s t . php,
, d i r . e x c l udes
, .
i n c lude s . ,
s r c / l ib - , ,
. , , ,
, , . ,
php, .
.

< f i leset dir= " src/lib" id= " s rclib"


excludes= " * * / *_test . php * * / *Test . php "
includes= " * * / * . php" / >
i nc l ude exclude f i l e s e t , ,
. , exclude
e x c l ude.
i n c l ude. f i l e s e t .

< f i leset dir=" src/ l ib " id= " s rc l i b " >


<exclude name= " * * / *_tes t . php" / >
<exclude name= " * * / * Tes t . php" / >
<include name=" * * / * . php" / >
< / fi leset>
f i l e s e t . 1 9.3.

1 9.. fileset

id
dir
excludes
i nc l udes
refid


f i l e s e t


f i l e s e t f i l e s e t I D

patternset
f i l e s e t ( ) ,
e x c lude i n c l ude.
.
- (,
conf i nc ) .
f i l e s e t , ,
f i l e s e t .
, p a t t e r n s e t .
p a t t e r n s e t e x cl ude i n c l ude ,
. e x c l ude
i nclude f i l e s e t p a t t e r n s e t .
.

1 9. Phig

493

<pat ternset id= " inc code ">


<include name= " * * / * . php " / >
< include name= " * * / * . inc" / >
<include name= " * * / * . conf" />
</patternset>
<patternset id="exc tes t " >
<exclude name= " * * / *_test . php" / >
<exclude name= " * * / * Test . php" / >
</patternset>
p a t t e r n s e t , id
i nc_code exc_t e s t . i nc_code include
, e x c_t e s t
e x c lude
r . p a t t e r n s e t
fileset.
-

<fileset dir= " s rc / lib" id= " s rc l i b " >


<patternset refid= " i nc code " />
<patternset refid= "exc_test" / >
< / fi leset>
pat t e rnset,
p a t t e r n s e t .

r e f i d . id
patternse t , . ,
pat t e rn s e t .
-

< f i l eset di r="src/views " id= " s rcviews " >


<patternset refid= " i nc_code " />
< / fi leset>
, i nc_code p a t t e r n s e t ,
, . f i l e s e t ,
e x clude exc ludes,
exclude. i n cl ude.
p a t t e rn s e t . 1 9.4.

1 9.4. patternset

id
excludes
includes
r e f id




p a t t e rn s e t p a t t e rn s e t ID

fi l terchain
, ,
. f i l t e r ch a i n
r .
. f i l t e r cha i n
.
, .. Phig,
. .

494

IV.

f i l t e r ch a i n .
-
. , ..
f i l te rcha i n ,
.
, -
.

< f i l terchain>
< s t ripphpcomments />
< / fi l terchain>
s t r ipphpconunents . , ..
. .
, .
,
. .

. ,
, .
, . .
f i l t ercha i n .

<target name= "ma i n " >


< todi r= "bui ld/ l i b " >
< f i l eset refid= " s rc l i b " / >
< f i l terchain>
<stripphpcomments / >
< / f i l terchain>
< />
< / ta rget>
. , .
. ,
todi r . f i l e s e t ,
. f i l te rcha i n . ,
, .
Phing ,
( s t r ip l inebreaks ) ( tatospaces ) .
x s l t f i l t e r SL-
! . , - replacetokens.
,
.
. .
,
.
replacetokens , begintoken endtoken.
, . .
. Phing @ .
, t o ken
replacetokens. replace t o kens .

< todi r="bui l d / l i b " >


< f i l eset refid="srcl ib " / >

1 9. Phig

495

< f i lterchain>
<str ipphpcomments />
<replacetokens>
<token key="dname " value= " $ { dbname } " / >
< token key="dbhos t " value= " $ { dbhost } " / >
<token key="dbpas s " value= " $ { dbpass } " / >
< / replacetokens>
< / f i l terchain>
< / >
, t o ke n key value.

. s r c / l i/Config . php.

/**
* Quick and dirty Conf class
**/
class Conf ig
pu ic $dbname = " @dbname@ " ;
puic $dbpass = " @ dbpass@ " ;
puic $dbhost =" @dbhost@ " ;
, , m
, .
$ phing

Bui l df i l e : /home /bo/working/megaqu i z /bui l d . xml


megaquiz > main :
[ ] Copying files
[ fi lter : ReplaceTokens ]
[ fi lter : ReplaceTokens ]
[ fi lter : ReplaceTokens ]

to /home /bob/wor king /megaqu i z /bui ld / l i b


Replaced " @ dbname @ " wi th "megaqui z "
Replaced " @ dbpas s @ " with "defau l t "
Replaced " @ dbhos t @ " w i t h " l ocalhost "

BUILD FINI SHED


Total time : 0 . 1 4 1 3 seconds
, ,
bui l d / l i / C on f i g . php.

class Conf ig {
puic $dbname = "megaqui z " ;
pu ic $dbpa ss = "defaul t " ;
pu ic $dbhost = " l ocalhost " ;
,
.

- ,
. . ,
. .
.

496

IV.

echo
echo " H e l l o World " .
, ,
. ""
, . . ,
echo.
.
<echo>The pass is ' $ { dbpass } ' , shhh ! < / echo>

- msg.
<echo msg=" The pass i s ' $ { dpass } ' , shhh ! " />

.
[ echo] The pass is ' defaul t ' , shhh !

- ,
. ,
.
, ( )
.
, ,
.
.
, /.
. , -
.
< f il e= " s r c / l i/Con f i g . php " todi r="bui ld/conf " / >

, f i l e . ,
t od i r ,
. , Phing .
, ,
t o d i r t o f i l e .
< f i l e= " s r c / l i/Con f i g . php" tofile="build/conf/myCon f i g . php" / >

bui l d /c o n f ,
C on fi g . php myCon f i g . php.
, ,
f i l e s e t .
< todir="bui ld/ l i b " >
<fi leset refid= " s rcl i b " / >
< />

s r c l ib f i l e s e t , ,
, - t odi r .
Phing , ,
. , Phing
. , ,
.

1 9. Phig

497

, .
,
repl ace t o ke n s , ,
. . overwri t e .
< todi r= "build/ l ib" overwri te="ye s " >
<fi leset refid= " s rc l i b " / >
<fi lterchain>
<stripphpcounents / >
< replacetokens >
<token key= "dbpas s " va lue= " $ ( dbpas s } " / >
< / repl acetokens >
< / fil terchain>
< />

. . ,
f i l eset , , .
. 1 9.5.
1 9.5.

todir

file
t s t amp

(
tofile)
(
todir)

f a l s e ()

preservemode


/ ( )




,

tofi l e

includeemptydi r s
mode

hal tone rror

ove rwr i t e

f a l s e ()
f a l s e ()

755

t rue ()
no ( )

input
. e cho
. . .
.
, .
. , ,

, .
. , ,
, ,
!

498

IV.

i nput
. Phing
. .

<target name= " setpas s " unless= "dbpas s " >


< i nput message=" You don ' t seem to have s e t
propertyName="dbpass "
de faul tValue= "default "
promptChar=" > " / >
< /target>

d b pas sword"

<target name= "ma i n " depends=" setpas s " >


<echo>pass : $ ( dbpas s } < / echo>
< /target>
: ma i n . ,
s e t p a s s , , dbpa s s
. u n l e s s t a rg e t ,
, , dbpas s .
setpass i nput.
i nput mes sage,
. p rope r t yName ,
.
<Eter>, ,
, defaultValue.
p romptChar
, .
Phing, . .

$ phing

Bui ld f i l e : / home /bo/wo r k i ng / me g a qu i z /bui l d . xm l


megaqu i z > s e t p as s :

don ' t s e em t o have s e t

db p a s sword [ d e f au l t ] > m yp a s s

megaqu i z > ma i n :
[ echo ] p as s : mypas s
B U I L D F I N IS HE D
T ot a l t ime : 6 . 0 3 2 2 s econds
i nput . 1 9.6.

1 9.6. input

p rope r t yName
mes sage
defaul tValue

, ,

1 9. Phig

499

maJL 1 9. 6

va l idArgs

promptChar

, .
, , Phig

delete
,
. ,
" . ,
,
.
.
.

<target name="clean">
<delete dir="bui ld" />
</target>
Phing c l e a n ( ),
de l e t e . Phing.
$ phing clean
_
,...
..
...,.
_..
__
_
_
_
_
_
_
_
_
_
_
_
_
i1811 UJ1:'

_
_
_
_
_
_
_
_
_
_
_
_

14

;..-w-

Bui l df i l e : /home /bo/wo r k i ng /megaqu i z /bui l d . xml


megaqui z > c l ea n :
[ de l e t e ] De l e t i ng d i r e c t o r y / home /bo / wo r k i ng /megaqu i z / bu i l d
BUILD F I N I S H E D
del e t e f i l e ,
. :
, f i l e s e t d e l e t e .


- .
,
.
.
. ,
. , ,
: ( - ,
) ,

README.
Phing
,
Ant .
Phing. , -

500

IV.

, , , ,
,
tar/g zip,
PEAR -
.
- Phing
, , Ant,
. !
Phing,
, . Phing
,
.

20

@@@

/)/
-----


, .
, ,
- ! .
, . .
, ,
.
!
.
.
, ,
. ,
,
, , , .
. (Continuous Integ
ration) - ,
,
.
.

().

Jenkins - .

Jenkins -
.


- ,
.
, ,
. - .
,

502

IV.

. ,
.
. ,
,
. , .
,
. !
1 8 ,
. 1 5 1 9 ,
.
, , ?
' (lest-Oriented
Development, D) , , -
, .
.
(,
),
.
.
, (test case).
.
,
. , -
. , ,
, .
, , - ,
, ,
, .
,
, .
,
, , ,
.
, .
, - .

, ,
.
.
, , , ,
,

.
, .
:
, ,
, . , ,
. ,
1 . (Iest-F'irst Developm.ent.
FD). ,
.

20.

503

, ? ,
,
, .
,
.
, , ,
.
,
,
.
()
( )
.
- . .
, ( ).

. , ,
( , PHPUnit Phlng) .
.
- .
,
. ,
.
, ,
. Di -
. , .
.
,
. ,
. ,
. .

, , .
, ,
, ,
. '' ,
URL? -
. - , .
Apache".

. ,
, .
!
,
. , .


, ,
. , ,
. - ,

504

IV.

1 8 I PHPUnit. userthing,
( thing). User.
(. 20. 1 )

. 20. 1 . n,
.
.
.
,
.


, .

( , ).
Git,
1 7 .

$ sudo mkdir /var / g i t /userthing


$ sudo chown g i t : gi t /var/git/userthing

20.

505

$ sudo su git
$ cd /var/git/userthing
$ git - -bare init
userthing
. gi t .
userthing ,
.

$
$
$
$
$
$

cd /home/mattz /work/userthing
git init
git add .
git commit -m ' first commi t '
git remote add origin git@getinstance . com : /var/git/userthing
git push origin master


. origin ,
. , ,
.
$ git clone git@ getinstance . com : /var/git/userthing

Cloning into ' userthing ' . . .


Enter pas sphrase for key ' /home/matt z / . ssh/ id_rsa ' :
remote : Counting obj ects : 6 1 , done .
remote : Compress ing obj ects : 1 0 0 % ( 5 6 / 5 6 ) , done .
remote : Total 61 ( delta 1 4 ) , reused ( delta 0 )
Receiving obj ect s : 1 0 0 % ( 6 1 / 61 ) , 9 . 0 9 K i B , done .
Resolving deltas : 1 0 0 % ( 1 4 / 1 4 ) , done .
u s e r t h i ng
.
.

Phing
Phing 1 9.
. Phing.

$ pear channel-discover pear . phing . info


$ pear install phing /phing

.
.
. .
. , PEAR.

. pear ,
.
, , .
.

<proj ect name="use rthing " defaul t="bui l d " >


<property name= "bui ld" value=" . /build" / >

506

IV.

<property name="src" value=" . /src" / >


<property name="vers ion" value= " l . 1 . 1 " / >
<target name= "bui l d " >
<mkdir dir=" $ { build ) " / >
< todi r= " $ { bu i l d ) /userthing " >
<fi leset dir=" $ { s rc ) /userthi ng ">
< / f i leset>
< / >
< todi r="$ { bu i l d ) /test " >
<fi leset dir=" $ { s rc ) /tes t " >
< / fi l eset>
< />
< / target>
<target name= "clean " >
<delete di r="$ { build ) " />
</ target>
< ! - - . . . -->
< /proj ect>
. bui l d
.
.
, . s r c
, ve r s i o n .
bui ld u s e r t hing t e s t
( bui ld).
, "
" .
phing
.
clean .
.
$ phing
---

....
.

--

Bui ldfile : /home/matt z /work/userthing/bu i l d . xml


userthing > bui l d :
[ mkd i r ] Created di r : /home/mattz /work/userthing/build
[ ] Created 4 empty directories in /home/mattz /work/userthing/build/
use rthing
[ ] Copying 3 fi les to /home/mattz /work/userthing/buil d/userthing
[ ] Created 1 empty directory i n /home/matt z /wo r k/userthing /bui ld/test
[ ] Copying 2 fi les to /home/mattz /work/userthing/bui ld/test
BUILD FINI SHED
Total time : 0 . 7 5 3 4 seconds

2 0 .

507


.
,
, .
PHPUit 1 8. , .
,
2.
$ pear config-set auto_discover 1
$ pear install --alldeps pear . phpunit . de/phpunit

, 18
userthing, .
( s r c) , ,
.
$ phpunit test
....
-

PHPUnit 3 . 7 . 2 4 Sebastian Be rgmann .


Time : 3 17 ms , Memory : 3 . 7 5
( 5 tests, 5 assertions )

--------- _"_11"1;:_"__.

, , .
Phig.
, phpuni t .
,
.
.
<ta rget name=" test " depends="bui ld">
<phpuni t>
<formatter type="plain" usefi le="false " />
<batchtest classpath= " $ { bu i ld } " >
<fi l eset dir=" $ { bui l d ) /test">
<include name= " * * / * Test . php" / >
< / f i leset>
</batchtest>
</phpuni t >
</ target>
, t e s t bui ld. ,
bui l d
. , phpuni t
p r i n t summa r y , m .

. f o rma t t e r
. ,
. batchtest
f i l e s e t . , -

2 pear . phpuni t . de ur 3 l 20 1 4 .
PHPUit PEAR. .
https : / /phpunit . de/ phar. - . .

508

IV.

batcht e s t c l a s spath. ,
. Java.
. phpuni t .
Phig https : / /www . phing . info/docs/guide/stale/ apcs59 . html.
Phi ng .
$ phing test
/1!1
...

. ,
1 ....
.

,
"

Buildfi l e : /home/mattz/work/userthing/build. xml


userthing > buil d :
userthing > test :
[ phpunit ] Testsui te : ValidatorTest
[ phpunit] Tests run : 2 , Failures : , Errors : , Incomplete : , Skipped : , Time
elapsed: 0 . 07081 s
[ phpunit ] Testsui te : UserStoreTest
[ phpunit ] Tests run : 3, Fai lures : , Errors : , Incomplete : , Skipped : , Time
elapsed : 0 . 02879 s
[ phpuni t ] Total tests run : 5 , Failures : , Errors : , Incomplete : , Skipped : ,
Time elapsed : 0 . 10772 s
BUILD FINI SHED
Total time : 1 . 0921 second


- .
,
,
. 1 6 phpDocumentor,
.
$ pear channel-discover pear . phpdoc . org
$ pear install phpdoc/phpdocumentor

. ,
bui ld.
$ mkdir docs
$ phpdoc - -directory=userthing --target=docs --title=userthing
--template=astract

.
, ,
.
, bui l d . xml .
PHPDocumentor Phing
phpdoc 2 , .
.
phpdoc , .
. , , , phpdoc2
PHPDocumetor. Phig
https : / /www . phing. info/docs /guide / s ta e / apcsS . html .

20.

509

<target name="doc" depends="bui l d " >


<mkdi r dir=" $ { bu i l d } /doc s " / >
< executae="phpdoc " dir=" $ { bu i ld } " >
<arg l ine= " --di rectory=userthing - - target=docs - - t i tle=userthing
--template=abstract " />
< />
< / target>
, doc bui l d.
bui ld/docs , .
phpdoc executae. d i r ,
.
a r g , phpdoc
. ,
value a rg .
, l i ne,
.
. Phig
https : / /www . phing . info/docs /guide/stae/apbs l 7 . html.


,
. PHPUnit (code
coverage). PHPUnit.
--coverage-html

<dir>

- -coverage-clover < file>


HTML .

Clover XML .

,
Xdebug.
h t tp : / /pecl . php . net /pac kage /Xdebug, -
h t tp : / / x debug . o r g / do c s / i ns t a l l .
,
Linux. , Fedora.
$ yum install php-pecl-xdeug

PHPUnit s r c .
$ mkdir /tmp/coverage
$ phpunit - -coverage-html /tmp/coverage test

PHPUnit 3 . 7 . 2 4 Sebastian Bergmann .


Time : 3 . 3 6 seconds, Memory: 4 . 7 5
{ 5 tests , 5 assertions )
Generating code coverage report in HTML format . . . done
, (. 20.2).

51

IV.

. 20.2.

. ,
. ,
, . ,
. 20.2. .
. ,
, .
<target narne= "citest" depends="bui l d " >
<mkdir dir=" $ { bu i ld } / reports /coverage " />
<coverage-setup database= " $ { build } / reports/coverage . db " >
< f i l eset dir= " $ { bui l d } /userthing " >
< i nclude name= " * * / * . php " / >
< / f i l eset>
< /coverage-setup>
<phpunit codecoverage= " t rue">
< formatter type="pl ain" usef i l e= " fal se " />
< formatter type="xml " out f i le="testreport . xml " todi r= " $ { bui ld } / report s " />
< formatter type="cl over " out file="cloverreport . xml " todir= " $ { build } /
repor t s " />
<batchtest clas spath= " $ { bu i ld } " >
< f i l eset dir= " $ { build ) / " >

2 0 .

51 1

< include name= " t e s t / * * " / >


< / fi leset>
< /batchtest>
< /phpuni t >
< coverage-repo rt out f i l e= " $ { build } / reports/coverage . xml " >
< report todi r=" $ { bu i ld } / reports /cove rage " / >
< / coverage-report>
</ target>
c i t e s t .
t e s t ,
. reports cove rage.
l cove rage
cove rage- s e tup. datab a s e
. f i le s e t
, .
phpu n i t f o rma t t e r . f o rma t t e r ,
xml t e s t repo r t . xml ,
. forma t t e r , c l ove r ,
L.
c i t e s t
cove rage- repo r t . ,
L- L.
. coverage- report Phig
https : / /www . phing . info /docs / guide / s tae/ apcs 05 . html.


, ,
( )
. ,
,
- ? PHP_CodeSniffer
. CodeSniffer
, ,
.
. ,
. ,
. ,
. , - .
$ sudo pear install PHP_CodeSniffer

Zed .
$ phpcs --standard=Zend build/userthing/persist/UserStore . php

FILE : . . . userthing/bui ld/userthing/pe r sis t /UserStore . php


FOUND 9 ERROR ( S ) AFFECTING 8 LINE ( S }
6 1

ERROR

Opening brace o f class must

the l i ne after the definit ion

512

7
9
13

IV.

ERROR
ERROR
ERROR

Private
Opening
Closing
l ine

memer va riae "users" must contain l eading unde rscore


brace should new l ine
parenthesis o f mul t i - l ine function call must on
itself

. , ,
CodeSniffer Windows: " Pear ,
CodeSniffer : \Users \ { u sername ) \AppData \Local \ Temp \
pear\cache".
,
Zend, !
.
, . , . .
. .
. . .

.

.
- . ,
. ,
- . . CodeSniffer
. .
,
.

. .
. ,
, , ,
.
. codesni f f e r
.
< target name= "sni f f " depends="build">
<mkdir dir=" $ ( bu i ld ) / reports" />
<phpcodesniffer standard= " Zend">
< f i l eset dir=" $ { bu i l d } /userthing" >
< i nclude name= " * * / * . php" / >
< / f i l eset>
< formatter type="checks tyle" out fi le=" $ ( bu i ld ) / repo rts /checkstyle . xml " / >
<formatter type="defau l t " usefi l e= " fa l s e " / >
< /phpcodesniffer>
< / ta rget>
phpcodes n i f f e r .
s t a nda rd, Zend.
f i l e s e t .
f o rma t t e r . t ype
che c k s t y l e , L repo r t s .
f o rma t t e r t ype de fau l t .
.

20.

51

. codesni f fer . ,
PEAR http : / /pea r . php . net /manual / en /package . php . php-codesniffer.
coding-standard-tutorial . php.



, .
PEAR pearpkg2. .
<target name="makepackage fi l e " depends="build">
<pearpkg2 name="userthing" dir=" $ { bu i ld ) " >
<opt ion name= "packagef i l e " value="userthing_package . xml " / >
<opt ion name= "packagedi rectory" value= " $ { bu i ld ) " / >
<opt ion name="baseinstalldir" value=" / " />
<option name=" channe l " value="pea r . php . ne t " / >
<opt ion name=" summary" value="ah h " / >
<opt ion name="description" value= "ah h h" / >
<opt ion name=" apive rsion" value=" l . 1 . 0 " / >
<option name= " apista i l ity" value= "beta " />
<option name=" releaseversion" value="$ { vers ion ) " />
<opt ion name= " releasesta i l ity" value="bet a " / >
<option name= " l i cens e " value= "non e " / >
<opt ion name="phpdep" value=" S . 4 . 0 " />
<opt ion name="pearinstall e rdep" value=" l . 4 . 6 " / >
<option name= "packagetype" value="php " / >
<opt ion name="note s " value= " notes notes notes " />
<mapping name="mai ntainer s " >
<element>
<element key= "handle" value="mat t z " / >
<element key="name" value="matt " / >
<element key= "ema i l " value= "matt@get instance . com" / >
<element key=" r o l e " value=" l ead " / >
< /element>
< /mapping>
< f i leset dir=" $ { bu i ld ) " >
<include name=" userthing / * * " / >
< / fileset>
</pearpkg2>
< / target>

, ,
, 1 5.
, r e l ea seve r s i o n opt i on
ve r s ion,
. , ,
f i l e s e t .
. pearpkg2 Phig
https://www. phing.ifo/docs/guide/stae/apcs47 .html.

51 4

IV.

p a c kage f i l e ma kepackag e f i l e
userth1ng pac kage . xm l .
. .
<target name="bu i l dpackage" depends= "makepackage f i l e " >
< dir="bu i l d " checkreturn= " t rue" executa e = " / u s r /bin/pea r " >
< a r g va lue="package" / >
<arg value= "userthing_package . xml " / >
< / >
< /target>

$ pear package userthing_package . xml

bui ld. use rthing-1 . 1 . 1 . t g z .


. tartask,
Phing https : / /www . phing . info /doc s / guide/ stae/
apcs 8 1 . html.
, chec kreturn.
Phing ,
.
, .
, , p e a r
. b u i l dpackage.
$ phing buildpackage
".

_
_
_
_
_
_
_
_
_
_
....
.
...
....
... .
_
,
.
...
"
...
,..
,
_,,
,
_
LOi&
!li
_
"
...
"

"
li
.
_
/IWlll"
"
"
...
...
"
...
.
...
_.
.
_
,
_
_

Buildfi le : /home/mattz /work/userthing/build . xml


userthing > bui l d :
userthing > makepackagef i l e :
[ pearpkg2 ] Creating [ defau l t ] package . xml f i l e in base directory .
Analyz ing userthing/domain/User . php
Analyzing userthing/pe r s i s t /UserStore . php
Analyzing userthing /util /Val idator . php
use rthing > bui ldpackage :
BUI LD FINI SHED
Total t ime : 1 . 7 6 8 5 second
, .
$ pear install --force build/userthing- 1 . 1 . 1 . tgz

instal l o k : channel : / /pear . php . net/userthing- 1 . 1 . 1


, ,
. . , ,
,
Phing. ,
-

20.

51 5

.
. ,
.

Jenkins
Jenkins - ,
"Hudson". Java,
. ,
, .
.
Jenkins .
.
. ,
.
. Jenkins? ,
. . Jenkins
. ,
, n ,
. , .
cepepCruiseCotrol (http : / / cruisecontrol . sourceforge . net / ),
. , ,
a Xinc (http : / /code . google . com/p/xinc/).

Jenkins
Jenkins Java,
JRE .
. , Linux Fedora
.
$ yum install j ava

Java
www . j ava . . , Java
, .
$ j ava -version

openj dk version " 1 . 8 . 0_4 0 "


OpenJDK Runt ime Envi ronment ( build 1 . 8 . 0_4 0 -2 5 )
OpenJDK 64 -Bit Server V (build 2 5 . 4 0 -2 5 , mixed mode )
Jenkins h t tp : / / j e n k i n s - c i . or g / .
- Java (Java Web Archive, WAR)
.
Jenkins.
Linux Fedora, .
$ wget - /etc/yum . repos . d/ j enkins . repo http : / /pkg . j en kins-c i . org/ redhat /
j enkins . repo
$ rpm -- import http : / /pkg . j enkins-ci . org/ redha t / j enkins-ci . org . key
$ install j enkins

516

IV.

Jenkins
. Jenkins
j ava . .
$ sudo j ava - j a r /us r / l i / j enkins / j en kins . war
, , ,
. . ,
,
Jenkins j en k i n s , root. Fedora
Jenkins , .
$ service jenkins start

:
https : / /wi ki . j enkins-ci . org /display/ JENINS / JenkinsLinuxStartupScript .
Jen k i n s 8080 (
. FreeBSD, 8 1 80).
. , -
http : / / _ : 8 0 8 0 / ( , FreeBSD,
h t t p : / / _ : 8 1 8 0 / j e n kins).
, . 20.3.

. 20.3. Jenkins

Jenkins
Jenkins
.
.

20.

517

- Jenkins Jenkins
(g Jekis), - (g Plugis).
(Availae),
Jenk.ins, .
(lstall) , .
. 20. 1 .
20. 1 . Jenkins

Git Plugin
xUit Plugi
Phig Plugin
Clove Plugi

Git
xUit, PHPUit
Phig -
XML HTML, PHPUit,

HTML, ,
PHPDocumeto
XML, PHPCodeSiffer,

HTML Puishe
Plugi
Checkstyle Plugi

. 20.4.

.

. 20.4. Jenkins

Git

Git plugi ,
Jenkins .. Git. 17
.
Jenkins.
?

51 8

IV.

, ,
Jenkins.
Jenkins (Configure Jenkins), -
(Configure System).
Jenkins. , / e t c / pa s swd
j e n k i n s .
/ us r / l oc a l / j e n k i n s .
. s s h ,
.
$
$
$
$
$

sudo su j enkins -s /bin/bash


cd mkdi r . ssh
chmod 0700 . ssh
ssh-keygen

j e n ki n s
,
.
, . s s h ,
. s sh - keygen
ssh.
, <Enter>. cepepy Jenkins
. ,
s s h / i d_ r s a
, . .
.

$ chmod 0600 . ssh/id_rsa

. s s h / id_ r s a . pub
Git. ,
1 7. . , Git
SSH.
Git,
.
j en k i n s .
$ cd / tmp
$ git clone g i t@appul sus . com: /va r / g i t / userthing
Git
SSH.
. s s h / known_h o s t s , j enkins.
Jenkins
Git.


Jenkins ,
.
, u s e r t h i ng , . 20.5.
. ,
- Git.
(Source Code Manager)
Git URL , . 20.6.

20.

. 20.5.

. 20.6.

519

520

IV.

, .
,
Phing.
(Add build step) lnvoke Phing targets (. 20. 7),
Phing .

. 20. 7. Phig



(.
) (Build Now).
. - !

(Build History) . Console
Output, , ,
(. 20.8).
, ! Jenkins
userthing Git
.


, Phing
bui l d / repo r t s , - bui l d / docs .
Jenkins

20.

521

(Add post
build action), (. 20.9).

. 20.8. ,

,
. . 20.2
,
Phing.
20.2.

Phig

Puish Checkstyle analysis


esults (

phpcode s n i f f e r

Checkstyle esults

b u i l d / repo r t s /
c h e c k s t yl e . xml

Puish Clove vge Report ( -

phpuni t

Clove XML Location

bui l d / report s /
c l ov e r repo rt . xml

Clover HTML report


directory

bui l d / report s /
cove r a g e /

522

IV.
.. 20.2

Phing

Puish HTML reports (


phpdoc2
HTML)

phpuni t
Puish JUnit test result
report (
JUnit)
phpunit
E-mail Notification
( )

HTML directory to
archive
lndex page[s]
Test report XMLs (XML

)
Recipients ( )

build/docs
i ndex . html
bui l d / repor t s /
t e s t report . xml
someone@
somema i l . com

. 20.9.

. . 20.2, ,
. , .
E-mail Notification ,
. .

20.

523

,
. . 20. 1 0 ,
.

. 20. 1 0.

.
. ,
.
API,
.



,
.
Jenkins
.
, Jenkins
,
, ,
. cron Unix.
,

524

IV.

. , ,
, Jenkins
, @hourly, @midni ght, @dai l y, @weekly
@month l y, . . 20. 1 1
,
, .
.

. 20. 1 1 .


, ,
userthing Zend.
,
- . "" -
, Jenkins .
Va l idate use rthing\ut i l .
pu i c function validateUser ( $ma i l , $pass ) {
11 ,
11
return false ;

$user
$this->store->getUser ( $ma i l ) ;
i f ( is_null ( $user ) ) {
return nul l ;
=

20.

i f ( $user->get Pas s ( )
return true ;

525

$pass ) {

$this- >store->noti fyPasswordFa i l ure ( $ma i l ) ;


return false;
, va l i da t e U s e r ( ) ?
fal s e .
, t e s t /Val i da t o rTe s t . php.
.
pu ic funct ion testVa l i date_Correct Pass ( ) {
$this ->assertTrue (
$this->val idator->val idateUser ( "bob@examp l e . com" , " 1 2 3 4 5 " ) ,
"Expecting succes s ful validation"
);
, , -
!
userthing . , -
. ,
. . 20. 1 2 .

. 20. 1 2.

526

IV.

, ,
" B u i l d f a i l e d in Jenki n s : u s e r thing # 8 .
,
, .
"


,
,
Jenkins. , ,
PHPUnit ( , ). PHP_CodeSniffer,
PHP_CodeBrowser, phpDocumentor Git.
Jenkins , .
,
Jenkins
, .

)/)

@@@
'''

'

-:......

2 1
i<

, ,

!/)
-----

- -.
. , -

.
,
.

.: -
.

:
- .

: .

: -
, .

: ,
, , .


2, -
. 3 , , ,

- . 4, , r
, .
, .
5 , -, . , -
. , ,
- .
3-5 -
. ,
5,
, , ,
toString ( ) , static, ,
, , , -, , -

530

V.

const, , clone ( ) ,
construct ( ) ,
.
, - .
,
. .
,
.
.
. Zed gi 2 5 -
-,
.
6 .
. -
, .

. ,
. -
,
. -.
( ,
), , , PEAR.


" ".
, . ,
, .
-
. - , ,
,
.
. .
,
. ,
,
.

,

. , ..
- , "" , .
,
,
. .
. (, )
, ,
,
. ,
, . -

2 1 . , ,

53 1

, . -
- ,
, .
- .
, .
, ? ,
. . ,
.
- .

(, Linux)
( Windows) , , i f/ e l se
.
(, MacOS),
.
-
. .
. , -
.
. ,
, .
, , ,
- :
. -
, ,
. ,
.


, , ,
. ,

, ,
.
, .
. ,
-
,
,
.
: ,
. ,
.
,
. I
, .

, , -
.
, .

532

V.

, API
, , ,
,
, .
, . .
,
. .
PEAR, ,
.
. -
, .
, -
.
- ,
.
,
,
. , ,
,
.


Java, ,
, , . -
, ( , ) , .
, .
, .
,
,
. .
, ,
.
,
. ,

.
, , ,
.
" " .

. , , .
. Perl ,
- - .
, - , ,
.
, , - .

2 1 . , ,

533


7. .
.


, . -
. :
, "
" ( ) .
:
.

r r
, .
" ".
.
, .
, ,
, .
.


-
. -
. . . ,
, ,
.


,
. : -
.


.
.
- , .
, .
, , .
. .
, , Abstract Factories
. , Abstract Factoy
.
, .
, , m ,
. Abstract Factoy
, -

534

V.

. Abstract Factory ,
Abstract Factory ,
Factory. .
, Factory, rn
Abstract Factory,
.
- .
: ISS ("
it simple, stupid" - " ") "Do the simplest thig that works"
(" , ").
YAGNI: "You are't goig to d it" " ". : ,
.
, .
9. ,
.


.
(),
, . ,
.
, .


.
. ,
.
, (
) (
Sigleto).
, .
.

,

1 ,
.
, ,
.
, YAGNI.
,
.
. ,
,
.
"", .

2 1 . , ,

535

,
, -
.

,
, "" , , ,
.
. , .
, , UpdataleThing. FtpUpda
taleThing, Ht tpUpda taleThing FileSys t emUpdata eThing.
-
. Ftp, Http F i l e S ystem - , ,
; UpdateMechani sm.
UpdateMe chani sm .
, , Upda tae
Thing, .
, ,
, ,
. : "
".


, ( 1 4)
, . ,

, . , ,
, Composite.
.

. Composite: ,
, , ,
.
, . ,
-
, !

, ,
, , , .
,
.
.
,
. - ,
.
:
, ,
, . -
, . , ,
,
.
. .

536

V.


- . .
.
. -
. . .
,
.
( . ).
- -
. ( )
.
. PHPUnit,
. 1 8.

, . , ,
. . , .
, . 1 6 phpDocumentor,

.
. phpDocumentor. -
.
. , .
.
.


- . :
, - . .
, . -
. 1 7 , Git ( .
CVS Subversion)
. . () , Git
, .
, .
. Git ,
.
.
Git . -
. . ,
. ,
.



.
. ,
- .

2 1 . , ,

537

, .
. , PEAR (. 1 5),
.
- Phing (. 19) -
.

- .

. .
, , .

.


.
!
.
,
. .
.
. ,
.
, !
, ,
.
20 () -
. /I
.


,
, , .
. - Bugzilla. .
, /I . -,
Mozilla.
Git, Bugzilla - .
. . Bugzilla
http : / /www . bug z i l l a . org.
Bugzilla ,
.

.
,
. . .
. .

. ,
- Bugzilla.
Bugzilla , .

538

V.

,
,
- .
- Mailma (htt p : / /www . gnu . org / software /mai lman/).
, ,
. ,
,
.
,
. ,
, ,
.
, ,
.
"" ( wiki " ") -

.
, ,
. - , ,
, ,
. .
Foswiki, h t tp : / / foswi ki . org. Foswiki
Perl. , -, .
PhpWiki,
http : / /phpwi ki . sourceforge . n e t , DokuWiki.
http : / /wi k i . spli tbra i n . org/wiki : dokuwiki.


, ,
. ,
, - .
, , .
, ,
.
. ,
, - ,
.
,
.
.
, .
. -
.
,
, .
, , Smalltalk, ++, # Jv.
- ,
. !

VI


@@@

)/)

@@@

,,

/)J

"/

1 . Alexander Christopher. Sara Ishikawa. Murray Silverstein, Jacobson, Ingrid


Fiksdahl-ing and Shlomo Angel. Pattem Language: s, Bildigs,
Constructio. Oxford, UK: Oxford University Press, 1 977.
( , , .
. J. . . - . . - .
, 20 1 4. )
2. Alur Deepak. John Crupi and Dan Malks. J2EE Patterns: Best Practices and
Desig Strategies. Englewood Cliffs, NJ : Prentice Hall R. 200 1 .
( , . . J2.
. - . . - . "", 20 1 3.)
3. Beck Kent. E.xtree Programmig Explained: r Chage. Reading,
Addison-Wesley, 1 999.

( . . - . . - . "".
2002.)
4. Chacon Scott. Pro Git. New York,

NY:

Apress, 2009.

5. Fogel Karl and Moshe Bar. Source Development ith CVS, hird Edition.
Scottsdale, AZ: Paraglyph Press, 2003.
6. Fowler Martin and Kendall Scott. UL Distilled, Second Editio: BriefGide to the
Stadard Object Modelig Langage. Reading, : Addison-Wesley, 1 999.

( . UL. L
. - . . - . "-", 20 1 1 .)
7. Fowler Martin, Kent Beck. John Brant, William Opdyke and Don Roberts. Refac
torig: Improvig the Desig of Existig Code. Reading. : Addison-Wesley. 1 999.
( , . . n, ,
. . . - . . - .
"-", 20 1 3.)

542

VI.

8. Fowler Marti n . Patterns of Eterprise Applicatio Architectre. Reading, :


Addison-Wesley, 2003.

( . . - . . .. "", 2009.)
9. Gamma Erich, Richard Helm, RaJph Johnson and John Vlissides. Desig Patterns:
Elemets of Reusae Object-Orieted Sojtware. Reading, : Addison-Wesley,
1 995.
( . , , .
- . .
. . - . "", 2007.)
-

1 0. Hunt Andrew and David Thomas. h Pragmatic Programmer: Fro Jomeyma to


Master. Reading, : Addison-Wesley. 2000.
( , . -.
. - . . - . "", 20 1 2 . )
1 1 . Kerievsky Joshua. Rejactoring to Patterns. Reading, : Addison-Wesley, 2004.
( . . - .
. - .. "", 2006.)
1 2. Metsker, Steven John. Building Parsers with Java. Reading,
200 1 .

Addison-Wesley,

1 3 . Nock Clifton. Data Access Patterns: Dataase Iteractions i Object-Orieted


Applications. Reading, : Addison-Wesley, 2004.
1 4 . Shalloway Alan and James R 'Itott. Desig Patterns Explained: New Perspective
Object-Orieted Design. Reading. : Addison Wesley, 2002.
1 5. Stelting Stephen and Olav Maasen. Applied Java Patterns. PaJo Alto, : Sun
Microsystems Press, 2002.


1 . Beck Kent and Erich Gamma. "est Irifected: Programmers Love Writing Tests. "
http : / / j unit . source forge . ne t / doc/te s t infected/ t e s t ing . htm
2. Collins-Sussman, Ben, Brian W. Fitzpatrick, . Michael Pilato. "Versio Cotrol
with Sbversio" http : / /svnbook . red-bean . /
3. Gutmans Andi. Zend's Andi Gtmans 6 & how Apple is the 'biggest barrier'
to obile's futre. h t tp : / /venturebeat . com/ 2 0 1 2 / 1 0 / 2 4 / zends-andi-gutmans
o n - p hp - 6 -b e i n g - a - de v e l op e r - c e o - a nd - ho w - a pp l e - i s - t h e - b i g g e s t
barrier-to-the- future-o f-mob i l e /
4 . Lerdorf Rasmus. "/ FI Brief History. " http : / /www . php . n e t / /manua l /php f i 2 .
php#h i s t ory
5. Suraski Zeev. "h Object-Orieted Evoltio of . " http : / /www . devx . com/
webdev/Art i c le / 1 0 0 0 7 / 0 /page / 1


1 . Bugzilla: http : / /www . bug z i l l a . org
2 . CruiseControl: ht tp : / /cru i secontrol . s ourceforge . net/

543

3. CVS: http : / /www . cvshome . org/


4. CvsGui: http : / /www . wincvs . org/
5. CVSN: http : / /www . cvsnt . org/wiki
6. DokuWiki: http : / /wi ki . s p l i tbra i n . org/wi ki : do kuwi ki
7. Foswiki: http : / / foswiki . o rg/
8. Eclipse: http : / /www . ecl ipse . o rg/
9. Java: http : / /www . j ava . com
1 0. Jenkins: http : / / j enkins - c i . org/
1 1 . GNU: http : / /www . gnu . org/
1 2 . Git: http : / /g i t - scm . com/
1 3. Git: http : / / g i t - scm . com/book
1 4 . Google Code: http : / / code . google .
1 5. Mailman: http : / /www . gnu . o r g / s o f tware /ma i lman/
1 6. : h t tp : / /www . ma r t i n fowl e r . com/
1 7 . Memcached: http : 11danga . com/memcached/
1 8. Mercurial: http : / /mercu rial . seleni c . com
1 9. OpenPear: http : / / openpear . org/
20. Phing: http : / /phing . i n f o / t r a c /
2 1 . PHPUnit: http : / /www . phpun i t . de
22. PhpWiki: ht t p : / /phpwiki . s ource forge . net
23. PEAR: http : / /pear . php . net
24. Pyrus: http : / /pear2 . php . net
25. PECL: ht t p : / /pec l . php . net/
26. Phing: http : / /phing . info/
27. PHP: h t tp : / /www . php . net
28. PhpWiki: ht tp : / /phpwi ki . source forge . net
29. PHPDocumentor: http : / /www . phpdoc . org/
30. Pirum: http : / /pirum . sen s i o l abs . org
3 1 . Portland Pattern Repository's Wiki (Ward Cunningham): http : / /www . 2 . /
c g i /wi ki
32. Pyrus: http : / /pear2 . php . net
33. RapidSVN: ht tp : / / rapidsvn . t i g r i s . org/
34. QDB: http : / /www . bash . org
35. Selenium: http : / / se leniumhq . o rg/
36. SPL: http : / /www . php . net /spl
37. Subversion: ht t p : / / s ubve r s i o n . apache . o r g /
38. Ximot - CVS Wiki: h t tp : / /x im i o t . com/ cvs /wi ki /
39. Xdebug: http : / /xdebug . org/
40. Zend: http : / /www . zend . com
4 1 . Xinc: http : / / code . googl e . com/p/xinc/

@@

/))
-----

Interpreter, 1 1 .
. , ,
,
!
. Interpreter.
. . .
-
,
MarkLogic, 1 1 . ,

.
. (Steven

Metsker) Building Parsers with Java (Addison-Wesley, 2001 ) . ,


. ,
.



, (to
kens).
. ,
.
S canne r .

namespace gi \parse;
class Scanner {
1 1 .
const WORD
const QUOTE
const APOS

1;
2;
3;

546

VI.

const
const
const
const
const

WHITESPACE
EOL
CHAR
EOF
SOF

protected
protected
protected
protected

$ l ine_no
$char_no
$ t o ken
$token_type

6;
8;
9;
;
-1 ;
1;
;
nul l ;
-1;

11
11
11


Reader .
.
function construct ( Reader $ r , Context $context )
$this->r = $ r ;
$this->context = $context ;
function getContext ( ) {
return $this->contex t ;

11

.
function eatWhi teSpace ( ) {
$ ret = ;
i f ( $this ->token_type ! = sel f : : WHITESPACE & &
$this->token_type ! = sel f : : EOL ) {
return $ re t ;
$this- >nextToken ( )
$this->token_type
$ ret++ ;

whi l e

sel f : : WHITESPACE
sel f : : EOL ) {

1 1

return $ re t ;
11
11
11

.
, ,
$ int .
function getTypeString ( $int= - l ) {
i f ( $ i nt<O ) { $ int=$this->tokenType ( ) ;
i f ( $ int<O ) { return nul l ; }
$ resolve = array (
=> ' WORD '
sel f : : WORD
=> ' QUOTE '
sel f : : QUOTE
=> ' APOS '
sel f : : APOS
sel f : : WHITESPACE => ' WHITESPACE ' ,
sel f : : EOL
=> ' EOL '
sel f : : R
=> ' R '
sel f : : EOF
=> ' EOF '
);
return $ resolve [ $ int ] ;

.
11 ,
11 .
function tokenType ( ) {
return $ this ->token_type;

1 1 .
function token ( ) {
return $ thi s->token ;

1 1 ,
11 WORD .
funct ion isWord ( ) {
s el f : : WORD ) ;
return ( $ this ->token_type

1 1 ,
11 .
function isQuote ( ) {
return ( $this - >token_type
sel f : : APOS 1 1
$this->token_type
sel f : : QUOTE ) ;

1 1 .
function l ine_no ( ) (
return $this->l i ne_no;

1 1 .
funct ion char_no ( ) {
return $ this->cha r_no ;

1 1
funct ion clone ( ) {
$this->r = clone ( $ this->r ) ;
11 .
1 1
11 .
function nextToken ( ) {
$thi s - >token = nul l ;
$ t ype;
wh i l e ( 1 is_bool ( $ char=$thi s->getCha r ( ) ) ) {
i f ( $ this->i sEolChar ( $ char ) ) {
$this- >token = $this ->manageEolCha rs ( $char ) ;
$this->l i ne_no++;
$this- >char_no = ;
$ t ype = sel f : : EOL;
return ( $ t h i s - >token_type = sel f : : EOL ) ;

else i f ( $ th i s - >isWordChar ( $ char ) ) {

547

548

VI.

$this- >token = $this->eatWo rdChars ( $char ) ;


$ t ype = s e l f : : WORD;
else if ( $this->i sSpaceChar ( $ char ) ) {
$ th i s -> token = $ ch a r ;
$type = sel f : : WHITESPACE ;
) e l s e i f ( $ char = = " ' " ) {
$this-> to ken = $ cha r ;
$type = sel f : : APOS ;
) else i f ( $char ==
' ) {
$this->token = $cha r ;
$ t ype = sel f : : QUOTE;
' "

} else {
$ t ype = se l f : : CHAR;
$this->token = $char ;
$this->char_n o + = strlen ( $this->token ( ) ) ;
return ( $this->token type = $type ) ;
return ( $this->token_type

sel f : : EOF ) ;

11
11

,

function peekToken ( ) {
$ state
$ this ->getState ( ) ;
$type = $this->nextToken ( ) ;
$ to ken = $this->token ( ) ;
$this->setState ( $state ) ;
return array ( $ t ype, $token ) ;
11
11

ScannerState,

function getState ( ) {
$state = new ScannerStat e ( ) ;
$state->line_no
$this->l ine_no ;
$state->char_no
$this- >char_no ;
$state->token
$ this- >token ;
$this->token_type ;
$state->token_type
$ state->r
clone ( $ this-> r ) ;
$ state->context
clone ( $ this - >context ) ;
return $state;
11
11

ScannerState

function setState ( ScannerState $state
$this->line_no
$state->l ine_no ;
$state- >cha r_no ;
$this->cha r_no

$this->token
$this->token_type
$ this->r
$this->context
return;

$state->token;
$state->token_type ;
$state - > r ;
$state->contex t ;

/ !
pri vate function getChar ( ) {
return $this->r- >getChar ( ) ;
/ /
privat e funct i on eatWordCha rs ( $char ) {
$val = $cha r ;
while ( $this->isWordChar ( $ char=$ this->getChar ( ) ) ) {
$val
$cha r ;
. =

i f ( $char ) (
$this->pushBackChar ( ) ;
return $val ;
11 n
private function eatSpaceChars ( $ char ) (
$val = $ char;
while ( $ this->i sSpaceChar ( $ char=$ this ->getCha r ( ) ) ) {
$val
$char ;
. =

$this- >pushBackChar ( ) ;
return $val ;
/ /
function pushBackChar ( ) (
$this->r- >pushBackChar ( ) ;
return;
/ / ,
pr ivate function isWordChar ( $char ) (
return preg_match ( " / [A-Za - z 0 - 9 \ - ] / " , $char ) ;
/ / , n
pr ivate function i sSpaceChar ( $ char ) (
return preg_match ( " / \ t l / " , $ char ) ;
1 1 ,
private function i sEolChar ( $char ) (
return preg_match ( " / \ n l \ r/ " , $char ) ;

549

550

VI.

1 1 : \n, \r \ r \ n
private function manageEolChars ( $ char ) (
if ( $ char
"\r" ) {
$next_char=$thi s->getCha r ( ) ;
i f { $next_char
" \n " ) {
return " { $char } { $next_cha r } " ;
else {
$this->pushBackChar ( ) ;
==

==

return $ cha r ;

function get Pos ( ) {


return $ this->r->getPos ( ) ;

class Scanne rState {


pu ic $ l ine no ;
pu l i c $char_no;
pu i c $token;
pu l i c $token_type;
pu ic $ r ;

.
. , .
: i sWord
C h a r { } , i s SpaceChar ( ) .. nextToken ( ) .
. .
S ca n n e r .

.
- S ca nn e r S t a t e .
, P a r s e r ,
, - . g e t S t a t e ( )
S canne r S t a t e , . s e t S t a t e ( }
Scann e r S t a t e , .
Context.
namespace gi \parse;
class Context {
pu ic $ resultstack

array ( } ;

funct ion pushResult ( $mixed } {


array_push ( $this->result stack , $mixed ) ;

function popResul t ( ) {
return array_pop ( $this->resul tstack } ;

551

function resul tCount ( ) {


return count { $this- >resul tstack ) ;
function peekResul t ( ) {
i f ( empty ( $this->resultstack ) ) {
throw new Except ion ( "empty resultstack" ) ;
return $this- >resul t stac k [ count ( $this- >results tack ) - 1 ] ;

, , ,
.
. lnterpreter.
!
: Scanner
. Reade r.
.
Reader S t ri ngReade r.
namespace gi \pars e ;
interface Reader {
function getChar ( ) ;
function getPos ( ) ;
func tion pushBackChar ( ) ;

class StringReader implements Reader {


private $ i n ;
private $pos ;
function
const ruct ( $ i n ) {
$this->in = $ i n ;
$this->pos
;
=

function getChar ( ) (
if ( $thi s - >pos >= strlen ( $ this->in ) ) {
return false;
$ char = subst r ( $this->in, $this ->po s , 1 ) ;
$this->pos++;
return $char;

function getPos ( ) {
return $thi s - >pos ;

function pushBackChar ( )
$this ->po s - - ;

552

VI.

funct ion s t ring ( ) {


return $ this->in;


. , , ,
. . Scanner,
. .
.
$context = new \gi \parse \Context ( ) ;
$user_in
" \ $ input equals ' 4 ' or \ $ input equals ' four ' " ;
$ reader = new \gi \parse\St ringReader ( $user_in ) ;
$scanner = new \gi \parse\ Scanner ( $ reade r , $ context ) ;
=

while ( $scanner->nextToken ( ) ! = \gi \parse \Scanner : : EOF ) {


print $scanner->token ( ) ;
print " \ t { $ scanner- >char_no ( ) } " ;
print " \t { $ scanne r->getTypeString ( ) } \n " ;

Scanner
nextTo ken ( ) .
t o ken ( ) ,
. cha r_ no ( )
. getType S t ri n g { ) .
. .
$
i nput
equa l s

or
$
i nput
equa l s

four

1
6
7
13
14
15
16
17
18
20
21
22
27
28
34
35
36
40
41

CHAR
WORD
W I T E S PACE
WORD
W I T E S PACE
APOS
WORD
APOS
WHI TE S PACE
WORD
WHI T E S PACE
CHAR
WORD
WH I T E S PACE
WORD
W I T E S PACE
APOS
WORD
APOS

---

, ,
, .
.
?

6 .

553

Par s e r
- P a r s e r .
P a r s e r , .
namespace gi \parse ;
abs tract class Parser
const GIP RESPECTSPACE
protected $ respectSpace
protected static $debug
protected $discard
protected $name ;
private static $count=O ;

1;
false;
false;
false;

function _construct ( $name=nul l , $options=nul l ) (


i f ( is_null ( $name ) ) {
sel f : : $ count++;
get_class ( $ th i s ) . " ( " . s e l f : : $count . " ) " ;
$this->name
else {
$name ;
$this->name
i f ( i s_array ( $options ) ) (
if ( i s set ( $options [ s e l f : : GI P_RESPECTSPACE ] ) ) {
$ th i s ->respectSpace=t rue ;

protected function next ( Scanner $ s canner ) {


$scanner->nextToken ( ) ;
i f ( ! $this->respectSpace )
$scanner- >eatWh i teSpace ( ) ;

function spaceSign i f i cant ( $bool ) (


$this->respectSpace = $boo l ;
static funct i on setDebug ( $bool ) (
self : : $debug = $boo l ;
function setHandl er ( Handl er $handler ) {
$this->handler = $handler;
final function scan ( Scanner $s canner ) {
i f ( $scanner->tokenType ( ) == Scanner : : SOF ) (
$scanne r->nextToken ( ) ;

554

VI .

$ ret
$this->do Scan ( $scanne r ) ;
i f ( $ ret & & ! $ t his->discard & & $this->term ( ) ) {
$this->push ( $scanner ) ;
=

i f ( $ ret ) {
$this-> invokeHandl er ( $s canner ) ;

if ( $ this ->term ( ) & & $ret )


$this ->next ( $s canner ) ;
$this- >report ( " : : s can returning $ re t " ) ;
return $ re t ;

function discard ( ) {
$ this->discard
t ru e ;
=

abs tract function t ri gger ( Scanner $ scanner ) ;


functi on term ( )
return true;

1 1

protected function invokeHandl er ( Scanner $ s canner ) {


i f ( ! empty ( $this ->handl er ) ) {
$this->report ( "cal l i ng handl er : "
. get_class ( $this - >handl er ) ) ;
$ t h i s - >handler- >handleMatch ( $thi s , $scanner ) ;

pro tected function report ( $ms g ) {


i f ( sel f : : $debug ) (
print " < { $thi s - >name ) > " . get class ( $ this )

"

$msg\n" ;

protected funct ion push ( Scanne r $ s canner )


$context
$scanner- >getContext ( ) ;
$context - >pushResul t ( $ scanner- >token ( ) ) ;
=

abstract protected function doScan ( Scanner $ scan ) ;

s can ( ) .
. s ca n ( ) Scanner,
. , Pa r s e r ,

, doScan ( ) .
-

555

. .
.
doScan ( )
, Cont ext.
Cont ext . Parser,
S canner,
.
Parser : : push ( ) .
protected func tion push ( Scanner $ scanner )
$context = $s canner->getContext ( ) ;
$context ->pushResult ( $scanner->token ( ) ) ;

, ,
. -,

dis card ( ) .
$ d i scard. -,
(terminal) (.. ,
). (..
Collect ionParser,
), ,
. , ,
term ( ) .
.

. invokeHandler ( ) ,
S canne r . Handler (.. ,
Handler ) Parser (
setHandler ( ) ). handl eMa tch ( ) .
, -
. .
scan ( ) S canner ( next ( ) ).
.
nextToken ( ) ea tWhi t e Space ( ) S canne r .
, doS can ( ) .
doScan ( ) . t rigger ( ) .
, , -
. t rigger ( ) , ,
.
Parser. Cha racterParse
, .
namespace gi \parse ;
class CharacterParse extends Parser {
private $char ;
function construct ( $ char, $name=nul l , $options=nul l ) {
parent : : cons truct ( $name , $ opti ons ) ;
$this- >char = $char;

556

VI .

function t rigger ( Scanner $ scanne r ) { return ( $ scanner->token ( ) == $this ->char ) ;

protected funct ion doScan ( Scanner $scanner ) {


return ( $ this->trigger ( $scanner ) ) ;


. t ri gg e r ( ) ,
,
. ,
doScan ( ) t r i g g e r ( ) .
,
. ,
. ,
.
namespace gi \par s e ;
1 1
abstract class Col lectionParse extends Parser {
protected $parsers = array ( ) ;

funct ion add ( Parser $ ) {


i f ( i s_nul l ( $ ) ) {
throw new Exception ( " argument is nul l " ) ;
$this - >parsers [ ] = $ ;
return $ ;
funct i o n term ( ) {
return false;

class SequenceParse extends CollectionParse


function t rigger ( Scanner $scanner
if ( empty ( $this->parsers ) )
return f a l s e ;
return $this->parsers [ O ] ->t rigge r ( $scanner ) ;

protected function doScan ( Scanner $s canner ) {


$start_state = $ scanner->getState ( ) ;
foreach ( $this ->parsers as $parser ) {
i f ( ! ( $parse r->trigger ( $ scanner ) & &
$s can=$parser->scan ( $s canner ) ) ) {
$ scanner->setState ( $start_state ) ;
return false;

557

retur t ru e ;

C o l l e c t i o P a r s e add ( ) ,

t e rm ( ) , .
S e quece P a r s e : : t r i gg e r ( )
Pars e r , ;
t r i g g e r ( ) . P a r s e r C o l l e c t i o
Pars e : : t r i g g e r ( ) , , C o l l e c
t i oPa r s e : : s ( ) . C o l l e c t i o Pa r s e : : s ( ) ,
doSca ( ) t r i gg e r ( ) s ( ) P a r s e r .
, C o l l e c t i o n
Pa r s e : : d o S c a ( ) .

. S equece P a r s e
, ,
, . S r

Co t e x t . P a r s e r
, S e quec e P a r s e .
Cotext ,
? ,
. , Co t e x t
S r . do S ca ( )
, . .
s e t S t a t e ( ) . ,
.
.
amespace gi \pars e ;

1 1 ,
11 .
class Repet i t i oParse exteds Col l e c t i oParse (
private $mi ;
private $max;
fuc t i o

cost ruct ( $mi=O ,

paret : :

cost ruct ( $,

if

<

( $max

$i

&&

$max=O ,

$ame=ul l ,

$optios=u l l )

$optios ) ;
$max > ) (

throw w Except io (
"max imum ( $max )
$ t h i s ->mi

$i ;

$ t h i s - >max

$ma x ;

l a rger tha miimum ( $i ) " ) ;

fuctio t r i gger ( Scaer $ s r )


retur true ;

558

VI .

protected function doScan ( Scanner $ scanne r ) {


$ s tart_state = $scanner- >getState ( ) ;
i f ( empty ( $ th i s - >parsers ) ) {
return t rue;
$parser = $ this ->parsers [ 0 ] ;
$count = ;
whi l e ( t rue ) {
i f ( $ this->max >
return true ;

& & $count >= $ t hi s- >max ) {

i f ( ! $ parser->trigger ( $ s canner ) ) {
i f ( $ this- >min == 1 1 $ count >= $ t h is - >min ) {
return true ;
else {
$ scanner->setStat e ( $ s t art_state ) ;
return false;

if ( ! $parser->scan ( $ scanner ) ) {
i f ( $this ->min
1 1 $count >= $this- >min ) {
return true ;
else {
$scanner->setState ( $ start state ) ;
return f a l s e ;

$count++ ;
return true ;

11
11

,
.
class AlternationParse extends Col lectionParse
funct i on t r i gger ( Scanner $ scanner ) {
foreach ( $this- >parsers as $parser ) {
i f ( $parser->trigger ( $scanner ) ) {
return true ;

return false ;

protected function doScan ( Scanner $ scanner ) {


$ t ype = $ scanne r->tokenType ( ) ;
foreach ( $ this- >parsers as $parser ) {
$ s tart_state = $ scanner->getState ( ) ;
i f ( $ t ype == $parser->trigger ( $ scanner ) & &

$parser->scan ( $ s canner ) ) {
return true ;

$s canner->setState ( $ s tart_state ) ;
return false;

11
11


.
class StringLitera l Parse extends Parser {
function t ri gger ( Scanner $scanner ) {
return ( $s canner->tokenType ( )
Scanner : : APOS 1 1
$s canner->tokenType ( )
Scanner : : QUOTE ) ;
==

protected function push ( Scanne r $ scanner ) {


return;

protected function doScan ( Scanner $ scanne r ) {


$quotecha r = $ scanner->to kenType ( ) ;
$ ret = f a l s e ;
$st ring = " " ;
whi l e ( $ token = $scanner ->nextToken ( ) ) {
i f ( $token == $quotechar ) {
$ ret = true ;
break;
$st ring .= $ scanne r - >token ( ) ;
i f ( $ s tring & & ! $ this ->di scard ) (
$scanner- >getContext ( ) ->pushResul t ( $ s tring ) ;
return $ret;

11
11


.
class WordPa rse extends Parser {
funct ion
const ruct ( $word=nul l , $name=nul l , $ opt ions=nu l l ) {
parent : = construct ( $name , $options ) ;
$thi s - >word = $word;

function t ri gger ( Scanner $ s canner ) {


i f ( $scanner->tokenType ( ) ! = Scane r : : WORD ) {
return fal s e ;
if

is_nul l ( $this->word ) ) {

559

560

VI.

return true;
return ( $this->word

$scanner->token ( ) ) ;

protected function doScan ( Scanner $ scanne r ) {


$ ret = ( $this->trigger ( $scanner ) ) ;
return $ ret ;

Parser
.
P arser, , . . 1 .
Parser
+sca n ( s canne r : Scanne r ) : Boolean

#doScn (scnner: Scnner) : Boolen


+trigger(scnner: Scnner) : Boolen
+te rm ( ) : Boolean

--

CharacterParse
#doSca n ( scanne r : Scanner ) : Boolean
+t rigge r ( scanne r : Scanne r ) : Boolean

WordParse

CollectlonParse
+scan ( s canne r : Scanne r ) : Boolean
+add ( parse r : Pa rse r )

#doScan ( s canne r : Scanne r ) : Boolean


+t rigg e r ( s canne r : Scanne r ) : Boolean

#doScan ( s canne r : Scanne r ) : Boolean


+t rigge r ( scanne r : Scanne r ) : Boolean

...._

StrlngLlteralParse

AlternatlonParse

SequenceParse

#doScan ( scanne r : Scanne r ) : Boolean

#doScan ( s canne r : Scanne r ) : Boolean

+t rigge r ( scanne r : Scanne r ) : Boolean

+t rigge r ( scanne r : Scanne r ) : Boolean

RepetltlonParse
#doScan ( scanne r : Scanne r ) : Boolean
+t rigge r ( s canne r : Scanne r ) : Boolean

. 6 . 1 . Parser

, Composite, ,
,
-.
-
. . 1 .

561

. 1 . Composite -

Al t e rnat i onPa r s e
SequenceParse

o rExpr 1 andExpr
' and ' operand

Repe t i t i onPa r s e

( eqExpr ) *

,
(
)

,
-. .
-, 1 1 .
operand ( orExpr 1 andExpr ) *
( ' ( ' expr )
1 <s t ringLiteral> 1 variae ) ( eqExpr ) *
' or ' operand
' and ' operand
' equals ' operand
' $ ' <word>

expr
operand
orExpr
andExpr
eqExpr
variae

'


.
namespace gi \parse;
class MarkParse {
private $expression ;
private $ operand;
pr ivate $ interpreter;
private $ context ;
funct ion
const ruct ( $sta tement ) (
$this- >compi le ( $statement ) ;

function evaluate ( $ i nput ) (


$icontext
new InterpreterContext ( ) ;
$prefab
new VarialeExpression ( ' i nput ' , $ i nput ) ;
=

1 1 n input
$prefab-> interpret ( $ i context ) ;

$this->interpreter->interpret ( $ icontext ) ;
$ result
$ icontext - > l oo kup ( $this ->interpreter ) ;
return $ resul t ;
=

funct ion compile ( $statement_s tr ) {


11
$context
new \gi \parse\Context ( ) ;
$scanner
new \gi \parse\Scanner (
new \gi \parse\StringReader ( $ statement_s t r ) , $context ) ;
$statement
$ this ->expression ( ) ;
$scanresult = $stat ement- >scan ( $scanner ) ;
=

i f ( ! $scanresult 1 1

562

VI.

$scanner->tokenType ( ) ! = \gi \parse\Scanner : : EOF ) {


"";
$sg
$sg
" l ine : { $ scanner->line_no ( ) ) " ;
$sg
" cha r : { $scanner->char_no ( ) ) " ;
$sg
" token : { $scanner->token ( ) ) \ n " ;
throw new Exception ( $sg ) ;
$this->interpreter = $ scanner- >getContext ( ) ->popResul t ( ) ;

function expres s i on ( ) {
i f ( ! isset ( $this- >expres s i on ) ) {
$this- >expression
new \gi \parse\SequenceParse ( ) ;
$thi s - >express ion- >add ( $this->operand ( ) ) ;
$bools
new \gi \parse \Repeti t ionParse ( ) ;
$whichbool = new \gi \parse \AlternationParse ( ) ;
$whichbool - >add ( $this->orExpr ( ) ) ;
$whichbool - >add ( $this->andExpr ( ) ) ;
$boo l s - >add ( $whichbool ) ;
$this- >expres s ion->add ( $bools ) ;
=

return $this->expression;

funct i on o rExpr ( ) {
$or = new \gi \pars e \Sequence Parse ( ) ;
$or->add ( new \gi\parse\WordParse ( ' or ' ) ) ->di scard ( ) ;
$or->add ( $thi s - >operand ( ) ) ;
$or->setHandler ( new BooleanOrHandl er ( ) ) ;
return $ o r ;

function andExpr ( ) {
$and
new \gi \parse \SequenceParse ( ) ;
$ and- >add ( new \gi \parse\WordParse ( ' and ' ) ) - >di scard ( ) ;
$ and- >add ( $ th i s - >operand ( ) ) ;
$ and- >setHandl er ( new BooleanAndHandler ( ) ) ;
return $and;
=

function operand ( ) {
i f ( ! i s set ( $this- >operand ) ) {
$this- >operand
new \gi \parse\ SequenceParse ( ) ;
$ = new \gi \pars e \AlternationParse ( ) ;
new \gi \parse\SequenceParse ( ) ;
$
$exp->add ( new \gi \parse \CharacterParse ( ' ( ' ) ) ->di scard ( ) ;
$exp->add ( $this->expres s i on ( ) ) ;
$exp->add ( new \gi \pars e\CharacterParse ( ' ) ' ) ) ->di scard ( ) ;
$cop- >add ( $ ) ;
$cop- >add ( new \gi \parse\StringLiteralParse ( ) )
->setHandl er ( new \ g i \parse \StringLiteralHandler ( ) ) ;
$cop- >add ( $this->varial e ( ) ) ;
$this- >operand->add ( $ ) ;
$this->operand->add ( new \gi \parse\Repet i tionPars e ( ) )
=

563

->add ( $ this ->eqExpr ( ) ) ;


return $this->operand;

function eqExpr ( ) {
$equals
new \gi \parse\SequenceParse ( ) ;
$equals->add ( new \gi \parse\WordParse ( ' equa l s ' ) ) - >discard ( ) ;
$equa l s ->add ( $this->operand ( ) ) ;
$equals->setHandler ( new Equal s Handler ( ) ) ;
return $equa l s ;
=

function va riale ( ) {
$variae
new \gi \parse\SequenceParse ( ) ;
$variale- >add ( new \gi \parse\CharacterParse ( ' $ ' ) ) ->di scard ( ) ;
$variae- >add ( new \gi \parse \WordParse ( ) ) ;
$variae- >setHandler ( new Varia eHandl e r ( ) ) ;
return $varia l e ;
=

,
, , - , .
(.. ,
-,
e qExpr andExpr ) . expre s s i on ( ) . ,
,
-.
11 expr : : = operand ( orExpr 1 andExpr ) *
function express ion ( ) {
i f ( ! i sset ( $this ->express ion ) ) {
$this->express ion
new \gi \pars e \SequenceParse ( ) ;
$this->expres s ion->add ( $this ->operand ( ) ) ;
$boo l s
new \gi \pars e \ Repet i t ionParse ( ) ;
$whichbool = new \gi \pars e\Al ternationParse ( ) ;
$whi chbool->add ( $this->orExpr ( ) ) ;
$whichbool ->add ( $ this- >andExpr ( ) ) ;
$bools->add ( $whichbool ) ;
$this->expression- >add ( $bool s ) ;
=

return $this->expression;

. -
, .
orExpr andExpr. ,
P a r s e r , , -.
, .
expr e s s ion ( ) , expres s ion ( ) .
, , ,
-, - comp i l e ( ) eva l ua t e ( ) . comp i l e ( )
. ,
Scanner. expr e s s i on ( ) , -

564

VI.

Parser, .
Parser : : scan ( ) , S canner.
, comp i l e ( ) .
S canne r.
, Expre s s i on.
$ i nterpreter.
evaluate ( ) Expre ss i on. r
Vari aeExpre s s i on,
$ inpu t , Context .
Expre s s i on. ,
$_REQUEST, $ i nput ,
MarkLogic.
. Varia eExpress ion, lnterpreter,

1 1 .

evaluate ( ) Expre s s i o n : : interpret ( )


. ,
Cont ext.

. 1 1 , Interpreter
Expre s s ion .
, .
?
Hand l e r , Parser
Parser : : setHandl e r ( ) .
. Va riaeHandler Parser
va r i a e ( ) .
$vari ale->setHandler ( new Varia eHandle r ( ) ) ;

Handler , .
namespace gi \parse ;
interf ace Handl er {
function handleMatch ( Parser $parser,
Scanner $scanner ) ;

Vari aleHandler.
class VarialeHandler implements \gi \parse \Handler
funct ion handleMatch ( \gi \pars e \ Parser $parse r,
\gi \parse \Scanner $s canner ) {
$va rname
$ scanner->getContext ( ) ->popResul t ( ) ;
$scanner->getContext ( ) ->pushResul t (
new Varia eExpress ion ( $varname ) ) ;
=

Parser, VarialeHandl e r ,
, handleMatch ( ) .
.

565

Var i aeExp r e s s i o n ,
.
Equa l sExpre s s i o n , Li t e ra l Exp r e s s i on . .
.
class StringLiteralHandle r implements \gi \parse \Handler
function handleMatch ( \gi \pars e \ Parser $pa rser,
\gi \parse\Scanner $ s canner ) (
$value
$s canner- >getCont ext ( ) - >popResul t ( ) ;
$ scanner->getContext ( ) - >pushResult (
new Literal Express ion ( $value ) ) ;
=

class Equal sHandl er implements \gi \parse\Handle r (


function handleMatch ( \gi \parse\Parser $parser,
\gi \parse \Scanner $ scanner
$compl = $ s canner->getContext ( ) - >popResult ( ) ;
$comp2 = $scanner->getContext ( ) ->popResult ( ) ;
$scanner->getContext ( ) - >pushResult (
new Equal s Expression ( $comp l , $comp2 ) ) ;

class Boo leanOrHandler implements \gi \parse \ Handler


function handl eMatch ( \gi \parse\Parser $parser,
\gi \parse\Scanne r $ scanner
$compl = $ scanner->getContext ( ) - >popResult ( ) ;
$comp2
$ scanner- >getContext ( ) - >popResult ( ) ;
$ scanner->getContext ( ) - >pushResul t (
new Bool eanOrExpres s i on ( $comp l , $comp2 ) ) ;
=

class Boo leanAndHandler implements \gi \parse\Handler


function handleMatch ( \gi \parse\ Parser $parser,
\gi \parse\Scanner $ scanner
$compl
$ s canner- >getContext ( ) ->popResult ( ) ;
$comp2 = $ s canner - >getContext ( ) ->popResult ( ) ;
$ scanner- >getContext ( ) - >pushResul t (
new Bool eanAndExpres s i on ( $comp l , $ comp2 ) ) ;
=

, Iterpreter.
1 1 . Ma r k Pa r s e , .
$input
' f ive ' ;
$s tatement
" ( \ $ input equa ls ' five ' ) " ;
=

$engine

new Ma rkParse ( $ statement ) ;

566

VI.

$ result = $engine->evaluate ( $ i nput ) ;


print " i nput : $ i nput evalua t i ng : $ s tatement\n " ;
i f ( $ resul t ) {
print " t rue ! \n " ;
else {
print " false ! \n " ;

.
i nput : f ive evaluat i ng :
t rue !

( $ i nput e qual s ' fi ve ' )

....,
_
_
_
_
_
_
_
_
_
$..:k....._.._ t.a.i.. "..,._.\wit."' 11 'lr

Accessors 63
Alexander. Christopher 1 73
Alur, Oeepak 1 74, 1 94, 336
Andi Gutmans 26
Ant 480
Apache 1 23
Assertion 456
Atkinson. Leon 27

Beck, Kent 26, 454


Bergmann, Sebastian 398, 454
BinaryCloud 2 7
Bugzilla 53 7

CI 391
Closures 1 1 2
Code coverage 509
Cohesion 1 52
Composite properties 1 02
Continuous integration 29
Continuous Integration 39 1 , 501
Coupling 1 52
CruiseControl 5 1 5
Crupi, John 1 74

D
DocBlock
42 1
Domain
Model 336
Specific Language 246
DSL 246
OSN 1 88

EBNF 24 7
Encapsulation 1 56
Erich Gamma 1 73
Extreme Programming 454
EXtreme Programming 1 93

F
Fixture 455
Fluent interface 369. 462
Foswiki 538
Fowler. Martin 1 60, 1 94, 336
Fuecks, Hany 2 7

G
Generator 345
Gerrit 39 1
Getter 63
Git 29, 386, 43 1

444
443
439
444

439
445
433

444
443
433
Gutmans, Andi 26

Hany Fuecks 2 7
Helm. Richard 1 73
Hudson 5 1 5
Hunt. Oavid 284

1
Identity 353
lnheritance 1 82
Interception 98

J
Java 76, 23 7
JavaDoc 389, 4 1 8
Java Web Archive 5 1 5
Jenkins 5 1 5
5 1 5

568

Johnson, Ralph 1 73
JUnit 26, 454

IOSS 534

L
Late static indings 87, 348
Leon Atkinson 2 7
Lerdorf, Rasmus 26

Malks. Dan 1 74
MarkLogic 246
m variae 4 1
Memcached 356
Mercurial 432
Methods 43
Mock 461
Mocking 78

N
Nock, Clifton 336

Orthogonality 1 53
Overloading 98

PEAR 28. 1 22, 385, 393


Foundation Classes 394
396
398
404
PEAR2 395
Personal Homepage Tools 33
Phar 395
Phing 4 79, 480
488
495
496
49 1
fileset 491
33
34
4 34
PHP_CodeSniffer 5 1 1
phpdoc 4 1 9

PhpDocumentor 389
4 1 9
4 1 8
PHPDocumentor 28
PHP/FI 33
PHPUnit 45 1 , 454
php-webdriver 4 72
Php-webdriver 471
Pirum 4 1 2
Plug-ins 1 28
Polymorphism 1 54
Productions 24 7
Properties 4 1
Pyrus 395

R
Rasmus Lerdorf 26
Reflection API 1 29, 1 35
Registxy 284
Review Board 39 1
RFC822 385

s
Scope 4 1 , 287
Scrum 454
Selenium 4 7 1
Server 4 7 1
Separated Interface 344
Setter 63. 1 00
SimpleXml 89
SimpleXL 48
Smarty 323
SPL 1 34, 264
SQLite 1 88
Stub 461
Subversion 386. 432
SUnit 454
Suraski, Zeev 26

Thst-First Development 502


Thst-Oriented Development 502
FD 502
Thomas, David 284
D 502
Token 545
racking branch 439
Thgger token 1 72

u
UML 1 59

v
Vlissides, John 1 73

w
WAR 5 1 5
WebDriver
API 474
WordPress 1 28

- 4 7 1
, 1 73
336

1 34
60

Xdebug 509
L- 47
1 93. 454
XUnit 454

f, 1 73
l 2 7
I 345
DI: 1 59, 201
r, 26. 34

YAGNI 1 93. 534

z
Zeev Suraski 26
Zend Engine 34
Zi- 395

r 1 24. 1 25
r 1 63
. 1 73
. 1 74, 1 94. 282. 336

, ,
1 72
1 09
228
46
1 62
, 2 7
1 6 1

1 58. 1 75
. 26. 454
, 398, 454

1 0 1 , 1 86
1 04
, 1 73
r
1 74
1 60
1 66

include_path 1 23
388
422
425
423
424
1 28
1 58

r 46 1
482
1 58
26. 34

78, 46 1
1 88
1 56, 1 88
501
545
74
Iterator 266. 34 1
342

569

570

Reflector 1 36
SplObserver 264
SplSubject 264
344
462
90
91

454
298
39, 40
ApplicationHelper 297
Exception 90, 92
MDB2_Driver_Common 1 88
MDB2_Driver_mysql 1 88
MDB2_Driver_sqlite 1 88
PDO 69
PEAR_Error 90, 9 1 , 401
PHPUnit_Framework_ThstCase 455
Reflection 1 36
ReflectionClass 1 36, 1 38
ReflectionException 1 36
ReflectionExtension 1 35, 1 36
ReflectionFunction 1 35, 1 36
ReflectionMethod 1 36, 1 40
ReflectionParameter 1 36, 1 4 1
ReflectionProperty 1 36
ReflectionZendExtension 1 36
RemoteWebDriver 4 73
ShopProduct 40
SplObjectStorage 264
WebDriverBy 4 74
72
1 53
422
97
1 29
1 30, 1 38
1 60
42

$this 68
abstract 72
as 8 1 , 84, 1 1 9
class 40, 1 3 1
clone 1 06. 2 1 5, 2 1 9
const 7 1

extends 5 7. 75
final 97. 30 1
finally 96
function 43
implements 74, 75
instanceof 1 30
insteadof 80, 8 1
interface 74
namespace 1 1 7
parent 59, 60, 68. 87
private 4 1 , 61
protected 4 1 , 61
public 4 1 . 61
return 345
self 68, 86, 87
static 68, 87
throw 91
trait 78
try 91
use 78, 1 1 3, 1 1 8
var 42, 6 1
yield 345

1 58

ssh-keygen 434, 5 1 8
touch 443
wget 397

DocBlock 42 1
226
1 63

DIRECORY_SEPARAOR 1 26
_NAESPACE_ 1 20
PATH_SEPARAOR 1 24
45, 1 04
224
43 1

1 06
, 1 74

1 72
2 7
. 26, 33
226

. 1 74

$_G 301
$_POST 301
$_REQUEST 30 1
43
_call() 99. 1 0 1 . 1 34
_callStaticO 99
_cloneO 1 05. 1 06, 2 1 9
_construct() 45, 46. 1 04
_destruct() 1 04
export() 1 36
generateld() 78
__getO 98. 99
getCodeO 91
getFile() 9 1
getLine() 9 1
getMessage() 9 1
GetPrevious() 9 1
getrace() 91
getraceAsString() 9 1
_isset() 99
outputAddresses() 4 7
PEAR
isError() 401
Reflection
export() 137
ReflectionClass
getEndLine() 1 39
getFileName() 1 39
getMethod() 1 40
getMethods() 1 40
getName() 139
getStartLine() 1 39
isAbstract() 139
islnstantiale() 1 39
islnterface() 1 39
islnternal() 1 39
lsSubclassOf() 144
isUserDefined() 1 39
newlnstance() 144
ReflectionMethod
getParameters() 1 4 1
invoke() 1 46
returnsReference() 1 4 1
ReflectionParameter
getClass() 1 42, 1 45
getName() 1 42

571

session_startO 290
_setO 98. 99. 1 00
_sleep() 294
_toString() 4 1 , 9 1 . 1 08
_unset() 99, 1 1
_wakeupO 294
44
1 34
60
63
62
98
63. 1 00
1 3 1 . 1 40
68
456
r 63, 1 00
1 1 2

336
452

52, 1 82
224
76
1 33
29, 390.
39 1 . 50 1 . 503, 537
39 1 . 503
, 336, 3 7 7

4 1 . 287
1 6 1

git-shell 435
-
1 48
34. 39. 40
Parser 553
1 30
1 97
224
- 243
459

-> 42

572

: : 68
1 05
1 06
catch 92
dieQ 74
if 1 59
include 76
include() 1 2 1
include_onceQ 1 2 1
instanceof 56. 1 30, 1 57, 233
new 40, 46
require() 1 2 1
require_once 1 20
require_once() 1 2 1
return 345
switch 1 59
try 9 1 , 92
yield 345
1 6 1
1 53, 259
1 52

1 64
==

===

1 1 5
Config 400
java.lang.reflect 1 35
Log 396
PEAR 399
DB 188
MDB2 1 88

PHPUnit 398
SimpleXL 3 1
98

34
35
- 4 1

$_SESSION 290
$this 44, 69
98
1 54, 335
1 06
1 88, 53 1
m 87,
348

509
1 54. 1 8 1 , 53 1
1 75
294
452
1 64
1 4 7
247

- 1 48
1 4 7
1 4 7, 384
1 1 7
1 23

1 87, 530
344
502
26, 33
r 336

292
-
247


1 72

r 336
26, 1 83, 301
1 02, 456
452

4 1
1 33
7 1
1 02
68
1 52

1 52, 1 88
454
4 7 1
292
285, 289

::class 345
545
29
284
390
68
1 60
52
, 26. 34

336
406
369
282, 452, 536
452
452
457
478
466

452
46
object 46
4 7
353
545
. 284
445
76

28 1
280
28 1
280
456

make 480
50. 1 60
5 1
1 4 7

7 1 . 85. 86, 200

. htaccess 1 24, 2 1 9
httpd.conf 1 23
package.xml 404
php.ini 1 23
pirum.xml 4 1 3
. 1 60. 1 72. 1 74. 1 94,
282, 336
455
, . 2 7

1 75
1 75

array_siiceQ 1 39
array_walkQ 1 1
_autoloadQ 1 27
call_user_func() 1 1 0. 1 34
call_user_func_array() 134
class_exists() 1 29
class_implements() 1 34
_construct() 60
create_function() 1 1 . 228
file() 1 39
fopen() 1 24
get_called_classQ 348
get_class() 1 30
get_class_methods() 1 3 1
get_class_vars() 1 33. 1 35
get_declared_classes() 1 29
get_iclude_path() 1 24
get_parent_class() 1 33
in_array() 1 32
is_a() 1 30
is_array() 47
is_bool() 4 7
is_callae() 1 1 0. 1 32
is_doue() 47
is_float() 4 7
is_it() 4 7. 5 1
is_iteger() 4 7
is_long() 4 7
is_null() 4 7
is_object() 4 7
is_resource() 4 7
is_strig() 4 7
is_subclass_of() 1 33
method_exists() 99, 1 32
parse_ini_file() 299

57 3

574

print_rQ 1 38. 340


rand() 260
readParams() 1 49
replaceUnderscores() 1 26
requireQ 1 24
set_include_pathQ 1 24
simplexml_load_file() 89
spl_autoload() 1 25
spl_autoload_register() 1 25
spl_autoload_unregister() 1 2 7
_unset() 1 05
unset() 1 0 1
var_dump 40
var_dumpQ 4 1 , 1 3 7
wri teParams() 1 49
1 09
1 09

284
. 1 73

28
Abstract Factory 1 72. 1 73. 2 1
Application Controller 280, 305
Command 2 73, 280. 299. 303
Composite 224. 226, 25 1 . 266
r 229
Composite 560
Data Access Object 336
Data Mapper 336
Data ransfer Object 367
Decorator 234
Domain Model 280, 330
Domain Object Factory 363
Facade 240, 325
Factory Method 205. 207
Front Controller 1 78, 2 77, 280, 295,
297. 304
ldentity 86, 352
Identity Object 366
Intercepting Filter 239
Interpreter 245, 545
Layer Supertype 327
Lazy Load 361
Observer 259, 402
Page Controller 280. 3 1 7, 320

31 7
Prototype 2 1 5, 2 1 8
Registry 280, 283. 30 1 , 467
Selection Factory 373
Separated Interface 348
Service Layer 325
Session Facade 325
Sigleton 20 1 . 2 1 9. 220
Smarty 294
Strategy 1 85, 254
Thmplate Method 25 1
Thmplate View 280. 322, 323
Trasaction Script 280. 325
rasaction Script 330
Unit of Work 356
Update Factory 373
View Helper 322
Visitor 266
1 94
1 94
2 79
1 74

1 94
1 94
25, 1 72
1 94


26. 1 93, 454
1 93
26, 34

224

MarkLogic 255
4 7
4 7

-
MYSQL


,
H T M L

,
, ,


.

MySQL

- .

.


,




.

www.williamspuishing.com

MySQL,


- ,
-

.

,
.

ISBN 978 - 5 - 8459-1 574-0

MySQL:
-
2-



-,



. ,


,


,

,


.


,
PayPal Authoize.net,

www.williamspulishing.com

I S B N 978 - 5 - 8459- 1939-7


Ajax JavaScript,

-
.
.

,
,
-
:

http://www.williamspuishing.com/
Books/978-5-8459-1 922-9.html.