以下皆为本人自我理解内容,如有失误之处,请多多包涵。 % i) p2 M& s4 T' v% h! D' v
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
) `1 N+ x# Q& [5 B
" w/ Z* {/ A! ]# ]. [5 ~2 S! l8 @使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; % l, L) U+ k$ P: ]" s. ?, O1 ]
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) % [5 x/ S1 k) V8 N% T
结合使用方法来进一步理解它的使用目的吧。 9 X! x4 G$ [; x* { d: s
2 P7 j$ d$ } w8 K% H) w# ?+ {namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;: w+ B- b2 B% F/ ]
- namespace One;
: v }$ h9 R- A4 ]3 [3 K8 H7 c: p/ S - namespace ONE;
复制代码 8 {6 S$ x1 f/ U; C* ^2 r
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) $ a; y% w8 A$ ~: A6 e5 ^$ M
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
9 X0 ]" y3 X0 k1 Y1 i/ G7 f - class Person{- s- j! d7 j z
- function __construct(){. _1 o& S; w# X- S5 U
- echo 'I am one!';& ~* n4 v3 Q) T& \( j
- }
) }. `% z; A' M4 t% ] - }
复制代码- //name.php# j+ Z) O+ ?/ J b! E; `
- require_once './1.php';) o0 V& D7 r6 L3 ?5 c
8 s: G9 V9 b+ d" Y8 T2 A0 }6 m& e- new Person(); //输出 I am one!;
3 C: R1 }( P/ y' l - new \Person(); //输出 I am one!;
复制代码
4 K0 t* z) Z* E. _# O$ Z8 ?3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
8 t) w9 ]8 j5 p+ b& e- g8 I+ }) V Q$ l - require_once './1.php';. g" t# L/ _" a9 f3 E/ Z+ T
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
3 Z% F6 @/ n9 r& o0 G4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php # m. m% W& Z. _- B4 R( R: c6 ^5 C
- namespace one;9 p, u$ J$ h$ A( r& H8 A
- class Person{
; o2 [0 d* y% P t! D - function __construct(){
- n$ V' l) U' W. h0 p' H' B - echo 'I am one!';
9 D3 X. Q, U" g7 o& C+ ] - }6 W) A' C+ i2 C: j. q2 J2 N/ O
- }
复制代码- //name.php/ l$ w: E6 b3 ~; d: O( Z) K4 g; _
- require_once './1.php';) D S$ O1 z+ z) N6 ^
- new \one\Person(); //输出 I am one!;
/ y+ L0 m0 q* [8 o8 y2 B& Z+ K2 N+ U - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 * `* A& G# o1 Q, J8 k4 w5 u
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 " ?* [# W9 }- O/ Z
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。6 m9 t4 G, \+ m& |' q& {: V8 S4 `, h
- //1.php , d; H" a3 L" p5 Z4 `
- namespace one;9 ]; R, M Q n' F6 `
- class Person{1 D; [# f ^& o6 I, t
- function __construct(){( L7 R* D/ z- v: q: Y% G$ f
- echo 'I am one!';
" }& H7 x8 [8 L1 q7 t: r - }3 N0 L+ l) N4 \" ` g- F. `& B
- }
复制代码- //name.php2 V9 G c1 ~5 K+ u" e
- namespace test;
! r, h3 ^% Y% N( |; W# V4 h! a - require './1.php'; ) M( _+ H. L0 \! D8 @6 f+ p% P
- new \one\Person(); //输出 I am one!;
. y* F& [; w1 P, Q - new Person(); //这里结果会是什么呢,猜猜看) F. ?2 `, u2 L& s$ H4 s6 U
- 最后一行结果报错:
- B4 l `4 d. [# U - Fatal error: Class 'test\Person' not found
复制代码
3 ^; S0 { ?$ u2 k% h) t/ w
- f4 A: |7 \8 I2 |首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
5 f- \# S+ o9 y结果报错: - Fatal error: Class 'Person' not found
复制代码 3 K4 T" z. w8 b% W
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php- P8 x% |" Q* ?, Y. q/ B' g5 p
- namespace test;
- ~4 R7 D- g9 f- {$ [& E5 X4 G - require './1.php'; 4 r) ^& h3 R' x5 j S9 L4 u
- 7 {5 u* p8 O( E3 l5 X
- class Person{$ ~& L* F5 d6 w* K8 T4 G4 _6 H
- function __construct(){ K4 @- W. ]& G7 b5 ~' d
- echo 'I am test!';% |* q* }1 L5 @/ H9 T& ^+ \* M$ `
- }
! @8 n w9 k1 Q, ? - }4 L4 `4 Q4 p7 f/ {; I
0 a- Z( m* H# ^3 D- new \one\Person(); //输出 I am one!;
" {& l. f6 i" w" A/ v6 U1 d - new Person(); //这里结果会是什么,自己猜猜看
复制代码
9 t6 t( k, p$ @" d) i2 s. ], ]# ~最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php% |0 _4 L* P' ~2 Y" g
- namespace test;
0 L' i8 P2 p X' }7 R( R2 s - namespace one;
* L+ Q1 [3 D/ [7 v6 m. n$ a+ S% L7 F - class Person{
9 j( E4 m, t4 H0 [, p5 x - function __construct(){
- g9 P3 w& _% Z1 R9 B$ r - echo 'I am one!';
6 ^) ]( Y% \0 y, n! N, l* x3 \ - }
( F" N% G. ?7 H' _! X - }7 s* n) l3 L9 x: a* {/ t7 }
- & A1 u2 k5 _$ O( o" N" \3 a
- class Person{% r0 {' F2 e+ o7 _- f- r+ y
- function __construct(){& Q9 Q2 T* n3 w& b( o4 j
- echo 'I am test!';$ s8 n W9 g+ ~, z! t7 i
- }9 _4 F0 l6 R: s2 d" `
- }
复制代码 # d' w% N7 w5 Q& `
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 , |$ i$ o$ a& {! q
看来简单的把require理解为替换,在这里行不通。
3 |8 Y! O: H, j3 b+ A6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。" E: b/ z8 \# V9 p; e6 b0 o# L
- //name.php
# \; {* b9 z r& W- f9 o& v - 4 Q7 c( v) Q2 @* b1 r
- namespace test\person;) H. z' w, z G/ z/ F2 D% ^
- % R& p6 R( y7 q6 j" o
- class Person{( A2 W, a% U4 k1 W* N, c7 W' D8 h2 s
- function __construct(){
3 z' w5 f( |' ^' z$ V- }7 Y - echo 'I am test!'; g8 G; P# [' `0 d
- }8 I: l& g3 k5 }' `$ v
- }& e4 d9 {. t% q$ a4 A
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 + l0 ^. p$ {) @, v Y8 j4 K
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 8 ~, W2 q1 G2 r# q4 f
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php7 {- r9 m. y9 v/ j4 x
- 5 f' u/ Q4 p8 X4 v1 \
- namespace test;: U. B6 T f: n
- echo 'zhai14';
3 Z7 k, q' l- K9 |& F \ - namespace zhai;& v" m/ `$ U2 B4 X
- require './1.php';
复制代码 ) a& ^ P* s% F
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
8 X) Y1 P; C n3 i9 ^8 zuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。5 [5 D" m6 G3 M1 s& n
- //name.php* v" {: D) S! m$ _5 R# f$ W
- % y3 O# R+ x8 j8 R1 _, J6 R
- namespace animal\dog;
% m, k% P6 \: L4 E
$ [: @$ `9 a7 b+ k* x9 F: O0 p! \- class Life{* i6 k |9 K( w6 {9 g; {5 t) |
- function __construct(){
s K0 ], h& y6 r - echo 'dog life!';1 [/ x: C( s7 H& [# D5 `1 F0 H
- }8 l/ D2 m/ ]6 G" D- `6 ^0 F
- }
6 A1 S/ M2 k9 }; ^ - $ s- t- ~, |& T! ~: w/ ?0 T: r
- namespace animal\cat;0 a' {: E1 L5 V& w! v5 {0 ]: a; z2 E
- ' T9 p7 A* P/ \% `0 m
- class Life{0 O& J, [! C0 Z8 A* C, z
- function __construct(){& ~% |9 f1 o- P( q+ ?9 G+ M
- echo 'cat life!';* Z5 A4 u) `& j" ]/ @; }, l
- }1 A) R: G) h& Y V# {- S; W0 H$ q8 `
- }
7 t# Z) L* }7 x) @/ [; L+ `* e M - ! W5 V1 M9 e7 ~7 u A1 M3 {4 U
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
' X% g% L: O2 c' \# m# } - new \animal\dog\Life(); //A. ^& ]" Q7 f( H) D5 S* @4 x- c
, b& t, ^ {& u d5 O- use animal\dog; //a& d. V$ F; p% P3 I! ` b8 ]6 {1 c
- new dog\Life(); //B
( @. c: J% [. r7 J3 ]3 \ - 4 T* ]* { P; x3 z! q1 H! z' n; q
- use animal\dog as d; //b5 J1 V2 H( Y% J* [
- new d\Life();
复制代码
6 s$ @. C/ L9 i通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
! m+ x, F. G8 h% E$ g# }& ?通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
. u0 S( A/ H( \/ ~4 A' @相当于
$ m0 V e- |8 p+ D# F7 Y2.namespace后面不建议加类名,但use后可以。7 Q) J$ n* {4 Q9 j: n8 f
- //name.php- Z1 _ U7 x' T1 x' A. u |" Q/ y1 j
& K1 q. c0 u4 Y/ S7 o- namespace animal\dog;8 T t8 |5 c* ~, ^
- 3 b& y0 N. _6 F
- class Life{
r2 ^2 F0 k# K% | - function __construct(){
2 m% g' r9 U5 f3 f( T9 n }) e& H - echo 'dog life!';' y5 J5 r& g) y; N" B! P0 f
- }9 o. @. _4 }; G
- }
* T/ s- D. h! e% A
$ {$ g7 q6 w4 A0 o2 x- namespace animal\cat;
0 B9 z) c% A3 x5 P9 q. L0 c; S - / a" a( p% ~" f' D
- class Life{& g8 G/ G% J/ u+ U) a
- function __construct(){
& A# J G: q( ]! d8 ^# M5 F# D - echo 'cat life!';
7 a2 a8 J' R* d9 u O - }' M4 I0 A7 i( f
- }
6 i- {+ y6 r+ ~8 z3 R) p D
$ `# a. s$ H) F- use animal\dog\Life as dog; 5 X+ u+ Z4 ?+ d, Q
- new dog();
复制代码 $ L" t: U4 o$ x( L6 f0 O
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 ) ^: m+ k$ h% V. A& N3 R$ f
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php3 ~! C! n0 l8 p4 c4 C
- 6 N. M3 A: D: u. V0 c) V8 m8 f
- namespace animal\dog;2 r( ^! s# b& M4 i+ w0 K
. z m$ _- Y* C# n( T' v- class Life{* J4 t1 w) Q5 ^+ t
- function __construct(){
1 w) N c8 H/ }5 n1 E, k2 Z - echo 'dog life!';/ ^* w- x! h$ t, |
- }
0 H7 T& u# e3 ^$ `: C; ` - }2 B0 D7 R Y- H6 I/ }
- class Dog{
& {: c, `* [/ c. i9 j5 v! |2 U - function __construct(){! z) \! s% V, r% r% o0 @, [9 x
- echo 'dog in dog!';
/ V+ }6 w6 O% x8 F7 i1 _( B - }: A2 _4 C; p$ U1 o
- }
, G {* Q4 S' _3 k) z - , b; L1 H6 m) y3 E, k* P+ g
- namespace animal\cat;
6 d- Q3 s" ]) A; Q2 _% c9 r5 V2 w& p
; U. J' z' C2 s% b+ e1 h- // class Dog{, d& Y/ s8 R% |: D- |0 t
- // function __construct(){4 c/ d, O) s% Q, I) J* s0 T/ h
- // echo 'dog in cat!';9 w7 m4 p3 B/ S& W9 P7 ~7 Z" z
- // }
6 c" f- ~% ]' s `5 }# v) ?; K% N - // }! L( i6 H/ z0 U7 y2 O6 K S
- class Life{
) s5 a. p0 Z, I2 r/ P d - function __construct(){
& \4 x9 d0 K6 Y4 C - echo 'cat life!';
3 h" o u( B3 u# Q. S% D - }3 h# A4 }" O& E3 h1 s. X
- }8 T E) a; a6 S* A3 [
4 f4 h, p) O" M5 C* a2 w+ |- use animal\dog; 9 p: F/ z5 M7 X4 r' q
- new dog\Dog();
复制代码
! b3 @ a8 \2 ?- k# ?2 }如上,使用了 $ _5 F/ i, W/ c) h# S0 e
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
! S; p5 a7 X: V* v1 \/ B简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
5 `- F8 f# @& N' p3 `5 ~
: h% G& I0 ]; _6 Q% n) }+ }
- o! Z0 E) T3 q& E5 d# h3 T% ]5 d. a. r( B/ d/ F8 R0 p1 u
3 m& x+ j ?0 J: F |