以下皆为本人自我理解内容,如有失误之处,请多多包涵。
; @% K, r% O. b! D7 t$ L文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 / e% y+ w" ^+ W" }7 y
4 X% Q- l( n- M A+ x T使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 0 W+ A8 B: A4 R8 K
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 9 c, o8 C0 F5 T& A8 p O5 f
结合使用方法来进一步理解它的使用目的吧。
+ j ^8 C( v. `( a/ E+ Z7 j" H0 w1 X* c- r
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;* g1 T/ r% M' o3 ^& Q# G. F! ^
- namespace One;
3 x9 r+ A Z* o% k, p. A - namespace ONE;
复制代码 : \8 H! G% k! q/ k- T' u; l9 }
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
n/ `; l; @8 J: j2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
& i* a2 e% F8 ?- C: a7 s - class Person{
9 {2 k; ]. Y* s3 { - function __construct(){+ @3 B0 f$ ]* u; h
- echo 'I am one!';
& L$ `7 `6 {! N S2 C3 A2 r& } - }
( P# t* k- F& ?: [) ^ - }
复制代码- //name.php
0 l, k# J _* h4 A: U/ w - require_once './1.php';, k# U) N1 l& e) m4 L) ]% Q6 A% j
& D: g- _7 I& z" g: a4 g- new Person(); //输出 I am one!;1 x% M9 M* |5 R" J8 D8 n
- new \Person(); //输出 I am one!;
复制代码 . @8 A! W; q9 ?7 c
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
4 E8 J( S0 @. l+ v! B; C. T# ^ - require_once './1.php';0 m# n, } X K# r
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
) v" H8 Q0 F' ?# R3 q& E1 x+ B, @3 t4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
' P( c, J8 Y8 v+ S( z3 y - namespace one;
+ a" k, ?0 Y0 d* G5 D - class Person{
, F+ A# t; H/ S! s9 K i - function __construct(){
' O9 G1 b. {# b+ K" u - echo 'I am one!';8 ?2 l* S8 j+ \: c
- }
v6 }2 b& c# f! B Y - }
复制代码- //name.php
* s, g, t$ z% E0 g& q - require_once './1.php';0 K8 t& `# b; Z; ^
- new \one\Person(); //输出 I am one!;5 M k( C) c6 `' j- x
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 9 ^5 w. n2 g5 T7 T- F( P
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 - E; k. s0 j+ Z' K2 `& ^
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
5 e, y) V4 I T5 ?8 q$ M6 w1 |- //1.php 5 i2 L: {) O6 t9 Q+ U" v
- namespace one;2 `" O: Z- N3 m7 J5 z
- class Person{
) J* t: H5 D+ {8 Y) r+ ] - function __construct(){
4 A( C: \; v6 A& G% T8 V3 g - echo 'I am one!';/ P1 w1 Q7 P8 ?9 q
- }
k$ {3 m _' f3 F5 X2 n - }
复制代码- //name.php
4 g$ M- n- B8 ?: ^! |! a - namespace test;
& \, i8 X* p; d8 y8 i - require './1.php'; ' P5 G: M/ ], U0 s
- new \one\Person(); //输出 I am one!;
3 Z" V1 V r! ^) u; B, q* v - new Person(); //这里结果会是什么呢,猜猜看
7 p9 N5 w$ {6 g+ x) t+ c2 T - 最后一行结果报错:9 A" s; ^, Y' i% b: F8 a
- Fatal error: Class 'test\Person' not found
复制代码 3 Z: w( P) X& L6 p5 Z
7 _2 S4 S0 l" O4 G; U% l( J首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 / |$ ?0 L9 T! B
结果报错: - Fatal error: Class 'Person' not found
复制代码
% U, R' O. {; u5 `+ j7 l5 d接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
1 k, [: K6 F$ x: O- s - namespace test;5 l, _# l# g0 h7 o
- require './1.php';
( ~5 t: X6 {+ o) w: e/ z0 F
+ x$ `2 J7 f5 ?# j4 X- class Person{3 k- B3 e, ?3 |7 i
- function __construct(){
, u+ s, l$ w2 A4 O4 K; } - echo 'I am test!';% \/ X; _! h# y) ]
- }7 \$ h# O0 Q/ M9 B3 {: J* k- E, |
- } a3 ?" q8 D! B: H9 H
& Y3 F$ ^, ` n8 _- new \one\Person(); //输出 I am one!;$ u# M/ R [# }- L
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
$ n+ \- M6 I" ` @9 p* U' p最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php! ]4 ~$ m1 Y$ N) W) H$ _
- namespace test;2 q. T# d# g, |9 {3 g4 c
- namespace one;
0 t% Z4 r# ^( E. ? - class Person{& o& i7 {) x( ^* O8 a* m
- function __construct(){4 N2 h: D! D2 ?7 J* i# x1 ~
- echo 'I am one!';! U# F( ~+ T! `# s
- }
+ h, R P: L M! o# Z% k8 Y# K% w - }
4 u5 _& f \- ]7 S# M) w) q' l - - W. _1 ] g" j+ X8 H
- class Person{
0 V5 }$ E! A& f7 W# }* [0 F4 h - function __construct(){
7 ?2 J- A4 ?) h+ I$ ]+ J - echo 'I am test!';' @( A. B* C2 W
- }. `. ^) D5 F4 r
- }
复制代码
: t1 d4 c' x& s4 Y8 b# M无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 4 ~3 B' b6 r& q! Z5 o) T
看来简单的把require理解为替换,在这里行不通。
2 |3 E2 I2 I8 T6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。; K2 L# A" R2 Z0 O
- //name.php
# K r+ ^/ Y' \" L
/ a1 E( ^+ l! D! v$ k- namespace test\person;
0 @* i2 q8 I! {( I, q% P; Q8 f - 8 E; a( k% a; k7 K* y1 U
- class Person{1 M3 j! V) w- C& w0 k
- function __construct(){6 ?! _7 ?" _. g1 D# t4 z
- echo 'I am test!';/ ]0 V5 `8 D b* ?1 W& J9 j; [7 R/ `
- }
2 l7 b- D/ s& c2 B% B( B - }
3 Y1 [ G) Z3 Q9 B5 R. K4 C" q+ A" c7 ^! y - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 / Y) I+ o8 j9 f
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
( m# j' ~# o [7 V: [7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php) I: p( G8 b, O5 ?8 R: [
0 \, M' E0 p/ b5 l p- namespace test;
$ k+ c+ L# {# ^3 F8 r5 v* z - echo 'zhai14';6 R/ Q$ q0 f2 s9 ?7 u" T2 q% X! e
- namespace zhai;
0 a- E2 R5 t1 Y/ Y! s - require './1.php';
复制代码
# Z; }( a( t5 a8 B5 X/ t9 pphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
& `3 [5 U+ E0 j/ ?( R8 M. Duse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
% {% P* ~9 o. L8 M# C- //name.php
" O. a% p- c L2 a7 ?, P/ @
/ z( a+ z" W3 G' U: s- namespace animal\dog;
) Y5 V5 I8 Y. \, ^* y
/ \0 m: `% w, b( ^* n" a2 x( u& O- class Life{
7 K5 W# M) ~0 k; g! u1 M# j - function __construct(){
( A- ?; \% K3 S' w5 m - echo 'dog life!';
$ k g3 J) j1 g - }
( I5 c& J: a; T& e6 [ - }* ]4 ~ O+ ~: ^, i/ \* K! H5 _
- o( p% r; C$ o y: W- namespace animal\cat;
5 M. l9 d; K/ \" u4 B - 1 z. k- W/ ?) S' v$ w- R
- class Life{
$ v- q j2 x/ x" ^, e0 a$ X/ c - function __construct(){) R& s5 {. `. W
- echo 'cat life!';: p9 Y' H1 ?2 v6 R- P2 N+ i" H/ N) }
- }' E) _1 N" s# V
- }# O: e7 E( N/ P3 ~- p. |0 z* F e5 @' V* D
- 0 @' ~$ I# o0 q
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间+ d R5 N/ U9 c/ M" I
- new \animal\dog\Life(); //A
' o# T- O' C- g' u! q0 ]0 \ - , i: F5 T5 v3 T! P1 y; o* M3 c
- use animal\dog; //a; N6 B# S1 _4 d3 Y) x1 C0 b3 x
- new dog\Life(); //B8 U" Y+ f* s- n* w) T8 H' N$ V5 U
H4 d* k5 \5 ]. M9 i- use animal\dog as d; //b) _9 P* k3 _, I' J
- new d\Life();
复制代码
! V( I) @& g" L. {( r, C' K l通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
9 t" s9 Y& H6 C( t: S通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 5 ]; S: R% o- l4 q6 l9 W0 I2 O
相当于
, _+ @" E$ @! X9 ^- s2 c9 `3 \2.namespace后面不建议加类名,但use后可以。
# J# k2 w" [5 p( i7 l3 Q- //name.php
[/ K9 j6 D6 C3 s0 u9 x& _, a' u - 3 A1 N5 w! M' v# M
- namespace animal\dog;
; P* B2 ~' B4 ` - 4 ?) w r6 u1 d/ y* P# J
- class Life{
: P4 W# k: i& F5 }* N' y/ K9 W% D - function __construct(){
3 T9 m5 ]& i: A4 L: k1 | - echo 'dog life!';$ n4 I Z3 ?6 E& B/ Z. a. h* N& k
- }
* A* R) g1 @0 [) v5 z - }# ` g9 f% O0 V; c7 q# ~
- & J( U4 i7 H' j5 V- e2 m% [
- namespace animal\cat;: Z8 l% \7 s" Y$ j' X9 k2 R
% Y' _* C' |* c( }8 p, X# N- class Life{& g0 E7 `; T' T! D' q5 n
- function __construct(){
" u/ N4 g3 n* S$ D- ] - echo 'cat life!';8 R/ M0 g7 S4 A, ?) D) d- p
- }$ {9 P! y( |* H2 T3 ^/ Q
- }' S: a% k5 Y) N5 @; w
- 0 Q. `' o/ i& M D# v
- use animal\dog\Life as dog; 1 c* S1 _, O7 @9 d, {( `
- new dog();
复制代码 ; L$ R$ h% ?$ d7 J) s6 @
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
3 | G7 _5 K1 Q因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
8 g+ K* Q% X9 k9 r! r) Q - 2 T) f' l( K5 B$ ]9 \1 E" s7 {
- namespace animal\dog;
/ J5 Q! \4 O5 C- B - & T; H8 M ~& J5 e
- class Life{
; l( k8 r% k# m' n - function __construct(){# [. Y" @7 U. B& [
- echo 'dog life!';
2 G2 V9 e r( T" Z) ~/ P# x( s4 ? - }2 w5 K% h4 F1 @8 A# v
- }
% w3 | G! w7 U+ ? - class Dog{
' h; |, K8 j9 W" Z - function __construct(){4 _9 T+ u: `$ M* o R! H
- echo 'dog in dog!';! }) W- d1 I. E. u2 Q3 e$ m2 z' c
- }
6 q9 m0 H, o' F - }) W, E4 _- K% m3 f3 k; R# K) O2 y
$ }2 r0 A b6 X8 w$ q6 v% ?4 I z F- namespace animal\cat;( P% ?. B5 y" w) | r0 z: w {; M* f
% l- L4 l: D" ^7 I, M% i- // class Dog{
. w6 g8 \: X$ l4 S1 q1 |: K, Z - // function __construct(){
- k3 o4 T3 ]/ p! z - // echo 'dog in cat!';
_: Z. T, {. A& o - // }: n: ]% g. c; ^
- // }
1 n2 G1 G1 Q, R& c - class Life{/ R* j/ [- P3 g& z5 L0 H$ C
- function __construct(){' e! } o; Y' C( I( r0 m- ^% R
- echo 'cat life!';/ D" {- N( l+ c' v4 ^
- }
) J z1 W2 U/ ?$ T& ] a: m - }+ k$ |' U: A* d- C8 w" t
- ' ^! h b/ r$ M* ?- r
- use animal\dog;
& b0 o1 I' ^: T, i& b- y, d - new dog\Dog();
复制代码 ! u- S# d. }. R1 P4 l' I- U
如上,使用了 ' v. z- [) w: l! q3 s T# L) v
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ! h* c: G8 W2 b7 c
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
; s4 y* r- ^4 \- G8 G! C; O. X9 t% I2 h# q. j( C5 K8 ^: E& b
% c/ b1 h8 g' D9 X# \
: _8 |% ^: Y& M) a, U) a" v# E, \" d' v" T, J* R4 W
|