以下皆为本人自我理解内容,如有失误之处,请多多包涵。 + o4 j3 B- Q8 v1 V# n4 F6 k: |# v! o
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
X+ K6 p1 ~0 ?8 B% d% X" [: [3 D# j. h
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; , l& p f. |" W. G# u4 V
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) & d" d( a- c/ S" {( Y
结合使用方法来进一步理解它的使用目的吧。
3 z& O* E6 ?9 d8 Z6 z, n [8 Z& b: S
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;% O3 X( z- A9 v/ B) e
- namespace One;
3 ^' q+ z, o/ m1 E0 I) l1 a - namespace ONE;
复制代码
0 V' F8 P1 l# v' f如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
. ?! @; R! {6 R2 U D2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
1 `0 J# @3 u6 ^ - class Person{
% |4 Z m9 ?( ~7 a8 b* m4 t - function __construct(){
6 R9 @1 v2 ]& Z1 O2 I9 |8 ? - echo 'I am one!';
1 s5 U/ D6 P9 X" m- p i - }; z- Q) d& A9 s2 Z
- }
复制代码- //name.php$ y) y' S1 W! i, @' G- J0 a1 r
- require_once './1.php';9 A5 D5 [) `8 k# c7 B9 i
3 s5 |1 G1 T7 H. n- s4 A. t- new Person(); //输出 I am one!;6 U/ `2 N( I% R
- new \Person(); //输出 I am one!;
复制代码 4 X% ~( |3 o7 q2 v. B- E
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php- n, o6 { g9 V. x
- require_once './1.php';
$ }5 z$ F: {; `, k+ j' L8 f) f. v - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
3 m9 g% q% u8 Q9 W4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 3 q# S1 r5 ^0 j8 f# M# @7 U7 u
- namespace one;
: w/ U7 R) O) d9 x - class Person{
8 Z( c. N. g- v' ? - function __construct(){0 r# N( r H4 V, p8 r! L6 j
- echo 'I am one!';
. Z7 h; t" j$ ^. f - }! g: g' T+ D/ }" }& c7 l: ~5 R
- }
复制代码- //name.php+ ~% h+ M9 q4 \- W2 `/ Q
- require_once './1.php';& O/ h$ o' j: ~' z) }% S% m& k* ^6 D
- new \one\Person(); //输出 I am one!;# V% _8 n( [1 d* ?3 [# A9 u
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
& B* n0 s3 y* P# G可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 % C9 T( v/ [5 Y
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。. _- k# w) C' P g' Y. G; d
- //1.php
9 `: H% r& w5 F4 Q2 G - namespace one;
- p! g! a, j* z' K - class Person{ r' \) W+ |* K( M$ p$ M+ }
- function __construct(){/ ?$ g7 f. p3 B3 _1 r
- echo 'I am one!';7 \4 j7 k6 F9 t" ^9 o% I1 T0 v- M
- }4 \' k- u+ V2 g5 u( ?
- }
复制代码- //name.php
2 L1 Y- `# C" N( } L/ o9 F - namespace test;
) _$ ~- K$ H- x C - require './1.php';
! M' ^3 T* L7 T - new \one\Person(); //输出 I am one!;! k* Z8 O6 N6 ^2 R1 Y* {
- new Person(); //这里结果会是什么呢,猜猜看
% D4 }# A* v8 @0 D; r - 最后一行结果报错:, | |4 t& g( f9 }! w' [
- Fatal error: Class 'test\Person' not found
复制代码 6 B- Z: Y! n8 a8 |; d6 G& D* ]
' G7 D; Y1 A) [
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
? s! [6 A+ n! d _$ G7 n结果报错: - Fatal error: Class 'Person' not found
复制代码
2 O/ w6 v# X* ~5 J! j% n- {接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php7 f2 E+ w' D. S* T& T
- namespace test;
2 J9 b! M+ o( X+ F& l# }& c# q - require './1.php'; ! A* o% }/ {- x% t; E
- : M3 _- [" T) ?% r+ ?
- class Person{
+ b7 {% u/ |8 J/ b - function __construct(){( a2 L2 s7 X" d& N L
- echo 'I am test!';- i3 r# n2 l: V
- }" R8 ?3 r! h2 P
- }' X; E. H6 R5 ]% u, Z
- 5 {6 }2 c$ v9 {7 J
- new \one\Person(); //输出 I am one!;+ J) H2 E. V( M y% a1 b
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 ' W" _9 U- A8 _" G
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php" a. S7 q$ T/ Z0 n6 ~! ]
- namespace test;
9 q, p2 b+ B* l C: ]5 W! `: c" n - namespace one;+ x2 z1 S9 Q- q$ X$ G9 U. K$ w
- class Person{* j! }; {8 B4 E. ?$ w' f( u
- function __construct(){
3 D2 l$ o9 {0 U, f. k - echo 'I am one!';
; y; A9 M( `% ?* [' U - }
% K: z6 L9 b7 H1 }, A - }
+ S$ l" y5 M7 v. a( [# k: _, U
$ w+ P" l- r; L) ^8 ]* P. c- class Person{
6 Y$ U8 x# \9 }2 n$ W! c9 w - function __construct(){, o3 h9 N& [# W: x# {" G8 `
- echo 'I am test!';6 N8 \3 J. a5 ?& G% { D) O
- }# a5 X& |* u; n+ Z
- }
复制代码
( b; S% l* \1 L4 ?2 S5 t! G无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 4 Z+ R* x3 L! A+ N3 l( }# S* W/ m
看来简单的把require理解为替换,在这里行不通。
, Q$ F, k$ R( o' I6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
) w+ C& Z3 T4 W+ f& d- //name.php3 j' R+ _" x; V* h
' u/ \. Q0 x+ E7 V$ ~) O- namespace test\person;
7 L6 ~2 F" |# r& \ - . a0 T: {* k: i l( b# a) H# V
- class Person{6 o/ F! o+ T/ X
- function __construct(){7 G- ]. [7 x" l0 C
- echo 'I am test!';
) y4 H& ^6 V D, n4 |9 U! [7 Y0 | - }4 H- w# T4 ^0 A1 q" t6 ~
- }9 b9 M1 e$ v" i$ y7 @# q/ }, c
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 5 ?, \- _, U: q' ^, Z% B+ W
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
# {, i3 y- _ i( J7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php2 ?- c, a$ y& i1 o
- 3 K% R1 A& ]8 Q' J2 Z, I
- namespace test;5 R# y% ^6 X( @2 |. V( P5 c
- echo 'zhai14';
) k( _$ g/ ^" R - namespace zhai;
! Q8 w- F# V2 k, y7 F - require './1.php';
复制代码
3 c) `$ p5 i/ N+ z2 I8 B9 U6 _php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 0 ]- i3 h( Z3 b. C
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。! `2 `$ Y) }* M6 |% F& v
- //name.php% P: W1 j. _8 L
- : y; ` |9 N0 _) y' L6 x' r
- namespace animal\dog;6 G7 E Z4 E9 m( u$ V
- 6 K3 j! y+ j1 p* I c% i+ r W
- class Life{
8 B9 c! \4 L6 N, {2 b - function __construct(){
5 ]6 R! y# \( Z. P% K- d - echo 'dog life!';/ {* |- |8 M d6 H" }7 R+ T
- }
. n }+ q7 R1 y4 q+ C) j" @ - }
6 N! }- y! b- Y2 |9 y/ @9 s- k - + e Z8 e8 I. q2 u8 x( V( M) ?2 k2 v
- namespace animal\cat;
% c/ d1 z' M3 {; |/ B
" O o2 Z# z$ E. n3 [7 G6 {% V7 m9 t- class Life{
7 T6 L, V6 h& s& d/ C" F- y - function __construct(){3 ~' Q) O! T4 }5 f* r+ q8 O
- echo 'cat life!';" k# U) C: g: x* e {# `- g6 ?
- }% a; y0 a# ?0 i2 B
- }3 Q: S" v1 s" G( o8 L8 k% T- ~( ^
4 M+ F! }$ g6 r" _) m8 [, q- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
$ H, A6 g- k' j# ? - new \animal\dog\Life(); //A
* m& V% D% {& E! y ]7 R5 D' H - . f& D \" K% z# ]3 e
- use animal\dog; //a
6 \ _7 f3 o3 H" v7 s# `/ t( O2 s - new dog\Life(); //B* B) ^# u8 i: a# l
- 5 _2 q$ K/ W* w+ q/ _( i
- use animal\dog as d; //b7 @ f' q; f6 U4 Y( W P
- new d\Life();
复制代码
" N& b) p* Q9 [' S8 B; q通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
/ S N, B; A3 m: c3 U通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
. u$ k, E: B3 `5 a相当于 . f' v$ w+ `. G
2.namespace后面不建议加类名,但use后可以。
( \" a; G5 e3 g, z* k G8 l/ E- //name.php
8 P- ^) ]0 ~+ S! D4 \( y
8 u, k" {7 T: F" r- namespace animal\dog;9 M" u* P' C/ @
9 v& p4 }1 u* Y$ z3 v$ P- class Life{" P' {) ^% v! j4 k6 b: t# f0 s* i
- function __construct(){
9 Z4 f% s: p; X) S - echo 'dog life!';4 r, P7 p9 h' r8 G
- }
: c) T2 D' b1 y+ w$ U - }
" a/ L* Z, @$ j, L8 n$ {" @
( G% {2 M) {8 x/ X/ X! o- namespace animal\cat;: d; j4 `# E& [
- + W( S! Y. A& \! X1 o& u j0 ^
- class Life{6 [. W- u' A) V! ~1 k7 [! }
- function __construct(){1 s! }2 `+ y. }" X& l% Q
- echo 'cat life!';( m; Q1 ^( q, a& k8 t' N3 I6 `+ p
- }
! y# k4 C0 P4 s% O' k - }
4 l. |) G0 s- ^1 p6 w4 b m) W2 X
* M2 h& ~2 o! R- use animal\dog\Life as dog;
. J2 N: w0 N3 ?& f3 t% B - new dog();
复制代码 6 d9 c* T2 @) H) ~& M5 `
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 1 X2 X2 [" o2 w
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php1 V, G# P' W, b
& I- ^( r0 V! @& R- namespace animal\dog;: i& S; J# s v7 u% r, m" q
- z$ o; K2 Z. o5 a9 t+ m- class Life{
, z7 r( b; o$ v7 P3 D/ C1 B - function __construct(){
" n1 t! f+ ^' G4 z" Q - echo 'dog life!';- Q! l! ?* Q* Q2 o) R+ d
- }
@& i" G d. }3 V - }9 w7 w7 h* J* F2 j5 j! L3 @& b
- class Dog{
/ N$ C& q5 G- l. d - function __construct(){+ g5 W! I [8 z0 V X/ E+ h
- echo 'dog in dog!';- d: ^% |# ?7 y5 b* ~# G5 }: r
- }
" L* L! ]5 H' i8 d% k; X% A3 C5 ? - }0 |3 T1 x, a. \0 u0 @* c
- $ g$ l+ s1 A3 S8 Z: `3 F2 d2 Y
- namespace animal\cat;6 |; g/ y' ]4 A7 j0 p4 K
+ s& l- w/ I+ l% n7 @2 B- // class Dog{; L7 x9 e& o4 z0 o
- // function __construct(){
7 s' }5 n# ?6 u2 ^8 J# ^ - // echo 'dog in cat!';
4 y- l1 s: I6 r: j( J - // }
* {% O9 x5 u3 S/ V" I - // }
A9 P! n% O3 h - class Life{
" X4 W4 j3 A1 S9 B7 q1 W - function __construct(){
4 s8 F; e y( {' E2 A$ T+ ?( x - echo 'cat life!';
4 _& h% v6 j2 L7 z; s5 p8 z - }
4 l a2 p4 m: F - }
5 a* L3 _# ]* E2 @$ A3 _" o - * Q6 ]% y/ h9 ?0 Z' K
- use animal\dog; I5 C2 I) P1 f! i
- new dog\Dog();
复制代码 * A2 b* L( \1 N O" i9 N
如上,使用了
0 g+ e2 w' M; t: L; a7 Zcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 - x+ S* ~+ ~6 A% `
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
! {: \. o/ |# Z, O5 F( j! q- F: \$ ]6 |7 u% f l8 L
2 B8 c& Y; D6 I# l5 H1 t: D' M4 Q; ?% d' J
* g2 i9 k) z, O
|