以下皆为本人自我理解内容,如有失误之处,请多多包涵。
* u2 U- O+ k7 l1 \) N' W文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 4 R/ w5 {6 d8 f4 R
7 G/ t6 ]( }) Z
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
$ h2 J5 N2 V+ q5 r) n据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) : Z- C$ Y+ U5 R p! T5 b1 }
结合使用方法来进一步理解它的使用目的吧。
% Y. Z2 E: v2 ]( z% r8 R( b# q. v5 F/ C7 [9 L& R
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
4 }4 _ |3 R$ G0 Y" W* c6 W - namespace One;
/ b- S- x, k& G5 v4 N& o - namespace ONE;
复制代码
% l) u. |+ Y7 i1 ` N如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 1 \ c! T1 ^* D* M
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
% s* V1 g; d. E( A- n% D& i - class Person{: g6 j5 u1 x1 b+ Y) q
- function __construct(){+ G4 T" ]6 G/ G; h+ y8 K* d9 X
- echo 'I am one!';
# c# u3 z' i' q4 @- u - }7 [. K' Y$ {$ f' U& a
- }
复制代码- //name.php
. S5 ]( k( b$ ~) m& m6 w - require_once './1.php';1 P Z" q# t# P# Y% z2 `* E
- ; O# J/ x4 f% z# B# ~
- new Person(); //输出 I am one!;
* M. B& e, E, Z6 t, p: g- p5 H q( `3 ^ - new \Person(); //输出 I am one!;
复制代码 0 P* q9 C7 v, A% j" y% G
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
+ w3 d5 E# ?& `% v - require_once './1.php';" y6 `. F3 u3 L# j+ ?/ A
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 8 w2 I, ]$ g* H* r) X1 O; t
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php ' x$ W7 B8 V4 [2 p, l
- namespace one;/ R& j+ U7 b, u' Z/ @5 |
- class Person{3 Z4 v/ U" J" i- B, X
- function __construct(){
, \" H8 A( `( u$ U& l - echo 'I am one!';' I$ m+ q& b" b$ {
- }
" a! w) [* v ?" J - }
复制代码- //name.php
' Y) _" ]! Q* b2 W - require_once './1.php';
1 @9 @$ I7 i# Q% V - new \one\Person(); //输出 I am one!;
% b) s! y6 F+ s - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
% ~5 j$ j% W, m+ q( V2 n% I可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
' D7 a1 K( Q: P! T& k5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。! y5 h" _8 ]" ~9 _9 C4 z: f, c6 C% c
- //1.php $ ?- ~8 o' [8 W6 N% p8 n
- namespace one;
6 ]: _2 y0 R) b- t; y$ w9 x# w ? - class Person{" |5 g2 j" F6 @0 a5 S7 D
- function __construct(){6 t, F5 J* Y( r+ m
- echo 'I am one!';
i$ x, u) T" a) X - }9 i9 ?9 r8 [1 h# e! o
- }
复制代码- //name.php* m7 e& S% K1 k0 B2 F* e+ R% y
- namespace test;
8 S0 d1 Z* O5 e; b8 n2 p - require './1.php';
5 t5 T6 } U' u. ]0 y - new \one\Person(); //输出 I am one!;. @- n$ G: h9 q; B* p" u" @
- new Person(); //这里结果会是什么呢,猜猜看
+ N* B X3 e2 }/ k6 Z - 最后一行结果报错:
9 R4 c2 k. d+ S8 y1 M - Fatal error: Class 'test\Person' not found
复制代码
2 @: N0 _$ j' D6 Z9 x8 A. {0 v4 e- q2 L9 W" T
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
5 n$ K L! z$ }# m4 W结果报错: - Fatal error: Class 'Person' not found
复制代码
% p. M+ ]$ T# b3 H( p& t接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php7 s. s' ]/ Z5 ]6 @
- namespace test;
' R" P1 {6 B1 P - require './1.php'; $ z5 Z; ^- `0 q- C& ]
- % z+ h* G- o' l; p$ P
- class Person{
; w7 F) a$ ?- q& X: ` - function __construct(){
: o N( Q; w: W4 |5 M+ c9 ?5 s - echo 'I am test!';
. h4 p; C+ e7 b% u9 _( S, U - }
/ G# G2 K+ q0 l& [$ _4 T, N - }% u$ q0 n* p/ {2 s! N) S
& F& F" M i: r6 p. c- new \one\Person(); //输出 I am one!;5 p* G: B$ B5 _; L3 U3 u
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 # z3 {$ w1 v$ a8 Y; a9 U
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php; e/ V% i' k8 q
- namespace test;
9 H0 K [, w- l! J8 U0 _' a8 j - namespace one;+ ~8 i% t, B$ D
- class Person{+ r$ p _; }' q, R2 q
- function __construct(){& A5 h' J* m. x& o, _' ~. R" O$ n
- echo 'I am one!';
* {7 T0 S' K9 E/ n - }
2 u3 _" \3 A9 T' N7 C9 |7 t( ~ - }& `/ X8 k3 _/ }7 F1 Y9 z% D) w
1 o. o6 K3 B' j8 a d- class Person{
+ a5 K9 F( @& H" M# M" R$ ^. n - function __construct(){0 e6 d, ^# [4 V S4 Y4 t
- echo 'I am test!';
) [9 e6 t/ e+ `+ P% Q - }% @. K2 k7 p& S% W O" y6 k, G1 a
- }
复制代码
* V- q# y( X3 U7 M4 ?+ d/ t# p3 O( v) D无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 + v) ]( `& z, x9 C, e% V# g) t8 T
看来简单的把require理解为替换,在这里行不通。
, S7 i& H3 }2 B0 g$ H6 v6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。& {6 m% i4 r8 G2 o u
- //name.php* G M1 b8 m4 A& B1 {- S( r% x2 ]0 k: q
- 6 t* J m: z# y# o6 C
- namespace test\person;
0 @# Q1 l9 K; t2 c2 R - 9 ?! X" y8 S7 L$ i2 i/ {
- class Person{
' u: l( h7 b& r - function __construct(){2 ~! `. S& ~1 v2 X
- echo 'I am test!';8 q! F0 p/ R) Z6 o: R( Q7 n6 V+ F4 \
- }8 d9 F& v5 k; p* _7 k$ x) r
- } ?; b1 b: K5 B& z* J/ c
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
4 A+ ]3 ?9 ~9 A8 I8 w) ^; e不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
# P+ H( `6 j9 ^/ O0 \: R `, S7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
# O9 F* D$ R. K - ; D" q9 z* p9 n- ]8 G
- namespace test;
$ R7 b9 w0 H/ T# L9 j! B! u) ~+ z* V" b - echo 'zhai14';- X! {- T9 H+ X4 S0 s- {
- namespace zhai;! u9 N- ^) [0 x6 p6 J
- require './1.php';
复制代码 4 ~4 n$ C0 I4 m' q# v& N
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 3 r) l! z/ F! ~, H0 \
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
H3 h& p6 p6 u8 K0 m) W- //name.php
8 i; l3 l" w! y8 V6 a# E - $ N$ _" X3 C5 W# D/ p! ?/ h h
- namespace animal\dog;
4 n. r9 D u$ b# t8 h( L6 T
. m+ z+ a' C5 o% c5 i; ^) [/ O- class Life{9 {; m: c! f' }" f
- function __construct(){* |+ E+ p" L6 I, i. ^8 n( I
- echo 'dog life!';- b1 B* o) [) t+ I, j* A# B
- }
$ K3 a: C1 V+ p$ S - }
2 }/ j0 l, n: [) U - " E' [* T \" a6 U6 j' Q. J3 a
- namespace animal\cat;, v/ f1 |( ~) b+ N
) a% ^# t5 t" @7 u( F' F; a- class Life{6 H9 v7 n% R4 {7 f x
- function __construct(){$ ?; ^* ^+ c4 n
- echo 'cat life!';* }- ]& a H& Z5 s. V
- }% u! w' I) p3 s! ~- K6 j
- }
. k5 E& t* j6 y$ [+ n2 ~2 W
/ z3 b0 ^ f0 @6 u8 ~- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间: M ~4 ^/ W) F
- new \animal\dog\Life(); //A$ s3 _( I3 ^8 J/ P
- 1 V% |# j' P& M" ]$ i- W1 p7 I
- use animal\dog; //a
+ G. d$ {, v5 E - new dog\Life(); //B% C6 T, v" [5 R7 F
% @3 f( T* g; s. D) v- use animal\dog as d; //b
8 U8 m8 N% ]8 n$ ?+ [& { - new d\Life();
复制代码 $ ?/ [7 P4 R! P
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 ; j5 J' |2 b1 T6 ]% }+ r
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: : f, K( ~1 o7 {0 d3 W; S
相当于
: C* |0 D% }4 c1 ]2.namespace后面不建议加类名,但use后可以。6 r" S3 j" S- G+ M; |
- //name.php
& h( K5 R) t0 i; | - % l+ l) l" @+ M' W$ D i! T6 t
- namespace animal\dog;6 i( _; o; ?7 D' y" S1 ]
6 w& v8 X6 Z4 A- _! B4 X- class Life{. n' b$ o) A3 j6 L/ b9 D
- function __construct(){# u% ?0 o2 P$ A
- echo 'dog life!';
| i" i! Y$ w& ?+ t - }; Q0 x; k& V/ J: F
- }8 B4 X/ W( |( p' m4 |6 c O' t
- 8 d3 ~3 L2 i! z; _8 N( y
- namespace animal\cat;( K. |3 m# n1 X: k( V
+ X* q! h0 G! u. J# I- class Life{( d( ]- {. @3 l; ?0 X2 z% q ?) S6 U
- function __construct(){" u, p" N1 H" j
- echo 'cat life!';1 q0 t4 b; R. O! L' H) M' S
- }* j* `# ]5 P0 N# K' n
- }( U, Z B2 \( d+ C" d& `, [. J
$ {( Y% O& Y0 w9 S8 W- use animal\dog\Life as dog; ( A0 B% {+ `& V2 X! T. I) w
- new dog();
复制代码
) ?( p0 ]" {% X) s9 [如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 , Y3 E B B: V
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php+ S# ?* V) J+ q Z
- , X. \- o$ P e1 e$ g
- namespace animal\dog;% q( A( i3 P7 y$ e4 g
; y9 P, r6 h2 x6 l% ?- class Life{
4 u; u! k$ Y' g3 d - function __construct(){% Z& w$ c8 i0 [: M, T8 o5 R
- echo 'dog life!';
) _4 ?# B1 S8 X, W - }2 I- a1 H; U/ i! Y x& g% I( s' d
- }0 `3 g# r/ H& @7 e6 a6 {! b: S. _
- class Dog{" e7 f2 H6 k) c5 i; z$ S
- function __construct(){
$ C" |/ E6 J- b6 h - echo 'dog in dog!'; v! O- A2 s- \' n" @* W
- }2 w- V0 w u/ {1 u$ c
- }4 q* b- X' Q R- g9 R
8 m0 p- f2 K; n9 J9 @- namespace animal\cat;! Q7 ]$ j6 N6 Z5 M8 @# Y8 ]
5 r u: M! V: h7 L- // class Dog{1 S7 z, }! `: V" `' N8 o; }$ E3 w, [4 f
- // function __construct(){4 C- w9 d$ U1 F( I0 H1 }
- // echo 'dog in cat!';3 H* U& @, T! Z
- // }
; o, ^8 P. {+ s: K - // }7 h8 L, L1 T: t8 L
- class Life{
8 S3 x4 e3 e( O4 | - function __construct(){
; P' H- b s# t* z - echo 'cat life!';. L; i) K( F) _& v3 r$ T
- }+ |$ b. w) D: m. j2 n
- }
5 ? f6 t$ _8 ^; J X2 j - 1 e( L* ]/ _3 M2 h" {$ z: H" {( d
- use animal\dog; 6 i$ H! k) o8 d; {6 J8 j8 V
- new dog\Dog();
复制代码 : W% y/ w3 J6 k5 H H1 I- V! A
如上,使用了
/ v5 ]) ^ G* b* h& D- q1 Lcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 9 L7 I% u9 f8 V* ?9 W. }9 T* L# m
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 9 U% A9 m( j# E) O4 J1 a
$ p3 d2 Q# e$ a
5 x0 q3 C# l! x" N2 \& V0 Z* \! w5 N0 h) h) q
6 g3 s/ J0 A9 y+ M" q6 _ |