以下皆为本人自我理解内容,如有失误之处,请多多包涵。
4 s7 X+ X7 J; @1 R" Y8 T文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 - v k# ~( @$ ^& c9 K
7 P0 M; w) m+ K& K. _
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
6 g6 F4 L5 K* S9 `1 M* X据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 0 m* W& Y2 c: E/ r3 L, e
结合使用方法来进一步理解它的使用目的吧。 7 K4 W ~* _7 H) z, |' Q$ z5 U% ?# a- {
$ s E4 E* [' i' ?
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;2 {5 p, w% S0 X
- namespace One;- u, V/ U( L, q6 l% u* P. _6 O
- namespace ONE;
复制代码 * T2 b+ B" y2 F$ p" l
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
; V: L" m7 G, ?2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php " }( a# @, G1 ]; `) ^: L
- class Person{
' a4 T8 {8 n; s* u( u+ U - function __construct(){
( S$ v- K( G+ v& Y+ [ _6 S& J - echo 'I am one!';
, R! V% C6 o" y( v% E/ K. g - } K, B6 v9 {7 Z7 R! y+ P
- }
复制代码- //name.php
4 S/ g$ a$ F: w z( M+ i - require_once './1.php'; v% F+ V7 {$ [1 _
& M6 g6 W: ~- Q1 f- new Person(); //输出 I am one!;
/ O& Z0 k& u" C; ^ P* f' t% j$ w - new \Person(); //输出 I am one!;
复制代码
( X, w0 \* w7 P" Z. @% ]" H( k3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
& [- I# @* s! L! ^5 \ - require_once './1.php';
8 n9 d- k/ l5 l8 o" t6 Y; i - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 6 a. e" o: ~4 _. J
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php % d# {/ r& o5 i( x. m+ A3 d
- namespace one;
! i1 |- m0 x, O L3 [ - class Person{' h- n% E& _7 H
- function __construct(){
/ ^. R$ w4 N6 i9 H6 j$ L - echo 'I am one!';
1 O2 K# l/ Y. F7 j+ `" K - }
4 J6 f7 x' K u - }
复制代码- //name.php
* G; F) O* C# I5 v- {$ r. {( ] - require_once './1.php';7 G* w, z1 o" h
- new \one\Person(); //输出 I am one!;6 k2 q; D0 D2 v; y; k
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 % U8 o1 R$ V; U' w3 i
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 # F) O% r3 a" _& D! s7 `
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。4 K$ `, T0 d( k2 F5 q$ p
- //1.php
* _: g2 C' X9 P8 b& n: c - namespace one;) i' b$ p4 L! h: e* M6 @7 `
- class Person{- |4 s6 ^4 r* U5 T8 e
- function __construct(){
6 S9 [7 \3 R# t7 a - echo 'I am one!';
$ S3 F# p6 \$ d - }
& @ _ b+ N U+ K9 Q - }
复制代码- //name.php
# e. B% L% X0 w+ w2 d - namespace test;
+ E- v& |. j- R7 @ - require './1.php';
) c' s" M$ k6 |2 f# _7 r& z. o - new \one\Person(); //输出 I am one!; U1 S4 T; N4 _2 d) |) q0 S3 H
- new Person(); //这里结果会是什么呢,猜猜看5 O+ i4 U# L/ \2 B
- 最后一行结果报错:4 W6 w% P: r$ C. P6 [
- Fatal error: Class 'test\Person' not found
复制代码
' m/ C( L9 c6 e3 X6 T
. r: @# k, l& N首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
6 T9 \/ ^5 D- T% `7 q7 `3 S结果报错: - Fatal error: Class 'Person' not found
复制代码
7 k" T; y A1 E接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php% G; E- b) ^9 F7 c8 f# ]
- namespace test;
* o; ^. O# ?. F% _2 ~3 n - require './1.php';
" f5 c' A9 j2 D4 P- i - ; \+ G0 k, i. U! M
- class Person{. j. t* E* j7 N8 l- Y2 X$ [8 P
- function __construct(){
7 I- c# w: u+ m& k7 P% L8 E6 K - echo 'I am test!';) U$ R) A' R8 |; _' U: A
- }
0 T4 ?7 T3 E3 ? - }
0 ^6 h: O6 a& i% L- v, \+ q4 P8 S - 9 P6 |9 I+ j% k/ R
- new \one\Person(); //输出 I am one!;: I; }% P$ a6 i9 s' h2 i3 z
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 4 H5 ?) ?6 q/ Y% a5 E% C# x% Q2 H% J
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
6 v' P# L5 J( L1 C - namespace test;
; ?# o- n, R/ _ - namespace one;
* [- e$ z" V( K7 H- P0 T - class Person{" T; \8 ?, w- [2 H+ J
- function __construct(){" L6 [% P( z$ X+ K; D+ ^% X
- echo 'I am one!';: r# v: U% Q E$ V% K
- }( Z+ l5 z' m) E7 Y0 u3 }6 c
- }
, \7 b: C. c% }: J- y$ ?3 y - $ m/ C4 I& M% J# Y
- class Person{/ y2 m' S& S" f7 e. j7 ]
- function __construct(){" h7 _7 A; p+ b+ i% I6 Q2 z, ?3 Z
- echo 'I am test!';$ @7 c0 A; @6 o! A$ I
- }
/ H: N- A5 y/ g* H9 h - }
复制代码 " ?0 d1 t Y6 i7 W! m
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 - \2 w: H! o8 v$ ^
看来简单的把require理解为替换,在这里行不通。
+ K& E. i/ ^( F1 ]( J1 ~4 f0 k; P6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
# |3 y4 K5 V7 C5 r# j% v2 d& |- //name.php) A: L i3 b! J( L3 {# b, `! U
- ^' a+ p/ H6 l0 O: O4 |7 j% G- namespace test\person;
, j1 M w( \# G0 x) }: ~
' Y/ [6 V( w) }- class Person{
: W" ^$ M* h% ~0 P4 @& `0 c0 L - function __construct(){
4 F4 @8 \" k, _- L - echo 'I am test!';
6 [- f1 M* w' ?" Q* J - }3 o. x& U8 P4 w$ L8 a; A
- }
J# p. \+ k3 F8 F; _# ~ - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 % G; |) z3 k0 d6 i' K( n
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 ; w. }/ R. o# J5 \$ o% u* D: h% z, N& t
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php V# z6 X+ b0 S3 A4 c
1 I' Z& A2 {8 h+ o# e; K- namespace test;/ d# L7 |. s. V4 @7 Y" m% q
- echo 'zhai14';) `2 ~) z8 D5 x8 T9 K! T2 V5 ~" _
- namespace zhai;
( J; a4 z; d. L) @% ~( y- F - require './1.php';
复制代码
1 j! z# f; f0 V/ m: V) a% Dphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
# H# e' ^9 U M2 ?: ]* w8 v1 s" ~use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。4 T5 X) \! Q8 j' L( E, n
- //name.php* W5 f" D! C7 i4 A# R
- ; F, V) f& V, ? K$ J9 ?
- namespace animal\dog;
- M6 |0 o( ^( I2 U - 3 h$ D/ @. E1 I+ R- u
- class Life{
* v& D" y$ x" h; H1 O - function __construct(){( k6 N* ~4 y( b4 k' ^7 V( ]$ j2 J
- echo 'dog life!';+ x$ U9 b* C% i: L! x {
- }4 V# }8 L# Z' J2 r$ H4 m
- }$ n+ S+ m- q$ e- d9 P. z
* [, z K! o9 h, s( w( ]- namespace animal\cat;, |3 K& k( y$ s& Y5 n$ K+ y0 O! U
$ u5 R2 t4 }, f$ |' E- class Life{" A- R3 z& B' @; |2 ^: r' y* p+ ]
- function __construct(){
" ^: {: I2 c8 `6 I - echo 'cat life!';
% Y9 s" b( U2 V - }$ `9 p4 B% d8 s1 O9 N/ ~
- }7 ]/ ]$ j6 t% Y" s7 I( G
( r2 s% X' X7 F: u- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间' l2 v( K4 S) _, \0 z
- new \animal\dog\Life(); //A8 s2 B' X: s! x: o- }/ ?
- ! b; D- G* U7 y
- use animal\dog; //a7 c) V6 h, @& V/ p3 l
- new dog\Life(); //B, j' X5 W2 W& B A: F! _
, r/ E) l( Q0 d# R3 s& p- use animal\dog as d; //b
0 g! M* Q# U& s) F - new d\Life();
复制代码
- [ u2 {+ l5 S' G通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
) Q& `1 U; A6 t# ?% i通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
; j9 z9 o) H; S5 J2 `9 Y相当于
7 y! z0 u" k. l. M$ V/ L) e! r2.namespace后面不建议加类名,但use后可以。
1 f8 e. i Z1 s$ Y/ M& O- //name.php* ]1 C o8 d( b
- $ g( [7 _& j; S
- namespace animal\dog;
' E" `3 v! C8 I" V6 n
* i4 o8 J* Y+ J1 t v% K) N2 w- E- class Life{
) Q2 C6 G# X# k! g9 B% B - function __construct(){8 R& v) e. i+ p+ j4 u
- echo 'dog life!';
- N& d1 [; ~+ K } - }; S& X9 Y5 N" s- J
- }" U! \% x% u3 Q: p
/ s0 v, |, r4 v2 g$ s) V& Y- namespace animal\cat;
' X$ q% b; D2 {$ _
o' _/ `1 f% d- class Life{) r! ~3 V/ g5 h4 M8 ?9 j
- function __construct(){
, p d1 }7 d4 R+ }4 F+ Q - echo 'cat life!';
/ n% a. ~$ k; D - }3 t- e& p4 R2 V( ?) R4 n
- }& C3 n1 E; V" p& f3 D2 ?
& r" b4 e, f# ^' ]2 P V0 J" t; j7 c- use animal\dog\Life as dog; , P8 L* t- i# {) v5 m& I
- new dog();
复制代码 # k# A- }% p$ }* \7 l6 l2 }
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
) }/ f7 a: H% a# r* |8 c因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php' U+ Z* Y( q" ?; l2 O
4 E, b% U: u' J" Q, z& Z6 [- namespace animal\dog;
; S* e+ D9 J7 g( Z6 c9 n# u
& y6 w1 ^$ b1 v+ f0 ~# o+ D- class Life{
% b2 [) w$ x5 i7 B" E - function __construct(){: N' G. y+ I% W# ^) m0 d9 C
- echo 'dog life!';- y3 b4 u" U6 n, ^4 i2 l
- }
5 z3 s$ U4 {9 `- Z+ Q! { - }
; N- V* E3 k% @ - class Dog{4 V. _( q4 ~( S0 }. [. c4 ~& l% W
- function __construct(){
+ u1 r! t2 V V5 i' O. ^! {% a. N* b - echo 'dog in dog!';
% Y% M ?6 b7 ^7 X6 T& Y - }' u: n8 x' d, n8 n9 ]
- }
$ H$ k. o( U" Y# l - * z# n2 g/ r* ^" F' M; m6 D
- namespace animal\cat;
, U* t! }* x* B% {: z" T8 x
1 ~4 A# f# R! S9 X- // class Dog{9 y |& L, z+ Q2 `9 l
- // function __construct(){$ ]; }, A6 O( I4 y
- // echo 'dog in cat!';
1 T, j8 [8 s1 f- K, S8 g - // }4 W5 Z4 G$ Q- D8 C8 A7 w% o
- // }
2 L' M3 Q4 r# r/ l' w! S - class Life{3 z% p7 ?- x% V* _) o
- function __construct(){
" J$ ] a2 I9 p2 |: t - echo 'cat life!';
! ?/ t( M& K# a# Z - }
9 @2 n- S6 M$ R5 @: i: \ - }" k1 J4 k% K9 A% k; N5 k. X8 `, w
- 6 ^9 ^5 K4 C9 w% U V/ s
- use animal\dog; 9 i! ?# G7 B# _! H
- new dog\Dog();
复制代码 % j2 X3 p0 l6 \" C# G" O" H0 S1 i
如上,使用了 ! O# C7 Q: c& \/ [
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
9 x% o7 ^+ n) E& s4 K- {简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 7 b/ `9 F) ?: ?4 m3 M* F* o
1 P. d+ ]1 v, w* H7 Y/ L0 {" g
: \* R2 w2 E# C7 E# g, i r% D( F/ f1 g* [% Q2 h
4 @* | F2 i( [: W- P
|