以下皆为本人自我理解内容,如有失误之处,请多多包涵。 # g. T: a# C8 n% ]
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 # x! e4 V* a* i- n1 V) u7 m
% g, k3 t- y% t R4 Y
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; + g$ Y! v+ y8 J |, N. m
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 6 m) s0 F" N6 M9 r5 e, m
结合使用方法来进一步理解它的使用目的吧。
0 F1 t7 o# ?" N n7 f: J E# q5 a9 z9 R
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
% O1 B8 W& F4 |+ S! c/ r - namespace One;
; O3 {( q4 z" u! N1 n1 Z Q! Z - namespace ONE;
复制代码
/ y, r5 \5 Z# G$ U如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) % p+ ^; _$ y: J
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
* A1 g. `8 a: r0 T ` - class Person{
* U. q+ F) l* \& S - function __construct(){
6 p6 n5 \2 G: R7 ]1 t4 K1 T - echo 'I am one!';' G5 O# a+ [0 e9 T+ g
- }
: S( B3 r- E8 ^$ W! s - }
复制代码- //name.php; ^1 l' H. N4 }( z. ` m( u
- require_once './1.php';2 h! D2 _) w( o7 S) H- T% L& Z
- 4 r$ N: X! ?. b- N4 \1 ^1 V1 `1 \' Z
- new Person(); //输出 I am one!;
, ?4 ^6 H ?3 F9 p+ K - new \Person(); //输出 I am one!;
复制代码
& q* X. l' d& Q. k3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php; h4 e* c5 W6 T! h, v2 z! g; k: F' P
- require_once './1.php';9 B' F2 U. r2 F0 `; _3 @
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
5 ?) @2 ?4 A, \6 l* E; ]( N& N4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
& r6 M: H' M( Y% Q# d$ S - namespace one;! A+ H: p6 M4 L) b2 Y
- class Person{
8 e# ?( J* {3 F' m+ A2 u& i - function __construct(){ i! O5 G6 }( r" @# G7 F
- echo 'I am one!';& i# N# s t/ g* ^- t
- }
$ u$ O" ?& U( |9 I) X8 [, d" n - }
复制代码- //name.php
: l, w4 b. R T1 G - require_once './1.php';+ c I8 } J4 O9 ^9 L: `2 u' k* ^
- new \one\Person(); //输出 I am one!;$ n o0 @* `) U
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 6 A# U" D. u7 q* O# `3 s4 O8 t! ^9 Z
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
( c1 T# z, `8 b# D3 x5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。$ _! W* ~4 [( v# m2 B
- //1.php
4 K2 z; h% u" N; @4 }( O# c - namespace one;8 g" M2 y& K' F/ s$ r s3 f6 p0 [
- class Person{
5 W8 A5 Q+ D- o - function __construct(){7 ~0 n) T3 u0 b* p, y( r
- echo 'I am one!';
S5 y, m0 m3 B( g0 y0 Q7 B6 S/ V- F - }
; I# K! E* y* g. a; h/ ~3 B. p4 t - }
复制代码- //name.php
4 K, Q. H( {% q/ j, U - namespace test;
8 E, l0 F4 T; h. Y, {1 |5 w5 G2 q - require './1.php';
9 m* d# L5 ~; e - new \one\Person(); //输出 I am one!;
9 U3 N9 X9 p5 n& {& ?2 q$ n, | - new Person(); //这里结果会是什么呢,猜猜看
% ?) w( J2 w4 O& x: J, R+ x - 最后一行结果报错:
9 c `2 S5 @! O$ ^1 N# o - Fatal error: Class 'test\Person' not found
复制代码
8 k& \- w, V8 T6 ~$ o7 I
8 Y# j' R- D1 }; @首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
_2 z# Z; d$ {8 j% |2 T结果报错: - Fatal error: Class 'Person' not found
复制代码
, X4 \, a# D* _! M5 ?- }接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php( W+ G4 ?0 x+ a1 B8 G% d
- namespace test;
b) ~7 R) s6 \ - require './1.php';
& `+ @: Z! a8 u4 q7 [( t S/ q - / y/ c+ N# {0 Q6 b+ T
- class Person{, P6 O4 r5 A0 v, o+ H, v9 [
- function __construct(){
. V, u1 s" \. \ - echo 'I am test!';1 w" O, f7 N9 L0 z ]
- }* g7 i4 k" T1 V- [. @
- }
* E, [ }$ q5 s! _0 M+ d6 j - / z$ C/ f& L( ]4 J0 a {
- new \one\Person(); //输出 I am one!;
7 T9 m/ c( ^1 W4 ]; D! |" u( { - new Person(); //这里结果会是什么,自己猜猜看
复制代码
K+ Q5 \9 j2 A B" b最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
4 p4 X/ e& R, l6 f - namespace test;/ M: O7 ~ N" D; b
- namespace one;7 f' X& g: h+ H/ {4 \8 T) f
- class Person{: C. `. k/ V. b" }4 T" x" e, i
- function __construct(){% b9 B6 P: n$ X4 j2 _9 q, O
- echo 'I am one!';
4 r; I/ v* i' D. V7 Q) U - }3 Q9 V7 V3 [1 {% H, l
- }
B6 @5 Y5 O/ G% i5 ^
* |" q0 I8 g% t; [2 i$ J- class Person{% w0 v; y6 U' C6 N3 t( D0 J! P9 n
- function __construct(){& a4 d: u% e, U
- echo 'I am test!';& P8 y4 O1 R2 R( J
- }: u% ?/ K. F ~
- }
复制代码
/ h {! e: L3 r" Z: _0 \无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
1 J9 ?3 J- ~+ E看来简单的把require理解为替换,在这里行不通。 0 p! w" r) a7 h! P9 H& H
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
( @* R/ d- q' h2 w3 |) V- //name.php
1 n% L. W( }. J k, X, Q
* F' t1 E' e7 }# U8 K- namespace test\person;
. Q: |% N+ U# m1 a. x
* `6 v5 k6 k9 t4 w- class Person{
9 m; D6 R7 q* `* S( [- H - function __construct(){5 B: [1 G1 W* p1 X$ D/ \$ Q; P
- echo 'I am test!';
4 n5 J, O) ~( G# |* Z( ^* d - }
& H/ ?+ Y. C0 E3 |& h( ~! R - }
, Y7 Z% ^5 s1 s# _' h - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
: r8 `% s4 ]" Z5 K$ z( Y不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
. R9 R5 G; }+ `8 }! t7 d7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php* K9 R; ^5 N) d# u. Q' A
0 C; L+ {$ _9 `- namespace test;
+ I& C& G5 Q! h$ R& C - echo 'zhai14';' Q& C/ f) V- O" j- T4 X/ E% D! m
- namespace zhai;7 L2 v. Z' I: r e/ ~
- require './1.php';
复制代码 ( p% \" E' d5 y% C7 @
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 1 t4 O. j/ c& e& z( b( F+ n
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。0 q3 k8 W. t" U! y
- //name.php
0 v* ~& t' C3 L/ T, r$ Y* \ - 1 a ?0 U/ d2 Q* S. z4 M9 k" d& O
- namespace animal\dog;$ `4 L# K' u3 k# F ]0 M& F
6 e+ i6 K9 J+ n& _# s- class Life{
2 g1 U5 ]. _% L6 [- Q - function __construct(){: S' M' p; A6 y8 e
- echo 'dog life!';7 t! B j! o" p2 ^" C) [- u* @ B
- }
! h- U4 Q; T- ^) l# O, v" J - }* u6 v+ Y% r4 l$ T) f. J
- $ v: N9 V9 a5 t
- namespace animal\cat;
! z4 H* y7 e4 F H) g - : F. T+ H( E- x" f2 f) G
- class Life{
. l% D, B4 l+ V# G- ^) C - function __construct(){. G* c5 u/ Z: d2 w# ], ]3 N
- echo 'cat life!';. F$ B9 I, T; L. v% }1 R
- }2 W1 |0 h( F; L# `: Z" B# h
- }
0 u. b: G7 D4 d2 s" A, m& n+ Z
. D( T' z" u* } d- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间3 ]5 l& q& \' p X: u( ~# N: D
- new \animal\dog\Life(); //A
. h* E! r) D$ k6 M% E3 L, O
/ k5 D, w- R! z1 Z' S# c- use animal\dog; //a( U+ q( ]0 \" v& O% B) y7 N
- new dog\Life(); //B7 B; q7 V+ ~5 `: G+ U, y' q
v6 C( O1 a1 X! H- use animal\dog as d; //b
( g1 f9 `9 w, O+ [ - new d\Life();
复制代码
5 ?2 R$ ]4 ^' M* d3 g5 j/ [& ?通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 # o9 `3 \! P7 h% P
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: ) J, V7 g8 \" @9 \$ c% y; V
相当于 + P7 E( G' w0 q& i; F7 J* u i( _ ?
2.namespace后面不建议加类名,但use后可以。
6 P0 O, X, P# \5 X1 J- //name.php
, s2 c3 t2 l y - $ B9 F; L' K# ` S- [4 D, g2 c
- namespace animal\dog;
9 o2 C+ k& L! j4 D0 A; G - : z6 V5 o" L4 \5 K: F4 q. i
- class Life{
( D: ~/ n) @ {$ _' c, |: t - function __construct(){
. c+ i4 {6 D" V+ x - echo 'dog life!';
. w2 \5 t2 Y s9 }6 q# ]7 V; W5 q - }
2 i3 Q+ L! i+ C# b - }
: k+ |8 }4 p% G' P- y/ G4 r/ u; r
5 |7 l, V; n# G# z! Y- namespace animal\cat;2 R* i5 B( d/ V3 l( y" [3 n
- j1 D0 f6 n+ i% v
- class Life{
% J+ L+ |( W1 j( {0 M; A) } - function __construct(){ Z' M. M! Z' I2 W8 W+ R9 c+ K
- echo 'cat life!';6 A7 w5 c3 l$ i( X4 `9 A
- }
( a) \3 a2 ^% R. T3 H; R - }) Z% N8 z4 M& A" {' \6 }/ y
z! m8 i, b' Z3 J* f+ I; ~- use animal\dog\Life as dog;
7 l1 p, X/ `, O" w( Y0 j2 i - new dog();
复制代码 $ I. ~- s6 B5 E6 x" A0 J
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 5 Q& G- z; S0 ~" j; \. E
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php; K9 }4 Q8 B: T/ O/ G
- : E. t0 M3 K3 K1 W( D
- namespace animal\dog;
( b. |" V6 G9 D
9 z/ ^% `5 {7 [3 e6 t/ E* R- class Life{/ g4 {5 M& i" V- R' a
- function __construct(){6 \0 V% F# n3 L
- echo 'dog life!';5 I8 Y$ A O, a7 p$ @+ e2 ~# O9 F. {
- }$ j" `6 |, X4 Y5 w) Y$ B+ O
- }
c: e( Z% c/ y8 m) G% k7 m* F2 W- s - class Dog{
" K3 j+ v6 M4 a0 \. H& Y - function __construct(){* y. N' `9 d2 p: q8 l1 K3 ~
- echo 'dog in dog!';) Q3 I( @! U; ~& c. D: {6 \- g9 G
- }* B) E( \* `( S6 ^; }( a3 l
- }
6 j2 H& K! F: t/ W& c
6 E& e5 f) \ f! e& s' a- namespace animal\cat;
( J0 n1 w0 [7 B! C1 m4 x
0 d% p4 {4 p9 |; F- // class Dog{
1 n. a1 @/ V1 j/ ]5 } I, |( c - // function __construct(){$ @0 @- q" H: b
- // echo 'dog in cat!';8 C8 z5 y9 I% }( e+ q& ]$ ?
- // }
. o4 J3 o. `' O - // }
" Z6 k( V" M% {4 [! |( a - class Life{
3 `0 {3 U* D, Y1 d$ e - function __construct(){
! Q O( |* q# G4 P# K& C5 U( a - echo 'cat life!';
$ F# J/ ] T# u# f! P - }
6 u, ` X2 z7 D/ ^9 ] - }
3 m N6 S! P5 j' Y5 P' \" [. X g - ; m: @; |2 W8 Y; M1 ]2 {" q
- use animal\dog;
" a, V; O0 {, @- J - new dog\Dog();
复制代码
' k+ r8 x& w# }* p* o如上,使用了
. x* O E# M" o* G2 ]cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 $ O/ R2 j- j8 m5 n4 x
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 , N# o" E+ U- V4 u ~
- Z; H8 u. w+ d
% D3 o3 q. _' t8 Z3 [: Q. K9 M/ Q6 C+ ^9 S$ K6 y
, ~& ?8 ?2 O8 j% I7 g' T: M |