以下皆为本人自我理解内容,如有失误之处,请多多包涵。 6 X; R2 b& D2 ^
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 3 N0 Q/ `1 X; m
- y9 M) g. `: K使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 4 N9 N, ^- [0 h: }
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
" h0 I* x8 ^- d" }结合使用方法来进一步理解它的使用目的吧。 2 b" B' f2 i ?
E$ f0 j% v5 T1 K+ Tnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
% m7 x- D# V" f) n" `/ l - namespace One;# A& @+ I* _2 p d; N7 N- J9 l
- namespace ONE;
复制代码 6 _- {% b, U# X, q2 W& C& E
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
9 O2 D" b, d8 P6 m' F2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
7 E! J9 D- {! a4 v0 H) d - class Person{
! F6 [ S; Y4 ?/ @5 c - function __construct(){
0 p$ ? _" k! X- M, F9 P - echo 'I am one!';
0 D( {% T* [0 V - }1 J" C. e0 c& D! Q" a; L2 d
- }
复制代码- //name.php
]) z6 T7 G- L d2 w. n' N. g - require_once './1.php';9 D1 Y7 u( ?- }0 ]- Y- |( K8 J
- / j4 f6 C2 J: i/ \: e3 w% i7 o
- new Person(); //输出 I am one!;
+ ^7 `8 Q3 ]# o - new \Person(); //输出 I am one!;
复制代码
7 w9 Z& M2 |. y- v: q8 c: p" e3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
- W7 K9 ~6 ~1 Y - require_once './1.php';( J! L! M6 X+ x
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
9 T# I6 }5 v1 k' J4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php * V0 u0 ~+ y* a4 ~5 _- `6 ~) G2 r
- namespace one;
. d( c$ E9 S+ O; j; d* `; G - class Person{
/ N; M. F+ v' i" B5 }* j - function __construct(){3 Y9 }8 d, ~% A& N, A3 R
- echo 'I am one!';
% Z* f7 ~7 C& B2 w: L' m- C) X; ~ - }
" G" _% I3 @0 A - }
复制代码- //name.php
& Q6 Z7 R. ^) Z1 D, W) } - require_once './1.php';
. f1 m; K9 `8 h# e - new \one\Person(); //输出 I am one!;
) ~; d: c# S, c5 A9 o, J - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 / y7 d3 B8 A' {$ ~% c# G
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
: `7 ?- | @" @9 A9 @6 Y |3 ^5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
/ Y- h. J+ ^+ H, N7 `) g& V- //1.php + q* K3 z# `! D3 R1 F4 m1 e
- namespace one;) \- {: X |) _ Z0 I
- class Person{
" I) ]# e+ E; Z! U - function __construct(){
& i; m9 i" U7 G( Q* }6 n, v - echo 'I am one!';
. I9 N$ i% Z7 v3 @9 ]+ a - }
. U. k3 X" [ k1 E J% d/ C - }
复制代码- //name.php6 B: X! s; @% q) }: @: p7 F
- namespace test;
S: \. L( J5 q0 a% `7 ]% K - require './1.php'; ( A- ~: t' @# t! H2 i3 S
- new \one\Person(); //输出 I am one!;0 e3 ^, |3 A5 [
- new Person(); //这里结果会是什么呢,猜猜看" x- B7 `/ O' x8 X( `
- 最后一行结果报错:$ Z2 W9 a: ]. x) U, ^
- Fatal error: Class 'test\Person' not found
复制代码 ( K- F/ _% `) u* ]3 i v5 M, W( d, l, y
. F3 r5 \" N" o1 i首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 * H$ |; g5 Q9 _7 a$ |1 c# {
结果报错: - Fatal error: Class 'Person' not found
复制代码
! ^- Z/ k$ z @9 M3 p& i接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
, K! F$ z4 j% o. I6 T' } - namespace test;
- y" s. E/ A1 h* y - require './1.php';
u: h! a a2 U- \7 R! L0 V5 ~ - 2 h1 [ Z0 L5 P7 X9 Z9 d
- class Person{
0 t5 h/ `4 Z( A: I* I3 l& O; j - function __construct(){/ f$ o8 }. T4 ~) E! U" W/ D3 ~
- echo 'I am test!';5 l, p, Z n b+ c* h2 t7 [
- }
8 O2 j0 W# `( T# M( q6 p {) E - }: L3 f# p( S4 K: O9 D0 Z
- # }. P3 M, ?+ ^; v, f9 \' q/ A8 t
- new \one\Person(); //输出 I am one!;1 ~; D' r8 T3 `& @
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
6 l2 K# \8 }" t# A9 h7 O5 x8 O* \最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php1 ^8 h/ c( {" {
- namespace test;
2 t$ v/ h3 o; U! R/ R+ Y2 @5 b - namespace one;! s6 L4 c0 L: V g# J' n% t
- class Person{0 E) ]9 e1 ~( f9 Z: u
- function __construct(){
' b0 Y$ Q5 e! Y% A" k- ?5 L - echo 'I am one!';% Z1 ?7 P. H% j/ E9 u1 [2 d
- }
9 w) F* n8 N, x' H+ w0 S" z - }9 n! _5 U' V4 g" [- m5 d# ~' F
- * m) ]6 @# H* D+ ?! m7 k8 H
- class Person{& v' ~5 j( X7 q j! G9 B' c. a
- function __construct(){2 |2 N' |! E- K6 l$ t. s; r: `( J
- echo 'I am test!';
" ~- e/ s2 J) p# {2 O( n - }7 s+ U# ~+ K! V
- }
复制代码 # X, X; e# w1 u% ?& P; J
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
1 X, f. b. C+ Z看来简单的把require理解为替换,在这里行不通。
U* |; s& T! s. K7 ?4 `6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
# K: N: P( h# E( J L7 o- //name.php9 D. q& p( ]1 x6 ]3 k7 @: T
- % {8 N# p% f$ |6 I
- namespace test\person;
6 U; r, h; _) ^3 B9 \: m) n8 x - 8 A& j6 n( L' F: J4 D0 \; c
- class Person{
( G' V, e. P7 `2 }9 x - function __construct(){
# [0 Q4 K5 D; J2 Z0 \# D2 T1 k) Q% P - echo 'I am test!';5 g T9 W+ Y) u& N1 V
- }5 z; _7 O1 S5 |% p" [* D
- }
( }9 ~( a6 q; U1 t: `& g - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
* w6 s% f* x: N8 q$ f& X不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 % `+ x) S+ V7 D5 `/ y n9 V
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php7 o+ ] Q9 B7 u. d
! p, U+ N. k* g# S3 X% u; c# F- namespace test;. `0 q2 z9 u. `: K- @) e
- echo 'zhai14';5 q0 j8 X2 j6 H3 k" |! U) r, g
- namespace zhai;) D7 l+ H7 [) Q& E( y/ N! C
- require './1.php';
复制代码
$ H# d m. H. T1 H/ c7 }! |- F$ Fphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
$ [: D1 a/ x' S" C) W& A' tuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。) e+ x% F1 [* x6 t' K5 Q# a1 A
- //name.php6 P4 W0 ^( q9 r8 R8 ~ l
- 7 e0 f* }3 @9 ^) A) ^) m3 v3 B
- namespace animal\dog;" z" G! p& c7 {" R
1 J! \$ [. a: _+ [- class Life{
# R+ x# a& o' I2 W+ S1 T% C/ t. V - function __construct(){ @1 ] `7 J+ U- T1 `! i0 s
- echo 'dog life!';
/ Q! T8 C3 M, ~/ C! W - }; K' g7 g5 r% B3 P
- }! ?# X2 h* Z$ J9 O- N* k o
5 z0 n. C9 x3 r- namespace animal\cat;: k5 w& g, `0 x
* S- g* ~ [" b9 o' Z% r4 Q- class Life{
' ]( X6 ` O y& k+ R - function __construct(){
# G9 u' t: r6 b! R7 h' F' a9 l - echo 'cat life!';
& q9 n. s$ |; T; e9 [: `+ o - }3 I" B5 `, @5 i' l7 ?( _( N
- }
+ {' m8 C4 ^: e' h7 r! [; N - , B; ]% |% s# A l
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间 ]! B8 i. T p- s8 D/ C# z
- new \animal\dog\Life(); //A
' T9 T$ U/ `: `
4 X! V7 b c, S4 N- e# j% t3 a- use animal\dog; //a
5 G/ [: T6 o( ? - new dog\Life(); //B
# g7 R, {- R& ?6 ]" x/ u6 m
( j; D" {) V( d# s2 E5 y; f( M- use animal\dog as d; //b# D& {; ?& }% w, w: J; K9 W( ^" J( y
- new d\Life();
复制代码 ; }4 f" x! s4 F" O' S4 T) E" t
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 ' e$ X7 }/ f" D1 {" r o- N7 _+ @
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: : I( T8 ~ ^8 ` }: Y$ w6 Q$ d
相当于
/ } I- D" P$ `- C2.namespace后面不建议加类名,但use后可以。& l! J' e/ v8 f' m5 l
- //name.php6 H% l1 i. i* ?( L9 ^6 d
- 8 B& r/ E! K) p& a5 O
- namespace animal\dog;
% {' s3 ^" s! f. g; o, A
3 M0 d* @( f+ b D- class Life{" W! @, X$ X3 ?- M2 X' k; a
- function __construct(){& n- o% p) s8 T) d( Y- t5 n
- echo 'dog life!';' F' Q' \9 V4 g9 i# V
- }
$ U, U3 R6 a6 J: x; | - } \$ b1 q& d' h6 u; y4 M2 J
2 i" ^: K3 W9 M! M- namespace animal\cat;) N! @) M7 T) z) G! k* j
- / s l$ S8 e9 t6 Q0 N
- class Life{0 v+ J: l8 Y# U& r2 F6 C( w8 z/ p
- function __construct(){
; W7 w; w) [# v0 l) Y N y1 v - echo 'cat life!';
9 X' O u" Q% N/ Y - }: t8 [0 i& P1 K0 Z! j( f3 a
- }- m. J5 W" Z! ^ m" M0 o
' T: s3 O% }& b7 X- use animal\dog\Life as dog;
( s) v# w# t& ]7 t - new dog();
复制代码
& B. L! [7 w1 b/ f/ o- n) c& D. w如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
- j& [3 |. `7 [: J1 H4 D2 k% v因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php/ y' c& d! I7 k% x4 b5 C0 d
* d, r* S; |5 b/ \$ F) _- namespace animal\dog;; d/ D {* S9 t
& T; ?) K9 `( `: {+ [# ?6 C- class Life{
/ B) m( v% H0 M - function __construct(){9 y8 @7 |( h% P$ v. D% j G
- echo 'dog life!';- a+ K. g0 \3 G+ N! x' r! k# G
- }
* ?8 `5 r. g* M - }
% o8 g2 S) O' B8 |/ Q$ P1 y6 B# A - class Dog{
9 @5 d/ V! z) v - function __construct(){
8 s1 z8 V2 X1 g7 a% ` - echo 'dog in dog!';
$ U0 j+ X- v6 f6 W6 S! Y- C+ O0 ^ - }# y) d8 ?$ G* @' |8 O
- }; m* h+ s; G& P
8 T, O7 @& a# F( s- M- namespace animal\cat;' F7 h$ h% B" N
1 L$ g/ i+ I# ?( w3 I- // class Dog{
9 a* ^9 z6 J: L" @ - // function __construct(){0 J; j1 F0 n4 D; Q5 r3 t2 |: N
- // echo 'dog in cat!';) I3 x: H. d7 t6 o/ y4 y
- // }
% v; w: ~8 B" m - // }1 w- k+ s: G/ B4 K5 i9 ~
- class Life{" @" o8 ?4 O* w, R3 g% [. m
- function __construct(){
4 \" W% j6 O8 |+ l. R: h - echo 'cat life!';& `8 a- G; q6 |" u+ K) y
- }7 O& w. O3 s+ V- K* W. Q4 b' C/ j( C
- }
) f6 g# K6 y' o% ?% n/ T3 }
$ ~( u: n4 ^" `9 @6 o' ^8 q3 [- use animal\dog; 2 v* M/ m) a) s2 z9 |
- new dog\Dog();
复制代码 ? Z& i: Y7 I; ^, {, R* `1 J
如上,使用了 " E3 ] A! Y6 W1 j2 Q8 z" U
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 . v+ ^" P9 |/ x6 b! t, a1 V# \! F2 Q- a
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 ' z, K& V0 w. k p4 n: D, e
- K& b. l: }" X* E
* u& `: V4 X* h' |
/ U8 O6 Y8 y8 Y
; z( n% z1 V2 U8 i. I2 w0 c9 c |