|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
4 [/ D9 E8 k% A8 j, } ?* u文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 / k- B# ~3 U0 f2 ^! Q- r; j
5 j& O3 ?+ Z6 D; d) h- Z$ V, R! M使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; : Q: d9 f4 _/ r& V
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
4 k* U/ b: R& b: C( X$ E结合使用方法来进一步理解它的使用目的吧。
5 z. b9 r7 E$ S8 v1 R+ `' F
$ z# @4 M1 e2 w0 knamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;4 {4 J" \& l7 d2 J# _6 M0 o
- namespace One;+ G% w3 R' ~. R! h
- namespace ONE;
复制代码 & k3 }2 S" N [" g
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
& R. L3 M P& X9 Z+ m2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php . V9 g* @0 d- q
- class Person{
8 Q* o& T7 U5 G6 G" ` k; R1 B - function __construct(){+ K) e" h, {% I- Y6 `+ U
- echo 'I am one!';5 m6 l0 j' t3 z) P. ?+ Q
- }7 _- e$ P& k) W/ U( ]6 ?
- }
复制代码- //name.php
. w; J7 `! r* E) n - require_once './1.php';) U5 h$ x0 X D+ ^8 G# e
- # A+ g3 X9 n8 H: Y. u/ @! D
- new Person(); //输出 I am one!;* T, `( H5 y+ @
- new \Person(); //输出 I am one!;
复制代码 8 n- y3 X5 X/ a0 t9 g7 E; p. c
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
, Q- f9 `9 Y B$ w - require_once './1.php';
- q0 V4 e- I0 B+ F - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
+ }$ V2 U7 r. ]+ u) T" w4 T4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
: i* u7 C ?1 ~ _) y - namespace one;9 j! O# T& k6 D5 @
- class Person{
, n6 m8 O" G( }4 c3 D - function __construct(){6 F% D+ Q# F* b3 s2 C# j0 q
- echo 'I am one!';- m. o) {& H+ _. H m
- }5 M0 w0 W( J* E
- }
复制代码- //name.php
4 m8 E5 D: A. b l- Y( r3 w0 q - require_once './1.php';, q: s. v- j" }! x3 {
- new \one\Person(); //输出 I am one!;
5 H8 O( A7 C" I% E8 j; u - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 - k6 I# @- Y: I0 S
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 ' A; ?( ?. u8 d/ h$ N; n
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。$ A& F( t1 B. y; V+ r! _0 |* Y% l
- //1.php
0 e% y+ w/ L! g6 h, l - namespace one;3 ? T" }! l- d, Z- f% G7 [8 w; n0 L
- class Person{
# U6 U' U7 t3 n+ c' e - function __construct(){+ E' J$ j z. i6 R) r
- echo 'I am one!';/ b- }/ N* e8 o. c" V, c( {
- }$ H, _3 d2 u ]
- }
复制代码- //name.php
]. V) I3 H3 k! a - namespace test;* \4 v1 i; f+ R/ `
- require './1.php';
Y9 e- x/ W1 H1 k5 u4 b - new \one\Person(); //输出 I am one!;
$ \' s' w5 A; }* T- c - new Person(); //这里结果会是什么呢,猜猜看8 f {3 X$ Q; k) \" Q: a6 }; P
- 最后一行结果报错:
2 ^; g, a& I8 Q6 @7 j' o5 n - Fatal error: Class 'test\Person' not found
复制代码 $ W% G0 T% G+ H5 R, f2 Y2 H
* y% [& P) B D( m9 b
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 : w2 d1 Y7 y- _: i6 f2 S0 Z
结果报错: - Fatal error: Class 'Person' not found
复制代码
! Z* [" |# a& W# X8 ?0 ]& O9 j接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
0 M' J9 [; D X& V* K( D8 f' J - namespace test;( c% W6 U8 B+ |9 a/ b1 ~0 h
- require './1.php';
& ?5 s! j" R2 Q C- x6 X! }7 C G# S( @
& I; `- s8 M. r, Q- class Person{) L3 Y' h! | ?! @, t E
- function __construct(){
& W- A/ `3 J0 ?1 O& @) x - echo 'I am test!';- |2 [1 s$ Q N: D0 F, V
- }6 ^8 \/ J* h9 j; y9 n
- }
- _) [; u. U% U1 M0 g/ r - 9 u2 F E' n& Y2 V% k- W5 N7 h
- new \one\Person(); //输出 I am one!;
) U( D5 {3 m+ b C9 d, v- C - new Person(); //这里结果会是什么,自己猜猜看
复制代码
/ w0 G" c1 X( O# Y$ C5 `6 X最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php+ D" }$ F8 A. f- ~
- namespace test;' [9 @* a: W$ S6 L/ @" O
- namespace one;
2 A: N5 _% s9 [+ A" { - class Person{' [6 ^: N8 Q, b( ^8 c5 g9 q( ^3 K
- function __construct(){
/ H8 q5 B& Y/ W - echo 'I am one!';& @- g$ Y- P" q \; Q% J
- }
( z" |: v& J( A/ y - }0 F0 A4 H `" B
- ! t" Y8 C# |3 i1 P
- class Person{: T0 E( } [. a* f% ~/ p6 }! u5 @
- function __construct(){
& _6 u1 _' L' l - echo 'I am test!';" U9 m2 a- L* r) z+ ^+ j
- }1 D! I& F% K! a+ o2 m+ a
- }
复制代码 ( e4 K" _. G! Z* O/ U6 f3 q
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 . d: @0 u& J- s4 I8 @
看来简单的把require理解为替换,在这里行不通。 7 ?( ]3 m0 `9 u: p
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
- \" l O$ f4 M' k- //name.php
0 h! ]: E: n* S0 P
6 ^; p; G7 |' c7 u4 Q( |- namespace test\person;
}/ B6 v$ z+ W+ i
0 l' D1 B" |6 S# n, B& v- class Person{; W. B7 U& X( h5 z0 ]7 I% A1 ?# O
- function __construct(){4 \9 b3 Z ^- `6 }* X0 b
- echo 'I am test!';
) A- c9 I& y! p) ~7 Q+ F - }
% y6 k/ z9 w2 A; H- R% ` - }) y0 R% d& k( `& O3 s8 A- ~9 A
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 9 } K3 L/ N" c. [: |
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 + k; f3 }, W+ J3 V0 r
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php, C" p0 S0 ?/ f5 G
- + l$ a: a- l$ k
- namespace test;
1 d* e+ R6 s6 m, r - echo 'zhai14';& q& X$ O. Z6 g
- namespace zhai;
% N# F1 k& u6 C- ~7 M8 m; Q4 | - require './1.php';
复制代码 ) F7 K' K I# h
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 : B" W7 x$ p; l* }1 r
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。- b! y5 V) d' I9 r2 V
- //name.php
' ^, {8 [& [+ C) v - $ o1 U$ k, S$ W$ M5 U8 T$ D
- namespace animal\dog;2 c G- \* j, @6 k! n. q8 W% d
- X5 T! n* y" m3 l5 L0 ], k- class Life{
/ j6 k# r7 z' \) ^4 H6 J - function __construct(){/ ^6 ]+ d- n) n5 X
- echo 'dog life!';
( S/ M" s# i3 N) Z! b5 G H - }7 J. l1 n6 s0 n
- }
; M/ t, B8 T0 ^5 q' {& G/ H
8 }1 B Y- G& y9 @% s; b* a- f% P/ G- namespace animal\cat;# P. Y" f: ]0 B' g" ^! `: |
( z3 \8 k. D; ?9 m' c- class Life{
/ x4 p4 ]4 ?0 C; T1 T) ^* Y3 t! \ - function __construct(){
6 L8 e, q9 [( B( U - echo 'cat life!';( A/ ^, m- s4 }) S6 N! h" [1 L; {0 A
- }
1 Q, X# _. L" _4 X) s - }
% F" i$ ?( Z* J6 `) t2 o4 q* J - ; o! ^. K3 P, F' X7 Z/ w8 S, W
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间- N5 y8 R3 P' f! V( g5 x0 H5 I4 g$ f
- new \animal\dog\Life(); //A
: y! r6 v( Q7 @- K7 S; E - & ?2 W4 F ]' g# L0 b* v
- use animal\dog; //a
2 r4 A! N$ E, a7 x" O - new dog\Life(); //B
$ t" ?& r2 M' b8 v, w! m3 r [- y4 ^
- g* N7 n6 D+ [. d% p0 D' i- use animal\dog as d; //b
) \) c9 d# H, u - new d\Life();
复制代码
9 @9 J1 I* I$ N# s" i ^) N通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
+ F2 i Y. [! I5 |% X& O通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
3 S: Z" y/ K. c1 Q5 O! G相当于
- D) I! m' J$ a! Q+ q' \9 r- W: Q2.namespace后面不建议加类名,但use后可以。1 X4 J0 f& x% o
- //name.php9 s' i, b7 ~8 \. @
- + r" ^3 ~: j8 e6 p: A2 M2 m h) R
- namespace animal\dog;
7 ~7 J/ l5 B' h* N- C) H! I" H
# G# u2 j6 k6 i- class Life{
' c- \. k' }# w, a3 A& V - function __construct(){" E1 q: P! m/ k. c, X$ O, I1 X& Y
- echo 'dog life!';3 z6 Y% U* F" r' E* s) `
- }, C2 |) }8 h% i# i7 t0 }1 i1 q. v
- }! t' r G* [* g1 S% X
" ]- i7 {* {, D4 [4 r- namespace animal\cat;) g! \3 T- |- q' v
- 0 T+ r" U, t3 P" c2 t7 D3 E" N
- class Life{
/ E7 s( U8 w _ - function __construct(){. u2 e2 B) b2 E: n. r
- echo 'cat life!';% T: }2 m2 Q- o7 `8 L7 D4 R- k) Y
- }
+ y) Q% y2 [1 g+ C& N - }6 e2 p% }9 X/ x9 t6 b$ ^' r+ D* D
l8 \6 g# G4 z- use animal\dog\Life as dog;
6 u" Z3 K; ?; K; g: L; Q$ v0 ^% a; R; S - new dog();
复制代码
$ _7 V' i8 {8 X {' V3 \如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
7 Y; N# e V* Y; `% t因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php' V: x: z: B; @1 p4 H
4 s& s0 m) y8 x5 @" H& P- namespace animal\dog;
- i- k0 d4 P- X5 G" n3 k+ \ - : ?" D5 C9 q* y; n3 M _) K
- class Life{3 ]* H( g1 L* V
- function __construct(){
; e& {# \- @2 t* }. X) q; R - echo 'dog life!';
$ `7 R6 L' i9 D) p: y2 [ - }
9 A. t8 E: K4 N6 U5 N3 T g - }2 J9 k' K( _ {+ G! a# N
- class Dog{( O/ y6 Z N! ?$ N* Q# K7 M
- function __construct(){2 V6 L4 e( U& W2 V
- echo 'dog in dog!';2 t( {, P! E6 \6 A6 k# m( M& {4 f& v
- }" A2 `9 c6 C! O4 Z( k# k
- }# X/ _8 S4 A, D5 g
- 2 _: _$ s# l# Q- A" `) o; D
- namespace animal\cat;- R+ [3 ~% B- K2 P/ ~" D7 Q- ~9 v; m
9 b; r" s4 q5 s o- // class Dog{
6 A0 V5 ?8 {+ y - // function __construct(){
" L* O- r# L6 w2 [ - // echo 'dog in cat!';/ w' N& R% n( |9 G" C
- // }
' F% e9 K S& }( X9 L - // }+ Y! c2 k1 E1 `. q
- class Life{1 R! z! Y' C" s% o" Z
- function __construct(){
; @6 A0 s- z# u" h$ j - echo 'cat life!';7 f4 `. y8 j" A' q8 Z" z3 X) h& ]7 C
- }' R4 C" x, N( a+ `5 e
- }9 c6 f( `. d( Q+ X
+ Q7 w$ L' v* n- use animal\dog; ) S3 H# J" q/ U3 e4 o; w
- new dog\Dog();
复制代码 4 F: L) i7 N U( B) Y' L
如上,使用了
$ Y4 `4 ]6 L8 i9 X# t6 e$ y, dcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
$ V# _2 V) h2 U& ]8 F5 a简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 5 v; q+ _2 C, F; B- @$ N6 ^/ `
* Y0 C5 U5 t" b% [ u) P, g2 T/ \) B( G
# V O x( x2 J/ e/ f7 a; {' e8 i+ W1 a; v7 s
|