以下皆为本人自我理解内容,如有失误之处,请多多包涵。 2 o3 r+ P( T. p8 ^5 A0 k
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 / @8 J4 |! e5 M( W
' ~9 {+ q" C! m9 s0 g/ L. r7 L使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
+ J8 j! N6 r* y! r% V; x据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) . d* s* Q+ P# K: X
结合使用方法来进一步理解它的使用目的吧。 - f8 W. X' o! h
3 U+ D2 @2 M7 ^& p Wnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
3 ]' F' |# K- m! f$ c - namespace One;1 V, e! ?' ?- e% C3 L. p. a* G1 l# X5 w
- namespace ONE;
复制代码 6 Q# d: D3 J6 R9 M
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
" x8 E6 k) [* M3 J9 Z( ]/ v/ I# {" m# o& S2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php , W. f4 c$ r3 N4 [! L& P0 M
- class Person{$ @1 S. Q* c- e: \
- function __construct(){
: W" K: X! h4 ^% V4 u0 ^ - echo 'I am one!';9 c* b8 Z( A$ U( f! o" \
- }
4 a8 X* _6 N7 [3 W9 a - }
复制代码- //name.php
2 k( h. [. w4 i: C; z/ S - require_once './1.php';& x, [$ p, Y1 j; A- `9 m/ A
- ! U6 c9 G: v% n; _
- new Person(); //输出 I am one!;
( [6 A) g' k: o/ L# q& Z3 V! S - new \Person(); //输出 I am one!;
复制代码
9 l! z) B! }% `3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
9 k9 A/ p# T6 ~ - require_once './1.php';
, m7 r. y4 c+ S1 P7 ? - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 v/ `: h" o {% M# ^& | ^
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 0 [; u: o& Q- g) X/ d& l! W+ [
- namespace one;. w7 X! j: ~; ?" ?8 q3 \+ p
- class Person{
T& G' y% N9 C! H - function __construct(){: q' J- o; X% s x8 Y* p0 P& u
- echo 'I am one!';
& L2 K: p: w6 s9 s1 D$ z% ~9 l - }
2 _3 O+ V4 r, q3 x* G: [9 w2 k - }
复制代码- //name.php
l4 F* Y5 l+ V& @* r - require_once './1.php';1 [! T+ m" p" h2 l" b: |
- new \one\Person(); //输出 I am one!;
( p' R$ ?/ ]* _: d& y4 d - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 / N) c3 E1 i. H6 z1 h# N$ m
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
7 s- U% J* |3 w7 ]5 [5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。. f; R) T: a; x
- //1.php * d7 ?9 @( O& ]9 Y. {& J/ m
- namespace one;+ ~$ ~( o7 l( I$ \7 v) W) t5 t+ T8 v
- class Person{& d r/ \4 H6 h5 S* x: h5 j
- function __construct(){
' U( j- j+ r; M/ f* P6 C - echo 'I am one!';" g k0 n7 ]5 q
- }" H* D) W" q t1 _% Z6 |3 ]
- }
复制代码- //name.php
. G3 ?5 N# z1 T1 R, | - namespace test;
% H. Z" _ v. ^# q1 K$ N - require './1.php'; & R2 K* k. }; ?: l4 M1 z
- new \one\Person(); //输出 I am one!;
: H, j& o+ ~0 X5 O1 L - new Person(); //这里结果会是什么呢,猜猜看
+ \7 J2 n- {% m' X* X - 最后一行结果报错:5 n$ O" D. ]* K
- Fatal error: Class 'test\Person' not found
复制代码
, `& `. c- Q4 G% W+ V4 |/ f2 ?# F1 M# X* V
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 / \5 k4 a- b& r# @: @
结果报错: - Fatal error: Class 'Person' not found
复制代码
, B' j, Z; S* [* T/ p9 h' O接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
" `2 g& \( J& L Q& t6 i - namespace test;
$ G+ C [! T) F; l" y/ y! Z; N8 b - require './1.php';
" X# }2 g0 T6 o6 I" b
7 } T! p h) [7 E+ b- class Person{
4 i' q3 j1 P6 y$ _$ `2 I d# @( } - function __construct(){
3 l8 G: o0 X# e" n6 V - echo 'I am test!';
( i- o) m3 ~& p" t8 A - }9 S' G% W5 y# i# t0 ~7 ]4 h! P
- }
2 \/ X. T* F6 v. V' V( i1 i
+ H" b6 p$ ?6 Y# A- new \one\Person(); //输出 I am one!;
2 C8 ?% s* i% r6 B1 G5 q - new Person(); //这里结果会是什么,自己猜猜看
复制代码 + I* H# `. i4 f1 R
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
" A# T6 u" j( g8 S$ A - namespace test;- f3 R/ k: s: ]1 t
- namespace one;
6 H1 J! v S9 ~$ Z# b" } - class Person{$ R& I: }/ D2 n3 y0 u. N5 o
- function __construct(){. @# ~% C2 i! T5 n
- echo 'I am one!';
" z9 z1 a9 O1 y6 W3 w J, \ - }; M8 e5 k3 `: Q7 r" m# d. x! S
- }
/ U4 [2 T' A+ \+ W, C - 6 j& \) v+ m' F& |. J. y/ ^8 V! j
- class Person{" O- S' A5 u! P
- function __construct(){9 c8 H2 g1 P! `9 h
- echo 'I am test!';
9 h% ?) s: n8 ]8 ^ - }
- V" H4 H8 Y+ Q2 u# ]( Y - }
复制代码
; a) Y! a5 B7 i- X* Y' T% |7 |0 R无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 ' j/ P0 ]5 T# E2 B" n
看来简单的把require理解为替换,在这里行不通。
; p# N7 h: `3 c: l9 L6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
% d0 |, L M& j, W- //name.php c5 N) ]- A$ k* c' H
- - M, k) W! B6 {3 F8 D
- namespace test\person;
( x# A2 L3 w v# f - % S' b; f) g" I# n% W4 Z0 r
- class Person{, H2 w% |6 @1 F( F6 L7 F- [5 d# k
- function __construct(){+ [$ [8 o1 P) j5 N% o
- echo 'I am test!';
* P( k, {& h/ K$ |" k - }6 t* L' e/ ^/ \2 y
- }+ \# i, i6 n) A" [* J! n
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 ; w: d+ y# @8 B! `+ c* W
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
6 q7 }' n/ R& g, ^7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php$ H1 c0 A( ^6 a: Q
% V# ]0 j! E9 E2 q! f8 q5 o- namespace test;
3 z+ D8 P: F0 `7 A2 M" d' j; h - echo 'zhai14';- B/ k! d0 u; k( J s8 [
- namespace zhai;- X. T" d- ~7 o2 d2 n* Y
- require './1.php';
复制代码
. F* c! K( r0 |, X$ J% }php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
, k0 m) L% X5 {5 E/ V: G: H! Uuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& h& E: x( J8 g: Y- //name.php) X7 }/ d! N9 n( e u
5 _* H( [5 @& W: a- \- namespace animal\dog;! A1 K- t. i1 `: g6 U
- * O; u; O5 I3 V9 K% S
- class Life{
6 w& _2 z q& p+ I9 h: l1 p9 u/ D; _ - function __construct(){
' r! b" g1 C0 d4 k - echo 'dog life!';5 H5 O1 f1 w; D* m; \# @4 h
- }
: |' {+ Y$ }8 @9 o6 S: d: }, I - }% n/ f* |7 g7 x- n8 x7 I0 O
$ l U6 U0 F2 R) r' V: I: t- namespace animal\cat;; B6 n T; ?; `+ @
- 3 {& `5 t) D# g) _- c
- class Life{- s+ u- n. r1 M3 A1 X; ^ U
- function __construct(){
1 ~, @/ E+ m ]4 ^ - echo 'cat life!';
0 @& a' F' @8 x& g7 h) R4 Q - }
2 v! _! L) y1 ^/ \) M - }/ J/ r+ g4 ^: ^
- : f8 S4 {2 E, F! @/ V2 v
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间8 s; t1 F& S! a, I4 \5 l; J
- new \animal\dog\Life(); //A' N1 B# J" T$ o6 D9 k2 F
" ]8 X# R; L6 P) V8 m- use animal\dog; //a
. Q+ W2 ]: `+ n" Y& e, ] - new dog\Life(); //B' H5 ]4 ~5 ~6 @; ^2 a5 G9 k
" d7 Y4 G+ B1 ~ J. T6 u- use animal\dog as d; //b1 d6 T! i! Y' P% x5 K
- new d\Life();
复制代码
9 F+ k& S3 N6 P, t1 {通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
' ^4 n2 T: C* a通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: - @ [+ q! l9 s$ r0 `
相当于
! K* w8 G" r. I: B* l2.namespace后面不建议加类名,但use后可以。 V# Z& o, ~" y1 ]( Q% |- o
- //name.php* D% g( U: S; k) ^
- , T6 j2 A! c2 O' }7 d7 G. m
- namespace animal\dog;7 Z' ~1 `" ~) T- k+ C& m
- 5 h; M z7 U( S1 Y2 U& e) e* a* T
- class Life{3 C4 k y, g. P& f
- function __construct(){
' Q. q5 s7 S0 r1 Z1 d& K- @3 O - echo 'dog life!';4 u! \6 m ?( J7 A
- }1 Y8 n" m. ~7 Q# j. ^% a: W' P8 d
- }
/ F k Y9 u. ^! ?$ E0 ?7 H6 E - 8 F9 ]# V7 x8 ^( M4 p$ j" @3 G
- namespace animal\cat;
8 K& i4 |& l$ ~4 f N# ^; R - * b- D& ]/ t, p2 H, h& V
- class Life{4 i7 t1 `- L$ G9 N$ j _# _
- function __construct(){
6 ]# H( H5 ]* v4 R - echo 'cat life!';
; _) F& D4 g& f - }
" l$ I. k( A3 ]' w& j& o' c$ A - }
2 p5 k8 H" R2 `" Q4 a# F! } - ! T' ]( b* D1 y& U+ g$ R: ?
- use animal\dog\Life as dog; 3 ]" z( }3 C" z! ]6 S W0 j
- new dog();
复制代码 / T9 P n z% e% [5 a, {% B
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 - ^7 p, E) d1 S2 i
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php6 f8 J% F" O+ U% b
- i3 F3 ~8 @& E: h: f7 R6 J- namespace animal\dog;; u k8 T! v1 n0 ~/ j& |( ?
1 C7 a* E. B# c8 H' f! v1 y; c- class Life{
# U( ~6 }/ a4 A4 L$ ~! ? - function __construct(){9 _* C' T; ^% T: v) Y7 j
- echo 'dog life!';' A) c \0 T" r: n: C' _
- }
2 C ~# [& D0 r% N; X - }
; o2 h# D0 ?: r8 t2 ]# K9 {7 M. x - class Dog{
+ i3 \9 F- `7 T' c5 }3 _% { - function __construct(){
/ N1 d# O @4 s4 u% V# V8 M9 a - echo 'dog in dog!';+ F. m+ Z- p# i
- }
% ^0 d4 J2 ~# ~6 m - }1 W, m7 E& r! r& J( f
- 5 I+ _$ Y2 O W9 H1 J
- namespace animal\cat;
3 [' z9 H; U. W3 u1 ] - 9 v: l2 l, {$ \; D& S0 D. g4 ?
- // class Dog{
) v1 h# ^! A v( }. @ - // function __construct(){7 b5 v( L6 j1 s" S- I" k: j
- // echo 'dog in cat!';
1 O' E" ]9 p3 g' d* A - // }
% J2 _8 c+ t5 n0 D0 t- L! ~. O - // }
6 B9 r+ t: e/ V* p - class Life{
0 l" U5 C" p S" c* q$ F - function __construct(){3 v5 _& Z5 |2 t" W% V# F
- echo 'cat life!';
8 K9 z. J3 n9 N( Q - }. Q+ w+ L @, l2 Y# G) P. r) k
- }+ ?7 y4 M) c8 |) z
, G& `! M/ R% K2 W' m% E, u- use animal\dog;
W Z& q3 H/ y6 |: x - new dog\Dog();
复制代码
. n$ q. s' J0 o( ^6 G x2 d如上,使用了 * g7 `; J0 D# L
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 0 V9 _, s+ C1 q, Y9 y4 E, o- b/ r
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 + R2 A: d* p7 J
1 U, Z" @4 m5 Q9 t
( ]1 K% G; E+ }; V! z9 ?
% h' U2 ^+ V+ y; Z8 C; b$ ?: l: }
|