以下皆为本人自我理解内容,如有失误之处,请多多包涵。
* ?+ x- p) @/ C3 M; a文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
0 ]. o& o6 Q4 d" G3 ?0 R/ @) w/ S, Q2 Y1 I) W9 i
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
# l0 w$ s0 g0 C# g8 m据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
: S& o8 D8 K- J4 |' W6 j- w/ W* o2 c结合使用方法来进一步理解它的使用目的吧。 % Z7 b: A. ~' t9 L2 T( p- t* n2 t
( C& Z, }3 o5 g; U/ q& L; F
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;1 v6 v7 ?$ v! u4 L
- namespace One;
: D/ D! N9 O+ z- \9 S1 W9 P( P; l - namespace ONE;
复制代码 7 H$ U3 D. K1 j; E& |' L
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
2 p/ X Y# e L" p4 D- o2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
( R5 ?4 B% L* J' V( M - class Person{
4 ^/ P& u3 M( f: a! z% u9 s1 W - function __construct(){
" v8 U# t7 W2 H+ L+ N - echo 'I am one!';# b' u! d4 X5 H7 V0 C9 h
- }& x9 E9 b: u$ K6 W) k
- }
复制代码- //name.php
6 m# A- r7 a6 V - require_once './1.php';
" q% L3 g; A3 F% s
: Z+ j8 { y$ f4 \4 N2 n- new Person(); //输出 I am one!;
. D* S" v# ^* e4 W4 ` - new \Person(); //输出 I am one!;
复制代码 / H: B1 O/ Y' j: k6 v0 n- O: ]
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
& \1 q" T+ V9 a$ A, Q/ T - require_once './1.php';! u2 e, Y) x7 r8 H
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
. `/ r$ X$ E( B4 i3 J1 \* M8 B4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
- f' I& r4 `0 X5 I% i. I7 M - namespace one;3 z+ |: |/ q; R
- class Person{7 _6 B2 M0 J) T D. A L" M* u
- function __construct(){
( d; @6 N; Y/ |' x - echo 'I am one!';
' a2 H% r1 j1 w- K9 S4 w8 } - }
+ |% U$ N" B/ h+ ]5 h' I - }
复制代码- //name.php
" Q" [" v; e" [) N - require_once './1.php';( R6 n* E. H( V8 s1 ~7 B
- new \one\Person(); //输出 I am one!;
' R: ]& Z. J5 n2 V! ] - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 , n- X# Y+ d0 @0 l+ v) x2 o& \- T
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
. p5 H9 ?7 [% w9 R' I9 y5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
3 S/ Y2 Y5 J- i/ Z+ e, x- //1.php
: S0 T7 S T% u [8 j - namespace one;
4 _- I* n: R% J! H% C. ? - class Person{
1 ~( B' t# \. R& K* ` - function __construct(){* N1 u1 ~1 Q6 }, b
- echo 'I am one!';8 @( e) u; [2 Y0 x0 O3 h
- }4 K! Z @4 c g; B* D k7 i+ M9 @* Y
- }
复制代码- //name.php8 y5 h( p+ d, ~* U) v6 G3 D
- namespace test;8 ^( s6 r; e0 v* I# D: M
- require './1.php';
! h) z4 r6 c3 d0 G9 J9 O9 O& a - new \one\Person(); //输出 I am one!;) r! R! [" A4 k7 X& h+ Z
- new Person(); //这里结果会是什么呢,猜猜看* Y, `: E* ^5 \/ V, \" z% \
- 最后一行结果报错:
( S; u9 E& B) X - Fatal error: Class 'test\Person' not found
复制代码
% b. Y" u; D. M9 R% @/ }4 f1 y9 k
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
. ?. u7 b; {; M% J结果报错: - Fatal error: Class 'Person' not found
复制代码 ; } o5 j$ } u, V( |6 P% t6 b
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php9 Y4 o# m( {& U4 n) I
- namespace test;
7 M3 E9 c4 i+ E - require './1.php';
& s W4 s. {" ^( ?- [% l, m - . O; V8 K8 h* N7 [7 d
- class Person{$ z& N9 N9 u- t, J W
- function __construct(){
7 R0 X- }/ _( ? - echo 'I am test!';
^4 u: q3 ~0 b; C7 }; G - }
) Q) W) @& X( r q3 b1 Z1 D9 V) o- ^ - }* s- {7 }$ H0 r6 Z/ E4 B! e
- ( I! e; O! p0 n% M$ k$ W' d
- new \one\Person(); //输出 I am one!;
* j* t# p; L6 L! e - new Person(); //这里结果会是什么,自己猜猜看
复制代码
M& s8 y; L/ Q8 S( E. g$ r6 |最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php S& J9 _1 W* w$ D& y+ e
- namespace test;
* c/ ?3 y1 I& u1 l' c9 k - namespace one;, V* ]9 T+ ^ I8 u3 u8 Y
- class Person{
7 V4 D( ~' A% D+ T3 ?3 V% p - function __construct(){
1 f! y) _) I, C4 o$ J, l9 O5 ^ - echo 'I am one!';
# d% S: P" ]1 h6 H7 ?+ k - }
- F$ L' c! I/ U( L - }% e+ N) n; Y8 g6 I: E; f
- 1 T2 @9 R- ^) N1 a9 B _
- class Person{
/ x5 m/ V! T/ u5 Z - function __construct(){4 Z. {3 L" I4 L- ^( \8 Y
- echo 'I am test!';
9 F: g. O8 W8 H: r - }* {4 j; s5 \" `: x
- }
复制代码
! @. S* k6 k, j/ d4 J4 M6 a无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
. Z, c9 ^. Q4 y" o看来简单的把require理解为替换,在这里行不通。
" [+ T O% ~7 g) ~: b5 Y" v6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
5 o" b9 w, D8 F0 ^8 x- //name.php3 ]* [8 d6 k7 }% |3 s6 {) {
5 t9 Y# H- F7 x& i: @- namespace test\person;
; a ] I9 b% l. n - ' N t% p8 |5 H
- class Person{/ p4 |+ e2 S' d/ v
- function __construct(){
8 E9 j% c4 \+ D k% Z2 F - echo 'I am test!';
" i# {$ @* @+ N9 L - }& I- n! ]' l: q/ r+ i
- }
. E5 _3 P1 F& O2 E! p - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 : G( D) k' L- i' A* M* Y6 Y
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
% _: z9 C9 ]8 O/ g) r6 Z7 H k; F7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php$ I5 j$ @7 g8 G
% B+ [# l& N# y) O8 B- namespace test;) E8 k7 V+ {0 G3 |0 y; K" Q+ S
- echo 'zhai14';
8 p6 s* g% h7 D& e) `- }" k3 H - namespace zhai;8 ?3 z8 a P8 [; ^
- require './1.php';
复制代码
4 }2 v9 ]) H5 d; Tphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ' x& t+ F/ z; O( G
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
3 A3 D6 ^, L7 Z- //name.php( q2 {3 E5 Y7 S. Q% @* y) c
; {$ M8 {2 v/ U+ A$ E2 m1 D- namespace animal\dog;
, H( h+ b. f0 l2 Q1 y- [' V2 K% n - . L2 ?# m) j' x1 T
- class Life{7 X! \/ i( d& }8 k% t6 D
- function __construct(){
/ x+ c Q6 F! ^8 Q - echo 'dog life!';8 d! b/ c5 K9 D6 [$ B7 |
- }7 m. k! S8 Y0 v4 e& `' @
- }
( W( t8 O7 q! e# E/ _- l$ r - ! ~0 r9 b' B+ G; D" e7 P9 t
- namespace animal\cat;, O& W m5 n/ U
" H, e {( X+ ^! K8 j5 n- class Life{
" Q' H: b+ e& X4 o# h% M6 I - function __construct(){
: W' p: z" z: _2 ~, O$ ^* D# R - echo 'cat life!';
# W2 E8 e( F$ Q9 G: \ [7 Y$ X* ] - }
, N8 ~) O8 u) D" f+ ? - }
* f2 f: R7 `6 M7 v A0 ~1 i& a$ S
: g4 a" I3 b; C! v5 f$ h0 l% \* k P- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
: h% u7 E. I( x! W3 z5 U6 T - new \animal\dog\Life(); //A
- \7 w. t8 C% T/ v1 y- }+ G
& X$ a$ z+ g# u/ L- use animal\dog; //a
! n+ z9 _% I) B3 T - new dog\Life(); //B
$ u9 l1 T3 c, @ - 9 e% o/ H4 n' x2 o: {
- use animal\dog as d; //b: g+ k5 }, [6 l( e/ q9 Z
- new d\Life();
复制代码 - D$ t* H V" Q$ v" T. p# z7 b
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
1 p% y' t3 f+ R2 m. r7 p; N0 I9 x通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 1 b/ Z; a# q) i9 O
相当于 3 j- n% O$ U) D& D9 ^
2.namespace后面不建议加类名,但use后可以。
+ P5 _$ }% q: {. E& B) d- `( p+ |- //name.php" L2 ?$ K6 K3 e8 M$ N7 a+ ]) ?
- " A2 ?. r3 |$ R* Y* {
- namespace animal\dog;
: h. S0 o6 @: A! Q5 \5 }- ? - / w: `2 |& k& E% p
- class Life{7 X8 F: P5 z: {& c: X1 `5 k
- function __construct(){
; D; D/ ^5 M5 f. a - echo 'dog life!';7 b. L3 @+ O0 V5 c; F! a
- }8 D6 ?/ S( R8 p5 k& E1 P: R* D
- }6 L; U4 E8 \% {& n! |! |! J5 R
! A; S- A, ?, f! X2 f- N- namespace animal\cat;
( H [6 G$ c$ ]6 U; ^! l
C, U1 A$ F1 V5 l! h/ n7 A- class Life{' L+ W, ]# K0 X d( x5 z$ P
- function __construct(){
. Q# ^% Y3 ^- f& J - echo 'cat life!';
h3 }4 V3 a9 e+ j1 v7 Q6 W; J0 P - }
! |: v" K6 D$ |" V0 c( b4 V, y - } Y) n3 V4 j2 v, ^+ P2 }: b
- . N6 \& w, Q, U! t! i7 V) K1 n
- use animal\dog\Life as dog; & L6 s1 @% H8 H
- new dog();
复制代码
) o0 a" b6 w7 l5 U0 I) G, E+ x如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 , s7 a3 X1 C" Y
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
$ H1 Z( c% Q( k) Q0 G' A; G. H, {5 P
9 r& D' }: f, i4 k1 \- namespace animal\dog;
% f5 A& i" B1 L' w& Z - 0 S' O: b T/ W/ ?
- class Life{. A7 E; n7 R" M0 T
- function __construct(){, U8 w7 S% ?1 [! p- }
- echo 'dog life!';
$ T2 F6 V" s& h - }( Q0 X0 j* ^3 b: L* ~3 T8 v1 S
- }+ Z- i) s* y7 B3 e
- class Dog{
1 Z8 ~% k: [% _ - function __construct(){5 B0 a/ x# d9 o' W9 L' Y
- echo 'dog in dog!';
; z7 M: |. @5 v" n* l( v+ j: i - }$ u, U& }& a, f8 ^5 o8 t
- }4 B. G7 r4 j5 W$ X+ ?
- 6 [- x( M9 _5 d+ [. w
- namespace animal\cat;7 {6 s h! h: J+ ^( D5 Y3 M2 c
- % f6 T9 f' N7 b% [7 ?
- // class Dog{
6 n7 |" g8 q) L7 a" p2 y9 N - // function __construct(){
2 i7 o" u9 B: C1 r' K' @ - // echo 'dog in cat!';5 }1 [: U' Y1 f( F$ }) V
- // }0 Z# Q9 {2 s% O" k8 y
- // }
# v# Y2 h. P9 S; k/ P& o( v - class Life{
8 ~% ^7 ^" s9 U# Z3 c2 X - function __construct(){
+ G7 u' r1 l' r4 m r0 r - echo 'cat life!';
- k4 c: q% G. R3 w. U6 y: Y* a - }
7 _0 F5 c9 ^* g% o% a$ Y8 H, k, A - }0 H% c" Z, ] C& Q
* O% N& n4 U' X, c- use animal\dog; 2 X& V$ v) R# {$ m/ J" E* ]1 M
- new dog\Dog();
复制代码
% Z4 ]* R. W& C3 S0 K: n: W6 u% i; `如上,使用了 * c. m+ l( k b
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 4 z9 T M5 e6 g; H; p$ z4 v
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 . o1 a6 s' Y. M5 J
$ I+ n% e) A* u) w. Y; s
0 O9 Z5 a% W# i; `4 o* ?) p8 v% v; ]- d1 `) \1 [: q2 z8 l/ e& ?' U
1 K% d6 O. S5 d, z |