以下皆为本人自我理解内容,如有失误之处,请多多包涵。
X$ \% m) R: }: o7 S/ p, P! T文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
5 P6 v' Y. K/ G8 f# D% G1 N, u1 z' _7 ~! N" g8 ]8 ~4 r
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; . M5 ^- U8 Z& H
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
2 c6 f: j% D0 t结合使用方法来进一步理解它的使用目的吧。 ) O) w/ m1 ]8 u: A6 _
; a" C" P; z, m" a* K" Rnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
y5 e; l7 S! g1 Q. H - namespace One;
i2 o9 d7 t: l! `. u4 X - namespace ONE;
复制代码 ' w+ M2 t3 ?: H* ]/ X0 T9 w- _5 ~9 V
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
+ Q; ^ n; L. `' W) y/ l3 z2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php " @: [& N: ?( K3 c) F* w
- class Person{
* h3 _# ~" ^! }9 _' C - function __construct(){
/ u) w* }8 f& p5 ]" ~ - echo 'I am one!';
- U7 p" e" y- h+ ~' c. f8 i - }) u1 k9 k/ ~5 ?6 @2 ]; l& E4 H
- }
复制代码- //name.php* X! H @# E# M0 Y w
- require_once './1.php';
9 X: R& Y6 J* ?* ~: ?) D+ u: E% b
9 O. K- l- i* p4 R# t) p- new Person(); //输出 I am one!;- T- D6 ]" Q+ S! \1 Z2 b
- new \Person(); //输出 I am one!;
复制代码 2 Y% l3 \2 @& D
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
; n0 ]9 i$ {7 S$ r - require_once './1.php';
% v6 J- j* o: t- ? - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
B, }) Z# c% U% `4 Z& F4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php * o( `" N* A0 d& h& Z
- namespace one;( E; F. J' L, F: H7 q
- class Person{/ p- k, S! A, q( X$ m! ]9 N1 Y* W
- function __construct(){4 d; _+ S/ a1 W+ Z
- echo 'I am one!';
2 K+ Y0 z% g8 E7 f# X - }3 F- d" f& ^& B! a
- }
复制代码- //name.php
( @" E5 I8 D0 C6 J, ]/ q - require_once './1.php';
/ t9 |) o5 V6 g - new \one\Person(); //输出 I am one!;
/ @& x. z. e, _: \ - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 , J& [. U5 U4 t
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 . [7 W# x p/ y, A( |7 Z7 k
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。. K$ t( w: ^9 r5 B: }0 W
- //1.php
% }9 p7 N6 p+ i, v2 q& I - namespace one;4 @& S& w& Z" c; {, p
- class Person{/ r9 Z4 S; n- `: n" X4 V1 ^9 Q( L8 t
- function __construct(){
+ }& s$ V$ g" s( v) s( o/ e - echo 'I am one!';5 V' \- h( G: Y
- }
- E& `" s% P% t - }
复制代码- //name.php
9 o, [" ^: U: h- ?3 f4 Q% ^ - namespace test;' w) U1 b( [+ m- e6 M' K- _
- require './1.php'; / S9 D1 u/ }( y1 W7 U
- new \one\Person(); //输出 I am one!;
$ E" F5 A$ A2 a7 B' U - new Person(); //这里结果会是什么呢,猜猜看
- k0 M& _' _ ^* Q* W" l) I7 _ - 最后一行结果报错:( i! S0 p* g+ E: @+ m- m9 X, m+ f+ S
- Fatal error: Class 'test\Person' not found
复制代码
+ }, D$ ^" N3 a; Y, d8 q5 X! H5 L# ^* k+ m5 f
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
1 s4 e9 b+ R4 f结果报错: - Fatal error: Class 'Person' not found
复制代码 1 C2 c9 I2 i+ _' F; M& u* m
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
. J3 d `$ ]* E* b$ e" R% v - namespace test;9 H5 |6 O/ B# q! k6 B( y% ^, z
- require './1.php'; 0 E+ I/ N( F/ T; T
- ; {7 H; W% u8 |1 Y
- class Person{6 X6 B; C& |4 x6 V9 P' R! k0 |5 c
- function __construct(){3 d: {& w. T$ `5 o6 C
- echo 'I am test!';
) J: I( z! ?; a- }# P( ` - }" x, V0 A1 K3 `$ G
- }9 c: \ i/ m2 m8 W" N9 ~. G. i$ Z
+ H7 u* U" h* {2 O, ]% q" ` ]" ?- new \one\Person(); //输出 I am one!;4 h6 `0 D: E+ S
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 $ U- a% J/ N. C% [9 t0 H. F
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php$ J: d2 s1 ?4 L
- namespace test;
+ }& v: s! {( a: N5 c - namespace one;
; h4 l* [9 j9 r4 j! R. @* z - class Person{
- ]; S2 ?$ ^7 v - function __construct(){
% k0 B+ z5 R7 N2 ]7 Z- P0 r* M - echo 'I am one!';
5 v. C& U; @4 S - }! c4 u7 P! a4 R ]
- }" v, r$ r4 {; m% `5 @
( L& f4 L5 P8 X1 R6 y1 p( ?- class Person{9 B( u% @4 ?8 Q+ W, Q( E7 s
- function __construct(){
* g- b+ @6 v A3 M - echo 'I am test!';* @( z5 B; q* O& Z4 Y& r9 i+ k
- }3 h6 {0 E9 n* N5 ~/ q* D M
- }
复制代码
- I" _) @) G) W; ^+ M6 c V无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 % l& e& S# w& C/ C
看来简单的把require理解为替换,在这里行不通。
( X3 r1 z, w5 p' W$ Q6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。- i; ?* m- S- r: S, \1 i
- //name.php, x/ Q0 R: E; @0 c
- 7 b1 r" G, h9 {0 P- r# z2 B
- namespace test\person;
/ G! |. c- |/ v6 ]4 M - 0 h! J. u. Y3 F3 I* t. E( Z
- class Person{9 b! h1 T/ @4 J' |# ` S8 a3 \
- function __construct(){) u0 W7 T; l ]: B
- echo 'I am test!';/ J8 x/ j4 x* o* s; j
- }; r$ Q# |* j/ ~' f
- }
; P- v3 U% F$ j# d: G1 D* H - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 . }& e& M& r8 V, l
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 + u7 @/ [$ p: w; O
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
$ j4 \$ {* @. G% t4 y* ~ - - g/ J6 a# `/ l( [# P# A5 l+ A, X
- namespace test;4 V- L! m& e S0 T2 h
- echo 'zhai14';6 q- E! P; ]# E3 d$ j
- namespace zhai;
6 b7 Z$ ]; ]) \& v - require './1.php';
复制代码 # F8 n( ^# d% J+ R
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
e2 d% } r' @( Xuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
2 B- o' X( C# i: G% a: ~- //name.php
! K, z" ~3 q) Y# f: {* y
* l9 K. R6 R8 A- namespace animal\dog;- ]; ?1 k) R3 d5 G5 a0 |( K: a
- - h8 ^7 X; X0 m, [
- class Life{7 W0 |" B( E2 [+ n* Z
- function __construct(){. O. R7 a8 `# |6 {- {
- echo 'dog life!';
" y' L t( a! _3 e8 ` - }5 L( y6 D- a; A/ K3 u E g0 Y
- }" k) H7 j' h& ?! I$ {4 e( ]
7 ~4 z$ P" G) `2 j- namespace animal\cat;
# C9 k) ^2 P. G H; v
; }/ s u+ Y+ n- p- class Life{
7 t2 p8 v( p6 g. f3 Y - function __construct(){
9 ?& T* p- C3 v$ B - echo 'cat life!';
" p! E: y U5 g% z! J! k - }4 V! V" u+ X. G
- }
- C' `1 E. @: }
" o* D. A: B, F5 S- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
( d8 m U; Q! {# g6 | - new \animal\dog\Life(); //A
+ X- f7 f9 p- ~ - * J8 \$ V- w) |! N4 S
- use animal\dog; //a
. X( g( T) J- f9 r7 J' x$ z" D - new dog\Life(); //B
+ j5 v" V+ c9 F% X+ ]; p - ) f: ^. d( c4 L* o
- use animal\dog as d; //b
4 V7 E7 _- ~. J: f0 } - new d\Life();
复制代码
1 s# y0 x4 V4 B! u" N6 k% J通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 9 ^" ]/ ]& u2 Z& g3 r" @" J: C
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: * i! E6 U0 W7 u: e" J* a. r, P
相当于 1 C6 D$ J% B2 x5 W0 r
2.namespace后面不建议加类名,但use后可以。
4 E) s/ j3 O ?' C$ z; L' c- //name.php1 x7 p w, v7 F2 S% L/ }
- 5 s# F; w) a* L9 P* s9 u
- namespace animal\dog;. H( Y: ^9 e: ]" [6 E, T! M
; `. q: Y" ?8 {# q; \9 y9 a' X6 o- class Life{3 X* h N# S6 d
- function __construct(){
+ l$ e, X7 Z! o - echo 'dog life!';
/ Q7 v8 O# z$ v7 b4 i- \ - }! V$ _ [0 O5 E
- }
% u# r- B1 E/ k) o+ O; n1 x - $ ]; o$ ~$ ~4 _$ z8 Z4 `! p* [3 S8 \
- namespace animal\cat;
1 ^% c3 \/ |2 R3 ~
* W( n1 n8 P, d* o+ K9 _+ N- class Life{
, G9 w: A8 [' |' O0 n( O6 z; _* m" M - function __construct(){
" S, s7 u" V: i* \' V% T9 D- X6 n - echo 'cat life!';
* o: u4 d+ f/ T) }/ |# k+ Z: I* d - }
; ~: n$ s+ v! u0 ~% t0 D% ~& C - }' A% k0 l, V! H; t5 s& G: g3 X
- ! n+ D+ S0 d. r
- use animal\dog\Life as dog; - O F* a$ [9 D* s1 `1 R5 _
- new dog();
复制代码 ^! t0 n- v/ f9 A# n
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 . m, O: j( _( r3 e' X6 J
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
; }! |( S2 ~5 V! E- F- o
: Z- }3 g) t# k. z- namespace animal\dog;2 b F8 ^1 ^# U+ t
& K. d0 z) @* C8 R- class Life{6 P* g) {! Y6 d* l" [
- function __construct(){% d2 q+ ~9 Q+ |. ]
- echo 'dog life!';+ u2 s. R x: \3 D9 j/ \: M
- }
9 }5 B( h; @. r- g9 K; D - }7 ?- C' T: r5 J M d$ W" N+ O& v
- class Dog{
' B* g. F4 I3 f5 _8 n8 N - function __construct(){3 b, V. {; D b/ P' H
- echo 'dog in dog!';
3 ?# k: _* G- f- e - }
' Y( Q3 l% U$ O6 e9 F) `* f - }: r) v6 O6 @" `) [
: I4 p! [0 D* l9 z% x: |& ~- namespace animal\cat;
+ U- h8 B! ~1 c6 J - ' X0 K! c" Z; A% f. O: o8 g
- // class Dog{: P1 F0 g0 ? C' ~- d( h% r6 r
- // function __construct(){0 f$ _* Z! V0 g: h
- // echo 'dog in cat!';2 l, Z1 s/ M ~% ~6 I
- // }
0 k; b' B- U. Y" ] - // }4 m5 ], |5 ], P6 C, W, |
- class Life{$ [% }$ t. L. w' L1 C" J1 K4 Z
- function __construct(){
9 A/ H- |, r$ A3 [ u - echo 'cat life!';
6 z' u, B9 n, l, ^$ r. D- e - }( Q) f" @9 @& S
- }
1 W" y( c% L. ^& i - 7 s1 Q5 [0 T# [) s* Q7 ^: `! f
- use animal\dog;
4 J; n2 o. c, u4 @ - new dog\Dog();
复制代码
; |$ M) f. |2 {$ g( _5 K4 T如上,使用了
W2 l* x5 t% @: L: V7 }cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
2 G! K# ]2 c! s& p简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
; ]( d1 @$ I1 _6 p: e4 l4 ^7 K. d1 g( x q. j- w4 k4 d0 n, q
4 a0 T4 F3 n+ x& X! P
; E0 q4 F: {# ^* F `
* }5 n% {! J+ P2 x* j6 g |