以下皆为本人自我理解内容,如有失误之处,请多多包涵。 % p, ?% J9 y/ p+ v1 y6 ~
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 % q0 X7 A1 Z3 e
9 U u% F9 I5 \' C" H, }
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; ( e# G) o( S9 m9 F) N! v
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
& e B" e m$ Y5 `2 J7 v6 m8 G结合使用方法来进一步理解它的使用目的吧。
4 N# Y: B0 p' N3 l: m7 W! ~0 \$ l2 V3 s' J! o' [
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;4 [7 g9 p) Q% z) R& E& k* P
- namespace One;
8 [- }/ K9 U: ~5 [# A/ Z - namespace ONE;
复制代码
( Q8 ~# a! [" B# a; _ ]- Q+ `如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 7 k$ ~3 ?/ C, h; V7 P- V
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
% \3 q# b& F$ F" n6 ^8 a1 K* I* b - class Person{
( t9 h: j& ]" Z- G& H - function __construct(){
' _. f; a% L4 E' i* z4 U - echo 'I am one!';
9 I/ R) Q) ~: A5 p1 `+ r* S - }; A8 o( Y0 O3 E, [9 A3 G4 o! N/ e
- }
复制代码- //name.php
' T8 m8 T5 _) ~. j5 O' e) p7 B; k - require_once './1.php';9 ?( X' e7 b% u+ ]
- # E. K4 P K) R
- new Person(); //输出 I am one!;
. g9 k1 {: g: ] t1 V. c. J - new \Person(); //输出 I am one!;
复制代码
( A- H2 [- n* J9 k! S$ d# n0 L& ~- X. T3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
& O9 S, | O0 v' ^ - require_once './1.php';
4 @1 _4 S* d' h; F7 O9 I - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
0 y7 z% x! ~& ^5 W1 `3 P. V* ~4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
$ ~" w ^! a8 O0 J! g, E; E; x - namespace one;
) X! O% J( s7 V8 G' i/ m - class Person{
, t$ I/ b* O! d - function __construct(){
p3 M8 O# o7 x$ e3 A3 r - echo 'I am one!';4 _7 g4 {/ S1 f3 C4 M- l6 S
- }! b' r# K- ~2 V+ p, ?' W. b7 Z; |6 |5 i
- }
复制代码- //name.php! I! d! `* B" l& n% _% Q) Q
- require_once './1.php';
" t5 O8 U. X) f" g: _ - new \one\Person(); //输出 I am one!;
5 w, f! L# P/ K% v - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ( g U( w# x) r8 w7 M( q1 q( ?
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 ( O# P: E) v* G6 P
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。( u/ r- L) \' X5 E/ m8 j
- //1.php % |6 S0 O' ]' c& m/ O2 ~8 y
- namespace one;' G: Z# w4 R7 d! g! T
- class Person{) D3 m* u9 H2 o+ I) |8 N
- function __construct(){* o2 i: `$ H3 G' A# N! u
- echo 'I am one!';2 h; P, J8 N1 x: v8 }1 q
- }
$ X/ c' j, L& D9 m+ y7 l6 d - }
复制代码- //name.php, s' c( X: s* `) N$ P% |( g4 l+ S
- namespace test;9 m/ w, L0 ^# P# @- O% n
- require './1.php';
; Y* C1 z7 y, q0 E* Q - new \one\Person(); //输出 I am one!;( u: ]7 {" C2 d: t# y: {
- new Person(); //这里结果会是什么呢,猜猜看* z$ z N3 \" @
- 最后一行结果报错:1 Z& Q5 K* r0 c; V3 u
- Fatal error: Class 'test\Person' not found
复制代码 " {% n5 T4 h! n' S
8 k4 H! o$ A( D7 o首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 3 u7 ] X/ N7 h$ V" ?* p5 v0 N9 z
结果报错: - Fatal error: Class 'Person' not found
复制代码
t0 z2 ^ r, h k, |: g接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php: l- m0 t' V8 a5 w
- namespace test;
6 k2 ~7 a- h/ j7 D A - require './1.php';
" s! Y9 k) Z4 U9 {4 E
' l' T* q/ G: V) V; u( R- class Person{
( p! y; y. C% y I - function __construct(){9 l) r& {) i* b; S6 l, D' n& @5 ?
- echo 'I am test!';' e$ }' b3 s& B$ ]( O z
- }
; Q) Z- r! z+ ^& P, e( t9 y8 a( \ - }
: B2 j* E8 @ |! u5 _4 N
2 c( `8 J! z4 G P8 x- new \one\Person(); //输出 I am one!;
; E" A: ~) f) R; `3 f! O7 N - new Person(); //这里结果会是什么,自己猜猜看
复制代码
4 L7 o: k2 I; t: S5 s$ Z5 }最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php% ]8 d7 S* w* {1 F# Y- G, v
- namespace test;# L/ I, t% a4 u! [
- namespace one;
# j3 A0 m$ a! ]3 U( c: x0 p - class Person{
2 y7 n2 i# E, f! s5 u5 I - function __construct(){5 P7 t8 z* M% R s" q
- echo 'I am one!';3 U! t" ~* t8 n
- }
0 z8 S, P' Y7 G/ R+ O6 f. b - }8 O$ E9 J+ o* W( s
* A* D; ~. V w* E' _) r* M- class Person{; x/ c6 c/ h5 D5 E4 r, D4 I
- function __construct(){
( V3 I4 o( S/ o" v" A - echo 'I am test!';- N: ~8 ~3 d; L/ R3 c
- }' j" u; U. ?; [
- }
复制代码
3 K, U0 ^' u; [& a7 l a无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 & C3 |9 t& Y3 X: G7 t1 {
看来简单的把require理解为替换,在这里行不通。 , g$ p5 P, t# O9 M4 f/ V' Q- W2 z
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。# A. z$ k! ]& l7 H
- //name.php4 X4 g& W8 M4 x0 ]4 k' v! T Y
- - K* b) f; I+ y' b0 ~# X
- namespace test\person;
. Z7 t7 l F' A0 f M - `; V0 z$ S7 w, C8 Y4 [
- class Person{7 V H. y) ^4 I* ~# f( n% q
- function __construct(){4 H$ q0 U/ H. f! h: n2 E7 ?
- echo 'I am test!';
" @$ [7 r8 {% p9 t, B# H1 c/ b5 O7 ^ - }
# T! p- i) y( [% F% o - }' c% E2 F8 }' \5 @: K
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 # g4 Y# x" H) c+ W
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
% T) u9 C& I8 r' I. ^7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
@7 a } q. ?3 e - ) c3 T. G+ P8 Z: [0 {
- namespace test;
. v. o4 n5 i0 J - echo 'zhai14';0 {4 Q6 O' `" i1 ~8 _
- namespace zhai;6 @, ]/ }, q+ f G& Z
- require './1.php';
复制代码
4 X' o# ]2 @: Pphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 7 m: `* t! @0 f+ `+ e
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& [5 a0 v2 j3 K4 S/ g9 l; ^3 j- //name.php$ o7 q& R. @6 n' Q* e: [9 y
- ; ?9 l2 f+ G4 p9 z* Z
- namespace animal\dog;
; s8 O2 c0 ?# F' O4 ^6 _' l. i/ s - 2 }+ q4 v5 r1 _- J2 M7 b
- class Life{4 ~- N( P8 u! C" `" R l' h
- function __construct(){: z f5 C9 f4 m9 `; V; K2 M$ Z
- echo 'dog life!';
# |$ e4 d6 ^) c8 H - }
1 C+ j4 K2 p; g1 O- P$ D0 @: n - }
/ ^0 O( ~! t% y {1 g! ?0 t
/ [. G0 n# A& c3 L5 n$ Q- namespace animal\cat;
2 M+ l) i* t+ x& t. [( r% t
( v& d! W* u% Y7 u- class Life{
* x) G) n1 A4 t4 m% M/ u - function __construct(){
% l, d6 @3 q, S5 E - echo 'cat life!';2 ~/ ?- b8 K! z& }
- } ~( _* c# b% t" D8 n+ P- E2 A
- }4 l9 ]) l: _5 l J. N3 f2 q
- t$ ]3 j! Z3 m: v- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间6 {( K" z- V6 [" v
- new \animal\dog\Life(); //A
! H! h* _4 Y! U: t( i; u: Z
* l; r0 T1 r* M: Y" F9 e X- use animal\dog; //a
8 P$ ^4 [, M$ B3 x# X7 l. @; l - new dog\Life(); //B; ~6 B2 m$ B# v
) E9 H! N8 k) F- use animal\dog as d; //b
+ d( G) r7 c' w) l5 e - new d\Life();
复制代码
; V1 {9 _: p* K0 p通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
4 l5 k3 Z/ c( ?& j4 \通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
2 m: n* Y2 N$ Q相当于
( K& ]; R1 V; W' X2.namespace后面不建议加类名,但use后可以。5 I9 H& B, p1 C9 L
- //name.php& y3 b! [" N/ O* n* l% U% u2 D1 r
- . ?3 Q: X: v2 g
- namespace animal\dog;
, d6 ?' K L* t - , {, v' B" d/ k* `6 W
- class Life{: x* X: ]6 Z2 c
- function __construct(){) X8 W& a& B2 t0 B7 L
- echo 'dog life!'; }8 E- g$ s% p6 u+ ?
- }$ U9 x# C; @$ ]1 x. d, E J
- }3 j. [0 K; D! k+ I2 [4 u
: E0 l' d% H4 V- I4 S$ O4 j- namespace animal\cat;. r, J+ M5 [( U4 N) i8 U% b
: C4 F) C4 W% i/ K- class Life{$ L8 Z; j: U4 \: K
- function __construct(){
4 J6 o- |( v9 I - echo 'cat life!';6 K' q X4 [3 l/ e, i1 B
- }2 J% y7 ^; e/ K* @* R8 d
- }, C. c' D" p" j9 e; ]
9 x" q& s( {* {! R2 R- use animal\dog\Life as dog;
$ |# B* ^) s. _ - new dog();
复制代码
; J( W( U$ P/ P) G1 @6 N, H如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 + B; f/ B- T* T: D' \2 \
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php2 i8 G: l) l3 p% K2 N8 Z/ x
: y5 I. i. W1 J; m2 a) R- namespace animal\dog;
, d* K5 B9 v8 v9 \, g8 } - + l: x; k& n: e0 V B
- class Life{
3 q G" m p9 y9 V - function __construct(){
! ?# g1 ]1 M: l/ ~# e2 `; B& n - echo 'dog life!';
9 q# _0 S2 d$ y0 C - }# X& B8 Q: ~+ t: Q3 U4 {6 b. K6 Q
- }
. r/ J6 _5 j2 x9 p - class Dog{
9 G% v7 b+ x+ c1 {) k# [5 q - function __construct(){
8 y! v: J7 M! X6 O: W - echo 'dog in dog!';
% l# u. [3 ?8 X - }. Z8 C" m* I& w3 g
- }
7 z4 w# R0 K% O
: ^4 Y }/ s2 n+ U# S- D- namespace animal\cat;
C( N. j: o. p& B4 ]7 a% e
$ V, p1 ^! W$ l: O" m- // class Dog{
! j9 f# @& B/ l( g* T( b - // function __construct(){1 z2 u# {) z9 q6 a" t
- // echo 'dog in cat!';# u& q8 x$ m/ r; ?; N
- // }: {% s. { G- B
- // }
; {$ V# H8 ]1 L" f+ y2 A, c7 x - class Life{( ~1 \; }) e7 \% j- V, i6 r2 f9 h: }
- function __construct(){4 A, |5 j: t# W+ O( V Z
- echo 'cat life!';
# b) K! c" o8 j - }
5 L- b& J: e7 w) a1 J9 P; I - }
; j0 _" E4 k r' Y F - 0 x7 I$ p' b, Z$ n4 c$ r7 m$ [& O
- use animal\dog;
. I8 I0 k n8 [! s; J - new dog\Dog();
复制代码
+ U. ~6 a; R' L0 G如上,使用了 4 K3 `2 ^" N3 U- ^& A% N
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
& O1 d* N0 f; h2 F. \: d简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
3 c5 x; {5 f1 f" X4 d! D6 v
7 u" i4 ]6 I# e9 V0 m( e" B# l! Y( o( P
8 M+ m1 M8 L4 O0 F3 n
$ {0 i$ @( B9 t$ D1 r. D |