以下皆为本人自我理解内容,如有失误之处,请多多包涵。 3 P; c! p" z3 {& f
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
- e. ^" `3 a5 Q, K) R: L3 w& G) R0 ?$ V! u4 O) w( h* N/ E
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
& U7 b6 G/ @1 ?据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) % x" }0 J" ?: _2 c) z
结合使用方法来进一步理解它的使用目的吧。 : A j! d* M; H9 o
9 G& m# R S7 W+ c1 Fnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
, o' P0 r* N" S2 X - namespace One;
/ {2 W) M, J- e5 ~ - namespace ONE;
复制代码 & S% }- z9 O# h I1 j
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
1 Q, M2 u& J1 _/ P. K2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php $ W9 U3 K9 W" ?6 @
- class Person{2 y6 @, ]" K: t8 [ h/ Y
- function __construct(){
2 }! D& A% v0 S - echo 'I am one!';8 b6 S# ^8 P- B$ Z# z8 f
- }) W6 q- R3 S3 W+ M/ G% p( Z
- }
复制代码- //name.php
) `7 k1 E6 y; d& [7 A( C - require_once './1.php';0 \2 o5 z/ P7 E: ]1 Z2 r x
- ) U8 d$ L; X6 S- u) X8 a
- new Person(); //输出 I am one!;
* b, F- U% o1 ` w) ~ d- _' z - new \Person(); //输出 I am one!;
复制代码 ' f% [; Q6 F% u; x& Z! J3 ~0 Z
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
. `6 ~# F* m, h7 v! x6 K, J! U - require_once './1.php';2 t5 G& ]7 j* o" M6 S( @* N% O4 _
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
7 c' |. `4 y8 ]4 h- c4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php - L2 j% z% f% }- C
- namespace one;
8 t X$ [4 b9 m3 ] - class Person{7 u- ^9 Y+ I" u' z1 X
- function __construct(){
7 t Z2 B- m/ P$ U - echo 'I am one!';! X) K! P- N# V
- }) t+ Q1 h% [' y# J- ?
- }
复制代码- //name.php
4 Y/ ~. ?4 ~# B7 u& c5 A$ x - require_once './1.php';1 u5 a' L. i; I7 T$ Y0 O3 V
- new \one\Person(); //输出 I am one!;
+ D8 ], E; Q0 S0 J' K7 g0 i* G9 L - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
5 j' O2 }( J4 ^6 y" Q0 Y' K+ @可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
8 s5 s5 X- O5 P" m }& B, j0 @5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。0 Q/ X( C7 S7 {3 ]0 g6 }4 {
- //1.php
- l: a5 s1 M6 S& d) B. J; } - namespace one;! k3 R1 F1 H: H4 {$ f: X; q' ?2 T0 o
- class Person{
) C# l1 S; z: P+ q3 T' W - function __construct(){3 v; O7 J1 Z* {6 b3 V) P; D0 K/ |
- echo 'I am one!';; r$ @& j; e& M7 \
- }$ t7 j, I' U0 m( v) | J
- }
复制代码- //name.php8 x9 s: ?- |' }! K$ p" Z* E; s
- namespace test;
4 U6 V' ?) P% Z - require './1.php';
6 `) d0 A# I6 B& Y. u+ }6 p% r$ R - new \one\Person(); //输出 I am one!;. K3 N0 a, |7 r r6 I! w
- new Person(); //这里结果会是什么呢,猜猜看 m9 n; q& T o" s
- 最后一行结果报错:! i9 t1 ]) `" C0 y1 G1 Y9 e: q. X, }
- Fatal error: Class 'test\Person' not found
复制代码
" P7 v/ T+ A, C: Q0 S
9 k1 H6 W' n. n2 T( v- Y首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
q0 @! _+ K1 H6 `% @5 L7 ?3 U( G结果报错: - Fatal error: Class 'Person' not found
复制代码
: m' m8 R' M$ y* t. Q) j接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
- E/ K- P: T8 Z2 I9 r* l - namespace test;
' X$ r& ~" e4 [. e& L+ l" Q - require './1.php'; - D+ `) d8 s& X6 s. C! j6 H/ u
) m( e: }- T& @& U- class Person{& M: G3 a; X$ a# x2 F: q/ C
- function __construct(){' T0 V8 C, n* w* f' T2 l
- echo 'I am test!';9 l' n5 |, E) I! N8 N4 X: p; V
- }
. J1 I6 x* Y( z- L - }
2 @2 {4 Q! s! S0 U6 J( ^% G - 6 {8 ~" j" n+ e- _* w) w" |4 F
- new \one\Person(); //输出 I am one!;, d" X" L0 ]9 ~
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 & H& S6 k& g# ~) z; n* q0 B
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
8 Y' M6 i2 A1 R- ] - namespace test;
: G/ p; c, d* f - namespace one;( u' Q8 W! E% Z; |- p8 o4 ?
- class Person{/ K/ H. \9 \2 |/ }8 ~$ t) U" x
- function __construct(){) O0 Z# c! F4 d' u* O7 q
- echo 'I am one!';1 |" j8 O) y7 n$ e1 a9 [, o
- }9 {3 ^% l! I3 g! T
- }
* V* s* o- h* f9 X) c* s& i1 e
. n0 @. g: j+ g3 r- class Person{( ^6 ?) E7 r! [1 ?6 g" Z8 k
- function __construct(){7 W, j- X; J3 p( B, [, l+ d
- echo 'I am test!';
& ]( n6 ? u# d( e1 L! {$ k1 t2 J - }
. @ X7 h7 D2 \4 N& }! x - }
复制代码
. w; C6 J5 i+ z2 Q, H% v9 k无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
c( p" w. R G6 }& W看来简单的把require理解为替换,在这里行不通。
6 e q+ K& @' I) i" N6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
5 B) I/ P! X+ W8 d' K0 Y- //name.php
3 g7 Z2 m5 k2 l9 O! K1 s7 m' z
5 s" g2 A2 `( ^- namespace test\person; s& C c3 Y. |) J/ P R
- / ~% D) S/ }0 O: _+ |+ a$ k
- class Person{
) F& |% g0 k& L8 Z4 z( N7 `* O! w - function __construct(){; s; ]* X3 W: x( O M
- echo 'I am test!';
- S) G: C6 z& P! n) w% ? - }
9 ?5 t3 Y1 c; F& D9 D1 m - }
5 M! a9 R( j- j! K1 f - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 9 V3 F* Q1 f. R+ l0 I5 Z
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 : m7 v0 ?1 C3 O, r: X3 g; \
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php1 d( r* W0 |0 M: R2 Z
- 6 x" ~8 B1 j( I0 ~% Y& h" O! w5 W' O
- namespace test;) t! J! W0 _, T$ Z2 G0 V. q" F
- echo 'zhai14';5 w5 T# \' J# K0 o2 y$ }- W
- namespace zhai;7 `+ x# F9 x( x' Z0 i( F
- require './1.php';
复制代码
4 H2 r ?9 W7 B; l. X) _php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 : |8 n& i0 J# s7 T) L+ v
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& x8 E8 i5 A5 l, D/ d3 V# o: F- //name.php
& Q; `, A" r5 w h) U/ J - + N- J5 R8 `2 Z9 q& q4 ^ |& M0 A
- namespace animal\dog;
, ^+ |+ S& A( Y& Z3 ]. h
( t: a M, Z" H( \. j2 j5 |- class Life{
0 q' y. e0 D: ~3 [+ G8 P0 Q - function __construct(){' A9 [: _& `8 a: H, e* K* L, F
- echo 'dog life!';1 M/ Z4 A6 h) n9 D
- } S; x# u& ]: D$ n
- }
" \) {3 M' m5 g2 C& U6 k4 M - 0 ~, x' {. u ?: @# k" K
- namespace animal\cat;
6 W5 N$ P' d) s - 8 N2 s5 V& A7 J$ A2 e
- class Life{* i6 U" C9 \7 t5 F- r0 |
- function __construct(){ |( T# f7 W4 h* ~* v! k& z7 J" p
- echo 'cat life!';
. x2 ? a" n) b1 K - }* `/ p" c9 d- G) G8 \
- }
4 }' G4 L* z9 U4 k9 k- g6 E
( x6 T) i0 Q. q0 N3 o- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
6 k$ A9 T5 {; u( C9 K- t' C - new \animal\dog\Life(); //A
8 t" z4 J$ t! k* d/ k+ F
. i8 \' P4 S5 Y$ O1 t- use animal\dog; //a
r6 n1 K% s+ c5 S' d - new dog\Life(); //B% D3 |/ I C7 p7 {$ l5 f) _
- $ L9 N3 S8 V; J+ P3 X+ }* a( {
- use animal\dog as d; //b
) n+ C; A& {+ F( @1 X - new d\Life();
复制代码 1 s) y( D, R+ T& J5 s6 T$ H* i& c# U
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
5 v. c( H0 S# F3 o2 ]通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
! {4 L& G8 s; A l相当于
. F+ k- D: b6 y. ~2 v2.namespace后面不建议加类名,但use后可以。
3 J( f# R* o7 A6 \3 _$ G- //name.php
. X9 Q6 o6 L* p4 N: t7 X - ( v) Q! ~2 m. q8 t) M: j" R
- namespace animal\dog;9 n& z+ s) }: l# @
- ) q& _( I* m1 P+ i" k
- class Life{# B, v: J/ o: V2 [: Z1 D( C; z+ s3 |
- function __construct(){
; s+ y7 {+ v' f( P3 M - echo 'dog life!';; R; s1 L s* d
- } p2 N7 I/ B' s5 D1 t3 x/ N
- }. _# t- A8 n; K I( j8 V2 }
1 d" Y5 I3 [/ p% O) }- namespace animal\cat;
, L4 T% I' L& i2 g' Y - $ b2 d; o9 K, c. @" X" @
- class Life{* D9 q r( E# U; f
- function __construct(){
/ p2 i( ^( i- |' E6 p - echo 'cat life!';% C8 M0 ?: t7 [# O: Y* s
- }! b7 j5 I: N' m
- }
& T- N5 t& ^. @, i - ' e; W4 s* o1 X3 a$ C; q0 Z- O
- use animal\dog\Life as dog;
" E) ]. W& v x! K; p2 }* J' J - new dog();
复制代码 6 }/ ^0 }3 p4 A. R/ W/ z
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 + T3 x3 l9 F) L6 {
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php( v& y/ h6 @2 v( I0 v: ~
" J. D- j6 Z& I1 [- namespace animal\dog;# D: i4 J3 K( A8 P( A3 ^
- 4 p$ `( P0 | \% l* m- Z$ V% f
- class Life{+ l' ~) x' c' q! q3 A- z7 c
- function __construct(){5 I% t9 G" T4 q, G
- echo 'dog life!';& _# R7 ?' p0 M4 o* k% _# ^) K' g8 |
- }
( V% z$ ~( w4 U/ ^7 g7 c - }; d/ S3 }2 `5 z L
- class Dog{- C2 r4 k" L$ N! Z
- function __construct(){, H" Z* |3 y" m& G# @: f
- echo 'dog in dog!';
# b# |2 G4 U( Q! p - }6 c8 c. ]' j) o" n' Z: Z9 R
- }
& S: L0 R U3 e) w - & ?2 u' m" b( ?6 [- t8 a. g
- namespace animal\cat;( r9 A6 Q* E" H6 s2 @
- 5 ]7 E( L2 L3 o4 F6 M2 H
- // class Dog{
# G# z* }; X* d. s4 W - // function __construct(){
( Y: a4 M9 a0 ~. u- A( N - // echo 'dog in cat!';" X* r' p3 ]8 I- D
- // }
v3 ]/ ?( j" u; I; T6 r - // }
7 U( I+ b/ I3 K2 G" n - class Life{
6 {2 ^3 |8 X' |$ E - function __construct(){
6 S6 ^3 v. D! B; L3 E1 _ - echo 'cat life!';3 Q1 w. B7 z! P0 m- i, p
- }1 H' H% w5 Z$ {% \" ]) V a3 Z$ Q0 P
- }( }& E& X1 O. ]
8 {; q0 F) j3 ?! d) t! Z3 w- use animal\dog;
; u$ s% l \ p9 R0 n - new dog\Dog();
复制代码 , @) l2 u5 A4 `, `$ D
如上,使用了
" D0 z0 m' b5 Pcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 1 B6 k1 z0 z; @
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 & X8 A& H( ]# }. Y/ y5 T8 W0 B2 m
9 C$ r* Q; X2 n$ Q( s7 h; [/ v1 `7 i
7 I* N0 M& A% |3 k ?1 d d# `8 b( Q1 X2 I# q: W& J3 D
* o! Q) [* _# V: \1 W \
|