|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 # c( o- j3 d# p
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 7 Z: ?* k5 v0 {2 a) A& p- ]2 a2 j- E8 s' g
0 N$ g7 h6 @; F$ l& R( d L使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 2 b. A3 {) J0 }/ t, w0 G
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) ! X* y9 z, y: s8 A3 k* U
结合使用方法来进一步理解它的使用目的吧。 / a( Y; ]' \% `5 b$ H; N
$ T A {+ b; K! L& I
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
$ w! i k* Z3 k! D* ]# L" U, P - namespace One;
7 `/ e6 c: N. I: x4 U - namespace ONE;
复制代码 8 P6 L, A+ ?. r! M* \7 S
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) , O3 u# g, y* |3 ^% P
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
; ?+ e0 y' s c' o. ` - class Person{2 Q g8 `' F# ^2 z. r4 a4 S
- function __construct(){% _# N+ s8 P: z- ]. r( Z
- echo 'I am one!';. m2 ?; _4 c3 }. {
- }
8 ?- M9 N7 s, ^ b, ?( R: h - }
复制代码- //name.php
" S% m& T# A5 d, ]; f0 ? - require_once './1.php';
4 c: _. k3 I( Y# R# @ - ! E7 ~' Z+ G: j3 C9 r) @
- new Person(); //输出 I am one!;
( k* T" y& b( U - new \Person(); //输出 I am one!;
复制代码 5 y- H I" u P: E' x2 F: \
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
' |% g- R" U% m4 u) O# y& e8 z1 b1 g, ` - require_once './1.php';( \. ^6 x& a, N9 o% P8 q, K
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
' `5 u' i6 i2 @3 M4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 0 m, @* }' d) f: Y
- namespace one;
" B; m: [5 N0 [4 g- O! ]8 Y5 k - class Person{. J5 ?( K* @ l' e! k
- function __construct(){% w" D3 B* L% l4 \0 f
- echo 'I am one!';1 o9 E- k. J8 y$ N
- }5 p5 b% M8 m1 E) y0 P; M; e5 R7 p
- }
复制代码- //name.php
0 ?6 u: n5 t! y1 x& ^; ^ - require_once './1.php';
6 |- H f6 [7 Z - new \one\Person(); //输出 I am one!;
7 t/ U7 T9 Q( a) y9 F9 K1 V' B) Z: p6 D - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
4 v( S9 s' m. @可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
# H3 c* ~& N. D: i* L5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
7 L9 {) v9 o- f( ` p5 l: X- //1.php
I0 e& t* s6 B8 q( Q1 ` - namespace one;0 K* R8 L$ o5 O' b: [
- class Person{
. ]' _, X+ V- y2 K* I# W# N - function __construct(){
/ T/ }. A W8 j; v0 l - echo 'I am one!';' h8 [4 l$ M8 k+ ~* b. ~ W; L
- }
; M, Z. B- b ]1 Y" x - }
复制代码- //name.php5 G+ W4 R7 A8 A5 l4 s
- namespace test;) Q% n# O3 t; ?' F$ E
- require './1.php';
; l0 D( _ _; |1 G1 V3 Y9 {: ^* m - new \one\Person(); //输出 I am one!;
8 e& @5 Z b" q4 t; L# H) n+ h, ?# } - new Person(); //这里结果会是什么呢,猜猜看
! t$ Q, ?0 b$ G0 ` - 最后一行结果报错: _9 t% o8 a# a# d) P* Q9 }( P5 g6 R
- Fatal error: Class 'test\Person' not found
复制代码
$ s6 G, R7 k: @. _& i9 J) X( y9 O0 R8 B
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 o! J) Q4 h; O/ D
结果报错: - Fatal error: Class 'Person' not found
复制代码 C9 L9 H* C Y s1 a( d
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
7 ^+ Y8 ^7 C% x7 h8 f! V2 {9 X - namespace test;
8 g% Y: x. i! r' f$ a - require './1.php';
5 l; K. X# v* S1 c - % Z7 a! j& ]) {! n: D( }
- class Person{$ z; X2 r: ~ m4 i5 i6 E& M& {) p+ }
- function __construct(){
# b; s: K& q/ y# T; g+ D - echo 'I am test!';
# _; t* x2 B- X# F - }
8 |. {8 Z7 c* Z+ M8 Q2 ^ - }
7 V+ `: B) T; e' O5 k8 R
|/ ?9 o8 ?6 V) h7 `1 r- new \one\Person(); //输出 I am one!;
: C6 R$ R- j9 m9 B8 o3 W - new Person(); //这里结果会是什么,自己猜猜看
复制代码 * f% }. i' Y5 }- Q) {# F
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php5 T8 F$ ]& {- j0 v4 y
- namespace test;
( o. s) H# O% r) T& O6 |3 i* } - namespace one;9 B# x' o @ B3 S3 z! t4 h, }
- class Person{
, G. b! h9 v, y& C+ X; N - function __construct(){
- U& v$ H% x, ^ V+ X - echo 'I am one!';
% L" ?3 L7 j1 S9 t+ F3 \ - }( L0 s0 w5 @2 U* k
- }
" {* S2 y3 ~7 _
% d+ Z/ ?( }/ l) b! H- class Person{; a5 k; ~2 P* R* {5 Z9 ]
- function __construct(){6 R9 ^2 D; N6 L) w. o; f2 P2 L
- echo 'I am test!';
; I. j' M" y( t' u3 Z - }
! p* U8 T* p; f' E3 B) I - }
复制代码
% P" h+ w4 Z% S/ Z. B" z2 f! p/ R无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 & t% |: V2 g& @/ Q* ^& m6 A$ K
看来简单的把require理解为替换,在这里行不通。
% L6 b7 X+ C7 L2 b2 Y) K" w/ a4 l* F6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
* N, z' S3 H6 Q- //name.php
$ z( l. ^8 p% B5 \! k+ K
4 H6 q, s! r4 T- namespace test\person;
' Z3 H- R$ Z& K/ \4 G* w
( @+ \+ t) [/ M) L- class Person{
7 T6 D: R9 S. S6 b0 } - function __construct(){
Q; w) n% ]* s7 v# ]2 K( b4 F5 E9 ` - echo 'I am test!';
3 S. z9 B: q r: S7 U - }, U3 ?1 p# c1 _4 C
- }7 q4 I. Z' K- w- q
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
; U6 y! z5 V8 l; c: K; {* L8 [不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
# q8 u* L3 j2 s' c7 O7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php' r0 [0 M6 Z E9 G4 I7 e5 _/ E( O
- * [6 a# z- _( k* o
- namespace test;
, s1 {6 X5 n2 U- Q6 D- J- z% \5 @ - echo 'zhai14';' C7 i! N! R# u" y
- namespace zhai;
: r- c+ m/ T9 C0 [, G; M% r - require './1.php';
复制代码 & D" k; O% w7 A: } e5 Y' U
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 . t1 u; m& R, \: `8 h
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
. }( `9 O- Y: @ s- //name.php
1 ?8 T+ E) p% B: Z
, C' [/ v T$ s8 }6 m3 X W* J- namespace animal\dog;9 ]) h, n: Y& s- ?( d
- 2 n4 S4 S- _) T9 U9 ~
- class Life{0 [( \' Z5 Z% ?- g/ m
- function __construct(){, d; _7 Z/ x6 U# D! n) J0 e
- echo 'dog life!';
+ C7 K/ ]$ F5 m - }
- v4 [. y: N4 T! d( F/ ^3 n - }
; Q. _! X7 t- K( D% b( b- V% ~& ~
1 ]' G" r2 b8 [. f i- namespace animal\cat;
- {/ v$ P n# R4 T |% s4 Z
4 y& f6 S3 a5 E) K- class Life{* G" v$ i7 s% F0 j' X* D
- function __construct(){% C7 s% D3 u. J) c
- echo 'cat life!';( {" M; O0 }5 ^. v, m) h2 `2 [
- }% f3 t3 `; T* s; u
- }
! U; M- @* v6 m$ c, E q) ?
2 V% p# @1 z/ R( ]6 Y9 y1 Z- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间! C8 [* D5 m; l. K4 b i
- new \animal\dog\Life(); //A+ `1 z7 }! X( h: }6 A
- $ c5 _$ O( c8 |! Q: ?4 ^9 ~
- use animal\dog; //a
0 B1 z0 \6 V8 d K; k) _! l' F - new dog\Life(); //B
. w9 J9 V- W# p n7 z - 0 v8 s, q) `, I5 s4 g
- use animal\dog as d; //b6 @ F4 f7 }. P
- new d\Life();
复制代码
+ }3 h% w+ k+ ^$ ~" S. E1 ?通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
% b- Y, ~, O7 I通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 2 j/ _" n7 \; i$ w* U
相当于 G% S6 v: ]# X! c1 f( f. `# ?
2.namespace后面不建议加类名,但use后可以。2 `! y& }( c1 @2 N& X! s
- //name.php
6 @; Y$ i% i$ C6 K8 g) _- D
0 W. Q( J0 e( d" Y4 j5 X- namespace animal\dog;
; E! d4 v4 a; x9 x% S& o3 }. r# o - & {1 F7 p" F/ B1 Y. l; s
- class Life{! C. [( M; U2 h5 W) O
- function __construct(){
5 E) m% z A4 ?( E- }8 N- F - echo 'dog life!';
# W4 k7 n& W+ p0 l7 K - }
B/ ^! [2 D3 n: X' m( q - }
( [$ ^! b+ @7 j9 _ - 8 G2 X; i3 P: ?% n9 _
- namespace animal\cat;
& U) j) C- Y1 ?/ P& V4 r* ?1 c* J( _
* V5 \! E6 J4 ?6 e' n; W- class Life{6 M; H. u9 y9 A( T
- function __construct(){' J' M' e0 E! z% N# Y8 U' h9 r
- echo 'cat life!';1 Y" p8 k3 ] h: L0 U
- }
& S( R/ F; E' f6 U3 G - }
! J# m, y: X: {! t @ - : ?2 S4 }7 y4 R. C6 \( i# D
- use animal\dog\Life as dog; % d$ u5 O/ Y2 T
- new dog();
复制代码 n: V9 C9 }* c) X0 d7 s
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
8 }8 a; }) {: S* B i/ a因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
8 }4 k' _- O/ [: p/ C - 5 y7 b* \6 X+ I& X' Y
- namespace animal\dog;
$ _# J) n2 l- _" y8 g
+ p2 q2 y, j) x x. a- class Life{
% e3 d- y. W- T+ z# X# { - function __construct(){
4 Q9 ^/ b( ~* O0 \' E! I6 | - echo 'dog life!';9 ]+ @( h9 @8 v P1 Y, X
- }
6 _ ]' f( o$ p& o3 |( d - }
, s$ M" g) c4 w2 w/ X - class Dog{2 N* m/ Z3 ^# m
- function __construct(){
/ w' w4 E/ g1 `$ [( R+ R - echo 'dog in dog!';( Z3 ^7 u& g: i% F# v) J% Q8 g
- }, c' R3 ]( c: G4 O+ o( b$ V
- }
* Z3 G9 b) U- N( K7 p+ v$ }
' Q; G3 q) M( A& I# d4 i; m- namespace animal\cat;
: m( X6 m; D) v4 g( W3 x
# _- k9 `9 S; @5 D- // class Dog{
/ J* W! d7 C! ^/ g, ?8 a$ T( |- ] q - // function __construct(){+ G' G& d' A) `& V) f7 l' w5 ]
- // echo 'dog in cat!';
, i! P Z* L1 S0 B5 n6 Z - // }' f5 L2 l- g4 _% p# ?
- // }9 h3 H# D; f1 u/ I" r2 U
- class Life{
5 V. t9 b( H& T6 e - function __construct(){
7 {+ e" Q4 o) ^) t" w - echo 'cat life!';
2 z! \' V! N& _) {/ G' g G: k8 _8 H - }/ Z) b; D6 p# X& r3 i
- }
: D( |: L8 l! |2 f+ Z
. M9 i1 b: p, A" e2 o% Y2 a2 ^8 b- use animal\dog;
! Q! ^4 z2 Q9 B6 b1 k b0 W - new dog\Dog();
复制代码
2 u8 c2 A- @" f1 o: n9 V4 e4 ]8 V. N如上,使用了
6 C3 g0 [6 [, j7 S6 wcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ( ?2 q. y# | R& p' w. r
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
: z4 l( Q |: W8 k5 Q0 {4 {# T
: a" f" \! t2 t1 `' X( `1 @3 {
5 f4 v4 j0 m( }" w# u: W1 H8 }+ j D8 r
( N% q' m. C7 B |