以下皆为本人自我理解内容,如有失误之处,请多多包涵。 2 e5 c: R& T" c
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
; r6 ?2 N6 ^: U% P- Z4 M d+ l4 b; ^
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; + T( ]/ m+ @, m0 o" s4 q
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
, d5 O, l7 {1 J* [( t8 v结合使用方法来进一步理解它的使用目的吧。
6 l4 S4 E, `; a( ]' l$ O c
/ k8 Z6 h& r4 @5 ynamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;1 q X4 j' h* v: z
- namespace One;
g) n' W% s" b* u - namespace ONE;
复制代码 ' C" i4 c7 |* l2 C4 X
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
; h) |+ y, }7 T1 x( {0 t4 Q% x2 C2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php % K9 E3 a- Q& M9 p' C5 L! r2 r
- class Person{. i& J! i& u1 g5 @
- function __construct(){
9 Y9 q. f4 v; y& J/ X - echo 'I am one!';
! S( ]) z$ A* `. O: v7 c' W4 ` - }
: ?2 ]) f5 E+ v; H" c - }
复制代码- //name.php
% r2 p- A2 M6 U0 ?2 @7 S. |" h' R - require_once './1.php';
1 a* \- B; M7 n( I% ]! s% q - 0 s4 M N, Y% p$ A# j% \7 B+ o% N
- new Person(); //输出 I am one!;
, x. T9 y/ a+ s) X/ F3 g( S - new \Person(); //输出 I am one!;
复制代码
' Z( P- ^/ C% q7 ?0 S: R' }2 |3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php0 K. e, J( B/ o* ~/ B
- require_once './1.php'; Z# m. p8 t7 @8 b6 P% o' S5 o0 {7 h
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 % _. q, S4 e; _% ^% r' |- W
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
7 `. X1 I6 b7 o - namespace one;
' H) {' G D7 i) [" m3 a - class Person{
# k' t2 {$ A- j- G D - function __construct(){
& s T4 F( x6 s; |: y3 s% x - echo 'I am one!';
: v2 h. H# W) [. J3 F5 l - }) Y# Z g) c" C; ~+ i
- }
复制代码- //name.php4 ~/ w8 u7 m7 W4 }
- require_once './1.php';
) a- W) r- v! e" l6 r+ h - new \one\Person(); //输出 I am one!;% K1 }1 `" [; e! F5 ]. t k( ]
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 0 |* \; |& t$ j& n! N
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 / x% A( ]2 H, G7 N( m! }! c
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。% x! k. b6 U* w2 j; G2 e4 q& j
- //1.php
$ g0 [$ V4 C1 G3 P - namespace one;5 A- ^0 W8 O* Z5 ]- m" J
- class Person{/ j' v2 I' z& @8 T1 z# n
- function __construct(){3 h q; U1 I8 ^+ E- _- q
- echo 'I am one!';: C# m6 M7 C6 n8 u# `; {
- }; x4 B! d1 |. J
- }
复制代码- //name.php
2 E$ m8 b/ o4 \4 Y - namespace test;
' k' T0 H' @3 j$ Q5 T - require './1.php'; 9 n5 U/ s, p3 @9 J" c' ]0 o. R
- new \one\Person(); //输出 I am one!;7 Z. }0 C6 E) Z) V, m
- new Person(); //这里结果会是什么呢,猜猜看) }+ I, B4 j; D; `) E( J
- 最后一行结果报错:
& p# H+ ?+ y& u6 _ - Fatal error: Class 'test\Person' not found
复制代码 9 {5 f' S8 j" [) ^) H4 d) `
- H9 ~4 o4 z8 E& d首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 0 L l8 K0 Z: E9 k
结果报错: - Fatal error: Class 'Person' not found
复制代码
( p* [- w/ e; _0 x, m接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
, N s/ O6 J0 H: f' x - namespace test;4 T* h6 f& K2 ^; b
- require './1.php';
" \+ [ x o9 n; I
; H+ c5 B' c" S1 j- class Person{
7 o* o# _; C9 r& C8 d) A - function __construct(){2 {! x0 l" j) v O
- echo 'I am test!';
3 | i& X" K) r3 z( R6 O( d - }# z" l. [3 A7 ?" |+ v* a! X
- }7 ~& w% K* Z1 ~) g' d# k5 N
- % J0 F! c$ E2 p9 I( D8 m
- new \one\Person(); //输出 I am one!; n& N/ b( X* F( I/ e- |9 c
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 " o* y7 o% N# H2 {
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php$ b1 k6 r( H9 w8 K
- namespace test;2 ?4 c# y9 Z, M: \3 D' c, g$ P
- namespace one;8 ~- }1 I2 a& m3 @9 Q
- class Person{
0 g) D M) y0 {1 H' f - function __construct(){
6 V I3 i) y Q7 d% `7 k# e - echo 'I am one!';
& q/ |, T' X* F2 S. A- l% b - }
7 x$ r E8 E" K$ F& l2 q - }- G3 b3 e, ^; I; ?% D& `- S
9 \& a2 |/ R! r9 m/ E2 V- class Person{! V4 O& }- q9 q, l/ P+ ~% X
- function __construct(){/ i9 ?- P! _; t8 o" x: D
- echo 'I am test!';7 R/ f& l, C& w2 |! ?( N) f
- }8 c* a; _! O* s) _2 r
- }
复制代码 9 X6 N) E' T# z: Q+ Q0 y3 L- o
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
; c9 ]& H$ Y' P* a. j9 D4 R看来简单的把require理解为替换,在这里行不通。
0 W: v7 v ?/ y0 S4 ?6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
0 J: B3 G7 H0 p' k: {0 ], Y5 k2 J9 p- //name.php
3 H' O0 {: a. \* B$ `* U6 ~
7 H* w9 E- w" x0 C% ~( x& k# P+ C- namespace test\person;
2 V; P& V$ s5 _7 v
6 F+ @% W2 ^0 p' \0 m' }& g- class Person{# g- J e* M: ?- K/ Q. d" |/ Z7 T( D
- function __construct(){
, a7 I% h4 ^ g7 N5 m' O - echo 'I am test!';
- e4 T P: P% j4 T% S v, l p - }1 P1 U6 ^5 u3 Z, _8 n7 o1 }
- }9 ^% Z$ ?. g2 ]2 u9 P$ A4 Q
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
3 V. }* t7 D- s3 N不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 I- f$ q: F8 m2 N$ o' C
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php+ X1 i& F$ Q/ N8 ~9 T
- " X, M/ L- _) I: D& [6 X0 H: p
- namespace test;& O, ?9 E2 s' ^3 e* D$ i
- echo 'zhai14';% [1 t$ W. K, y9 t9 ~9 j
- namespace zhai;
) e& V8 |/ u. B3 C. P9 }6 x - require './1.php';
复制代码
6 M2 D) O& \, `8 _0 z: J4 iphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 2 z) |2 r) b& n6 i! _
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。4 i& q) d2 _2 T9 Y7 s) u( q' x
- //name.php- n' x: r. b" H* w8 Y/ M: B
: X" g" u+ a; o6 s0 E- namespace animal\dog;
6 R b3 C* U! Y5 { P; _: N# O$ l - , ~- j9 h+ e* _: s, j
- class Life{7 y/ o. I v( a' q
- function __construct(){
0 n. @$ A% Q d: }. x5 {+ ` - echo 'dog life!';- U1 V+ T, l" M+ D" ^: `
- }
0 _- I: T6 I% O) Z8 @2 y - }( e* S- K: f8 w8 U) B& h3 V
- ; I6 n: R* _$ W* ?2 J8 q k
- namespace animal\cat;
3 R( u2 d4 v: R9 A0 ^) A2 W - 3 U! H. i, N( w* O6 H8 K, i
- class Life{
* O1 h+ ?+ p+ w5 ] - function __construct(){( Y& \. U9 w! {, G4 Y; u
- echo 'cat life!';
( i8 m5 N. U/ W: ^# d6 l3 A- B - }* W, P& L% U) S& k
- }
- P6 a d5 @' c* F: s" z! }
9 {0 q* j7 L2 [: X- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
+ z! L/ @: e) r2 A; c8 l" u9 }- T - new \animal\dog\Life(); //A0 F, j4 g0 F! }! O! ], z
- 9 z" q$ Z6 V! b
- use animal\dog; //a
2 D0 ~: P2 K: Q/ ?' ~, `* \, F& P% s - new dog\Life(); //B
}( d& {# s0 {4 Z6 | r* x$ l - 7 E! M, H! L3 C2 O! @+ O& \
- use animal\dog as d; //b
, s4 L0 a# X( \- x) w6 O - new d\Life();
复制代码
3 z% f4 n$ z2 J通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
5 M, [7 V; l% ]3 }# _- T通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
2 k" ?- [) Y+ x相当于
; @: L0 W- Y. {3 h+ U( I; Q3 E9 m2.namespace后面不建议加类名,但use后可以。
8 g$ Y4 S. e& s& o! Q; |8 r2 b$ I- //name.php
$ E% _4 C: k P( J. w# Q
; v2 W2 ~" E4 {4 u) t- namespace animal\dog;8 m3 D7 A. I: H4 V& n
7 s# e9 w0 b) {" y8 \! n- class Life{
9 O9 O$ ^0 o( G3 x' [. D a - function __construct(){
: I( X& i4 `+ F G- H% t - echo 'dog life!';4 ~; K' b- M& K$ Q; G* K) o. S
- }/ ] \ L: y4 p& k, F. q8 t$ @
- }0 X4 D( G7 B% Q$ p. S
- 0 c: z& g; E$ p
- namespace animal\cat;
. W, b6 R5 a: }1 C* G
* [# p9 e) Y$ u$ G$ i/ X5 S- class Life{+ Y: d$ [7 _+ _$ C
- function __construct(){
" O2 ` [/ q. B1 ] - echo 'cat life!';
: K4 e) y y/ e, [+ k5 b - }6 m2 |: ~2 o1 B1 T+ X
- }! y! m$ W8 A; m+ F6 s9 V
) S# V. p3 O% c0 b- use animal\dog\Life as dog;
: [" l5 t2 K! }8 I. c( J7 ~* b - new dog();
复制代码 * n9 Y$ d6 j2 \' J$ G8 I' k
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 : R" ?# U6 o& W2 i1 \
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
% \. A7 ?( H& {: r- L- Y& q
1 O: T) n! ^- A1 T4 E- namespace animal\dog;& f7 F6 u7 U m, V8 c
; i' k, a1 Y, |7 e+ F- class Life{) B7 W; T% H5 b( v
- function __construct(){
3 }2 ^, j# R+ p# U8 m/ X - echo 'dog life!';. r, K0 J+ ]7 S: N: U& p/ u
- }
+ Q" q+ Z x8 b, y - }
% K5 z& ~; v) x; g. S9 X" o$ { - class Dog{
1 |' `( D6 O) G+ |, g4 H. y - function __construct(){; ^7 q: \5 ~5 P% C
- echo 'dog in dog!';; h- g4 U' j" p
- } ?8 o$ h8 f x& L
- }
8 B* L. E8 ?* |& g+ ^, D1 y
3 d0 K8 K4 A: _# g/ S% `' Z- namespace animal\cat;
: H8 G, O' A: t' U1 w
4 H( l. e& } }6 P- // class Dog{8 u* Y! T. ~9 C- W5 e
- // function __construct(){* h. n' j4 w$ L& {8 M# G ^
- // echo 'dog in cat!';- a% u# q5 h! \
- // }- [. m2 ~( }. @7 }$ O. q. ]
- // }" s& l% \. w$ w/ G
- class Life{' N0 a: l. f" w' ]
- function __construct(){
6 Z$ Z1 _4 t4 M) ^ - echo 'cat life!';
) Y- w1 @6 d9 v0 Y - }4 k3 y: P/ R4 i
- }
( I: q0 m- o+ E" U. f0 ~ - " @; z8 r$ D- f8 I
- use animal\dog; % u$ @% g. Z; i1 G" b7 R& `
- new dog\Dog();
复制代码
" d& G, h+ [' r/ P4 U4 v2 P4 l如上,使用了 9 N5 X6 n5 Y: t; B: r0 ^! Y
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
y( I8 [3 h# S; S简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
0 W7 H Q; \4 m0 P4 U" _: a' b* S( F5 w5 E; c8 Y' V; o
! g" f- ]6 e* p! x5 M( B& q
5 t8 M' Y$ j7 I! }+ ^ l$ J/ v! Q& T ]. x/ }5 t- ?9 x5 S# g4 ]
|