以下皆为本人自我理解内容,如有失误之处,请多多包涵。
6 U' C% x/ T" ]: c' I文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
7 H; X% ?- m+ P; X& L3 r0 @/ I; t, G, q0 e: \3 S
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; ; q- W" Q1 Q: Z' O. C; S
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 8 m U) w" U* w8 W0 o7 }- H4 e
结合使用方法来进一步理解它的使用目的吧。
+ V$ G y- A4 h8 X p) L2 }! H5 X2 B) R' m9 z
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
, l4 r) M1 J" S2 J - namespace One;
4 P) g! t9 u9 m3 K! l- E4 A' g - namespace ONE;
复制代码 1 z8 P% R( H4 y& \2 J! A, G% |
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
; O2 z" y/ }' w" a2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 5 S& ]+ G+ _& `. m! P1 b
- class Person{. V# C5 M5 A0 o
- function __construct(){( s- V( l: p3 A6 B! t
- echo 'I am one!';
! c/ J' P' V" [( N6 E% J# Y9 B - }+ b! X! N2 ^1 {/ I. h/ _2 n
- }
复制代码- //name.php2 q0 K" q8 n2 o- p- a
- require_once './1.php';
1 i" O3 Z, J% b$ l$ j( [4 G. T - ' V3 e6 \+ G: N& w; a
- new Person(); //输出 I am one!;7 |: s+ }0 }7 a8 E/ \. |- H/ x
- new \Person(); //输出 I am one!;
复制代码
) m2 @0 y8 e" g4 w3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
$ n9 r: D/ u' ]2 { - require_once './1.php';
2 G2 V) m+ s* W9 Q2 ~; N - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
5 A, V0 ~+ N& C4 h/ t5 n4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
# C) Q. a4 G0 h - namespace one;
5 P; U) L7 ] u! e6 W - class Person{/ P6 J$ K/ U: O" Y/ |
- function __construct(){8 L5 n9 T u t4 K/ |$ i. E- b6 G% F
- echo 'I am one!';0 o) h# p* v+ v8 d( Q+ p2 T4 x
- }
7 X2 u, |5 S7 ^& c - }
复制代码- //name.php- y$ `6 k4 g3 b/ b3 b7 V
- require_once './1.php';
" E2 |8 K: B# _, ` - new \one\Person(); //输出 I am one!;
9 N; @% h4 m R+ Q' e2 {4 Y* [7 } D - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ; s# _8 S6 M4 {9 e. z0 A5 Z1 Y
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 3 j( W) |. Q; G8 a" }0 y
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。+ t9 i5 b1 a" F
- //1.php
8 q! V1 K: {/ c - namespace one;5 X S! L0 T+ j# o
- class Person{
. f4 S. Z- g% B0 ] - function __construct(){
7 J6 F4 r* E. S" P8 y& |1 \0 n" o( c - echo 'I am one!';
6 D& B! k/ ]& b5 p - }
) u+ o+ g/ ~; r6 p. D( O - }
复制代码- //name.php6 G! q M) a1 _5 W5 Z
- namespace test;
; Y& M, W( u7 N, S$ [ - require './1.php';
# P6 h4 V7 G0 F. x) {7 w. R - new \one\Person(); //输出 I am one!;: N% C; Q2 u x8 _3 Q2 T, S ^( v0 v
- new Person(); //这里结果会是什么呢,猜猜看& V$ `( _% [0 R: R' e8 U
- 最后一行结果报错:! l3 a" H. x' l
- Fatal error: Class 'test\Person' not found
复制代码
8 m; p( I& s( Y8 f+ D+ W5 `1 t; \6 ]; N5 w- L/ o
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 + S- X9 _* }" [( E/ L4 q7 d
结果报错: - Fatal error: Class 'Person' not found
复制代码
( u" M4 Q- K; L! E接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
4 c, S6 ]$ h4 O7 d - namespace test;* L" h( \. S8 O0 O2 v7 Z& o# r
- require './1.php'; . N$ P; `* k: T3 A# F9 G
- % A6 _& x0 P7 ?0 E
- class Person{3 I0 i' G- c' M
- function __construct(){
8 x! M% ~: O1 h, u0 ]7 w5 B - echo 'I am test!';# T6 Y- o' w. M; q
- }# n! l* L& [% R1 r3 @! N# I9 T
- }
6 J, b- v; J) H5 }" _( N
9 C/ I" M0 {7 g1 U% K$ C# F) S- [- new \one\Person(); //输出 I am one!;
* i, o' L$ ^- r% L* S9 h9 G. J - new Person(); //这里结果会是什么,自己猜猜看
复制代码 7 B. d* n- l# o0 F4 g
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php/ v& S) i% {% E
- namespace test;
) \' s; ^1 E7 D7 f; a0 X9 A9 J - namespace one;
, L6 ~* a4 y2 T0 |* q# ? - class Person{
# i, M7 _2 m7 A% p6 Q- B" Z - function __construct(){
$ ^% |2 A# `4 c% K: u - echo 'I am one!';
- G0 ?7 c0 D/ ]7 l& L - }
6 h0 L& @5 f% X& c2 g - }
/ B- o0 Q* p, X; }
2 d) o) r' p2 @* l/ Y1 N: |. x- class Person{# w9 x2 l6 E7 h
- function __construct(){
; Y- `9 B* P5 h- l, G3 o - echo 'I am test!';. S ?6 m% y. `! ]& ]
- }
' R ?/ C% E5 ~6 y, L - }
复制代码
2 k! |1 [2 y! Y. p0 K无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
* Z9 y* K | b x/ w9 S: F看来简单的把require理解为替换,在这里行不通。
5 \5 i. n7 A$ w6 w. S9 ]1 e# T6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
7 c& D4 z t: G% Z: r- //name.php
& M) O2 o2 _4 h - ) A( b" u- q* B* t( d8 D
- namespace test\person;
: H5 a J D) g. F
: z; h1 U! Z: D H2 }1 ^) ^- class Person{
) j s% O7 ~, Y! ] - function __construct(){, s0 f* R" N& l" Q+ h# Y, Q" {
- echo 'I am test!';. ~9 `8 l) w' u; N7 M; z) P
- }" |9 y, g0 x+ k, I6 _. I v
- }
1 K5 M8 ^" J3 `& t, G - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
, K* B; a# }9 ^2 R不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
' r+ y" Q2 k) W2 S+ h7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php9 @- Y% a4 r* _( n, _
) E' w' F: V- v' M2 N- ~3 k- namespace test;9 J8 \5 M% F g( G' y' z- g9 x' l5 J
- echo 'zhai14';
, z z- t+ {2 L9 E - namespace zhai;
9 z! F0 K3 S3 g" D/ W: E& z& p - require './1.php';
复制代码 l0 b) D9 s: r& O& v
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 0 Q3 O! G# F. a- b" p
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。* n8 F# `; ?4 v1 A& [2 x
- //name.php
* S. x3 j8 v0 N8 @1 c# M# Z$ `
" V8 k8 g- ?8 C- namespace animal\dog;
" N( u j/ i; g- }; ? H4 ]
; Q8 F5 H& D5 x& g- class Life{) ^' D0 ?! ^# t8 p
- function __construct(){: b, w* _2 i6 R7 q5 N' q
- echo 'dog life!';
! U. `( Y0 c3 ? - }5 U" B" k2 y) }/ X
- }
3 k; U) B* A R1 G. o% z0 ?
2 s8 i% z2 K$ Q! C2 E+ n- namespace animal\cat;2 m. y5 z ?! G9 `7 V
+ S) U9 N9 P% f( E' Y8 Q; G- class Life{
d$ j, O3 S# i9 E) d2 S - function __construct(){' X, V- i$ n U5 j
- echo 'cat life!';, }/ w" @) U, H0 Y9 R# m7 z
- }
% x. } |, N& p: W X" j1 @! H - }
5 \4 T8 S0 n9 B6 _' q
- X- s7 C9 R f! e, a" O( ?& ^/ i. |- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间* R; P* T/ Q3 c% q) e+ J
- new \animal\dog\Life(); //A7 M N, W# r1 S! o1 o/ X) t" l
- - y# L3 F2 N% y, U
- use animal\dog; //a5 s$ D: n. N) H y" o' p* x4 J
- new dog\Life(); //B
, S, [$ D; C2 K
4 X$ {# r" T& d! \$ @8 g- @- use animal\dog as d; //b
- E; O3 w% ^/ o- u$ F# f - new d\Life();
复制代码 |% J4 y% g3 c* F. T. C
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 1 d$ u3 h3 \2 a
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
' u9 f; Z% o g相当于
2 j3 O$ B/ ~. u0 `. S0 y% B. V2.namespace后面不建议加类名,但use后可以。1 J( R0 l$ ~0 _" ]+ n5 y
- //name.php4 ]/ i! k7 |$ n2 q; o4 T
: u! o1 W- m* _1 m# S* |! m- namespace animal\dog;: ]8 t0 \0 c5 i
- 0 Q" V3 x3 r& {% `7 H& O
- class Life{
) S' K' a# x9 P) M - function __construct(){+ |, T. s- t3 n; G1 S# b
- echo 'dog life!';' K, Q2 K8 c: [1 |, t' C
- }
$ T' T3 ? D" X. q8 s. _) {: S - }
3 p- _, Q5 o, J. g9 H- e7 u8 h
L+ j6 a$ ~& s8 i& v4 b4 t) A- namespace animal\cat;- Y3 `) y) Q: b- z4 O
+ Q/ ~8 G0 h- _' y) D" _$ [- class Life{. M+ t* ]/ V: H0 T( m
- function __construct(){
* V5 G+ c( L: W3 p4 @ - echo 'cat life!';: [/ g3 @# r* E. W! s( b
- }
; r* G- o5 }* K h7 V - }
9 P) f' x% s4 b
$ `! ^6 s; {+ H2 T# n- use animal\dog\Life as dog;
: Y$ X6 G3 |) T: ]& W! p - new dog();
复制代码
I& o; b8 J0 b, [! ?如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 & z* e% A5 r. R$ A @
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
0 z2 ^6 H4 v, P4 v; O _
7 J: h% ]+ w1 n$ G0 ?( R2 O# S: {- namespace animal\dog;* }, U* |3 [: t3 d( ^: c
- * {8 F. y5 V9 i, ^4 u( c4 j$ c$ `
- class Life{! d" d! N7 d9 U$ n. g0 `; s7 ^
- function __construct(){5 B% Q5 V, ?0 i" D) v. o9 Z, g
- echo 'dog life!';0 E/ n1 t7 r) m* l- A) G
- }
; d4 @. t3 n* Y& ^" }, g. w - }
7 @4 r8 s% r) ^0 O - class Dog{
+ {* l/ l" f/ p% h4 Z - function __construct(){9 i6 F. ^: w7 d% u% _
- echo 'dog in dog!';
5 a( L2 S* b s - }6 ^6 g* R" Z S; M0 h h1 V0 G. t. m
- }
. h4 `/ @( t( o' B2 F) p3 W- j$ p
7 c. o C1 w+ W- namespace animal\cat;
/ W' G- e7 ~6 g( z
/ G$ d4 H- W/ D2 L! w6 M/ [- // class Dog{% v0 z. L" t( J M) l% ~: @& S
- // function __construct(){1 e) w4 S( f" M
- // echo 'dog in cat!';2 n/ K3 w# [# E9 y* W) N: N6 M
- // }
% D5 h3 e2 a* Y- h - // }1 u+ `5 k# |0 c. p9 Y" u
- class Life{" t" w) V' m4 d |
- function __construct(){
# L0 z! b- i5 ~ - echo 'cat life!';
- V. Y& J( x+ z1 I - }
; G6 X# C1 `" S7 o+ b - }
% b$ B5 T# ?5 L' h
7 F9 M( D+ E; M1 U4 Z6 W- use animal\dog;
+ w! J0 I) A' x$ _' A' e* L. c - new dog\Dog();
复制代码
5 w, N1 F0 n& n, U, H如上,使用了
# N; Q/ h; ?. l! k1 D/ \* Ncat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 $ i" v+ A% Z7 y3 ^" }/ f: h+ g
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
: p7 }: \ e9 }$ n7 d7 C7 l
4 g' x. L# Y7 H" I8 |
: w8 E; G& a& N6 V; t+ N9 F' j+ W& {- H4 @8 X
. d2 T1 F4 m/ F7 E# s |