以下皆为本人自我理解内容,如有失误之处,请多多包涵。
5 o( j# X6 C) g0 [& V* R3 A文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 Q% Y$ g, }1 v1 F. U$ B5 `
$ x! D# y1 T h7 Q# ]
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 6 h; X3 {7 Y8 I. ~( U) n6 Q& e
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 3 E+ L. E3 j2 ]$ f7 t
结合使用方法来进一步理解它的使用目的吧。
- h! y( e2 M" U: f4 K- @5 L! ?. H( {- B: [% u9 ]# h- }
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
6 \- w# z2 V6 s3 e, y - namespace One;
$ n# K! S. `/ x: M - namespace ONE;
复制代码 ' ~# P4 K/ v4 t1 ^. Q
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
5 n2 j. k6 \0 v- V4 \2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php + L+ Y9 P. }) @
- class Person{
' K7 {* H: w4 V9 l ^) ^4 w# t - function __construct(){
6 c* m3 R) ]1 m; F; w - echo 'I am one!';3 d; F8 }: S! n s# ~# G% N
- }
$ G, X% A- i) h$ ~4 L* V - }
复制代码- //name.php8 ~# [' ~1 f b& v, U6 E% I- o4 Q
- require_once './1.php';
. _+ z$ {. ? X$ j& {' R
I g) Y3 h. z- new Person(); //输出 I am one!;1 Y. O/ C4 H- A+ E3 W8 W5 q1 S ~, p, X
- new \Person(); //输出 I am one!;
复制代码 + w% P, i) b* p
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php3 g" |7 O8 n# }$ r6 X$ U& I
- require_once './1.php';1 `/ X5 w3 V! l! k2 r# ~
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 # O# h" T1 r! g% q! }
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
$ r% C0 }3 a* M" D O- w/ W - namespace one;
: J1 f+ G8 P% m9 ?* i - class Person{
h" F1 T" y2 J* f" v: @ - function __construct(){! ^7 \* y9 y0 L
- echo 'I am one!';% T* Z( [! W/ i* ?, I3 d
- }
; C! g. D! t3 l! J - }
复制代码- //name.php% {) ^0 U, v1 E b, _
- require_once './1.php';
; j( Z0 d# M! ?# a4 F - new \one\Person(); //输出 I am one!;
- n- U- w" o% t4 k4 [8 \ - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
" b w) a V& f# B% g5 p" ]可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
2 H) @1 M+ Q1 J3 M, q" g5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。7 E. i, a9 y9 v! [: K; w% l
- //1.php
3 K( X, x) \, K! L - namespace one;6 a: n6 h+ I; s; W* `1 v
- class Person{6 J6 U1 E u! G f/ d% \6 c% x
- function __construct(){5 E9 R# n L. B" Q$ R
- echo 'I am one!';$ i' @" Z" r3 q0 i" c! o$ x
- }
0 O4 Q3 T" k0 W5 w9 x! z: { - }
复制代码- //name.php: R# u3 r( ^- C& b
- namespace test;
3 y/ ~: B I a, C5 k) J - require './1.php';
$ ?4 S. ^) R) f$ Y' }5 `* X - new \one\Person(); //输出 I am one!;* o2 H( ^8 m: n; Q3 W& P6 f+ l
- new Person(); //这里结果会是什么呢,猜猜看
4 u2 n/ ~6 S$ [- R F) @ - 最后一行结果报错:
6 G- F; n [' A; d5 p" o - Fatal error: Class 'test\Person' not found
复制代码
8 p7 I. j x! P/ O9 t- @
% O g) ]# G* W3 q' Y0 O首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 6 K$ P" K$ _8 D2 W8 ?6 f, O+ |
结果报错: - Fatal error: Class 'Person' not found
复制代码 ' t/ k4 L; G2 k$ v& f* c, z* c
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php8 }7 w( i& C' K/ j3 l' a
- namespace test;
8 T; E+ ]3 N4 f" }- R$ h - require './1.php'; & O$ a% L6 s/ R9 e' i Q! {" V P, L
8 U& W R0 h2 ?) d# S; Z, R- class Person{
( t) T* I' U7 Q3 d - function __construct(){/ O- x& C7 Y" F
- echo 'I am test!';
& X- w4 v4 G7 [, B: [ - }& d1 |/ Y8 k5 k, \! W
- }
, i {8 k( y4 B' K/ R& _2 R
" l( Q4 _; C# h6 g- new \one\Person(); //输出 I am one!;
* [* B8 C* U9 P( w7 L, ]3 c - new Person(); //这里结果会是什么,自己猜猜看
复制代码
: @7 p: |" n, X最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
3 F/ ?1 d; F% T/ u4 k - namespace test;
6 N* h+ D8 q8 {! b# x; ]; r3 A' N - namespace one;
) O( I c7 d- D - class Person{! q$ |0 r2 K' N: e4 a
- function __construct(){
+ g9 |' M7 ]. \% V6 Z$ o* s - echo 'I am one!';" z" x" l# t! Y7 y4 G0 J7 B
- }7 Z$ `( j9 K4 W6 M
- }
' T$ W5 ~' _; k% N$ k
' {8 o1 K, ?! l+ X: j/ i; ^% }- class Person{$ B9 B! B+ X9 g) }
- function __construct(){' t, |! s5 @) V# A X/ G
- echo 'I am test!';- S) k+ e* ]* |- p. e' r- |
- }
0 @& C7 u H& }9 S - }
复制代码
6 C4 l& b1 t. h; W9 V无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
8 H. o8 B4 K3 ?( ]( p3 l看来简单的把require理解为替换,在这里行不通。
3 v- X( U6 b1 `6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。* v! s: Y6 X! l$ C% b
- //name.php0 ?& Q R# B7 N
- 8 j" R! m1 J( B i- x0 r
- namespace test\person;
% I$ i( H* B9 X/ f" Q6 A% n
5 A+ ^/ V6 L/ a* `2 A, [6 ~8 W- class Person{
7 |2 b5 E! `) I% Z" ^! f - function __construct(){ s! k9 Z9 e# V# ]4 n
- echo 'I am test!';
9 ]/ H% q( o9 L4 c( m% f - }
- h9 I& ?& Q. C1 v Q w - }
( l& U: @2 z, Y h; L4 _0 d" A6 \ - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 1 U% h% }/ }- l
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 ) ^/ p7 U5 w7 @
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
% S. v+ G! r# y9 d - 5 o8 G8 ]& o7 W9 j6 T# s
- namespace test;
; ]$ E9 I5 F# }' B6 Z' \ - echo 'zhai14';5 s! a. ^+ q& F5 B* B9 I0 K
- namespace zhai;5 j" P$ v5 O9 E- L/ b
- require './1.php';
复制代码 0 V3 ?' R% r7 a& @
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
+ ]. _: a4 T7 U% y+ Fuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
' K3 y2 Y/ o4 u4 i5 U3 ~" k2 x- //name.php) E. q$ \* P, V! K2 G9 K
- 2 ?4 p i9 q* F7 Q
- namespace animal\dog;& |( r: x' Z. Z! N" j3 w! O* z' K
- Z, ] x( J5 R" V- class Life{0 x6 J8 u& v) `- c/ e
- function __construct(){
4 v; J& z& H# {2 H* B, p - echo 'dog life!';
; c& v7 ?5 V) F& S! _' `4 [ - }
* H" Y7 @" S7 X# x) _ - }5 j5 E9 g, {, l
- 0 D/ |% N) ~7 f+ Y M
- namespace animal\cat;
4 y5 T- y8 r. R. k* v# Q; v0 Q3 x1 P - 0 B r: x# T4 m5 M
- class Life{0 Z3 q& X3 m* l# R
- function __construct(){
3 S& B. I; X. O" m9 R% ^ - echo 'cat life!';3 q5 A/ x1 @: s2 U
- }9 P1 T7 c5 Z. {. G
- }
: l! x" l5 Y+ B; R% F - ; B* V. C) H6 j( x, B- X' P
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
: I0 [- J6 E, [0 |8 i - new \animal\dog\Life(); //A
5 Z- Q1 S! O$ j7 g2 G! P - - Z5 O" r5 ]5 h# B& \
- use animal\dog; //a& y2 z0 e$ H7 l d+ u$ H. b
- new dog\Life(); //B5 w# Y5 t- M j, ]2 c
- $ b! ~7 ^& L/ H4 f2 p: g: T( M& {; k
- use animal\dog as d; //b+ E7 w7 x( P9 S, f$ u. i
- new d\Life();
复制代码 1 y' T: B! k& i" R+ s* F2 Z9 x
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 * c. N5 g! f4 X$ J$ _) |
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
/ g5 M$ @5 r9 B/ v相当于
/ r J* ?& _6 C$ s2.namespace后面不建议加类名,但use后可以。3 W% J! c1 ^% f- b
- //name.php
% w, P3 y6 [) @9 F7 [) E: z
8 ]6 X) k2 q0 Z2 `* Y# I5 R! {* z( ~. t- namespace animal\dog;
+ g1 H9 y4 w' G+ X5 F - 6 ]" Q% P5 P" `
- class Life{
$ [2 l; B( O3 i5 N9 m - function __construct(){
% L( i# O, ^) ~2 v2 A7 u1 u - echo 'dog life!';1 H/ R$ }& p1 d2 W. n1 @
- }
3 Z$ S8 z, T* {8 [/ C" F - }9 p3 X& \' y/ y" c$ _4 g) d
$ N6 I: D* c8 t) I8 z- namespace animal\cat;2 r; }, U& F8 p1 R: y
$ Y D4 ~$ a2 q4 E. ^% ~- class Life{
( f% q! O- ?8 `# G" [ - function __construct(){( P) Q7 J# z6 |+ |
- echo 'cat life!';
! l$ a4 {8 ^2 j2 j# ~0 c" y - }3 f3 a( e* F, ~1 j" N) R5 T( t
- }
# l- u* ]" B- W- ?- ? - 4 j6 O2 F( t" M' P. i4 z
- use animal\dog\Life as dog; 9 I, v9 Y( A& t' v6 _
- new dog();
复制代码
7 Y+ e* f* ?3 ]; O1 u, o0 o如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 3 o% u9 N3 t$ e9 u
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
) J/ s+ ]7 z( [+ l, n" v& y
+ y5 y+ r, @) {5 S( P$ U- namespace animal\dog;: ^% ]* U, l5 L% p2 ]
- ' r7 ]3 N8 o) Q6 J3 a+ A
- class Life{$ J8 n& h9 w W- `& I% v9 J
- function __construct(){0 D2 q: f: q6 ]' M9 I
- echo 'dog life!';
7 d, d- q5 Y" u - }9 t7 \% u8 E7 d0 R
- }
$ {; S4 x+ h6 _+ W2 i( y. ]2 E - class Dog{
5 k& ]& L F( b1 [, J - function __construct(){- ^1 W% c. D$ [
- echo 'dog in dog!';
' r8 g. v6 O+ m4 y& r% b; X3 T - }
7 q" t8 ?$ }# b - }
$ U, V( b _) `, L) _$ |4 K; n# I
9 {# A! u' C* n* u% K) V- namespace animal\cat;$ Q# z0 w% c+ d* X
- - D; Y5 ?( ~7 @" o7 l0 m
- // class Dog{5 B; {# f: X% ?1 T9 k
- // function __construct(){$ q T5 j& p8 E( B
- // echo 'dog in cat!';
) N, r4 L6 ]/ d$ W8 u" B7 h - // }- h9 t6 ^3 g7 U9 l+ U
- // }: ~ H' Z% Z# s6 W$ j
- class Life{4 L0 P" s8 o% I0 W0 L
- function __construct(){
4 T, s5 g% n! c& y - echo 'cat life!';
( d" @1 J0 c7 E2 p. E4 M - }
2 d+ j, m) M+ \; X& N3 W: x. l - }
! G0 f6 o. |8 L9 K8 Q - . j/ Q% I* g2 h" J
- use animal\dog;
0 f. q0 a" j7 i: v7 x" h - new dog\Dog();
复制代码 1 Y. h/ W. H; q* D/ y
如上,使用了
1 F$ T" ~2 M, L) V7 {cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 * e2 [5 w- p% n7 A
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 ( L6 s- n+ A5 X4 a; F R' B0 f. V
3 b7 B8 M3 n( J v4 {8 V$ z8 y( E, I! Z
7 t4 t7 W+ s( ]7 A0 u
F" r0 R; i4 Z
5 e: a: u# \5 l$ A |