以下皆为本人自我理解内容,如有失误之处,请多多包涵。 * C& l8 @& U2 @2 S
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 ; W% a+ @, q$ A
9 R( E- {. c* a
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 3 W9 ^+ U( g9 x* ?# S3 E
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
' l, P: e2 P7 U# a6 K结合使用方法来进一步理解它的使用目的吧。 ) j- ~9 J. ?* Y% A6 P. [
; J) g0 K2 Y1 [/ A+ J _" y* Q
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;* |; e" s7 p$ s* x
- namespace One;
! ?+ x5 E+ d# ?' M5 t# b! q - namespace ONE;
复制代码
. C* B9 {/ y2 s) t2 a2 e4 Q如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
0 F! v4 E7 U1 `* T, }2 i2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
( k0 {! `1 B* A! ~6 A - class Person{' h2 s2 _5 V' \( x: d
- function __construct(){
2 n* [1 v) w9 g6 G; Z+ P% ~2 f6 X P - echo 'I am one!';
. k5 B0 ~8 m; U& m9 u- C7 V$ F! Z - }
4 D" e/ m+ ^/ `- [( v/ c - }
复制代码- //name.php3 y6 R( b0 D, ]( X5 ?
- require_once './1.php';
- x5 u9 o* c- R# p
" V; [) @% r6 i2 t4 p2 ?- new Person(); //输出 I am one!;
6 r3 G z4 f& {% O( V8 |" Q0 F - new \Person(); //输出 I am one!;
复制代码 8 `+ a* D/ V; O! `, o! {9 R, y
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php0 H* @" a$ u0 w* V' x7 H
- require_once './1.php';
% K7 ^# M A j) S - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
/ T& p' x# A6 G5 s) v8 y4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
" H! W2 u& a- u% v - namespace one;
' J3 S0 U: S4 S" I - class Person{
1 O8 `4 i" j( f - function __construct(){
- Q! k2 \) X: L+ r( X# Q" g0 T - echo 'I am one!';
! R+ Y: \( P& ?3 ?$ p& V0 `8 o - }
7 z5 `: Q0 o0 [3 F( }6 f - }
复制代码- //name.php
3 r* _: G! a0 N" ` - require_once './1.php';) c2 e1 r% J! u1 i
- new \one\Person(); //输出 I am one!;, O# ?2 i0 n) c, ~8 ?
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
! j$ X% ?$ u2 H可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 0 d0 S% T; L3 q2 R% G5 j
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
* j8 K0 \" c5 d: r$ z- //1.php # G& I Z* A% q+ Y$ J+ ?% ^% B
- namespace one;7 D7 I1 [0 A- Q: V6 r: U
- class Person{
* W7 Z& t: N/ @4 U - function __construct(){7 e# T7 u: P7 {! R
- echo 'I am one!'; f3 @' z3 h3 m* f: A$ j
- }
4 G7 y+ ]! F3 O6 v7 C, F - }
复制代码- //name.php
0 ^, O0 T3 r" W1 g* H4 i9 V8 e - namespace test;
9 a1 n4 v- ?2 D, u9 J# m& B, ~$ } - require './1.php'; ; ]* g/ B$ ?1 L' }! w
- new \one\Person(); //输出 I am one!;
; D% L; a) e) {+ y- `1 L" [ - new Person(); //这里结果会是什么呢,猜猜看
z3 n6 n5 N( U) n - 最后一行结果报错:
I/ m* D! O0 U+ T! a0 M# ~3 X - Fatal error: Class 'test\Person' not found
复制代码 9 ~7 A4 C2 K0 H: }. m8 I! E1 O
* I: \8 z8 u8 t R
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 5 d6 r( `* P7 a5 Q
结果报错: - Fatal error: Class 'Person' not found
复制代码
' J7 ~* \0 h% F& q. V接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
# \ a9 g6 M& a( m. V$ u9 K - namespace test;
* ?. \5 F& h% W4 q- n0 A& _& ^ - require './1.php'; ' z$ b$ Q: Z3 ?) C3 a9 p) J7 ]0 V
+ u# V4 c" d4 [5 ~- class Person{
5 Q$ e. c0 A4 @( {2 } - function __construct(){1 R) G: M! [# x+ Q, i4 ~! R$ N
- echo 'I am test!';: U3 R) K6 Z; V4 O I& d+ l5 Y1 W
- }5 x' o+ z/ t- f4 s1 {, [$ G
- }0 ~- E t, h4 E Z1 Q/ H4 z1 d
- % z# L- I, F4 }6 }
- new \one\Person(); //输出 I am one!;. [+ h" C2 l- w& m
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
* _5 b0 ?$ |3 h9 k* F最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php: i. E) P" S! J2 p2 d
- namespace test;; ?% L- y7 I) k. [. u, e$ b! q
- namespace one;6 w5 u7 f' P3 `0 \3 Q
- class Person{
# y3 C' w# f! \7 l$ @. r - function __construct(){
2 B8 N3 g" A8 I* O+ Q - echo 'I am one!';
! n' W' M; G( Y9 P4 [) p - }; _/ U+ b2 d* J- R4 `
- }+ v0 o! S: R W( l. _% }+ Y
+ ?# v7 f/ L- t8 |- class Person{
) j7 }0 `' z: P, y' ?3 M$ S' I - function __construct(){' o6 V. s4 P' p( A5 ]: p2 x
- echo 'I am test!';
6 ~6 s# |- p' u9 Q - }
4 j: T0 Z6 Z( v4 s- E" H - }
复制代码
; b$ F+ \. l5 O" m无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 8 m0 ?0 r, p7 _+ Y: y
看来简单的把require理解为替换,在这里行不通。 ]; P% ?; I! E% a) p- t3 K# ?
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
H' u( y5 g D: N1 o8 ^4 d+ l. M- //name.php4 D( D' @( t9 Q( S7 y1 b, A- p1 n2 D
, Y) O( S9 Q3 {0 H- namespace test\person;
, s1 U0 a/ ?' S( o3 K( s - 0 A5 s& X; Z: t
- class Person{4 F$ N/ d5 n# R" E% D* Y) o) U2 ?
- function __construct(){
& T5 q1 B7 D7 | - echo 'I am test!';' j- \/ S/ p5 Y; n: Z% g# F
- }
6 i' O, v( x/ Y" V2 {# d - }7 v& r# ?* P$ o, ~9 E1 X0 m
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
& U L2 p, G" L* m3 E" ^7 ]6 T5 M4 {不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
1 [4 I; u( U, ?+ z+ F# m/ x7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php) U8 l6 c. w; P* O% M) g
- 1 B( C4 S- P! m2 e6 |6 k
- namespace test;4 m4 h, R3 b5 g0 Y
- echo 'zhai14';
2 c2 |) s9 }( d$ S - namespace zhai;; h3 Y9 O: Q& t/ k+ P
- require './1.php';
复制代码
X9 ]1 }$ X+ [ yphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ) U5 I+ X( u6 a( ]( @
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。$ u/ E0 v- s9 o2 L' Y1 @2 g
- //name.php n8 i9 m( n0 O; w% z m# W
9 l% W; W* D7 w, V- namespace animal\dog;* M- W8 N" w f! h& @) {
- $ p1 V! ~; X& B& b- u N8 f5 K* `
- class Life{& Y) S1 @, S% [ w3 g- _
- function __construct(){
* D1 _1 B1 b, B1 `# @/ s) p* T3 A - echo 'dog life!';8 Q8 S2 B' q, s, t' E* ]3 D
- }7 D/ V! }3 a8 e4 e5 I+ R
- }
! i3 K$ u6 h+ l( t. ^0 @9 t
6 q1 M2 K; a1 u7 ~; G t- namespace animal\cat;
* L2 k# ^' ]9 e; F: H5 |' V+ ]8 Q: D - 3 t r: m/ s/ F% I& R) x7 \. \
- class Life{
7 d9 R- l2 Z& Z - function __construct(){" [# @, o3 m- O. R( q
- echo 'cat life!';
; H; Z3 ` ?9 E: ^( H - }
8 |& I$ i6 l8 F* P+ y% i - }
+ ^. o. R4 u$ f, x7 Z" Q
$ B3 q% Q4 }. O5 R9 @! @+ O- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间* H* A; J2 L! j4 _& Z) l
- new \animal\dog\Life(); //A. v& z, T) R5 p. s
, h( f. q9 g; D# y' p0 _* V- use animal\dog; //a
7 A7 {" m* M# i J6 B( }7 x2 a( S - new dog\Life(); //B+ q4 G* G9 }9 x4 u9 z+ E
- % b! U9 R0 X) d/ n
- use animal\dog as d; //b
2 C$ S9 \. \5 ]/ ^/ y+ e - new d\Life();
复制代码
+ ^9 @) g5 V, f5 X通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 8 T) h& d. ]: @) v& O# D8 E
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 1 Q/ K: Q8 v- M& K$ B
相当于 , S# Y6 e' L8 d9 X# S' j
2.namespace后面不建议加类名,但use后可以。. Y! n: P% k: i, C4 i
- //name.php
, L l' z, e' h% }2 \ `
5 K: `1 a j+ U1 u6 {/ t M7 z- namespace animal\dog;% Z& K7 L! [1 Y" j1 x$ I
- - C5 h- \) C2 \$ p# Q+ R
- class Life{
9 `* U) M/ ~3 u5 O7 I+ \ - function __construct(){7 Q$ D, o2 [2 }9 e' n
- echo 'dog life!';+ |- Z- D, v6 b- |. z
- }
6 p! n& J9 v/ p ^ - }
! O' n) m8 K- k5 ] Y
0 T* Q! K, ?9 g' Z, _; I- namespace animal\cat;! P( }# D( ^2 z4 @; H/ }
- + k! ?+ Q! x- ~% u
- class Life{
W/ H# [3 x& u+ l0 U5 A; H - function __construct(){- ]: m3 f( r' o7 y0 {
- echo 'cat life!';& V+ w7 V9 N" E; ^% ~
- }
7 x8 g3 r. @, h. j8 x3 \. Z - }
2 i, ~' b; o7 n - 6 t' D3 H4 `& X
- use animal\dog\Life as dog;
2 ~ [- p" W7 p/ S- r - new dog();
复制代码 / I( J: @) C7 b4 ~; R8 y
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 3 ]: M: h3 ?& Q6 [, }# j6 x) b
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php- V& w& s; \! I
) H3 p q4 h' t0 @- W- namespace animal\dog;
' e! f# k* @3 Q9 J+ {0 d" r: W: h, f - ; s2 o* i2 K& z4 x
- class Life{
# M; G! m5 o% {; T) \& [( C - function __construct(){: H: o: S& K! N+ Q8 w3 {0 |
- echo 'dog life!';
3 h( d, ^6 L" C6 i' n - } r3 ?9 |, R& e' ^- b
- }, W; Q. c/ e" ?, r* y" D
- class Dog{
i5 b8 V ^$ I2 L - function __construct(){
3 _8 F! `2 r [/ Q7 o! E8 } - echo 'dog in dog!';4 @6 \. m. U$ v2 W7 M- y |7 F
- }
' V0 R) `0 f- w: e1 s, d - }9 g8 G _" U0 c6 _
5 s7 n! m% r& V9 D) Z6 ~' j- namespace animal\cat;
& M5 K' L3 |/ {1 j - m: I! F2 |! Y, ~6 J# m, l8 w
- // class Dog{
& J/ y7 U, d. h. \7 A2 ]4 T - // function __construct(){; C% e% l: N! N
- // echo 'dog in cat!';
. F# s/ H- p, N! l$ ] I8 }8 } - // }$ J) m. d v) ^
- // }, b" P2 A* r+ U1 O
- class Life{
1 x+ I6 n$ h% o& y - function __construct(){
e. k0 [: H( p! Z; h - echo 'cat life!';
) M8 W' {" e e# N0 S0 ]3 _; F - }6 T3 v) Q8 H E) |' G
- }0 a1 H$ y3 S h* S8 ^* {0 A7 `
- 8 Y+ j, ?+ ]# [ l' E: k' V
- use animal\dog;
* _) a5 X- k; Y% J: H, Y - new dog\Dog();
复制代码 " l0 W# J: R+ v" y7 y0 ^
如上,使用了
0 g. m% y, z6 Rcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 7 j$ x0 _, L2 g% U. t3 x' V; z
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 2 g$ _: M" j$ ~7 z) t8 r
3 E/ V" j; C5 n" G1 p4 T# d7 c- i3 B1 |) ? p4 n
0 @3 P- M% C7 u9 h* J2 |% u
/ N" M+ u& r# ~, K1 u+ p |