以下皆为本人自我理解内容,如有失误之处,请多多包涵。 1 C: T* @. k! r6 a. x5 C7 l
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 6 G( w- F. ]) y& `4 N+ n
* K6 U4 x$ [$ I+ K使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
9 Z5 o* X6 z. }8 a0 q9 Y据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
4 L+ V3 m* r1 G1 m, ]; E4 f结合使用方法来进一步理解它的使用目的吧。
, X( V, ^$ G* _3 k2 R: p. h- N( p9 G4 q
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;( }* }; R9 H" d/ a6 t2 L: J# v
- namespace One;& F2 _- e0 \9 v& G; @! R
- namespace ONE;
复制代码 # t) z# E8 z% ]* j" }* Y6 |8 Z
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 8 m1 q9 {; E+ A: X; t8 i$ T+ C' U v
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 1 @6 E5 C" U2 Q" p* q
- class Person{( E, D/ ]; h' L
- function __construct(){1 b( i0 p' D$ ~/ h
- echo 'I am one!';
1 v" a8 Y8 Q6 h6 x: h* d - }
4 d7 r# w/ R. q9 } - }
复制代码- //name.php9 i$ a1 n4 _6 u" t, \
- require_once './1.php';0 J7 k1 G9 B8 s* U3 Z( U
- 2 ]% C2 n' n2 p. M
- new Person(); //输出 I am one!;
0 U, \( G( N5 b I$ L0 x - new \Person(); //输出 I am one!;
复制代码
# W! x; |# L, V/ w2 _9 n# W3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
' _ k6 P. F; D9 y7 g9 z - require_once './1.php';
8 s7 `/ m5 p: y+ @; N/ _7 x: b - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 J- R0 `, u% N7 @/ j: Q% X
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php , b \" J0 |" `* y! |! ^! ^. X' L
- namespace one;. j; d4 d- e* Y( c
- class Person{
( a5 _0 B8 Z! s* `, `- U ? - function __construct(){: L N3 c# G e! ^
- echo 'I am one!';
1 N+ {1 J! _) I2 @* b0 P/ e: L - }
8 Y% L' L4 r- t - }
复制代码- //name.php
$ h* e G0 _- e/ k% Z& t/ b2 [ - require_once './1.php';
. v5 L3 l1 B: q$ A5 p3 X" G - new \one\Person(); //输出 I am one!;
/ L0 a8 O" \# z- i( w9 ~ - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
9 o+ c4 d1 t, ^可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
t( P, D! y. l9 J/ i* ~/ C5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。9 y$ U( g e7 M# K6 U8 w, Y
- //1.php
$ L' r( W( J6 N, }, S - namespace one;0 V$ e1 C7 K R; ^
- class Person{
2 p/ M! s5 _* N0 v) Q+ q3 P. [ - function __construct(){; b1 a& V* M& _4 K; `/ M
- echo 'I am one!';" n/ C/ {! b( \' e' V7 o
- }
. d6 I6 K4 k. C1 A7 L4 K' t4 u - }
复制代码- //name.php8 o' u8 G- S1 \) k7 }2 J' d
- namespace test;; `5 A/ H3 n" k0 K+ B2 q7 R
- require './1.php'; 4 b( V6 q/ n) }' ~
- new \one\Person(); //输出 I am one!;3 ~$ U+ }: r- }4 e" v6 |2 R9 a
- new Person(); //这里结果会是什么呢,猜猜看
' ?( Y! t6 E, B - 最后一行结果报错:
6 ~: N4 o( T; E5 n - Fatal error: Class 'test\Person' not found
复制代码 + K" F6 y+ W7 u! q
# d5 y5 ^) `7 q% H首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
5 A5 _* B9 u0 g! j0 v+ J结果报错: - Fatal error: Class 'Person' not found
复制代码
* O* c& v. q% t+ _: }$ V/ T接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php$ ^# c3 f# i( P8 z P s! j
- namespace test;6 s8 C ~1 u5 o6 x0 h6 n
- require './1.php';
U) ?0 p. c' N5 l( F - - D" J! ?7 M7 m9 ?' ]
- class Person{
% O* G" z9 _. P( E - function __construct(){- a& q, v9 o& Z2 Q( E) C
- echo 'I am test!';
# i9 N0 ~; Z& ]; B% Z - }, Z$ N& R: w3 G6 f
- }2 l' d4 Z* N! _( P$ s
- ; P! }) m/ E7 F1 g& D# }
- new \one\Person(); //输出 I am one!;8 c+ Y9 z! B& ^; _8 V/ l q) t8 N# X
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 , U4 a; F; \5 r
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php- D1 x! u2 X+ ]9 K( J7 s
- namespace test;+ u/ c" ~; Y# R$ D; i
- namespace one;
# @) M1 h0 t+ Z: N9 h - class Person{
8 b9 x% D, ~' ]+ v5 w b, G) N4 R& n2 L - function __construct(){
3 X( E2 e2 h! [ - echo 'I am one!';
' U6 z& m: @! \) k' z - } X: O- _) g; L! b+ T' P
- }
6 ?# |+ Y1 ^" L# t/ S. i
8 X+ U, x* v9 V9 R0 u- class Person{; W, Q h/ f2 n0 X8 t
- function __construct(){; I) [# L6 R1 L2 X1 J/ V i
- echo 'I am test!';3 j' F6 G: [9 k# @( k0 ^% v
- }% `, W7 l& P1 F/ Y0 U0 X# k
- }
复制代码 $ Y8 S, l) Q9 s+ ?' m" \) J% \
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
z# o+ \- {9 K! w7 a7 y8 `3 W1 l2 I看来简单的把require理解为替换,在这里行不通。 . Z. J2 t/ W. I* |
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
6 t8 M5 u) G+ j- //name.php. a! \& x* d Y k) `" h. l
' }8 z. I/ m+ e- namespace test\person;
. K+ K% ~, q* O$ b' T" C - ! p: ]$ N: K/ z; l* ]( R% Q9 _% H
- class Person{
8 z/ ]" L. l. v6 Q! f" }- { - function __construct(){
, a1 E& V5 P& M' b- O - echo 'I am test!';
7 s- _$ L9 q5 }$ T' U; W - }; c+ M. y8 I( N7 V0 ]
- }
. ?- L; l' b0 e& R3 K$ R( k5 P: y - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 * W- E( G7 \# p- v
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
9 l/ ^) ~, h. p# c; s7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php/ {) L: j* V4 H- X( o
0 p8 p8 `% M" m; H/ p- x2 Q- namespace test;
! I8 M! b8 J6 @3 z7 f p+ Z - echo 'zhai14';* a9 P8 ~& U: M; V# W
- namespace zhai;
; D o# {. C. w/ |" z9 N - require './1.php';
复制代码
- ], j& ~; _/ J# lphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
# R& B8 s6 C; Duse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。" P2 t _/ U( c7 X/ C8 h6 l* d
- //name.php
7 ]8 _& B+ O6 w4 ~5 R - 8 N, x3 P8 h9 T. V9 c0 Y% p
- namespace animal\dog;
; k a& D7 @/ s" } T# u$ x
* I; r/ D& m: h- [! H" {, }1 t- class Life{9 H C- C. L( t7 l1 l$ M
- function __construct(){
' P9 y; r2 w9 x1 @# r2 l: o9 p - echo 'dog life!';
: ~- A) l7 e7 W5 r - }. J- |- K5 g) `
- }) C) b$ d$ Q8 r( X; r
+ X2 l& z" m& K3 x- namespace animal\cat;
1 h" |4 a/ I+ S6 _( _* n: H0 d - * | q. Z( n. s( U0 X
- class Life{2 M3 ]6 U, t8 Q$ j7 w2 H& {! M( u% ^
- function __construct(){) b: o* S& c( Y4 C
- echo 'cat life!';% S4 L) K8 r4 z6 N: C7 ?4 `2 ]
- }9 z3 O5 h/ f/ K* n
- }' }4 u9 b* Y9 X: o) _
- + e* n4 Y+ N; r5 i$ T! z9 n3 U
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间+ }: C1 v9 P2 Y! j2 N" W5 T: V
- new \animal\dog\Life(); //A
5 o. a3 _8 S& I% o5 t# H - ( A5 K3 l+ K6 s! R* j
- use animal\dog; //a/ R# q; B$ g( [2 y
- new dog\Life(); //B
2 U- U# t4 s& Y7 g m" n0 p
: j2 z, R% E. O) n: f" o- use animal\dog as d; //b/ i( o4 R# g5 P2 R3 V
- new d\Life();
复制代码 9 i( w, r! P: }" b3 B, v6 R
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
$ @* x+ z0 X6 b4 h9 P/ n通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
4 n9 J& i& A0 D6 C0 J相当于 ; Q; d: c: c+ I2 b
2.namespace后面不建议加类名,但use后可以。
J0 Z8 F1 Z* I i U4 O! M$ ?- //name.php" x9 q" K- y% Q8 t* D: `
- 0 ^+ B9 j/ H/ o2 H: M( S
- namespace animal\dog;
) }' L" G+ m7 h7 V
$ V1 D x' K3 N1 U* `* G; n- W- class Life{
u+ B% \0 n$ ~% }* r; {1 k( C- e - function __construct(){5 D9 q6 S( g: [: [, G; q
- echo 'dog life!';
0 F$ D. W# r2 A4 I7 u4 Z - }2 V$ A- B' @$ j" v( `6 H/ G
- }) y$ `1 T3 O8 {! {$ d) x# t
- 5 p1 o' `6 B T9 ~6 Q3 s4 s5 G7 d
- namespace animal\cat;
5 H9 U7 \: N) n5 u6 f
5 H4 @. J: t: u( ?- class Life{5 R& Z* q p% ^1 N& a1 e; I9 g2 a
- function __construct(){4 X# K* c" E7 z7 I( ]
- echo 'cat life!';4 m+ m0 P% u) W. l, a; ]
- }6 |, F2 B! E' i$ F$ d. I
- }$ a& k% R( @9 g; D8 w
- `8 G# Q) @* y( K" R3 U1 X0 |; ~- use animal\dog\Life as dog;
0 c, b5 _: Y8 v$ m - new dog();
复制代码 9 K- I3 u, g: H' d( ]) f
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
9 e9 u% L+ v- c因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php) B4 u9 O7 Z* _' W0 [: L8 L
- ) e8 S l+ k2 b" f- e
- namespace animal\dog;( ~, X' r& a: m$ _2 t
- " ]/ a8 V$ J) F; B8 O! {6 _
- class Life{" e A: b' n! @* { u+ X/ u
- function __construct(){1 t4 E3 v3 C5 b/ ]" U
- echo 'dog life!';) D4 _4 }6 v6 W! I/ e
- }7 E* z% @* z2 v% j, K5 w" Z
- }
, Z" s* V* Q7 {* v - class Dog{
# m& c: T% Z. F, _3 W. c - function __construct(){: T! L% N6 u9 A+ R9 k
- echo 'dog in dog!';8 o" C) R9 \+ ~ q6 U
- }
2 `8 n6 w7 J3 y, g - }1 J/ l5 }7 d' ]# C+ \
- ; F0 a3 @. X& I. ]
- namespace animal\cat;
2 {3 Z+ M8 f; s V
7 }, s* y$ [" ?. B; m0 p( _- // class Dog{
/ ~8 L+ {7 m$ `& T% w8 q$ [ - // function __construct(){
3 A+ D, C" F3 K0 @* ? - // echo 'dog in cat!';
! I$ z/ c3 L+ N, o' ` - // }
! ? v0 @% D" ~9 x8 @" {& U - // }7 x0 c' N) d" ~# z1 y
- class Life{% N3 k3 \6 R2 X) Z: E; V
- function __construct(){: E# B' P1 ]5 c
- echo 'cat life!';/ g9 q( \! c/ [ J* R# o& N5 _
- }! v( s3 ]( q: R; e) r6 l2 M1 E
- }1 x' j! f; B# F6 P
- ; G) k1 n) @) z+ k: _& _5 i
- use animal\dog;
$ }: N, }( S( m- Z2 m9 G - new dog\Dog();
复制代码 - K4 w" D2 h! B- A$ q
如上,使用了
; ^. M' w# E, s' Wcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
: t/ D0 o& P9 Q0 S7 U0 v- X2 y: o2 f简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 5 i9 v/ K& U }
+ s3 R7 T$ J8 e9 W1 A
3 p9 l2 U1 Z2 S* _5 ~" G
. |) Z6 {! l- A- E3 a8 T
6 Q! H7 ?8 ^2 c' t
|