以下皆为本人自我理解内容,如有失误之处,请多多包涵。
2 F) S9 G/ w; a( L. I# x; u文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 2 R6 \/ Y8 n A
+ |8 W. h: A5 I5 Y使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; + t5 ]3 h. N8 J# I
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
+ s* k7 u( B% W5 @, P2 p结合使用方法来进一步理解它的使用目的吧。
" J- V$ U+ |3 i8 e* n. E1 {$ G7 [$ u: Q# M5 O1 V
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
, T' _- L0 Z7 O2 R% N - namespace One;
: P+ c& Y [ e1 r - namespace ONE;
复制代码 2 G# `4 S$ [+ A/ a
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
" ~% L1 I5 E' a! j0 }; i+ j2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php ( {8 F0 Y$ V9 S9 E/ i
- class Person{
1 {) M8 [/ v. ` - function __construct(){6 H. g& }& `0 A7 `3 A- ^7 Q
- echo 'I am one!';
7 J* g1 `: b1 A5 U- G2 e1 f - }# ]9 r0 j6 \( X7 B" e6 B M5 b
- }
复制代码- //name.php( o! o) h- ]" X
- require_once './1.php';
4 U# `7 T$ q9 u! |: Y' W1 D0 `- W
' d& [- ?( F- j" l, ^- new Person(); //输出 I am one!;8 ?! M6 [0 K$ \+ H
- new \Person(); //输出 I am one!;
复制代码
. k, K$ a. v2 y4 R: n1 H' m3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
& N1 j' X+ S' e: S6 w& Y+ D - require_once './1.php';
! r" M M1 P5 w9 A: y) k; s - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 6 L+ j# J. o* F6 [$ @, l w* A5 h" T: g
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php ' w2 Q) C6 v, Q/ c. A' x1 S
- namespace one;
1 w- s, r" Z0 E - class Person{( L7 ^5 y9 g/ P: S
- function __construct(){1 `6 M& z# a6 M+ e! @2 A: k
- echo 'I am one!';
! O/ }, G# T7 C( g5 A6 X - }1 V& C0 ~: F/ I' G* U
- }
复制代码- //name.php
5 x6 ~9 A6 F/ Q) O - require_once './1.php';
9 X% k4 x( g d- s- }* A8 H - new \one\Person(); //输出 I am one!;
: N$ r- t$ ]; U' a - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
9 D# ^9 K3 I, u# E可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 & N" G* C1 N7 }3 k/ S& K# H1 R
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。* j' O5 r% c8 R T( m3 C2 D
- //1.php 6 _; q2 V# a) j* [( V9 g( G2 Y: }
- namespace one;! U) Y1 e- S: X+ B* E7 R4 G" ~& x
- class Person{% E7 Q& w7 y& ?, O/ @+ v0 `5 h; |4 f
- function __construct(){8 z' p* J: Z8 K
- echo 'I am one!';$ b1 N/ U C2 \- z7 c
- }1 m b0 M7 ? @* a" b
- }
复制代码- //name.php
% w9 x r2 E0 R* ^% k - namespace test;. V2 C7 P' m# \
- require './1.php'; + O3 n7 p* Y6 i- @5 _
- new \one\Person(); //输出 I am one!;% C$ {8 H$ z0 B# A8 |+ q1 T
- new Person(); //这里结果会是什么呢,猜猜看5 ~3 Y; E6 T. f4 R7 Z% V7 t
- 最后一行结果报错:
0 k$ l0 N+ T+ a6 i- ~7 g8 r7 ^ - Fatal error: Class 'test\Person' not found
复制代码
& Y; t8 X* i# f2 @. Z5 X5 b3 s. j+ L# j6 W* y3 x" s
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 & P$ u; E* `0 I3 B! h
结果报错: - Fatal error: Class 'Person' not found
复制代码 4 {* y$ X- R2 ~ f, p0 h; n9 q( L
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php: E4 m0 v q( i) X
- namespace test;
P' C2 w7 {1 O$ o2 V - require './1.php'; `# b. c4 N& [: e
+ T' @& k& f8 f' W4 d% B- class Person{$ W* h' W$ U. Y% i& D8 a6 U/ O2 ^
- function __construct(){
6 z2 S) t) S n1 C8 T; s - echo 'I am test!';
' Z) g8 Y; N3 m) k: d- W( | - }6 N7 u6 x4 Z( O
- }& u8 {% q- a# x- g+ M! e) N3 x
- + A( L- r" p% c2 c* Y
- new \one\Person(); //输出 I am one!;# g/ d+ ~4 u7 Y
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
* O, ]% ]' F8 _# Z3 ~最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
T& c; F- c7 @9 q. U, Y - namespace test;# V# t/ T, y6 M% R
- namespace one;) b$ I; c( j, } q
- class Person{
# h- Z& p: v; t. w - function __construct(){
& n) E7 I# |/ E( A - echo 'I am one!';
4 @ ~1 y- ]4 t& H* J& X - }0 Z3 R$ O' [7 A2 e$ ^
- }5 f( {- q( m2 L( w% A* h+ g. m/ d
- 9 b5 m3 L# J* ~+ T) D, N: d0 N
- class Person{
8 o1 v* o8 G& i' Z/ K0 I2 ? - function __construct(){
) v) j% H5 |6 A0 ~ - echo 'I am test!';
; O5 e# o7 p0 ~ - }
! y5 V% n$ b5 _& d& H - }
复制代码
$ [( `0 g3 ]5 y3 |6 h+ b无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
5 f! L6 G) }8 T( d看来简单的把require理解为替换,在这里行不通。 ( o X3 l9 {) n7 Y
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。" f) J5 {6 b1 O6 m
- //name.php2 x% V6 ?4 A8 ?& v4 x
- 1 X* G* V) [% ?; {# D# e5 Q
- namespace test\person;8 G/ _0 h: s' r1 _& H) j
% D {) c; s8 @9 ~4 U! J- class Person{2 Q! n9 Z2 u' X
- function __construct(){# \# `; M# p& e
- echo 'I am test!';
" J8 w3 L' l) U* Q - }
5 L/ |5 C" J" j - }& {2 ]( B5 V J" ]0 u- Z) h3 y
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 " R d- n U6 V6 r9 Z
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 ; i0 N3 U6 w6 F$ Q( J. H2 R9 \
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php- O: v' J4 }2 x8 [
- 1 F# U$ a! A, @& j
- namespace test;- ?9 q- n% ?3 J5 @7 U2 }
- echo 'zhai14';4 \6 n. O/ x$ f
- namespace zhai;
- c7 g. ]1 h5 {: H - require './1.php';
复制代码 2 ^$ c" z- E- n8 L* w0 @3 Z
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
# ?) R9 q% {8 z X9 ~use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
( G/ T6 t1 ^1 r% W: D' y- //name.php
$ a9 z) H0 T! i4 b0 Q7 X( n5 J" b w. u
1 B$ f. n3 z# W- namespace animal\dog;
& o+ Z* F8 d c# z7 g* g) N7 z
U" J6 b6 h+ e. J- class Life{
) t# o. s2 P0 T" r3 O - function __construct(){& k0 o8 x7 L& R$ D I
- echo 'dog life!';; i% r8 j; }0 b1 e- g% @0 @. P
- }
# b0 U u; i+ c: g - }
1 ^, u# k1 }' r/ C$ ~! W - + l7 ~9 h7 v O0 z7 F
- namespace animal\cat;
3 j. I- m# ~2 K. E4 g- Y - 0 C- {. E4 ]* @( ~' S
- class Life{& S4 B4 X$ D8 q: p. Z5 k
- function __construct(){
; u, S8 e; }; s2 u, d! k3 [ - echo 'cat life!';
& f5 P, m, F$ ~6 ] - }
1 }& u* k+ i. I8 y1 M( b - }5 d1 o. p& ?; R) t' o) [
: B& l4 X4 f8 h- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间/ J+ X. Z9 f6 ~( J% S2 J/ `% I' C4 @
- new \animal\dog\Life(); //A
0 B5 A( [4 c* H
9 E$ L4 ^2 f/ K# N: G1 B2 s- use animal\dog; //a* q1 L+ L! j9 h2 |: Q. `
- new dog\Life(); //B
- K! \! d- P: P& `0 T - 6 U* d! n: o: Z
- use animal\dog as d; //b
2 @0 [' A& |) x: N6 ~) n - new d\Life();
复制代码
: r0 S6 r2 U% N7 `4 E通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 : m5 b. Z1 ^1 H3 y
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: , s% \. ?% h% W w8 l j
相当于 # {4 }6 P9 p" H. h
2.namespace后面不建议加类名,但use后可以。* [' }- G$ [( l" t+ t# {1 ~& F
- //name.php7 ?0 c8 z( @' w$ B" F
* A$ X: _7 u0 E- namespace animal\dog;+ t. `( c# ^6 {/ s1 p9 N7 ~
- 3 J, }9 V4 N" Y% q2 X
- class Life{! ~; A7 D$ M! n2 Z
- function __construct(){* b5 N: O0 W8 c- q# _
- echo 'dog life!';$ N8 k0 A* }- i. D1 e1 a
- }# t" e: y0 _5 X" @
- }
& K( Y0 ^5 _ g, C% O4 [, ~2 W$ R: t - $ t$ @# e6 N$ k3 S$ ?
- namespace animal\cat;
4 T8 l: Z2 d7 x; G/ Y, a
- n+ o3 n3 I1 A$ y) y- class Life{! r6 k* N G6 i# k# _
- function __construct(){
. L7 |' a. h: ?& J; f - echo 'cat life!';; W! z2 v8 e( m2 q% w2 ~' }7 L
- }. h7 a3 T. \6 q( B, Z' X3 N
- }4 u1 D# Z' e# p& N- N
- 7 `* l% @8 ~+ {! q- G' R
- use animal\dog\Life as dog; 4 b) J' H# \% d l5 ?6 j
- new dog();
复制代码
1 Q# ?. U- s9 w( _5 W2 }- e如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
1 U2 A8 H* t3 |- o8 ?9 C因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
& Z$ i+ d, k. W8 x* A- C - 7 r+ Q7 U5 B) Z$ r) r( {) T
- namespace animal\dog;
# S. P- g; s" [, Z { - 5 ~3 [0 y! W. E* |$ O: N( k
- class Life{5 u X- n7 c& V3 Q0 X+ F3 k
- function __construct(){+ ]( K: y+ z7 @3 E1 ?6 S. A
- echo 'dog life!';
) k$ O* [7 Z' R+ o - }8 a- B' n0 z/ N5 m; t
- }' `% g% H! b& Q, h. L
- class Dog{6 Y3 @" }% a- k5 j% |+ S8 ~0 r
- function __construct(){# }# f4 g$ C5 j' E4 J& e. [8 u V
- echo 'dog in dog!';8 ^# x, b* y3 c1 e9 Y6 Y
- }" U- E% N& J0 D' q0 I* C
- }
) K/ c" E" S1 ]0 m/ v Z* R
+ L4 H" q8 u4 }: A7 G* Q$ D2 w& g; ^- namespace animal\cat;! q- s* D- ^: B& j
- 4 i7 I9 N, ^. R- f& o2 ]6 [; M5 d, W
- // class Dog{; Z- e5 G+ Q4 V: i# u! Y6 K
- // function __construct(){2 [( w' T4 u) |6 G+ S- [# B
- // echo 'dog in cat!';
1 F8 S0 T- E: m8 }! O& m - // }3 \, Z& [. t+ s& U
- // }& V V# X0 ~9 ^' ]9 t+ d7 C9 h3 X
- class Life{
# B( L0 W2 J- ^7 ^0 h - function __construct(){' Z9 o4 D% ^0 ?
- echo 'cat life!';
! z' z+ o8 W( G& P3 a - }4 }- J9 X8 V0 P7 h4 `. J
- }2 Z6 W( ` [# y1 f8 I0 o
T1 \6 d- \5 c9 P2 q) I1 O- use animal\dog; & o' L" S+ p y# K+ u' O
- new dog\Dog();
复制代码
" R7 q# e+ T. o+ `; L. _如上,使用了 1 H6 q3 F& w3 E. m
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ( }9 L6 ^! A& A( o4 W: i
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
% ^5 O& M7 n+ P' O- V$ {2 P7 D6 N" x8 \5 N) \: T; p- [" p! x
# B2 ?- {: L3 C" p8 i- w7 M' b! k4 G0 B$ p( q# ^. h; D+ |) {
( c" _3 P3 h# @) @ |