|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 5 ^1 L& e/ z; {" U
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 % v0 s, ?1 f e) I; r# h
7 Y% f* M$ K: ^0 P9 h6 g使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; & W7 Y" f& l1 `( T5 X
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 9 S- y1 j/ ^1 ]" ~# e
结合使用方法来进一步理解它的使用目的吧。 % h+ t" M- G& l" ?" y* D
. g, z: ~0 P8 A, ?8 ^& S& bnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;/ c( {6 y5 R$ m* y! V! R. P
- namespace One;2 F/ I( h4 b. ~( H/ J4 h n
- namespace ONE;
复制代码 $ P: Z0 Z, F9 a6 L: p2 R
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
' Y5 ~8 s3 v3 I, X2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php % M! Z# z: }: u# W' [: f
- class Person{5 b) a2 |8 j) P8 y
- function __construct(){
* j1 O! g7 r6 W& v: z - echo 'I am one!';
, J2 d0 f5 Q* }4 ~' b- i - }
; T9 ]1 u3 o. j y( Y3 Z - }
复制代码- //name.php
9 P+ \& Q$ o1 E1 E% x* j8 | - require_once './1.php';$ c4 M$ ^) j- `! y' W% p9 O. G
+ r" Z7 y7 R |- new Person(); //输出 I am one!;6 V& ^4 z9 I2 ~4 |9 F* }4 {5 O# b
- new \Person(); //输出 I am one!;
复制代码
: Q# [& {6 t. A0 v/ O4 }3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php2 }: W( E2 r! ?9 ~! |
- require_once './1.php';
. u C _. k2 l9 u, r - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 . k" o2 [/ D. d; a
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php % `+ ^6 e3 {8 \8 C
- namespace one;
' r! n$ @% ^4 x) U2 ? - class Person{0 M" s" o/ p+ O
- function __construct(){
9 S2 h3 S% [+ ~1 l8 i4 i - echo 'I am one!';1 D4 b r* Q& G7 |* Y* [1 A
- }5 e% P6 s( _$ \! V! C0 @
- }
复制代码- //name.php6 T8 r, {* Y7 F' Z( {0 M& V
- require_once './1.php';
% R1 _- B) F9 }* a; w# \0 M - new \one\Person(); //输出 I am one!;1 H+ u1 X+ J4 n! |4 L3 i
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
" \; K# u9 x( A- c可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
- u7 M4 N' H8 R" {. s9 H0 u! W% {5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
1 ^& J( w9 R9 s4 \9 Q2 ~- //1.php
A2 c5 y* b6 d% N0 q' G - namespace one;8 Y; y" T. F+ P: E1 I
- class Person{( L r" q9 p9 ~, C3 I% S
- function __construct(){
$ p5 p$ g& J. E! M* w - echo 'I am one!';
* r0 y9 n- C1 Z O - }
8 P: z- o* {6 F2 x. { - }
复制代码- //name.php+ ]* [1 z( x1 Q; ^: D7 j5 c/ j
- namespace test;
$ E2 n3 K7 ^# F# j1 L - require './1.php';
7 T( _' y6 ?# L1 Y2 O" _6 H! Y - new \one\Person(); //输出 I am one!;: }( S! [, Q9 p" D5 P
- new Person(); //这里结果会是什么呢,猜猜看; z8 T9 s4 I$ {) _, K8 {0 X
- 最后一行结果报错:8 M9 ]* K8 C$ `% r3 e
- Fatal error: Class 'test\Person' not found
复制代码 5 i( c0 K5 K9 h
& f9 e8 S) _: }7 Q, B9 M7 B首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 ( b j: I8 g, _
结果报错: - Fatal error: Class 'Person' not found
复制代码 : F- y) _# c- _6 R( X" B* X$ D
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
; y+ t0 \6 s! z$ E, ` - namespace test;, S1 f; t7 m1 m; n
- require './1.php'; . V$ E6 ~% Y7 l; W+ S4 X
- 2 w6 E7 b" i* m+ `* }
- class Person{
; L7 @7 d, |. D# ]9 [/ M - function __construct(){6 }- m$ A* i: _* P7 k. X/ r
- echo 'I am test!';
. z9 Z1 c `# m - }) ]9 ]8 m6 e5 R! R4 F/ n$ D/ e5 n
- }
0 x" ] F) Y0 r5 l$ f: H - 3 [+ F, }, i! k4 r# {) W! @
- new \one\Person(); //输出 I am one!;
* G2 _' H4 G2 ^7 J& Y - new Person(); //这里结果会是什么,自己猜猜看
复制代码
/ }% k9 }8 M3 r; ?9 M. \' y最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
' f+ C& ]3 B5 p, ]- a9 S/ k - namespace test;
( |- |9 A! R# k - namespace one;9 Z( Z& _7 ^. v! H9 N9 ?6 I. [
- class Person{
' |1 _* x; t) Z% a4 c' T/ @ - function __construct(){% i; k2 L. ?+ n% i
- echo 'I am one!';6 f: v+ W- p; \$ O& ~
- }. k( i4 { I. ~* P9 r
- }# l8 f' f6 E8 v i" }$ b
. e" F- m8 }! u6 s- class Person{
7 x; D+ e0 U( v% h6 n7 w& A - function __construct(){
, p2 r: A1 G8 @$ u - echo 'I am test!';! \- E% s4 N+ `$ `0 L
- }
1 u& q! ]& E& ^; R4 o) {: I - }
复制代码 ' p. `, U8 y, G1 k
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 `# F% r( s }. o3 X% u
看来简单的把require理解为替换,在这里行不通。 $ ~7 n2 L; q' [. ~0 x* R6 E- M
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。7 i! A6 J5 m8 W( r: Y
- //name.php( n3 O& f2 x" ~: r1 h
- 8 j6 y' q# J; b- y8 i7 U* O
- namespace test\person;
: T8 @7 ?& ?# C
( I, K1 _) V8 ?- class Person{
) Y$ D- s+ E! b. ^ - function __construct(){
$ l2 Q8 D/ W9 N7 w1 m4 u" c - echo 'I am test!';
: z4 |3 L$ z* ^& n - }
& x P9 U Q: m, x - }- R* l' h; R6 p$ `$ y
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 + F( S+ \# l, u# i& R
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
+ J; s- l0 d; K( N7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php; m- F5 p8 `, u% i9 K( l3 M) c
% u6 M9 [1 I8 C- M; }* q* {/ [- namespace test;! n8 \4 ~6 v& S9 W
- echo 'zhai14'; Y* v% r# r- ^
- namespace zhai;
) G% o" @" _& u3 q+ d" a - require './1.php';
复制代码 ; M' K1 X0 ^" n) m' W1 f+ j
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
$ v: H y( {7 m. q0 cuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
$ J U6 i) g$ c( I( S2 M- //name.php3 T/ }3 _9 @3 ?! r
- 1 E' c, R' d/ p' r+ z# Q7 g$ h
- namespace animal\dog;
4 V" y f5 Q8 j9 ?; d& i3 I8 o
2 E1 k, |/ J! y! Q- class Life{
$ V+ }% w$ U. _0 _- z. O& C* R [ - function __construct(){ z n1 q6 T; d% e. D
- echo 'dog life!';! u5 b! {( r, [0 B; L9 N
- }. b( f) L" X7 J
- }
: ?0 O0 r5 {3 `3 _* Q* X, S
) H3 ~+ a) d3 H% n: S: J I8 |- namespace animal\cat;
; H+ s1 \# q& x- I' W. s# w7 N
4 m6 ?& k2 ^/ p9 F- class Life{! b5 b* g' H' n- m1 @& a% g
- function __construct(){% }- X% _0 W) a! u* a
- echo 'cat life!';, e/ j/ ~ e' c N
- }' _% `4 N9 ~4 N7 W
- }
# I) M [ o, f6 Z - " S( @: @' h' A2 ~
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间* Q2 O; `# G) y2 [2 V" {$ F: U
- new \animal\dog\Life(); //A/ [( h& V( @9 g, f; J, V6 P4 B
- 8 [$ w8 N- s5 s4 l
- use animal\dog; //a
9 C: g! i. I! T* E. j4 z+ x0 D1 @ - new dog\Life(); //B
2 B) p' j/ T5 ] Q% z
8 I, ]( k: [5 U% Q; {6 j7 F0 V- use animal\dog as d; //b) r0 d! ~" v# w! }% r: O
- new d\Life();
复制代码
/ V' t0 f6 r* C0 L+ a通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 ) K# J* L( p- C* m) N- W1 F
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
6 b. S$ C! S3 G$ k1 ]相当于 , S- z7 C9 W5 U& k3 I
2.namespace后面不建议加类名,但use后可以。8 A2 }/ D) Y& I) Z; J) Y
- //name.php
$ O9 \/ E) g! {( T) o" r4 H1 q$ ~- x - ; A# {/ g2 R/ |! i( j( G0 p
- namespace animal\dog;
6 U* I3 _7 J6 d- y- l8 ?0 p4 s
2 N0 E- v( |' e' F' v% {- class Life{
( e- M0 F, p) ~2 t6 L2 a! h4 d - function __construct(){" x( M& n4 s: J, i
- echo 'dog life!';; t' [+ C6 L/ u$ L B1 L' n! {/ Y
- }
+ l9 @$ | Y, E3 L5 R; H& D& t! ` - }; h6 Y N: g7 r3 F
- ( [/ U/ t8 g. b6 V1 o* b% e. ?
- namespace animal\cat;" G( X0 \. D* l
3 w3 O. L2 O. p6 A: P; B- class Life{
5 M( a: ]: w% x# _, u - function __construct(){7 t. h- p- R Q' m6 p) H
- echo 'cat life!';
5 q* y6 u6 X' E - }
; S! t( b; s8 {2 f/ _ - }: K* t9 ], M g* {2 s
- . R: g+ X1 L% Q. y) a
- use animal\dog\Life as dog; 1 q) m. X- {; g% g
- new dog();
复制代码 6 o7 ?( d! d6 o7 i. R. X. z& T
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 7 K. T5 y0 x& C: {; ]" k; r( n
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
* [1 R( |7 R' l* t" e - 7 R" s; S5 i( P" _* v) b, |
- namespace animal\dog;
- |3 s+ V: y, u6 u
- t- C2 K+ A, X- class Life{
' x$ V5 y( v# Z/ A" r0 D - function __construct(){
: ~/ V: B! [, K3 W! \' o! v - echo 'dog life!';5 S, t3 e& i+ Z' A! K& m
- }. P/ N6 |6 ?: f8 V" Z
- }
7 o9 Y4 ~! n/ k: y - class Dog{( ~0 `" y) ^8 I! G v
- function __construct(){
: V' h# T* b3 ~! S - echo 'dog in dog!';
5 v, N- J3 b v; |& g - }
) B( y" G3 O1 ?9 Y* T1 b& E$ ? - }, h" h8 n$ D3 n
. k; t! f; e& V2 k: w' |- namespace animal\cat;
" W1 F1 M2 ?' U3 m3 n
H1 K0 P2 w# K' e/ i) h7 q- // class Dog{
! Z& R' l B3 w# c - // function __construct(){8 O, q3 h/ J: |& a
- // echo 'dog in cat!';. \7 q+ f% R' o6 D7 I
- // }
! Y3 b, F, R% Y5 V& U - // }8 F# k1 H: P- X0 u4 u' s5 N4 X. }
- class Life{
$ P7 ?5 M# c' c! U; F; e) r - function __construct(){
; @: `) \/ ~8 R4 n( D, h8 ? - echo 'cat life!';
' E: u, o" G) g6 m5 m# K - }
2 E$ O/ {* {/ Q, [ - }
$ r; U8 C% B/ Q! F - ( b4 i3 U1 k9 A5 r ]4 ~% J8 o; ?1 V
- use animal\dog; 2 F. z- `4 I$ }1 J
- new dog\Dog();
复制代码 2 C \: d5 w# k; _7 a9 R
如上,使用了
6 Y& }: H i0 d$ `; W' w1 icat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 4 E% Q- W4 m. C7 k6 ^: W
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
! C1 _, y x4 B4 W
' r6 S& W8 m4 R; g1 C0 I
1 g8 ]0 h3 |2 z( I% M; `1 G7 _. d% N( U$ W
( M3 t. n6 n: a8 W/ M; u
|