以下皆为本人自我理解内容,如有失误之处,请多多包涵。
* i1 u% X( D) K! R$ `3 u* _文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
% j) M$ l0 Q/ Y! b5 N9 \ @3 J2 \# j+ [
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 6 P0 T4 A5 |% v: d
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
0 ]' W3 S, n8 U7 `2 b1 ^2 I7 K! Z结合使用方法来进一步理解它的使用目的吧。
$ B% x' ]' B* q) }0 W7 D1 R( C& A+ m
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
) Z7 f( Z, L# L - namespace One;" t, ]& M0 |5 j6 e5 R
- namespace ONE;
复制代码
8 t5 B: C0 Y* P1 J+ Z' }如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) * O7 ?4 h7 n! _- h+ q9 c$ p9 q1 A
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php & W3 }# N2 A3 L" J- G
- class Person{
- [9 R1 Q( S. `& i1 z5 h. a" _0 c8 ~ - function __construct(){" l" P! _6 T) s$ s" T5 p
- echo 'I am one!';
0 t) ]) l' o; k1 E - }
8 D6 d, N) o0 \. ]' R& V - }
复制代码- //name.php- R+ | p5 m3 L
- require_once './1.php';% t; H9 P5 s4 K3 d' K( `2 }
- - M! L! f. P$ b6 I
- new Person(); //输出 I am one!;
& }& m) S3 u& i8 U" d$ ` - new \Person(); //输出 I am one!;
复制代码 ! p4 ^7 ~2 F( Y
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php, C+ F; E( h" \$ h; c, N# a
- require_once './1.php';
% I" {0 r. N% J; w - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 ( Y& t$ K1 Z7 Z# {
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
) W: g9 H4 q' k8 m1 ^9 {+ D8 T, b/ J - namespace one;: n% p/ f2 E X$ K' j# J* L6 E& X
- class Person{
; d6 B. W4 j* b" `5 p% b - function __construct(){$ d( e( U# C5 Z9 X* N. K' I& @+ q
- echo 'I am one!';
; z( l. t' j% v9 [( L - }$ B* I9 ?: U" J- ~2 E8 Q
- }
复制代码- //name.php* E$ R4 [ w- j) I e& y
- require_once './1.php';
1 g, P9 M# z1 z. o - new \one\Person(); //输出 I am one!;
! e3 h8 O9 y( M" T% p - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 4 E9 y; K/ i3 j3 k
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
' n0 f u5 E8 k. r e8 H& b5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。" J+ k) }8 q% l; Q* M7 F8 C7 ?
- //1.php $ F8 h. b# j4 U g; U# G6 A! y2 M
- namespace one;+ y: D( ?* A# K
- class Person{+ w4 R5 u1 C) [4 M& K9 V
- function __construct(){ q2 J( ]/ L( _2 M4 f
- echo 'I am one!';
- Z3 Q" Z% Y: U8 U5 e ~. J$ p - }8 |, {+ m/ b6 p8 M1 x+ y N
- }
复制代码- //name.php2 I6 o/ S7 B V: U
- namespace test;
/ w+ f M& a' a$ M - require './1.php'; , \( y- s! T9 E4 T# e9 t- A. x
- new \one\Person(); //输出 I am one!;
# B; g. ?* a, ~" s - new Person(); //这里结果会是什么呢,猜猜看
, {5 Y9 s; j+ A) e/ n; }2 A - 最后一行结果报错:! d" x3 Z7 Y5 |8 i6 x
- Fatal error: Class 'test\Person' not found
复制代码 % Z$ ^! P6 @, t; }( q6 R
+ m3 S) U u$ f5 t& G6 I
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 + @) N& X& i5 y8 l$ S+ s# q- Y
结果报错: - Fatal error: Class 'Person' not found
复制代码 7 O' R( _6 }+ ^' N* I
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
: t( T# X5 j5 W - namespace test;
0 g# V8 k# s; |& P2 t# h - require './1.php';
4 Z3 d/ y4 v0 M. K0 H+ R* B - ' k: A& a0 p$ h/ f2 P4 G; U
- class Person{
& X0 [+ ^7 ?9 r0 W' y7 H - function __construct(){
8 r# s1 J c% @6 v! Y% W* _/ t/ ^0 t - echo 'I am test!';) K4 e9 K. p3 F. h& Q! v
- }
" {( H' \& u& I - }
* T. \1 [8 T) L, }3 q1 C3 T4 Z) a - 9 a& j: `6 a& U
- new \one\Person(); //输出 I am one!;3 ?" o' x6 K2 f2 l+ ?4 S
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
0 y+ W- U4 Q) a" N# ^( f最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
2 y# U4 f2 O5 H5 W- i/ a - namespace test;% h& }$ T: F% e; m/ c1 T
- namespace one;
3 |5 Y5 y" g3 D, N% B% j( g( \/ V - class Person{
0 ?* f, P# E' k - function __construct(){: s j* \/ @5 \1 n
- echo 'I am one!';
7 h+ J8 s% b6 I. H( Y/ b$ I% U - }
# B( a+ p, C# O, D - }
) b+ X# Y* x' B( c, j - 3 h8 {/ F7 O: k2 e, K
- class Person{
) t9 {3 b \2 b" U$ d - function __construct(){
# X: R1 l8 z) f' Y; c - echo 'I am test!';$ h, L) u! J: N" {
- }
! w2 d8 A( K' b - }
复制代码
. V$ K5 N* A* p: x无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 3 H. Z: W1 H N
看来简单的把require理解为替换,在这里行不通。
7 O$ R0 R2 _ \7 E! e% w4 Q6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
' k/ E5 U# q# H# u+ m h. }- //name.php8 }' {" e3 W! b3 n* z) X H# t
: H- x. C4 U0 m/ l- namespace test\person;5 z; p/ S5 h9 U8 j/ U' d
) N0 ?! b/ i0 `, L- class Person{/ y' ?% `+ x2 ~' Y! b) T k
- function __construct(){
# H+ o# p) E# C* ~' [( t! l - echo 'I am test!';
3 m9 H7 a! {* |. I8 u - }
8 e# m( ?8 O3 A2 U! l y h - }& ^& |( |6 Y( k0 x3 C$ U
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 - c: }5 H& T3 r4 y% V! s: i
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
4 E b6 ?! W& j/ q# Y" l+ a! I/ K7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php& _# k; Z! {$ Z, a. T
- 4 N/ i# S- Q+ {, v; n
- namespace test;, R) S7 U/ S5 N2 [' b$ Z
- echo 'zhai14';6 z! p8 @- b9 s& \: M/ s
- namespace zhai;+ u' T) S+ {3 N
- require './1.php';
复制代码 2 F$ E: V& `9 t! W& Y1 i, X
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
7 H3 G+ ?) w2 n. R, vuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
* U9 y4 `; ^% t3 I) I- //name.php
4 Q6 T1 ~% Z# B- ?
. Z( k5 M; ~. @! U+ |/ F- namespace animal\dog;
4 m2 m1 C- u1 a7 W- E' L% D* C8 O( L, c
2 [# s9 ?0 o M$ ]* A/ n, m- class Life{
% \. Q' d6 c$ }1 Q4 o1 y# @4 ~ - function __construct(){) @1 j2 y: {0 ]/ n# w& p/ _
- echo 'dog life!';1 I6 v. q# @! `% p
- }7 h6 g; f- z w# }- A
- }
/ I9 F) `6 A7 C. _& _2 o% e1 t
1 d" s, }% ?2 O G6 P1 |1 l7 [4 M- namespace animal\cat;
1 M3 c" {: E4 z2 T4 `: U }3 S
' i1 ?" |! x: H9 V/ o! A0 _ f- class Life{1 X0 j, s1 x+ \0 [9 N
- function __construct(){
& L: ^' P: m0 w) E1 t; q d - echo 'cat life!';+ A2 p5 k! l( N5 Z
- }2 y- y; r) e8 ]' L- f e, c+ x; S3 O
- }
s9 ]4 m e4 Y9 \3 L5 ]
* A' i7 U x4 u$ {: E0 t$ T1 u2 D- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
. w/ T& l* l9 b$ S1 s5 W - new \animal\dog\Life(); //A
# q1 V' V1 ?0 J: P, I2 J$ D - O( n& g' O: [' F
- use animal\dog; //a
r+ {! j1 r' k - new dog\Life(); //B
8 q( \: n3 k$ C7 Y2 t5 _- q, N D
3 R: }( V8 h& o5 g! L- use animal\dog as d; //b3 U: V Z& _+ p( v0 c9 X s
- new d\Life();
复制代码
" @4 f {7 }/ ^通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
# Q6 q m% z3 F2 c; ~8 m ?: A1 t通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
1 E) Z6 B" A" m' R, e9 k: c相当于
7 o: U6 |+ G! `" O: S5 f7 Q2.namespace后面不建议加类名,但use后可以。
& b7 }0 e+ ?0 ]5 y- S( X7 v- //name.php! r) L i4 f& v7 m) o8 v
, A" P4 |$ J- X& p- namespace animal\dog;
# x0 b, ~5 R3 r* K% N) y+ q9 o7 `% d7 K+ G - 9 q3 N3 y) _( N% ~
- class Life{& L) D d) H2 E" R, a1 e
- function __construct(){. y. U! L: p. p
- echo 'dog life!';
. H1 O% Q" E8 {& n$ D, L; f - }: A4 H& K/ @$ X' d3 m% a
- }
7 r: H! C( d1 n5 Y3 Q& O
7 L6 x1 i, i4 u) [5 ]/ q* E- namespace animal\cat;
3 q: W2 P7 i8 ?7 ?* o1 D - 9 \; g3 W e: q6 U9 G( p( @
- class Life{
3 e/ O g: U& y0 q1 o6 _ - function __construct(){
7 @3 Y4 O, e0 [9 _; v+ _ - echo 'cat life!';
5 O. }0 o" D' ^1 N/ ^ - }
% I( E$ N- J3 C9 D0 Y7 Z+ c" i" I - }
* C' K+ M! L; B4 ]4 g
2 c+ K6 R. e. ~6 _" ~- use animal\dog\Life as dog;
# E) v; Y& @+ S) E( p/ ]3 t( K3 [- Y - new dog();
复制代码 $ |' ^6 p; s8 s9 K
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
0 ?6 Y) d( c3 H/ {因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
8 U0 S/ L8 w6 F8 x( _ - Y, S# p; i" D* m
- namespace animal\dog; x* O* k: L P5 u
- , _- A; O$ V# E/ R
- class Life{1 V- @6 n1 T5 r
- function __construct(){& u6 A* I! J( v
- echo 'dog life!';+ M. g( @0 _/ L6 B
- }5 A$ ]3 z) e' I3 v
- }1 k, H6 \, a' M( X& i
- class Dog{& D& }7 p1 ]/ n6 w5 {) {( Y3 k
- function __construct(){
- ]. Z" W0 i! s) S/ h+ t - echo 'dog in dog!';' s+ A6 w/ a1 W8 C/ F% c
- }1 S/ w. |+ z7 n' T+ J) ~! i. d/ O
- }6 G2 P8 [, G5 @
- : ~' Q' i) [: F7 }1 }' |
- namespace animal\cat;
: |- ^) X1 D1 J2 J; o; D+ O - % @4 ]! i e2 Z2 ~0 _9 W
- // class Dog{ g: a* s, V6 A5 d
- // function __construct(){+ \" J# k- t" g P
- // echo 'dog in cat!';
4 {( ]% R7 x/ X' g# S1 u% r - // }
1 n. J) ]& N9 ~! ^ - // }) G/ J1 X0 b/ j- j
- class Life{& _, D' f# v; D9 H5 s3 O
- function __construct(){
+ Z7 q4 _; F0 j- H9 q$ S* L- {% K - echo 'cat life!';7 S1 {! I$ [0 G: f; k: n" E
- }2 ]0 E8 R6 \2 D+ ]) b- V( ?# Y) P: f
- }1 j/ N& T" a* S
- ! t; H: i/ h8 H) _. f0 M. h6 U: g
- use animal\dog;
& t% T& C6 v, b p7 R+ B: Z - new dog\Dog();
复制代码
( A% p# r8 V- m- l+ U4 i如上,使用了 X) i, \6 p# j& }% c
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 , B8 U% w6 F3 }' r8 _( ~
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
1 r" R) Q) x1 `( V b' w5 V, e$ q3 A7 {% T
7 y6 L7 U# s c2 [3 a) u5 k
" B! X+ C: J# c) e; J6 a# |4 y( B1 G9 Z1 }5 N. C, c% ]! L
|