以下皆为本人自我理解内容,如有失误之处,请多多包涵。 ; Z& U7 \( p& g& x- k
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 3 v3 f" ?9 u5 y, J
) @- u( O5 s4 I2 y0 N* p3 O使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; . o! ?/ |0 t7 Q
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
& V/ ^' F, Q1 q# f: F结合使用方法来进一步理解它的使用目的吧。 4 H3 O0 g5 Y- T8 `% Z
8 Q$ w; M1 f; C' P' x+ Z, m+ knamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
3 S/ V2 g( y/ r* y7 Y# e - namespace One;
" w( B) \/ _8 L3 k( ~ - namespace ONE;
复制代码 / J& ]; V, s2 B1 D- r
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
: d) q1 j% Z% Z/ U L; \2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 6 P" ^+ O/ A# |" E* W" H
- class Person{1 K1 i% u! E8 | C2 {/ ?9 a& q
- function __construct(){' Y3 d P. ~1 e+ s8 z) h7 l* Z
- echo 'I am one!';1 z0 ^/ b( g* Y* n
- }( ~; {. M h8 V: f! b5 n
- }
复制代码- //name.php
" v; J1 l" H' m6 {% ` b' U - require_once './1.php';
" |; r \& q; [" A1 w
" ~7 u$ r( B3 Y* R! X2 q- new Person(); //输出 I am one!;
" _; l; t5 V* }8 _5 T - new \Person(); //输出 I am one!;
复制代码 + b$ l* A9 T) k: B1 H) _
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
' T2 p- ~0 z' V- D" n - require_once './1.php';$ @! K7 n8 n) K* q) Z
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 : b) u; v- y, M+ s9 z1 F
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
0 B( E' E7 n6 v* r- J5 @, e; L - namespace one;
: Z; V0 K2 W: Q, j/ h - class Person{6 k2 k' M# j( c9 S8 a! |# k0 B; m
- function __construct(){- _: P6 {8 U% m0 K F7 O9 Q4 K& p
- echo 'I am one!';9 W" {0 @: A) f: Q# v4 J' k& [6 Z
- }9 E R6 M" f6 w1 j; G! i, z, [
- }
复制代码- //name.php5 x' @' Q {9 R% m" A* _4 z0 Q! W
- require_once './1.php';
1 Z9 a8 P& g- t$ O0 S0 H - new \one\Person(); //输出 I am one!;0 M8 X+ k! c8 O3 q
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ; ^9 k% U) Y: l5 K2 g2 l
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 , e; L% a' x) S8 W0 j2 W' [6 G* [' V
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。, @1 I) K% T/ m- s- K6 l- H
- //1.php
% x" o. P4 e8 k* a - namespace one;& v* B) L/ ?. D' p0 C
- class Person{
. M+ l/ B, Z: {0 \- M. `! t% c, e - function __construct(){
* p$ K& g- E i+ C: D - echo 'I am one!';# w* g( @- @4 \1 l% B
- }
: K }1 a0 n: ]: l) I - }
复制代码- //name.php1 |& N/ S; s4 |5 a$ B! _0 L2 }
- namespace test;
9 }: X: i2 i) G/ s9 V9 s& L - require './1.php';
; [1 Q6 g- ^; _( M8 { - new \one\Person(); //输出 I am one!;4 i4 }( n8 [6 b8 A1 p; \; u+ U0 G
- new Person(); //这里结果会是什么呢,猜猜看- }: ~) t( s- |0 p0 ^) Z
- 最后一行结果报错:6 d3 a k3 s# i
- Fatal error: Class 'test\Person' not found
复制代码
# G6 T* m1 Z/ c" V5 K! z2 d K8 K4 M# x: ?& s
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
" F9 {6 I& f3 C3 P- R% l$ |结果报错: - Fatal error: Class 'Person' not found
复制代码 " u. P, B# L- Z1 w" L
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php, K& G5 u; c5 _! P/ E
- namespace test;/ l7 w: X3 F( K
- require './1.php'; 5 ^# E% ] O4 Y$ w( _9 v
- $ n K, o3 c0 I& u
- class Person{" O0 h. ~8 Z8 m$ Z
- function __construct(){# F( t8 o# M, S' z
- echo 'I am test!';' r4 Z% e' D: I g( l$ Q9 f/ Q
- }+ u: q) B6 Z5 e, v+ x' ^: Y
- }+ Y& V. R/ b7 U9 k
2 B3 m J; c7 v/ Q% [7 o+ B0 c- new \one\Person(); //输出 I am one!;
' n6 Q; m! o7 ]8 f - new Person(); //这里结果会是什么,自己猜猜看
复制代码
1 x1 o6 m. |6 m, ~- e7 C最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php4 b) N, d, R8 Q; s3 [/ |
- namespace test;
# \* f d7 _) x - namespace one;
. h: R" I& D8 S) t1 f6 ] - class Person{
1 t4 [+ s- x i/ K6 R- G - function __construct(){1 J; W9 K9 ]* q! U, g- |
- echo 'I am one!';
1 e% J9 N$ a. ^8 u& J9 |1 x - }
& C( K. f* b ~4 M X2 M6 ] - }
& C0 U9 v- Y; S
6 ? d5 m, {- C. \- class Person{
8 R6 t" _$ q5 V& \( b3 @& u$ E - function __construct(){# x3 v j0 V1 D: b1 c. _0 y
- echo 'I am test!';
) L! t! ?7 [3 u7 w" i - }
& W$ x! o# O4 U' x; S2 z - }
复制代码
* z' a# o- F' T! K7 a+ N4 ]" o1 U无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 4 ~6 V4 e; s# |7 k( V! d
看来简单的把require理解为替换,在这里行不通。 6 [( `! ^$ E: L4 A; d A5 V n5 \
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
( M `$ ^' q8 R5 @ Y& t5 I- //name.php
3 b+ V" s! L4 C. _) @ - 0 \, v/ v$ f; L2 h8 `
- namespace test\person;
* ?; I P3 _! X; Q
; E. A$ E) y( l; ?* d/ O- class Person{
) Y6 y1 M* F3 L - function __construct(){
' Y6 t! P) Z, g ` - echo 'I am test!';
* A- p6 h; N+ @ - }8 r: L& z+ S# P R9 u/ y& ]" k
- }6 y* ?. k: o# z' I6 Y/ R2 }
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 ) t. h! c! f/ M" O+ w
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 . h* ~4 [: M+ ~" X& z- G4 O
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php2 \) c* @6 H% S! b
8 j- Z* d7 s! ]- namespace test;
1 C- z t g& @/ g- N/ C- y6 W - echo 'zhai14';* O @' B- _8 @& h7 O6 O+ J
- namespace zhai;
1 ~6 z: Y% q( e' ^ - require './1.php';
复制代码
- J8 y8 b& \5 j- D: z3 hphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
" \# S/ B+ @( ]; }+ H/ {/ juse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。7 ^- o0 L* F- r6 l
- //name.php3 [4 T4 Z$ @. F9 e/ z" U6 w# a
- . s0 l S- n/ f" Q2 b
- namespace animal\dog;
L. U" ^! o$ s; D - , W0 l1 K8 R, u& }* z7 i& G& Q
- class Life{8 j8 j! y3 J8 Z7 H2 h' `1 ^( W
- function __construct(){
+ @' c# X( V4 h; g - echo 'dog life!';# M8 y) V# p- c( y
- }5 a2 o7 X8 d" o4 Q1 Y
- }
# x1 T5 `1 i" h7 p* R% z( F
% W$ T9 [3 o2 ]. G5 [- namespace animal\cat;
1 ^, X! F7 y- N! O6 g: l* S - # ^4 W0 c" I8 H( U9 _3 n
- class Life{
" }/ I" V9 A1 t/ v - function __construct(){
2 q$ U8 n3 ^2 g: m9 ^" c3 Z4 ~ - echo 'cat life!';# a8 T" z( }* S: R5 a2 L
- }4 O% V, \& l! F' {
- }
- C3 ~9 D# f1 J0 C3 [ - " n" i9 Y1 k2 @5 _. @! k
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
: J4 x% X, K# W. G5 t - new \animal\dog\Life(); //A; \7 j$ g p2 h- L' x- D
- " Z! O! H" ` @; k6 m
- use animal\dog; //a2 ?. O- U0 o, h' R% x1 L
- new dog\Life(); //B
* r0 }: [' L) l2 V) A1 I - 4 x# @2 d& }& l0 r* ?+ X# S
- use animal\dog as d; //b. E( L- Q* z* ?% w6 c& q
- new d\Life();
复制代码
+ ~7 l% f: W3 |! Y6 }通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
# G& G1 M) _! M [通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
1 z3 F/ K+ N) p7 }, f; m4 T相当于 ; v I) X6 {5 j" s+ @
2.namespace后面不建议加类名,但use后可以。/ O# I: Q. N9 s' E! {+ x
- //name.php; _6 F+ a9 P5 K# ^2 b
- - i/ ~: W' ]& z2 l+ _9 _
- namespace animal\dog;
5 V8 @% Q F7 K, L' e
2 e- D9 R0 u X/ q7 y- class Life{3 a/ X9 N. h( x0 T
- function __construct(){
- B0 G7 O; D9 x p, A& c& b/ [( h - echo 'dog life!';
0 I; e5 v5 N( E2 @/ z - }+ ?/ U5 ]8 R/ N7 ?% _7 ]1 E$ @
- }
0 T9 P5 A. l s$ a - & X1 m% [ r+ R; f
- namespace animal\cat;
6 C- |$ Y( U7 E6 {
/ Q4 b5 V- P, u- class Life{
* i1 ~% P. E L0 r - function __construct(){& b v0 b b5 I* i) G6 ]1 s! V
- echo 'cat life!';% A: e: k" t v! _5 E
- }
: z: K- A0 V" ?$ n - }! W. _7 ^6 V: ^3 h9 r: V1 w
- ! d! k7 h* s! I1 A" X
- use animal\dog\Life as dog; " I$ H- W2 ~& ~, R! B2 P
- new dog();
复制代码 ; C, \: ?: b* u! E- \6 \
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
* i& ~7 h# P' X因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php7 X& y0 n# N. E8 h. N5 N' p
- 6 {( x! K4 U5 _4 H$ Z: i: Y- m
- namespace animal\dog;
/ {! C6 g! W0 b; j/ |6 F - $ S, G1 z+ \. c1 X
- class Life{/ H5 p5 `1 c+ m1 S* v5 o) V. n
- function __construct(){
( W o6 e; B" \ - echo 'dog life!';6 S+ F# Z, i6 i2 p1 a }
- }
+ [' ?% F4 H( M0 t' R- O - }
! Q$ I) }* z* s/ A7 z& i+ |5 O$ a - class Dog{
' D4 u" j* r' s8 s6 U8 d - function __construct(){
3 O0 {7 ]5 }1 Z* C& _; k! A* p# s - echo 'dog in dog!';
4 j# b3 o( J7 l! [' W - }
" q3 }: D. b6 o5 S4 @6 N - }3 D& x6 y3 R& z( q. `2 ~# x
- 6 l, V& U! }. F6 E0 A- F
- namespace animal\cat;2 p% g- T; V$ r! G' g V( H
- " X& |7 d+ L6 c4 T" y% _
- // class Dog{
/ U) k! h; E1 E - // function __construct(){
& C( E# V; a! U - // echo 'dog in cat!';
3 S% z; \/ n0 i k5 v - // }2 h, d8 X! k: g& J( Q" L
- // }8 r5 |7 o3 r; G/ R
- class Life{
, L3 |4 j/ Y4 @8 }- V - function __construct(){# e& c+ G2 W4 N7 n8 T
- echo 'cat life!';
3 `8 u3 Y( q$ I$ b3 d - }
D8 p7 X6 b6 E! v - }8 o' y9 z, `0 o4 z( B
- % o' N! ^* |: }0 a! ?& f: N
- use animal\dog; 4 i) h2 v# B l/ s' i
- new dog\Dog();
复制代码 8 X" e" v( ^/ ?9 {6 h6 s
如上,使用了
) ~3 \, _- s' `$ D) e+ rcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 0 |/ F2 y2 _- e- N4 M0 H: T8 @
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
/ n+ _ o3 l$ L- L }/ D! I6 o
6 e5 ^+ _$ R1 G$ ^$ C$ R0 O' N# v; Z ~& E5 c# z0 b
9 p o: n7 B; q: o4 o$ v/ r, ~9 M
6 S$ E2 u/ z6 t V' i! y' `8 J K |