以下皆为本人自我理解内容,如有失误之处,请多多包涵。 * X+ h( s* `- V7 E2 Y' D
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 $ ]4 P8 L4 |7 a/ Z, }$ t3 N0 r
: K8 E* l% B! d2 j6 s. r. ?1 E) k
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
5 a+ J8 B/ d7 s9 g' a1 ~% y) j据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
. N" E! ]; n0 n3 N结合使用方法来进一步理解它的使用目的吧。
; G) S* n; J0 W! S" s% m3 v; g
. X* W: M) w5 _' ?/ Jnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;! T2 ?2 r1 U8 W" N& q' Z) t. G
- namespace One;
5 l9 t' C% M$ R5 k - namespace ONE;
复制代码
( {, `6 D$ M; e/ k9 v; Y3 o- J如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) D+ y& k# R8 y/ U1 t# `2 y0 h
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php ! {, i4 n- x$ ~) ~8 z3 K# Z
- class Person{
0 I. i' K. _% Y/ G! h - function __construct(){
5 ^! _2 S) t: X4 A; G( G: o7 ^) ]5 L - echo 'I am one!';3 w& r0 r# r9 r7 `& e
- }
7 Q O) P' ~+ L1 x - }
复制代码- //name.php
' H9 W2 G* n9 X9 ^5 N3 H) Y5 ? - require_once './1.php';6 b$ X9 g8 r' q- P4 ?( f$ u' K
- ' ?' G( @* x X: p" E
- new Person(); //输出 I am one!;. z! S# A/ C1 _) \& T8 Y3 u
- new \Person(); //输出 I am one!;
复制代码 4 J2 v4 i) v' L- c+ y* o- w+ Q
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
' M4 m9 ~5 v0 p" @5 _- g7 @( { - require_once './1.php';, x, i; ~( ]7 T
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 1 j; d- @7 j5 a' |
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
% p) O! ?1 g$ K- Z5 J - namespace one;/ [8 s. m1 s8 {8 j' k V* k
- class Person{! k9 u5 E7 O! d# e# ~9 n/ J* B$ ]
- function __construct(){
7 H% w, j5 I6 ] - echo 'I am one!';8 Y4 h6 g% F o: Z; q
- }
" D, N8 D9 q: H9 D; W& E+ v- V1 E8 i - }
复制代码- //name.php. J7 Q$ j) [# j0 I4 O; w$ T7 p5 R, r
- require_once './1.php';
7 p9 d3 }0 o' V3 A: u# T# ] - new \one\Person(); //输出 I am one!;& N$ Y$ H% {9 g/ }& N8 J1 K
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 3 u- t; P0 ~) @* U( v, R$ j
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 8 S8 N) n& w3 r
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
+ Y' ^+ V3 T' o& G8 ]& ]& h1 a- //1.php
' z. X0 r% K4 D6 @5 i |% Q: u - namespace one;
. b+ g: E1 D5 {! b H - class Person{. [6 C- I% h$ [
- function __construct(){, C, b+ u2 x5 h9 i }
- echo 'I am one!';
' n5 [* T2 v& t, x6 \9 c D- c9 Y9 I - }# y. i, s/ S- Y
- }
复制代码- //name.php
1 X) }, u+ K3 d/ t/ } - namespace test;6 R, Y) K& E$ L; K* {5 a
- require './1.php';
r+ s, w) Y0 ~6 |# D8 t3 w - new \one\Person(); //输出 I am one!;5 b4 _ j% b- ]4 a
- new Person(); //这里结果会是什么呢,猜猜看; i! n2 ?4 u# t/ q+ w6 x
- 最后一行结果报错:# e1 D* \5 P% t* t2 R
- Fatal error: Class 'test\Person' not found
复制代码
3 u3 ^+ W& k5 B# Z6 X% G. }& B
2 M4 @7 o. [) r3 m6 t M% v首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 6 \$ m# }9 ^: X( ]! N( |) O- y# u
结果报错: - Fatal error: Class 'Person' not found
复制代码
/ O; h5 v5 i. Q; W# @接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php# P* U% S6 I. N" R
- namespace test;
7 N' c/ s4 T$ ?$ s- S8 n - require './1.php';
0 i) t/ J' w! F% F/ W- y7 { - ! M* K" V- W* G7 Y+ ?
- class Person{5 {9 B" l- z' r% J4 y
- function __construct(){+ e6 ?" F. X) V* A
- echo 'I am test!';
$ |7 ?$ _* b1 m R* h2 A - }
) w& P: J& V# U2 n4 H4 i* s# H - }
0 g4 ? z* q' B$ W# ?* h! \$ b
6 v D; V' N) S& Q5 j0 R( x- new \one\Person(); //输出 I am one!;" |' I/ R& L, p7 u6 m) v8 `& G6 Y% ]
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
: m2 M+ S" B) \9 g0 @. f% V最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
1 [$ A! F4 _4 `8 o+ |+ l2 e - namespace test;7 S# ?0 z) e0 A
- namespace one;
4 W$ J" t, I* Z8 _8 ]& W( t: R - class Person{
7 M% ~" t! t) p7 M! }% j% B - function __construct(){
# Z1 Z+ N, D. a2 w, j - echo 'I am one!';$ u. F$ P0 N1 v6 Z2 ?
- }
* w' |" _8 R2 ^) W2 D ]' T+ @/ P - }3 `; e7 i; V* |" b" H0 z1 d
- $ T, e& Y6 t- s9 y( z, o- _% {. O
- class Person{
7 ~* a8 t2 I1 H, P+ J6 U - function __construct(){
& x% B) g) x$ Y9 C0 H - echo 'I am test!';7 B* N( O+ G- e; ^$ W- F9 w
- }
* ? z6 x2 B) M7 }* ~ - }
复制代码
4 I2 p# y4 p* Z5 @8 s E4 Y无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
5 t" Y: v5 R4 S2 R* M6 K看来简单的把require理解为替换,在这里行不通。 ! z; b6 O x) [; m
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。9 f* J+ ]5 d7 D/ z# L
- //name.php9 T3 e) w( d) P4 ^' U5 P, \
) D' _) u L3 T. v" b- namespace test\person;/ q* H% ^$ X( F! j8 {% _( G' @/ |& i
- % s* G% g& Z. Z% l7 s
- class Person{: u3 b) e* @" S: U: ?% i
- function __construct(){6 u3 a" W4 ] m/ c. W' K
- echo 'I am test!';: @ x M* G) q" @
- }, j/ J3 | \/ c) A) B% ^( T
- }5 P. l7 X& N1 K) T/ N; e: F
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 5 W5 O, f7 `" B5 w$ d% e
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
( a2 R# u0 ^$ i7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
+ E6 d' d5 K: N* J+ Q' y
" `" d' C7 t0 F0 @- namespace test;
5 r8 Y# Z4 v- o# y - echo 'zhai14';
6 v! ]1 l- D5 O5 k: Z u - namespace zhai;
$ j# O- G Z5 q9 M/ ?' ? - require './1.php';
复制代码 : T& X- {& L5 p' Y, N
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 $ V1 O- [5 T$ B9 \3 G! h
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。2 i" X% \: H( \7 U+ A' D, m. b: c$ n2 u
- //name.php
. g ?3 w; |0 B M: Y o* Y
2 m+ w' O& r# R& S: @- u2 F- namespace animal\dog;
$ p8 V. s6 I' V* v2 i, E5 Y$ T
6 X: h; B X$ M8 U/ g- class Life{) [' N2 S6 @% p0 m
- function __construct(){
, l! b5 d) X. S' g - echo 'dog life!';
* A2 L+ j8 n0 v$ J - }
1 g! b" D" {% B v3 [8 r: n - }
# t) x: {: o, g3 @$ W7 e - 2 p1 v- {" ~/ S2 o
- namespace animal\cat;4 d$ E- R$ r; b8 Y# W3 g v# e
- 5 H5 Q& Y, ]. E2 \
- class Life{' S, H/ K6 x+ T
- function __construct(){' m6 T; i" Z7 ~; q- B
- echo 'cat life!';; z U* s) c$ M$ y9 D O( J
- }+ M9 ^* i M. `: K
- }
+ a! g' P) F \/ F/ E! I* M - - }$ N% ^5 q" I2 d8 Y' Q
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间; F1 Y- y- {* L8 ?
- new \animal\dog\Life(); //A
6 D0 i1 s9 C- Q - ( a# H f# G6 ?& b) W5 ~
- use animal\dog; //a
2 n$ v* {1 g- b. j0 ? - new dog\Life(); //B
" q+ a3 E# H- V- i - - b1 z8 U9 M1 e$ L, p1 D
- use animal\dog as d; //b
4 l! l- z& g' ~- e! d$ i& F. d. W - new d\Life();
复制代码
% _- I" a3 S. Q4 M( Y/ `通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 # [& m* V" K/ w6 E" e
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 6 J! u, [' C1 w1 T& `* X
相当于
# d% u$ m0 m" l6 F2.namespace后面不建议加类名,但use后可以。
- y) a. l z | e) b) S' Q4 S- //name.php1 H! p' a1 \# F/ P/ P1 t# o! D
- % @8 Y2 X# `/ ~3 ?
- namespace animal\dog;
1 w' o5 b, q/ a" v8 }8 q2 F! H - q t7 ~4 J% m) U2 e, K8 C2 F1 h
- class Life{
T3 T2 Q1 }, h - function __construct(){
9 M1 E! i: ~3 M7 {5 n1 S+ ^0 G. _, M - echo 'dog life!';6 W" S0 C( M: g9 r' B: W1 G
- }. W4 |1 P( n) G9 l5 a
- }& |. D4 A. U; ~
& _" p" Z* z2 K7 s; b$ S- namespace animal\cat;+ `2 O& |/ [8 d/ }& c4 r
* d' D- n( r- z/ g- class Life{
" x. U6 V8 R0 A; R - function __construct(){2 U1 k; O T! P- T& ^9 K
- echo 'cat life!';
. a5 _0 ?! X" a% o3 V - }
6 c9 M: B. X v0 z0 q9 c - }3 a# D1 x, I) B8 \! I5 O
- & O1 P. k0 G; C6 t' p: D) v' q( ]
- use animal\dog\Life as dog;
6 Q+ E8 ~, [; U: o+ y - new dog();
复制代码
7 P: N1 W6 \* C- i: \" y* j如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
/ f0 c' U' m: e5 F因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php: e8 h7 R, n* F4 @5 Z6 t; k
& B. Y& S1 f! \" { @ r- namespace animal\dog;
! Z, w0 C- y$ r! Z9 n8 M$ T' t! Y+ l/ w - 6 j% P Z& x- I& x w& D8 ^- M
- class Life{+ {2 b i1 h4 W; Y
- function __construct(){
3 R0 U3 ?1 |2 f2 i ]$ l3 X% P7 e - echo 'dog life!';
L5 \. |* o: p3 V& ^ - }
" A. N6 `6 Q7 H4 |4 V - }
1 v: Z& }1 y$ z8 n7 X* l - class Dog{" y, s6 M' x I
- function __construct(){
T. K8 f7 L B% X4 ? - echo 'dog in dog!';
( v4 Y; R) E3 D- j - }' w) ?& J4 Z; X; X+ E# f
- }
( M+ U- V0 ^. f" Z6 d2 @
4 g& g' e$ E, G6 m: `- namespace animal\cat;
1 }: {9 Q3 _8 a2 p
" e. h' |( L7 J3 S) c, _6 v8 `- // class Dog{+ d) Q6 b* I7 c5 _9 R1 B
- // function __construct(){ l2 `$ X! t: ], \9 {- g# y6 v2 [. K
- // echo 'dog in cat!';
, y, r0 x" Q1 o. K( F$ I - // }1 A7 O. u8 m. S
- // }
3 ?6 L! V8 Y" o. Y - class Life{. k6 o9 ?' `7 i: |; f# V: T
- function __construct(){
E3 w: u; l" }1 w/ @ - echo 'cat life!';% E* s5 ?* a6 _$ r" x
- }
2 z" d6 ], Q# g* j - }& Z0 S& I: N! r
: L1 j9 Y- r8 ^- V2 @5 O- ~- use animal\dog;
, V' v5 ~# F& U: B! G3 ] - new dog\Dog();
复制代码
; G9 I1 w: ]6 I! t如上,使用了
# s8 i! t( I" z; Hcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 6 R; j" f' A. q% I5 v
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
8 S2 J4 n7 U8 i4 ?
: Q6 U5 G1 K1 b3 j3 i0 M
P6 S; }0 q1 ~% `. m4 b/ ]% f X. {0 U
1 b6 J( U& l( A0 `- y& I# C |