|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
+ s, `1 k" A$ C2 m文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
- f- z3 O6 l$ Z+ I8 n" g/ M) |9 w; M6 V7 x8 f1 J
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; ( j T+ |# H6 L, ^
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 6 C2 Q5 z; S* T" Z
结合使用方法来进一步理解它的使用目的吧。 % G: i- C1 v2 T U. X) Q
; K. j' x+ j) N! n
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;1 M8 v+ n6 L, Z& s4 k, m5 F8 Z+ Q
- namespace One;& h3 [8 N5 K2 Y4 x+ `
- namespace ONE;
复制代码 * i; |9 r- W4 `3 }& |7 Y7 {4 Y# d
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) $ ^9 B1 R0 V. {) n3 @! J* }/ O7 }
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
9 \0 X* I% n3 S2 l - class Person{& J9 J4 h/ Z8 z6 Q6 z! @! j/ b
- function __construct(){9 ^, t. B; B1 X {
- echo 'I am one!';
6 ]2 \, j% Z! @* _2 d2 Q; j. ~: _ - }
; h: Y$ G* a8 t6 H$ Q3 X0 w6 k - }
复制代码- //name.php* a! H+ b- E+ y2 R1 k
- require_once './1.php';& G d; u; v. C( J4 z" y, m2 w
0 @3 H ]7 m9 a* T9 }( f" R0 _! ]- new Person(); //输出 I am one!;
" \' t0 M( @ w) [: J. x - new \Person(); //输出 I am one!;
复制代码 8 G5 p0 P' S1 q8 w3 G# f9 U- b, B9 {
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php0 k% u1 h5 Z9 {# r: E
- require_once './1.php';
- m6 A: T/ T4 E - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
, O; Y- o+ L# D& ]& }4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
* z2 k6 ~5 r( ?" ~/ @$ L - namespace one;
5 `7 y* ~5 n" ` x5 o3 Q0 r - class Person{
- i! v! ?1 Z+ o - function __construct(){
2 C$ L0 z. M. d" b% @; Y3 r" ~ - echo 'I am one!';
9 d4 G/ C# z: `5 U - }1 H4 w5 V; ]5 W0 ^- o, e
- }
复制代码- //name.php
. T% A% U* z. m( b4 f' g - require_once './1.php';+ D4 |3 i% n/ R3 t* c7 e; U
- new \one\Person(); //输出 I am one!; S" E" j; S$ C# x
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 % s/ k7 P' J* s: D0 u
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
6 Q( }" @ A! k5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
j% [4 h; Z: z& i8 ]9 n4 t- //1.php
1 b x0 c9 z4 U& u# k3 M; f8 ` - namespace one;
# z0 v2 w# Z. W3 {6 M - class Person{
' q) w5 ~; ?3 O4 o2 n+ d* ]7 P - function __construct(){
3 G9 a T, N# ?$ L$ W - echo 'I am one!';7 h+ m& ~" D" N0 ]5 X
- }
6 L' w) Y' r& t+ V- B - }
复制代码- //name.php
/ T! ]% R7 H; ?$ ]) _9 J0 a# _ - namespace test;
4 |: R8 [- |7 }9 W: s - require './1.php';
1 I6 I& E; g* q ^ - new \one\Person(); //输出 I am one!;/ a4 L h5 k* W8 [- A" A
- new Person(); //这里结果会是什么呢,猜猜看4 r% P3 h7 Z5 S$ ]
- 最后一行结果报错:) ?, A! F P( }0 h4 y- \. O
- Fatal error: Class 'test\Person' not found
复制代码
6 Y5 ~, E" s8 t0 `* l- H- T1 f d) y$ ~- _& b8 Q( `1 \3 b
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
( i+ Y0 i# R) z: {: K结果报错: - Fatal error: Class 'Person' not found
复制代码
5 B4 z' [$ S8 \7 c9 i1 D" o接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php, }) }6 u( o3 f7 T
- namespace test;
( ]! ?) p0 r4 }8 |. |3 Z( x, M - require './1.php';
$ e8 r F* X* t0 y ~8 x+ {
- j! v- u& p0 B: ^4 E2 o- class Person{2 w$ Z# x$ ?9 b" ?2 M/ G" b; t' o
- function __construct(){ i" Z e) n* ~6 U9 o" H5 l
- echo 'I am test!';( v2 W. I& h% ]- y. j8 q5 ]' H
- }, C2 y X' w, R6 b2 ]- @# k
- }
8 k* _) Z V& m) |) f
2 f. C, {/ q+ Y/ z& ^2 P5 M! g- new \one\Person(); //输出 I am one!;
) F" L- l+ w9 g8 i% d1 A5 ^! | - new Person(); //这里结果会是什么,自己猜猜看
复制代码
- T! h# j- k2 t; K/ G/ c* p最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
, o/ l, |$ X2 p# g3 S1 }& i# _ - namespace test;
- Z" S8 o1 [2 H8 a( T9 Y - namespace one;
, t2 E% R: @2 H; O# y$ J+ ]6 |+ Y - class Person{, Q5 r9 [6 M! G6 p' J7 Y; ]
- function __construct(){
5 l9 ?+ \$ M$ O$ b5 K, k1 b: s - echo 'I am one!';
1 L2 W. j- P; P- B, \' h- r - }' S( F5 ~5 j6 k6 k$ V0 V$ \
- }. F! |' c1 ?& G8 F# T
- P8 v, o: t5 r$ b- class Person{! w) h) g L6 N/ R* }2 J5 T: U
- function __construct(){3 [' G1 X- T/ k; {( R
- echo 'I am test!';
1 E! D! j9 a. [) R, ? - }
& G( \5 v' \' E) { - }
复制代码
& \) W: y8 B+ \2 m5 \5 N无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 % \ p6 Z; V5 z! o
看来简单的把require理解为替换,在这里行不通。 ! o, l: J5 A* B1 {% x- h
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
1 P2 Z. r/ a# o2 Y. a% j5 t8 R- //name.php
8 i y7 C) A# x - / @+ y1 G- t5 k3 v
- namespace test\person;: a+ i/ }5 u! ?
5 Q1 P' S5 { p* w9 i- class Person{+ c4 Y# \$ ?9 L% j$ x" Y
- function __construct(){
# T8 ^ A8 @' l R - echo 'I am test!';! J2 f- N& F& X0 q
- }
) c/ u n% q3 n I) ~ - }+ o) k9 t9 g8 o& O! l0 l0 v
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 4 D3 D1 z, Q' L3 Q6 A5 w
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
0 [4 w2 |6 F ]6 s3 C$ z1 h7 s1 J7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
. n7 E4 C9 ?5 [' w: p
8 N" E9 s7 U. }2 F- namespace test;0 A% @ j3 v7 ~
- echo 'zhai14';/ d6 S5 Y9 ]/ j, }+ S
- namespace zhai;5 ]( k! [' a% B) s0 e
- require './1.php';
复制代码 : u' U3 s. u/ G( s% `' q! }; }
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ! t* ^5 G. [) s# d4 z+ F% T) T F
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。+ W6 m9 |, [9 F6 v
- //name.php
" f; |6 r; _7 V9 F* v9 j - ( t( L" N# b8 i1 e; U0 Z" c% V
- namespace animal\dog;3 @( H5 F/ z' J$ [
( D# }( A5 A2 {5 R" Q- class Life{
7 a: V3 }+ \9 n* _ ^' y: t - function __construct(){5 O2 z9 h: r% k
- echo 'dog life!';6 ~1 w# n0 G$ a' R
- }) g9 x5 K1 I/ l& v: B! ^8 A/ Q
- }
- r: T; J! o7 u
+ D7 W7 J0 I9 b7 c. W( ^& v0 q& A- namespace animal\cat;( ?- ~& Z4 i/ x" T, |4 r$ {, Y
3 l8 ~+ R2 c {7 F! k4 U- class Life{9 H( _* o# w" J
- function __construct(){ ^" s" @0 j+ h% p9 g' ?
- echo 'cat life!';: W& q9 N4 c. D/ \: H& S/ I* ^
- }
$ _! A& [/ x' M' v Z7 P N, L - }8 |! P1 G- G9 L8 t4 K* o
- 0 ~' n- h3 h; v1 H' a
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间2 w1 J* `7 X( n# W2 C
- new \animal\dog\Life(); //A
! n# _% E! F" R- o; E - $ |3 [: B& f: a# s/ X* N' ~
- use animal\dog; //a
4 `1 G8 i7 A% d. J - new dog\Life(); //B
9 U: T( ?$ a. U* z9 \$ G
0 _7 Z4 d7 N. f' v- use animal\dog as d; //b
+ h3 v, F y$ g* k3 ~' h2 ] - new d\Life();
复制代码
- K) L, T/ s% `: n1 x7 y通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 & {4 r' Q9 `* e$ }& w/ u4 F$ C, |& _
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 1 W# \& G( }0 @( [! R
相当于 : a0 e8 S6 ~; a$ D
2.namespace后面不建议加类名,但use后可以。8 @! K# Q3 j' o; S3 u, o7 n
- //name.php
& f3 x `" @; y
/ {& C" s5 z1 E+ Y' d- namespace animal\dog;/ k% _ N1 g& m" S6 Y
6 z8 X* q( M7 K8 H1 j9 U% n- class Life{
0 N/ T: Q3 ?; i# O: s* r - function __construct(){3 G' Z& z7 k4 x/ a5 N! d, |
- echo 'dog life!';6 G3 Y( g3 p& v' [! }
- }
5 Y; }5 O. y6 Y7 n; {8 r - }
% y1 u/ m4 O/ B2 c/ _. Y - : m9 e Q& r, `, ^) d8 ]) ]
- namespace animal\cat;
, k: h* c: q7 j g8 i @# W' h - ( k% j& ]- m5 l: V7 A1 v3 l
- class Life{' y4 h: _: h* e Z/ c: j, J3 p; c8 G
- function __construct(){
% t" @ Y# e3 u1 f - echo 'cat life!';
. C l z9 a/ V$ f - }: D& N X6 m2 P r1 s
- } X. l( Z k+ d6 t, Z5 M4 b% K
! B+ O8 m2 Z7 F. Q6 R- use animal\dog\Life as dog; 4 U2 o8 d0 Z6 m# Q0 `/ W
- new dog();
复制代码
; g+ z }7 q% W. `3 n2 P9 A如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 : `2 q; h$ q' L% q
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php4 S0 ]: u3 s, a, c; x
* S6 b+ _! C8 n+ j- namespace animal\dog;
; _/ o/ b' S1 W c) i
, n4 Z) s" k6 x0 k- C- class Life{
) {; O0 }) }# P4 N5 E- S5 {; b - function __construct(){0 @+ J+ D7 B, o) s1 B* O' }
- echo 'dog life!';
$ O/ ?7 N1 I* B( ]5 w) I - }
2 A6 y# X! f5 |1 p. C/ O! f. A0 I - }
, x' }6 `- Q D' d, [ - class Dog{
% p; [8 Y6 l _ - function __construct(){( K* ?4 g0 b! d% ^7 K
- echo 'dog in dog!';
/ J' c( _3 V7 ^) d4 { - }
1 S5 E. i7 c9 B) V6 d% J - }
/ N3 `5 L( \7 @2 `& j
: D$ W4 v3 _* v6 A7 Y z& X5 s. I7 X- namespace animal\cat;
+ g; M- ]( U* z8 @ - , J7 E8 m) y/ ]5 W. E3 A# [. t k
- // class Dog{: z1 e- x+ Z+ F6 p# {0 k2 x: F7 _. @
- // function __construct(){
/ z) B& S+ U. [: g7 { B: A7 F - // echo 'dog in cat!';
/ C# s, `8 u3 x! x; z9 w; H - // }' K. f2 r1 B; A: B4 F
- // }
; Q# r: Q0 T6 n - class Life{
; j u& i/ ?# W1 A - function __construct(){) t2 W# B* S. J$ V% X% {
- echo 'cat life!';: J* E" G# ?- P# M. y
- }- r) S" S& _/ Y4 n D; s
- }
+ _' x) R8 U- D! k$ C7 q - $ j! U0 s& k% {9 V
- use animal\dog; ; n8 J$ J* y% g. C9 Q s( }, I
- new dog\Dog();
复制代码 0 R# g, z% ], [' ] [
如上,使用了 8 s( Y' w( l! p# { t; o0 Z
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 # M) T& H3 ~' t/ ^
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
. m, O# M4 k- W$ p$ @4 A2 ^
5 o9 P* l$ G. Z" L% [
/ d/ y* n" d& q3 G, ?$ k( i' B i) ^4 A
- ]! q# n2 T5 b, ?
|