以下皆为本人自我理解内容,如有失误之处,请多多包涵。 ! B8 i0 ~! ?- t4 \/ }4 f$ h
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
7 B! g8 a) @2 a' f! r7 e* l9 g' k* f
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
1 \( d+ Q, m; f# M2 E: b, j据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
/ X8 k1 ^, S) s4 j; b: s结合使用方法来进一步理解它的使用目的吧。
- r' T) }6 _7 Q4 p4 V, p
l7 d8 U& v$ ]; } unamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;; E- `& D: H; d5 i
- namespace One;' ^* l% X! p4 h. u
- namespace ONE;
复制代码 ! ~1 v$ v+ ~6 P' x
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
+ U$ |8 ]: X0 T2 l$ s* R# e2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
; ~- Z; U# C0 ~* f - class Person{
6 i1 j4 b/ |# d- F" N) [ - function __construct(){4 w6 T$ s: r# ~# D6 B
- echo 'I am one!';
' s: Y1 y, M$ M: C# L; {: t, J0 D - }
9 @/ I2 T, X2 ]; ?! o/ O! F( m2 D1 z - }
复制代码- //name.php! d' |. S. @9 e8 N9 y( s8 D
- require_once './1.php';
* R0 ^$ `+ ]$ a& c2 Q l! w
7 n" T, k1 h# Z n2 i! z- new Person(); //输出 I am one!;
* a! x ]7 N) { p% J. r. c - new \Person(); //输出 I am one!;
复制代码
4 o, e+ X4 q" {2 `1 q) G7 i3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php3 \0 I0 Y' X* V; x
- require_once './1.php';2 J- d- I9 A7 f
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 8 a8 n+ B$ ]. [% n- J1 C
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
$ ?6 C# u% n( c- F' _ - namespace one;
- c4 |" a8 r2 _4 R* S - class Person{
0 M1 x: @& g4 q/ M - function __construct(){
( ?+ v7 u- T' F; A - echo 'I am one!';9 t' e, g8 g A
- }
0 ]) m" D" [6 r1 x( P2 I - }
复制代码- //name.php
2 }& }! ? H9 S1 d- y - require_once './1.php';# X. g) m8 d/ Q
- new \one\Person(); //输出 I am one!;$ ?, W1 B# `" q
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
/ v; r: M6 @ E Q! r6 t可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
4 }$ V; Z3 }7 n$ w0 W5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
7 Q" H# K7 C6 V5 |) m3 _- //1.php 4 k& [- |/ n2 _" ^% s
- namespace one;
' J+ Q9 ^& r( \8 b - class Person{. C6 k1 z3 S2 R/ J7 R
- function __construct(){
- Z- `; o+ u9 m- } - echo 'I am one!';+ }4 w# J# u) f, R, b5 I4 O
- }
6 Z; Q5 h9 E$ M, u1 r- S - }
复制代码- //name.php7 `+ |8 J6 C9 C4 ^( d
- namespace test;1 A6 g* C2 `* B! L0 W; q
- require './1.php'; " u+ x3 x+ d# _& [
- new \one\Person(); //输出 I am one!;1 t ~' E4 F# v `# z% p
- new Person(); //这里结果会是什么呢,猜猜看
! K! Z0 T8 E4 \0 R - 最后一行结果报错:2 X8 p9 a; x( I2 ^4 i+ T% b+ I
- Fatal error: Class 'test\Person' not found
复制代码
( x0 ^0 s# @% p4 T) {/ o% m# ^" l) D/ S% L5 s% x0 k& P- M
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
8 A m* `, |, R( n结果报错: - Fatal error: Class 'Person' not found
复制代码
: u6 J' b, X4 s- z接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
4 l# q8 q* H H9 b2 N( R; q# O - namespace test; \! r0 u6 y; N; n3 e- o$ b0 e) ?; {
- require './1.php';
f: m0 B6 x/ R# c o
1 ^7 q t1 F$ [2 k/ E5 G; x- class Person{$ p9 R: e& I9 x
- function __construct(){& s! v( P2 X& E8 H. L
- echo 'I am test!';' X& z% v& ?1 w x% W% p7 p
- }$ q1 C! B4 D" r" `
- } @( S8 {, ~+ W- R# J: C+ ?
, a R" s, X0 G8 N3 c- new \one\Person(); //输出 I am one!;
% n/ Z9 W& j, W* O% N - new Person(); //这里结果会是什么,自己猜猜看
复制代码
9 _% A$ @; Z0 P3 m) D$ [最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
- k) n8 z7 j% ~& x - namespace test;0 G: U' m$ D8 F
- namespace one;
5 t8 k4 C [# L$ S4 E! K9 y - class Person{
& l4 _! q7 S7 Q4 X+ F3 y/ }5 D7 L - function __construct(){
9 d& l8 s+ R7 ~9 E1 E3 c) G - echo 'I am one!';3 z6 F+ @" @, D. o" B4 a7 `8 G$ I
- }. u$ {: o. q, U7 B' p# _1 x0 P
- }$ p7 w( d1 W/ }9 I
, P- \8 y2 q% V/ I3 Q; _- class Person{
2 ~" t1 c$ `; z, u m0 A - function __construct(){3 \* L- }$ ~. t' M5 L6 d* \' D
- echo 'I am test!';* `6 |5 g, x+ [4 c
- }
7 a: q) Z. q9 p+ d P - }
复制代码 ' v2 ~* J8 M {
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 ) [3 O! q1 `0 g, D# A
看来简单的把require理解为替换,在这里行不通。 ) g- c+ m7 j5 B" v1 R$ H
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" e% [6 i* u. p; u- //name.php, F* {; }* c; Y
- : ?' |7 |8 W: c6 O5 J! l2 Y
- namespace test\person;
e4 s9 v1 Q' @5 S
P, F6 a% O m7 J- class Person{& V" J$ u9 o _- C
- function __construct(){) T1 X3 f% F o J8 }1 S
- echo 'I am test!';
- Z' Q z1 \0 J1 i0 O5 z2 j1 Z( A - }! B) y. c: _) g0 c- m8 l' `
- }
# `- R! L" K$ B7 ?# N - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
( V8 n, e" |& E- A不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
7 W, C/ r l$ F2 U$ p, V. s7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php4 k7 n% t; a4 j( u) a( b
- : p: N6 J1 U; u r' x, @5 O
- namespace test;
X7 Z- g1 q& L. H - echo 'zhai14';
& Z* @) V/ f3 _1 N* c! p - namespace zhai;
" y+ B+ |8 v2 u0 z - require './1.php';
复制代码
- e9 z& { t. C, g7 `1 uphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 / l) P. j. M" W1 y( K0 ]' H! e
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。. B( Z, w; T' z5 |9 p' V$ o
- //name.php
/ L4 ~, Q8 t N, [) z0 i! E7 j
: o3 b; ^3 G' x Y! I0 ?6 V- namespace animal\dog;
3 v; \ D/ \+ k% K4 Q! m H8 y - ' Q6 h+ C- a V4 p! h6 m
- class Life{) [8 S$ {( @* w/ G1 I
- function __construct(){4 ]- H0 P! ^/ n8 {
- echo 'dog life!';6 R$ w6 D- k6 l4 {" e5 O) e4 F
- }
( T U0 f$ x6 i: U - }+ t8 r$ s; B2 ]" y- G
- , O# V2 K( E5 _ z& M: S2 N% j9 r
- namespace animal\cat;1 ?: A/ J" r9 v! C( H
- % z/ v2 j6 R, i
- class Life{
9 F" d( e1 j) f2 |4 z - function __construct(){) n1 |% ?" @2 f2 t) l+ T
- echo 'cat life!';/ R6 K0 p7 _' n$ ?% s6 }
- }
7 f1 T. \1 c5 W - }
+ I( G0 s; Q+ i: [: K
9 J4 B: D1 D. s* [+ M5 a0 r: z l- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
' V% c E' G/ c - new \animal\dog\Life(); //A
1 X$ P9 D$ b& P3 B - & v* f/ U8 ~$ ]) k
- use animal\dog; //a/ U2 B" S) G3 k
- new dog\Life(); //B
5 U1 Y. @' m' i
. S% I' g* @5 J( R$ j4 n- use animal\dog as d; //b; X0 K2 r4 V1 p8 i3 \* r1 R- d
- new d\Life();
复制代码
) I* a; O/ j7 g/ O5 {1 {通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
+ B3 z' H! m6 }1 ^5 [2 w0 `通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: . g/ V9 x+ t1 O% d, k5 ?& X" U
相当于 6 L: ]' ?9 K d* s; l5 w
2.namespace后面不建议加类名,但use后可以。
! ~* C- d& T4 U. z2 p1 r- //name.php
4 k3 S( ]' q% j4 C" f) `
; Z, u8 J7 @2 c2 y5 F- namespace animal\dog;
$ U" _/ S! e( W% D; w& `
, A: w) s3 c/ l8 i& ?3 o- class Life{4 l+ A7 ^& r- z
- function __construct(){
9 X% s4 k$ R2 ~: l' s) i0 O - echo 'dog life!';
" o8 l5 ^7 V3 d5 @$ |, e, M; u- v - }3 i, @! ~7 p; {
- }
" M; y; u4 M) \8 }, c5 T$ y9 K, W- q( Y
4 Y8 Q' {0 D3 M* Y# O4 t! l- namespace animal\cat;$ ]7 ^6 H7 N+ Z8 X5 U; L2 d
- 2 j8 O: |, X7 F. p9 m
- class Life{
! D) H+ J; ?# h K) B - function __construct(){
! k( w u! N; K7 G - echo 'cat life!';; b. h: R% s! N! J1 |) f
- }: f5 G9 \6 a4 _! |# h5 ]9 ?& z
- }
; l8 Q# y0 x5 ]# m
" d# o2 q6 U- Z) j# `8 d2 u- use animal\dog\Life as dog;
- \3 `0 m) h& b - new dog();
复制代码
9 |5 ]: ?! I) e& n6 v如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 " @' Q) i/ C5 f/ j; I& l, O. t
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
$ T' h/ A4 J V0 k3 m) V* o2 f0 O) r - $ V# U2 J$ }% k) k. C( j1 L; A# H
- namespace animal\dog;
5 h1 b$ e/ |8 d, f6 H1 O' F( j! W% d
. ]8 ^1 X# n0 w3 c! V$ u& h# h- class Life{
7 k$ a6 T2 J* g - function __construct(){8 R; M( B! h( K
- echo 'dog life!';
9 T& x$ S# h) Y - }1 F; L! o3 ? u5 D
- }
3 L2 v6 M N& h7 C3 } - class Dog{
. \, y) [' t2 w4 _+ ~$ k& d, p - function __construct(){& K! A; v/ N8 Q% @) X
- echo 'dog in dog!';1 I9 B6 K f$ X6 R" e
- }6 }# Q" p" ^$ |% q
- }. u: l8 d# e5 \$ X3 w' F
- 7 _; F2 d+ n! P+ G% i* u
- namespace animal\cat;
. w& t5 V5 p3 q, Z2 D
$ u" G& z% C3 `# D6 C6 I+ @$ w- // class Dog{9 l k1 l$ L( W
- // function __construct(){
6 ^2 ?/ w3 d k5 T - // echo 'dog in cat!';4 U( ]8 S1 R6 }. | z# z' s$ e
- // }
. d F" L {( Y! B2 Z - // }
0 i' T, M, b! n - class Life{
4 O3 f: \# p+ l- P - function __construct(){; v5 v# K ]6 ?7 f3 s C
- echo 'cat life!'; n: w: j5 @; y q+ e# d: c/ Q
- }
( `5 V; |: M6 n1 n, b3 K - }
' y9 e, S. Y0 t: r: }: I
5 o; [ a( C: I0 |! q0 a- use animal\dog; ' v" t) y* C9 n# ]& o; C# c: E$ ~* U
- new dog\Dog();
复制代码 - z, G$ _5 G6 j1 R& b* ^
如上,使用了
$ y) `! q. ]0 Q* D* K! Tcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
6 h. Y* s% o6 x' E简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
8 D# b$ X8 t( X6 {* k) U" J# c& T# @# G# r5 C7 h& z
) r2 p- e; T" v
, G1 h g. [% i8 @4 l
% P7 X- l' P" h' \7 B5 U1 t8 M |