以下皆为本人自我理解内容,如有失误之处,请多多包涵。 ! M5 M) j' Y. V& s
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 + O4 Y, W) R1 z |# Q
. ~1 x/ w! j' L) H% A
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
; r$ r+ s+ X4 k4 y0 _- Y据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) # @ S! o- z9 M# }5 r; v: F* U
结合使用方法来进一步理解它的使用目的吧。
, j# W& X: a0 r' m+ o9 C6 O Q& v
- G! p; D" x- D4 lnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
- I1 w3 A( F7 o5 h" d - namespace One;
. X: v- f2 J1 B7 O* J9 Z - namespace ONE;
复制代码 " g, k) e0 a' E: H1 c
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
7 |3 `+ g- f7 J- x3 s/ ~2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
. E: {9 p) [7 h2 g, @- K - class Person{
" z, F/ i; f% e& o0 c7 x r$ r, r - function __construct(){+ U# u8 O9 w' }! E5 ~( z
- echo 'I am one!'; u1 M/ A. S8 m+ _8 n
- }
, J( u- N% G4 [4 t1 { - }
复制代码- //name.php
, q7 z9 b& |8 ]1 P: W% T# P - require_once './1.php';8 u/ y5 R$ n/ R+ N( Z
* I6 q5 A7 m0 ?- new Person(); //输出 I am one!;
) Z' H9 H; u3 } - new \Person(); //输出 I am one!;
复制代码
. \/ x3 l1 _. l3 t3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php" N& E- O9 U4 l3 n4 J: z
- require_once './1.php';+ Q" l( N8 q/ L0 T& O; w
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 M: x% k m* G/ B% n
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php ; c) p8 d" K: e
- namespace one;
8 [& w5 Z9 N _+ r. ]8 s! e c* k - class Person{
) [1 |+ R/ Z8 \3 ] - function __construct(){
) w; W( W' z0 x) u, _7 ^ - echo 'I am one!';; `( c8 h- p' T$ p- z* O' D
- }
+ d, C( k$ K3 v1 t - }
复制代码- //name.php
2 @" ] @* h( k J; x - require_once './1.php';
6 n1 p4 P. {% e1 d( X r/ J" t& g - new \one\Person(); //输出 I am one!;
$ y- l% P X- f; } - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 6 P" O r. Q# d* l" i
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
& ?+ ?8 K& X1 |2 ^) p5 D( ~5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。+ H& ^1 {3 _9 @1 o' u- G
- //1.php
1 k$ W& _0 c) m; g: L# W - namespace one;" s, z( S7 v; Q/ D' a( d
- class Person{
5 h9 l5 Z" ] K/ }4 Z: | - function __construct(){
, Q; h' p! B2 ]( W% h5 K" S - echo 'I am one!';
" T' n" x* O0 ^" m - }# m L5 O' O- e0 C
- }
复制代码- //name.php) i5 m: ^1 B; Y, Z3 U; s! ^
- namespace test;
_4 z# O/ W# y8 e - require './1.php'; & f) Y; @6 E) f$ U
- new \one\Person(); //输出 I am one!;) q& ^8 ^; |8 J& S; [
- new Person(); //这里结果会是什么呢,猜猜看
% o8 g% t! _. L - 最后一行结果报错:2 r6 w" N5 k; J
- Fatal error: Class 'test\Person' not found
复制代码
! c ~7 C ?$ x" `. z5 V/ W
' M0 |% L/ T2 s! Y首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 ! O, k) w. n F
结果报错: - Fatal error: Class 'Person' not found
复制代码
, r; i# c" F' Y0 V: s: J/ z接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
9 v' }' P! \9 N3 o0 c - namespace test;
( e* \8 n0 ~$ z8 ?- \ D - require './1.php'; , @! @) f" z6 u$ L( m* f, D
- m6 R( n2 x z; G, V) H
- class Person{
9 a6 P) ]% O2 E$ ` - function __construct(){3 Y- W$ {, j C% _% w0 t1 z3 [
- echo 'I am test!';
2 V) d. y9 J, o/ } - }
6 s5 _) p" J' w# f; L4 D. j6 m - }
- t: Q# F. q9 z/ C& R( R l
, x* o2 o/ m7 ^# m5 H% }- C, Y- new \one\Person(); //输出 I am one!;
# L8 N# |+ Y' I2 i2 n* O - new Person(); //这里结果会是什么,自己猜猜看
复制代码
$ `* Y7 e! F% ?6 d最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
1 C( T0 i2 d( r/ h% @2 g3 @ - namespace test;# w9 ]# i. r; c! ]$ D
- namespace one;
( {" w, s0 X' ?3 {' d% j - class Person{
- {5 t( v7 {3 g# i% o - function __construct(){
/ t, I$ {9 X2 S6 g - echo 'I am one!';
0 }) _+ `, N: Y: Y" i0 v - }
& J2 C( n1 k+ ^ - }
- X5 B' b6 f" S9 x" C
0 u% R7 k* D0 d- class Person{& |, g! r! e: `0 C/ G- ^
- function __construct(){
4 x1 ^+ }4 i2 E9 T - echo 'I am test!';
$ L& }% |' ?2 X1 t5 l% v+ T% E7 | - }; ]# J, T5 [. s$ M9 P
- }
复制代码 6 }& p$ c0 X! ?$ X! N' ?7 O: R
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
0 V! \: B# n8 k9 W; t看来简单的把require理解为替换,在这里行不通。 & I7 i& c4 _6 s% j, _: b( l n
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。$ k% [( c$ [) t, I5 f& ~
- //name.php
9 S d' G. L% N - 9 C+ `, Z0 {) d. n# E) @- X
- namespace test\person;
4 q, [7 [( A) D5 D, L - $ Y7 \: F; l6 V* O7 i" G. z
- class Person{
5 e" Z1 ^' r6 {# Z) P - function __construct(){, ?4 ?, M9 A x+ @% h _' p. _
- echo 'I am test!';2 A+ I8 ~1 U$ s% [, X; ~
- }. m5 B) T3 q) }9 B! V' l b; y
- }
5 r \# w% Q: n: y6 z+ A - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
* C4 Y7 K, M# ]3 E- F不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
2 v( g7 k3 L* _$ h6 g7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php8 i3 T8 M) W: p& R( ]
6 B) v+ I* B0 A2 r, _2 }' K% i- namespace test;
& X5 R, b8 Q. L$ |9 \6 [- Y - echo 'zhai14';
+ y% ]0 d" D* L7 U/ k" n2 Z - namespace zhai;# F$ L s- F! x$ y8 B k
- require './1.php';
复制代码
! y1 x' m+ i7 P+ Xphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 . z' K0 i) c; I" P2 n) s& F
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
6 S& L: n8 `% m+ m6 O2 D* L" V- //name.php
( J5 j1 q7 Q% e6 ~1 U
! o1 Y! P" O/ A3 ~9 M- namespace animal\dog;
1 A- g3 |6 e4 D% F7 E - / `5 y& W9 g1 m0 X0 e6 S" H f
- class Life{
. O+ h7 B& ^( W) n& E( h. [ - function __construct(){
- ]7 F! P2 u# V; {% K8 J& t - echo 'dog life!';
( R! j) I( x) ?" h, d1 A N - }
! |3 k( A$ S8 j- p& j9 x4 A - }
! d, [+ f5 K/ Q4 ]6 ^( C - ) [/ U3 l5 l% ~% \, c7 W
- namespace animal\cat;7 a4 V- L3 @( G$ C
- + ^: k! a; h6 p1 P( x9 y
- class Life{# m8 O" e8 o7 Q$ U
- function __construct(){
( s7 l9 w. J) E8 W' j7 H- ? - echo 'cat life!';' J$ M2 W& P0 e0 T# y
- }8 W9 C0 U1 u0 B9 k! P1 y% ?
- }0 W# ]2 x. B, D+ }1 ]
- ( d, G- }% F! U5 r& {2 n; G
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间2 s [; y; t x' e+ L; W
- new \animal\dog\Life(); //A, }. U( }, p9 c0 h2 _+ x3 h6 L. C8 U
- # j" Q: D1 W" t2 }( ?
- use animal\dog; //a7 m0 n" _2 ^1 t/ t
- new dog\Life(); //B1 o- W& J* K& A; V. ^* N
5 x9 H/ y" [' G6 y- use animal\dog as d; //b" h, a# D0 H4 d0 P, r" a
- new d\Life();
复制代码 5 r7 Q7 f) Q, l
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 . w5 y m# W% J* |9 U% r. d
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 6 L Z5 i w, _1 B! Q4 Z3 U. L* r
相当于
, I' j/ A9 \7 b6 z2.namespace后面不建议加类名,但use后可以。) w. N' Z4 r: n2 {4 s: t, S
- //name.php, s4 G4 w4 R3 k7 [" Y' s( w
% B+ Z5 R, M6 @- namespace animal\dog;( l" T1 f9 b8 x i* ~
( r X) L* ~: R9 N) {7 I; a# l' k; D- class Life{
7 D! v3 ?6 P9 j$ T0 N/ J - function __construct(){2 V. X2 Q/ ~2 Z9 ]7 D
- echo 'dog life!';
% Y/ p2 I: m) w' Q8 q2 e! T - }" s: a; K, U& ~$ @) P
- }3 a, u0 ~1 r1 f! v K) W
- 0 [$ X% J* ^/ E% R- Z
- namespace animal\cat;
& S; ^ J# W' T/ q/ p8 C0 L; Z
! b# }5 C* w/ ~6 q1 e; t- class Life{. h9 Y4 B3 }+ N' a7 Z
- function __construct(){% y h' N3 o: E% c
- echo 'cat life!';
/ u& T7 j! Q3 a( W - }
. G, T0 Y& ]- X! F+ x - }
: Z" I- E* `1 Z' \& |! g+ N - + Z( ]" z; S8 A
- use animal\dog\Life as dog; $ J7 r) V( _, N5 i( U8 B) y8 W
- new dog();
复制代码 3 `( F# i0 `! Z/ K: f7 R# ^
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 - g. c! @* z1 e; X
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php4 X/ ~4 G( @' g3 T! Y }4 H, r
1 l; Q7 F/ p5 F- namespace animal\dog;
% `' i! D( {- h" N - 8 ~( P2 @$ I5 E* i& R
- class Life{& ]/ h1 T, k5 K- F
- function __construct(){
6 T6 @3 ]; ~% _2 w7 {; R% t' e: J3 S) a3 L - echo 'dog life!';
9 F/ x) E! I( T- g5 Q) I- ]6 G - }( i- G$ l8 E5 A
- }
% \' S2 e+ P" l) ?2 w3 c9 _2 n9 G( F - class Dog{, ~4 D) F. U1 D( c# w
- function __construct(){
9 n( g( G$ ~; v, E - echo 'dog in dog!';
4 ?8 s8 G, b, c7 c6 y. k - }
2 h& z+ w4 o/ p - }) x8 L$ C6 [( O( b- ]$ |7 s
/ w0 ~: N1 Z# O# B* S9 z- namespace animal\cat;6 `. U2 C9 J) q! H& ^3 ~/ K |
- 7 H S0 G/ q2 h
- // class Dog{" r$ l0 u0 l0 S2 _
- // function __construct(){+ H, N/ Q `7 ^! Q/ U
- // echo 'dog in cat!';# R+ X( q' u9 `4 _! a, t' a
- // }
% K) w0 @% P5 g' K4 ]: l - // }( ~! w# O' e: u2 w# D# V
- class Life{
- ?, |/ y7 T H. o" z9 L$ R - function __construct(){1 s) g1 P9 W" g2 @
- echo 'cat life!';
. G6 t: b# D* G7 X - }" f. [' h; w$ ]9 M) I% R! L
- }% @7 i7 C1 W' X$ y, F5 x
- + I) d- l, m* I4 X
- use animal\dog; + K2 v7 ^/ I& i5 Q
- new dog\Dog();
复制代码 6 X9 p3 n+ M3 }) ~
如上,使用了 6 Z4 }+ r- N* L$ W4 `
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 , {) b' Y; j9 i& M
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
% h& Z0 B" u* c% N9 H2 V( `* h6 Q: [; ]: h1 D2 X+ m% V
5 R6 z3 m" }& H# h4 I# w: X2 p
9 J8 b# K: x( t+ h9 b$ j8 Y
* y+ s, ^5 Y' E C; Q2 u. G |