以下皆为本人自我理解内容,如有失误之处,请多多包涵。
2 T. V0 [# o2 \/ T) M文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 6 e/ `8 R. l* F1 o$ d
" ~, g& ?! P" U, O b6 @& C1 ]
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; ) v8 ^ X3 T' o) Q8 L! |) R; h X
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
: ^, x9 L7 r& s! c1 @结合使用方法来进一步理解它的使用目的吧。
, R7 x0 j, d: O8 R+ H
: ~) D5 J$ b: D# B. Dnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;0 n- a% |( V2 W, U1 i3 c9 R* ]
- namespace One;
l! @9 @$ W. l7 {3 T* P - namespace ONE;
复制代码
( q1 A3 P8 ~' v# w% n* J2 B; ~* Q# L0 j如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
) Q$ p7 P7 X- ?* g2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 2 F. r; z7 i* [+ j
- class Person{
5 l- |' T9 U3 z0 q O - function __construct(){
/ A. ]/ G9 M# f* G - echo 'I am one!';
b; g5 J# d+ N% Y5 `, Q5 a - }
6 w. {) F8 c9 W - }
复制代码- //name.php
* {+ b/ l; l) s( V# R - require_once './1.php';) }2 t! y- o0 O/ F; O* S8 m# ]8 U
, y& X7 \. o1 B2 V4 S- new Person(); //输出 I am one!;; \: n- y2 v S
- new \Person(); //输出 I am one!;
复制代码
8 \* l/ N5 U; C3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php2 }( N E% A4 w0 c7 p2 |0 d% Y
- require_once './1.php';% r* M8 J( O4 k' D# U2 g) C \
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 h. r8 A- C9 X3 g x
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php - Z( p& I1 G4 v y6 L
- namespace one;2 b, P+ q% {+ c+ R, x- m
- class Person{" e# x' S" B% P* [1 Q6 Q
- function __construct(){0 q! W" F/ e( j! R* M5 j
- echo 'I am one!';
) X! e k- u! L6 d6 ?$ |) o9 z; e - }' z0 N& O% {6 r1 {& O) X
- }
复制代码- //name.php
1 _. p( K. T2 ?% C& u! }/ k - require_once './1.php';/ C4 H- n9 E f' d4 I* X9 A
- new \one\Person(); //输出 I am one!;' z- ^/ M8 s/ Y2 F( \
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 / R- R0 ~: m, r. X8 Y3 b
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
7 j/ c- W3 y5 ?7 z V5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
7 E& A& b& V1 j- //1.php
4 C$ z6 P( w) G: e% h) Z' j5 K3 p - namespace one;
1 a* x% V2 `' K% q6 | - class Person{
( v$ G! R/ N/ K3 C/ O- X4 w7 z - function __construct(){
- K$ Z4 @$ R5 u( ^0 K- J - echo 'I am one!';
% \' I- b" {+ Q+ u5 ~- ] - }/ E. R% Q5 b9 _0 k' k* ]
- }
复制代码- //name.php0 [. x" o! L4 Q" k4 J' E5 F8 ?
- namespace test;9 P2 h/ A6 M! b
- require './1.php'; * y/ V* p& ^+ p+ _; B8 y
- new \one\Person(); //输出 I am one!;
' Z. v4 M+ _0 }0 a - new Person(); //这里结果会是什么呢,猜猜看
6 t. w0 A2 i8 r" [# D& a. B5 S3 ? - 最后一行结果报错:
4 S/ _5 B# J; Q+ v* K% L - Fatal error: Class 'test\Person' not found
复制代码 ) a! {" f% o# _& _6 g
* z: x9 r/ F4 g1 y6 Q
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 & Z' h. w5 d+ P) i8 V: a
结果报错: - Fatal error: Class 'Person' not found
复制代码
$ F2 C0 T3 l2 N% y9 Z* { {接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php5 _2 q4 K ? b. l; k, G
- namespace test;* m6 ^5 p6 n* H. K# {
- require './1.php'; ! O" H; x. d8 @$ @& x
% {7 _1 A+ j& s- D8 c! l6 g& @- class Person{" X/ ^7 T1 r0 E8 p- N; e' q. u
- function __construct(){
2 e& M" J8 [1 N - echo 'I am test!';0 ^( e, [0 ], i' I. d0 e+ I
- }9 l k9 `0 ]0 ]" ?3 [6 p
- }; m ~* B, j/ `5 g2 J. n
- $ f# i, n3 l& L8 K* T G
- new \one\Person(); //输出 I am one!;
* Z# i _: L d1 o - new Person(); //这里结果会是什么,自己猜猜看
复制代码
" q" h: m* T) \1 T$ }* a最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
, A3 C' ~/ P$ k7 I$ {$ \ - namespace test;# \4 U+ R: ]9 y8 ^9 U& j
- namespace one;
. @3 _( x' C# M! g$ t: q( Q - class Person{
& p3 o/ a+ s% k S$ E% s - function __construct(){8 l3 ?, ^" G6 a% \/ H$ g
- echo 'I am one!';
( B# ^# c6 w3 G6 L. E g - }
7 ^" J" a7 h$ d& f - }
8 i: G9 X4 k: L) X% M `; g* A
5 l! q5 [, j4 K2 D* C, }5 f/ P- class Person{
2 i" _+ Z# I7 D. B2 |+ h - function __construct(){
% C7 n* t. x s - echo 'I am test!';
W; t- e8 F" t - }& K5 d, n# [, i' U* b7 n; L1 ~
- }
复制代码 , s$ {5 A5 R# s* @
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 2 C) M8 W& U) [2 r
看来简单的把require理解为替换,在这里行不通。 . I( y) o7 g9 `0 u7 Y$ I3 i+ J) k
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
0 s$ \0 Q- u, j) p# a7 l: H- //name.php U3 a6 t: o& w2 X$ |
* u. w1 e& \* b; d& T- namespace test\person;8 W- o& S- M7 `/ ~1 L) X3 n1 C
! k2 w* ^ `4 P6 r. W0 m- class Person{
: J7 Y1 S) u' _) m& O& V - function __construct(){- j A' f* D( ^$ a5 C) e
- echo 'I am test!';/ P6 j9 g& q; {8 q% l2 S; c
- }
2 S- A+ S' M8 K3 \ - }
2 K3 S3 F! D9 V* V% x: c9 s/ m8 v - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 ' z$ e- Q9 [% {5 J" E
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 7 |. ]0 H5 O& X0 I' @0 L* L
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
, z% G5 i4 t, T6 I - ) K0 k, ` i5 I& P9 R' B2 |
- namespace test;, V: y) c9 a' b6 m- w
- echo 'zhai14';$ x0 a! f- J5 V9 ]) t! j
- namespace zhai;: `8 h* l3 ]+ u9 W
- require './1.php';
复制代码
9 |/ R/ v7 m9 Cphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
5 \$ X/ k1 K) P0 j5 D8 n) h- ^; Q2 Xuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
3 R N ~( H6 {, U! q& n( V/ A5 i- //name.php4 F$ {* m& R' V k0 Z
- ^& E4 y8 |3 @% w: K# y8 S! L- namespace animal\dog;
* ]& P2 a+ q$ {3 ` - ( y) d" n5 E" t7 \
- class Life{
( O3 @8 l/ G) {! @ - function __construct(){& e" t2 W- o+ n% J
- echo 'dog life!';
% Q6 k: h" k3 Y7 @2 M3 |2 N5 I+ d - }* d7 @" m" V$ P& I; k
- }1 S8 R( U# S4 L0 h9 `0 a4 [
- 7 E; S; O# v# Z) T
- namespace animal\cat;
; n6 B6 e. t: F9 M0 K- Z* U' n - ; y6 e( a! x$ K' c
- class Life{& o+ o- {/ s- y1 }5 z/ N X
- function __construct(){
1 I1 w+ L* l E9 C8 A - echo 'cat life!'; Z6 I7 O+ y$ U
- }: V) V. l4 _ I6 `& q
- }
- s2 z2 z0 P8 e q$ z3 L! ^* \4 c - 6 D% y- a8 q; J7 m% a- H. B8 v
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
0 b8 L% ?; n+ H3 m - new \animal\dog\Life(); //A
) C' r1 ]+ f1 _7 U& J8 F" Z
* h7 |5 l" Z: P- use animal\dog; //a1 c c" G' l" p
- new dog\Life(); //B, F0 L( Q% J. p1 n7 N& J% P
- % G5 l8 C' g+ I2 I$ ?0 u
- use animal\dog as d; //b, T- D& M9 F# c& t# ?; t
- new d\Life();
复制代码
' t% v8 t" Z4 D1 B+ f/ j通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 * q# r; H' h( V& j
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 4 C# f, w( K! x" @5 s
相当于
, S$ d7 s$ z2 u. D e T2.namespace后面不建议加类名,但use后可以。
2 _* L8 v, ]5 I4 ~- //name.php
2 r* h- S3 b. l' \7 {5 H+ S3 D
) [* _& i1 I' L3 F0 o: n- namespace animal\dog;
N) W& d: h* J5 N) N9 T4 ~$ ]! b
0 L: v7 Y+ L. X$ e# [4 x- class Life{
6 R/ G/ J% b& R; y$ g" m - function __construct(){
; o; G4 g" w9 v4 O& d9 ~ - echo 'dog life!';
" U: u4 a4 x, k1 c$ c8 l% L; h - }( ?$ J3 Y+ C" _, P _
- }; T e% z( H5 B6 S
; r; e( |1 p, z; a- namespace animal\cat;
1 a3 |( k' g' A1 z& V$ m" _- S - 0 T& r" u3 S0 C. W4 x
- class Life{8 [; d. W$ v. V1 E( ]
- function __construct(){
$ u* t! {+ ^& c$ ` - echo 'cat life!';& @) K- B5 v: { \1 o3 Z- `
- }; n5 S$ _3 E; O+ ?4 r6 P
- }) {: g2 G ^( w! P( d
- " H* e' j3 X& n( z* e
- use animal\dog\Life as dog;
( h$ B+ B- C* h& \ - new dog();
复制代码 9 t& q! u A% ~+ x! K! H
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
& x0 i. b4 g$ y8 ~& ]3 o6 o# B因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
# |# O/ n7 L- N$ V/ l6 B' { - ' A. G ] a4 m$ V: \( a
- namespace animal\dog;
/ h: ~/ F! Z7 b1 x+ r2 j1 h - + S) E2 S) Y5 k; h
- class Life{* l8 {$ I, U5 u) Q- `; s
- function __construct(){
; u# @# y/ F) {* D/ l) ] - echo 'dog life!';2 e; c% g5 V/ f; s; C+ c0 e ?: X: S
- }+ F3 E# z% _. i% l# d8 L) ~
- }
@! B" V7 f0 [+ x1 o/ { - class Dog{
# Q: j4 G4 h& ~$ l - function __construct(){
, `" D* G# Y. d - echo 'dog in dog!';
/ y; Z! N. f. b! j; ~+ l - }( e. A# ^! j% C7 V' A& P/ V8 |
- }0 t" B2 }/ M, g3 {( M6 I! g
- - O c3 R# Y8 s' ~/ }
- namespace animal\cat;
+ H- a! i, n5 g' O8 @7 c) j - $ `% H6 V- B* N# Z9 C- C
- // class Dog{5 h8 r8 A3 ?! ]+ ?( h
- // function __construct(){
3 ~. ^. H) n2 [. l) m - // echo 'dog in cat!';: p) c+ c2 Q2 y1 \) T# i
- // }4 D1 z" K x* z0 I" K
- // }3 A- _* K1 Q P- g- r6 ]. d& W# B
- class Life{
! d: y* J1 w; q, }' L - function __construct(){1 o! M: b; ~, c0 Z7 S8 L
- echo 'cat life!';7 v" i' P7 @2 `, L
- }, G, ]) `' _: e! |, I: j
- }
9 j" `4 p, e: R6 o- | - 5 X% `$ K+ O: Q" J' s/ P4 c
- use animal\dog; 7 v" E t3 w' J) U& _1 L9 P" k
- new dog\Dog();
复制代码
2 F' e/ B" n$ h$ O- b( h如上,使用了
6 ]8 o8 l- T9 z [) D- Xcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ' w1 [& z0 G) k& T
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 5 }4 z8 @) a7 o
9 L4 l9 d/ `: \: l7 {. ]
- M6 w- B$ w0 S; h/ U
+ c/ T+ ^ ~5 m3 H* h3 l+ q) ^0 S8 m: f* Q6 z8 t8 ~: m+ H
|