以下皆为本人自我理解内容,如有失误之处,请多多包涵。
6 {0 }: B& `. ^; m$ J文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 ' z$ p' o! N2 A- R( i
! G+ O% w( E" e( A使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 6 D3 p8 x! Y7 X8 Q4 `& @. ~
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
; s. Y5 v$ r' s( ]9 I" d, {结合使用方法来进一步理解它的使用目的吧。 1 a: N; a% |& K
6 ]: V5 w+ F! S% Dnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
3 R& k0 d( u- c% j$ I7 o4 i6 n6 |8 i+ e - namespace One;" g8 d$ F9 ~! A3 p4 y* T; |
- namespace ONE;
复制代码
# r1 C" n1 z j8 q% K8 C如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) ( u2 z2 B$ y2 N
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
4 K- X6 p9 q: z, {+ _; f, g1 j C - class Person{2 W4 b. M5 g8 U& {( j
- function __construct(){
% i2 m4 h9 q8 n) { - echo 'I am one!';" @ p; ]) {+ B c9 {! H
- }
7 l& Z' L8 W1 J X - }
复制代码- //name.php: E' `, G1 Z2 w( }
- require_once './1.php';9 I- _; C0 E, S0 I
- ) x7 q8 X/ J7 j; q' y; U
- new Person(); //输出 I am one!;& v G( U* c3 J. x E. K( N
- new \Person(); //输出 I am one!;
复制代码 ) K$ P3 R- o6 C$ o* z7 U- ]0 W8 S- n
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
+ S& @$ t( t7 R* }4 D( m - require_once './1.php';
" a! N+ v g+ B% [' J2 T( y - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 % G+ N' ]6 h. V" Q: {. X) ?
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php ; V/ a& Z( ^/ ^8 x( A5 y
- namespace one;
" F7 ?) e% s6 V9 i/ O$ O - class Person{
7 k' C: V7 r" t4 v* o. c1 o7 Y - function __construct(){- }' V9 c2 k2 o: a
- echo 'I am one!'; C2 m) V5 r _9 O) O
- }
U1 ^0 \7 j+ p6 c' g. X" T/ V - }
复制代码- //name.php/ t5 Z0 z A: h7 |& o
- require_once './1.php';
& u& E+ e& F- K z - new \one\Person(); //输出 I am one!; I4 x) h3 F, ~3 w4 K5 |
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
! B/ q @# Z) y+ v& v* [可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 % x$ @' b% I5 r: E( D
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。 {: P, u2 G# I* ]* { d& v4 x' g
- //1.php 8 q& T( f& f7 D m$ |
- namespace one;6 a" m3 O% x! b; X4 W
- class Person{
: w# | o" \. A V Q9 u8 q - function __construct(){5 `# I7 p! I4 O' g0 Z$ L
- echo 'I am one!';/ V7 }0 s3 ?( f+ B
- }
' G+ T# s u3 F0 {$ M) x! G - }
复制代码- //name.php5 e3 ]; T# J; V) \! b& D6 K% [
- namespace test;
8 Y5 R" ~) ~3 v2 g4 H - require './1.php'; 4 ^ F1 _" V6 x- E. |2 `; o7 G
- new \one\Person(); //输出 I am one!;
/ v j3 t2 M+ g1 g# _# T - new Person(); //这里结果会是什么呢,猜猜看
, ^* s( o8 o$ }9 F; m2 Q - 最后一行结果报错:
2 t0 {* ]6 k8 b, Z* @0 m; T. N - Fatal error: Class 'test\Person' not found
复制代码 0 i& L& |# G4 ?
3 Z( }; b1 k) X6 s/ l, ?" G
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 1 Z) I! b v0 E1 @1 k0 W
结果报错: - Fatal error: Class 'Person' not found
复制代码 % @- Y$ K: Z" k8 o3 J" S
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
! U8 e1 \' O+ H/ i7 F" L - namespace test;' {% T8 y/ ^" b9 l; b$ a7 w& A
- require './1.php';
" \# G, N4 [# |, i, F# s I - 0 G' \% k; K: B4 t: s
- class Person{% Z1 D1 l8 ?) l6 z
- function __construct(){. ~% T0 [8 y. q* Z6 A
- echo 'I am test!';
" ` ]3 f' z, r: _+ h - }$ S9 n" `1 R$ p4 S* Q$ R6 Y
- } v: s8 X9 k; ]5 ^4 L E) z
8 [! E- g: Q% Q% H d7 U% a- new \one\Person(); //输出 I am one!;
! B7 e0 }4 O; Q+ j8 N0 v3 e0 e - new Person(); //这里结果会是什么,自己猜猜看
复制代码
. J9 i. R7 L2 P/ V* {" n% f最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
* i' |+ h8 j \# H( c ? - namespace test;' A. B6 q- t5 n5 H# l
- namespace one;9 e" q" j1 U0 t$ j
- class Person{
6 J) g+ i+ Z# G- `0 U1 d - function __construct(){+ G3 D* e. Z2 ?5 @/ Z
- echo 'I am one!';
# N2 Y& L$ R. I9 e7 j5 Q - }
+ G9 {8 E6 I' _9 A - }
1 E& X+ M1 Y% r* R. |! ]4 u
. S. }: Z u: {1 \6 `- class Person{ p; J; M' }5 x# a4 \0 F
- function __construct(){" i n$ S/ C. Z8 L: G' d% D
- echo 'I am test!';# }# `2 }( r* J) [8 o7 c; G
- }
# O/ f8 F6 K) k/ b4 n# {5 u - }
复制代码
) F9 b( \$ z8 \; T无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 2 v9 |8 }* Q# c
看来简单的把require理解为替换,在这里行不通。 , U1 X6 a- y" K9 E
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。8 S, b: c# A7 X6 I% v% f8 V
- //name.php
( O* C' m' C8 U- F" b0 P) B - 1 n4 t; m% c ?' z# `7 B
- namespace test\person;
2 x9 O4 p0 M" o4 y$ r& k- M - * e& ]1 l7 s' G+ @
- class Person{
* T/ W {( s5 f7 g4 J- a0 V - function __construct(){
( y3 ~- ?+ z8 T9 l: B - echo 'I am test!';4 V1 |+ f5 j1 u
- }- E0 @$ r9 o5 O. ~" c2 O
- }
) A+ m/ | f; h, G - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 ! _% l" H/ q$ J1 u$ t4 T' Z
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 6 h6 q1 S: V D# v0 Q& W2 R
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
( t; Y0 R+ f9 j# J8 P [4 d/ r- g& U - 9 s; H' T5 {, R x/ Y$ O$ M3 A
- namespace test;- `4 [9 D- b3 }4 L- A! I& I1 t3 U, S
- echo 'zhai14';* r5 W/ T* Q; C3 Y+ m( m$ i* {8 T
- namespace zhai;# y4 G9 Y6 O3 v% k
- require './1.php';
复制代码 / u3 C4 l7 n: J" R9 ^2 M
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
: U' N$ ~4 T7 n9 b! d suse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& f! w1 n! ]( X& Z- Y- //name.php
2 ]* ^ o/ e& {) O0 u - % Q( v. K5 j9 A
- namespace animal\dog;
. K7 f7 ]2 ^4 a/ S$ P - b& D8 v1 N7 v1 V; |/ G
- class Life{
8 G9 C( D$ ^) u# W% I$ i. r - function __construct(){
% j) d& T) ^. s T; ? - echo 'dog life!';
. o5 r' o- Y9 F - }% F" |# @3 f) e) `3 h
- }0 @; _6 H9 ^& }' ?% ^5 M/ M
- 2 ^, u1 R: Z2 m' P9 ^6 I: `/ J
- namespace animal\cat;
$ a3 p! x5 p1 T9 g7 J - % V# C; N/ t* ?0 T" k6 G. C
- class Life{
, q% K3 ~6 l8 F4 G+ q - function __construct(){$ f( b/ F' b- g! h/ T4 O% c
- echo 'cat life!';
- r& P7 O' r% F% E3 {2 G' P( X - }
( @8 R9 r# ^+ r1 Y+ c - }/ q8 P2 |( M0 e% J7 [0 \0 v% f/ R8 V
/ K1 B3 M: |! }7 u! W- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间* ~7 _' h/ g2 d7 F
- new \animal\dog\Life(); //A- |) P# ]4 ^' m: |) l+ L3 _2 T- H
6 u$ m, [3 X# t# n- E" P- use animal\dog; //a
3 V+ f0 ]! m0 h( E9 H - new dog\Life(); //B
4 U) e! h+ o7 F+ k8 c3 t9 x
; d! M$ R' t$ T# i& x9 }1 t- use animal\dog as d; //b' |/ Q- Q( L9 L& {- C# J1 A
- new d\Life();
复制代码
, \% r- l0 k4 q, ~, x0 |" Z( Q4 q通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 9 O8 ?. S' s( V! I# j
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
7 k6 V4 t( h! l: P' Y; \相当于 : E' `! B& H, [! t5 p
2.namespace后面不建议加类名,但use后可以。
0 ~ o' r- s" W1 Q0 B. M: K7 Z- //name.php
% e* s/ s- w- G% k - 8 U. N8 R5 K' B" v" h
- namespace animal\dog;
2 @2 h& h# l5 `/ E4 h2 e2 H; W - * V6 W# j y6 U- f# k q2 h
- class Life{3 z2 O- \( T5 f5 y
- function __construct(){$ C( E; }. b/ R1 o. ~
- echo 'dog life!';
7 d' C6 d5 H1 e" y& C! A- C - }
' M0 \% m. L( o i& e1 z3 d& i0 M - }
+ u9 G, ?- ?& e+ Q
, l# N( F. c2 {- namespace animal\cat;# q! G/ g3 A' ?: {7 f5 g
- 8 j9 ]& c9 |9 S
- class Life{
8 P3 m0 u, R9 E3 @+ [( Y - function __construct(){0 A2 n! A$ F5 Q2 M( b( D
- echo 'cat life!';
5 z0 A; c9 [& M. i$ m# ^5 x& n/ N, v: e - }. s0 k; m' o5 G* I: m% O
- }- {- D# d7 y% f0 r8 v
R& K c! y! a' N- use animal\dog\Life as dog; # `0 X$ R. ?; I" e& _
- new dog();
复制代码 ( b$ h+ g! g- v3 F
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 6 u* V0 V: I; r. I% M h+ j
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php) J; ~: \: t, g. G
- T& j; ~/ h. \% {. q5 ~9 m" w- namespace animal\dog;( S. J) E2 ]; [* A
( B7 W! K+ g- k5 q- class Life{
* g- [& b1 J4 J; N# M9 r1 `! I' R - function __construct(){! c5 g( Z/ P& y: t3 l. @1 ~
- echo 'dog life!';9 G! V' R. C0 l& L& m5 a3 |
- }/ R9 a W/ a: s+ x! H6 k: h
- }
3 z0 ?) a; V4 L+ Q& z8 K1 [ - class Dog{
8 { Q6 y7 C/ J' u/ R - function __construct(){, p6 e6 ~% w. R
- echo 'dog in dog!';
1 f3 {* y+ C& Q* m* B6 e6 i - }
# x! g1 l7 I `7 ~# M' t - }
6 n9 w3 _2 O" i3 i: y. \ - ! W9 }, ?, d& z" Z' j
- namespace animal\cat;
1 F/ b, \8 |8 b6 T% h- E% g& J3 B - - Y! W0 X7 W* E4 l# b
- // class Dog{5 q( D2 d5 e! U. y5 i4 K
- // function __construct(){
/ p8 @" ?, @; F0 T - // echo 'dog in cat!';( A: ]1 N" ~) O' d: x
- // }
9 o( _. c/ R1 v. c0 P/ l% ?. h - // }8 Z/ y( p H7 X
- class Life{
0 _' `# {7 G( j; t( J; M d - function __construct(){' Y( g O. v' u# }$ @
- echo 'cat life!';0 [ f% ?; W- L, G- V1 Z; C
- }
7 R+ E0 p/ O" C: k* D - }
/ h* V2 ]" e7 @" {4 x$ w$ k
2 @( F% [% [ w- u8 ^* [, }0 B& ^4 B7 j- use animal\dog; ! N' i; z. |, y. l
- new dog\Dog();
复制代码
9 ?- I0 i* S+ p) c1 W+ Y如上,使用了
6 t+ A: f, ]1 dcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 7 _# k7 q% f+ a- k; i
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
# ?+ T8 y* Y4 J+ M& g, V( J y* ^3 Y9 F& ?+ U" p/ c( L
3 ]& g) i3 o- }( s& M9 ?
: ]8 O. s( T$ ~/ |) h- X* c" k& D2 t
# H5 Q1 H" X0 C. h" L |