|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
9 F- A5 _8 d( w* E6 R6 g文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 0 q6 f5 }) J: K
) o z9 M9 X) e/ U9 _4 S使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
/ W8 J" N" P1 T% ~$ h9 b/ q) X据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) . p+ [- j( S* r' v6 N
结合使用方法来进一步理解它的使用目的吧。 7 A' r- g* ~' P# \' e
- A8 h; \ G) Cnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;0 A$ v* i* u8 V
- namespace One; z: ~6 f# _6 Y) G
- namespace ONE;
复制代码
1 ~. ~% y4 g9 u如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) ! v* y$ P7 I' n$ z! `* T3 R# r8 c
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php , W) G3 _: m' Y0 ?, f- L# D- I
- class Person{
; r, b2 i3 `1 Z6 `9 l. x3 O' T - function __construct(){2 j0 {" V# I/ k* E! d0 R. F
- echo 'I am one!';! M( C+ t, m7 i
- }
1 k6 S4 y) r. ]7 Y) f# c" S - }
复制代码- //name.php+ ^5 ]: j$ q6 s& A. H- P
- require_once './1.php';
- Z* n/ T s: P8 O6 m. B( o
1 C% {% K7 J+ l- Q8 ^ A- new Person(); //输出 I am one!;( n( Y: f# `9 a+ T
- new \Person(); //输出 I am one!;
复制代码 6 m6 N. I5 w* T# _
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
' N7 T. ~! ?8 A - require_once './1.php';1 F" A0 W2 Y, v6 d1 M$ {
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 + y+ E9 D! }9 ~8 K3 E; R
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
7 z; E& z2 H/ ?- {3 [ - namespace one;* |3 N# n3 a; {
- class Person{3 a# _$ M z% f7 U) N
- function __construct(){
$ c: Z# d3 }. ]# @/ M. `! K8 S9 X - echo 'I am one!';
+ O$ k- h) h) O, M) ^8 \ - }, @1 Z; K+ v! x/ y
- }
复制代码- //name.php. H& s: P1 T/ J& a v
- require_once './1.php';; [( ?% t( s) {" f6 ^" j
- new \one\Person(); //输出 I am one!;* g$ |. q' V7 g0 k( N
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 9 A; e' Y+ q. p7 P% Q3 h0 n) U
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 8 `; x b: J% L7 {6 ^
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。2 e- {! j5 t8 D5 w( D5 m
- //1.php
! C' }: j0 m2 o( P5 |0 n5 P - namespace one;! y, `3 @: ]- c7 K7 L% Q
- class Person{7 K6 \5 A6 y" V
- function __construct(){1 |7 E; W& w- m
- echo 'I am one!';6 E* L& W. l6 U
- }
+ v1 C9 p8 S' `0 m7 g2 H - }
复制代码- //name.php
$ |3 |3 I1 _. {/ Z" I - namespace test;
! P' R6 v' ~* } - require './1.php';
7 q: |+ B6 Z5 `/ Q4 A, F - new \one\Person(); //输出 I am one!;4 E8 \3 |7 }7 n0 g& T
- new Person(); //这里结果会是什么呢,猜猜看, y& M' V' \& A" m( T
- 最后一行结果报错:+ \" a% G( c& X+ {7 S9 p
- Fatal error: Class 'test\Person' not found
复制代码
# c! l x F- ^0 w& X9 {! S9 S6 b, {. l7 C
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
' M3 l3 p% b, J3 K A. H结果报错: - Fatal error: Class 'Person' not found
复制代码
* L: A! Z8 A5 D% e5 K6 o8 O: }! z# e接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php5 J5 r0 h) }; i
- namespace test;
' E& F9 @1 }+ H" @. e' i/ y - require './1.php'; $ L4 j5 A) _2 l% w6 h5 ]
4 t( | x) e. V2 A* U- class Person{! L* c. a; s5 @
- function __construct(){
( r. `! @7 p n& ` V# ]- K! F - echo 'I am test!';
% `: u' S7 d7 w! s+ N" h* l - }
* N& h3 z k6 Z* J4 z - }" o7 k* M6 X' D
- : S/ E) D9 i+ C3 ?
- new \one\Person(); //输出 I am one!;( h5 z# w* ^: o( Q# T1 Q
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
0 W. @/ e: z! H" x7 C) J# Z最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php o* M5 K* ~- {
- namespace test;5 Z: ]: M0 V3 N6 K
- namespace one;9 O# |; X# G6 a
- class Person{# f# v: G8 @# [0 L( k" d
- function __construct(){
& V v. q1 `; j; x* Y m& c+ I - echo 'I am one!';* w n( t3 _/ Z3 ]2 u3 X7 h
- }
. \" j {) ]4 P: l - }" g. j. s4 ^/ B* r- p
8 |7 I7 e3 r8 v( e5 l Y, a) `2 i- class Person{
5 w S: p. C. `! m - function __construct(){
5 G& C$ [) L o8 c - echo 'I am test!';
: p7 s- z. k0 y1 C# M! a - }
3 i; `2 F/ L& w8 ` - }
复制代码 & r1 q8 Q- e7 `% w
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
- D D. M' c9 ^) l5 U6 W y/ z8 z看来简单的把require理解为替换,在这里行不通。
1 P2 v& W- b1 x! N6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。+ V1 {) L( i; K# d0 p5 ]" j
- //name.php. ^# c0 T5 V E% i7 L6 k" R, N9 w5 ]
- 3 ?& _' b- r0 ?
- namespace test\person;2 r- A, M2 @+ t3 \+ L
% t7 R0 B& i! k+ o: j/ ]% M* t- class Person{
* q6 w& ~. l& l$ r$ o - function __construct(){
" e" ]5 }! A! t: |8 u5 F - echo 'I am test!';6 {3 J9 j. [& ^! @4 f2 N# F
- }: _9 @# ^' r1 `5 O8 |( q. S
- }
1 k4 q& x9 c: T - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 : F% ? @4 L6 o' f9 X8 G4 T
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
- p1 W7 I- ^8 \$ T1 B! U6 A7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
, b* w G& v' y# v& j
& _4 z1 @/ |, a) P% _, Q$ _- namespace test;! r$ d* b$ o) W1 j& }- o- w3 \- O
- echo 'zhai14';) v8 } `' H0 v& b
- namespace zhai;
3 e$ X1 x# I3 C - require './1.php';
复制代码
, i( m8 @# Y/ h. q( J! _: Z0 tphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 . d6 W% H, g4 T% l
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。0 L/ K, C [ c. E/ a; B A
- //name.php
" p, H1 @" ~% \
! {6 |1 U% m( M+ L7 Z$ g) o( ?! {- namespace animal\dog;, j( v# Y) h$ g' Z3 M
- 9 @% D# o% y1 C z7 z2 S5 ?3 j' J
- class Life{
! \( B; {7 ?! q! [, T G: I - function __construct(){
) ^+ R: M: I3 }2 K; V. {- H0 d - echo 'dog life!';
* ^' ?+ I+ Q+ d& p5 _- ~2 P - }
0 R2 H: I: j& k+ E# h k - }3 Z6 E0 T0 Z4 Q0 ~+ W
& w7 V/ {, K/ C4 g& L- namespace animal\cat;
* k8 M, ^& V8 I0 J( c7 A! V - # H: n5 E7 W. k# V, d; W5 o
- class Life{
( j! c c1 y! Q5 _# s' a - function __construct(){0 p% X6 E8 t1 m5 U# ?5 C/ D; e' T
- echo 'cat life!';; Y1 ^. n" O! N. k
- }, C4 V* ~# J+ I% h X7 b
- }" E0 A3 l" F0 Y! f' q
- 7 x8 y: G2 h2 @# p8 |
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间7 Z; G1 c9 d" s' a
- new \animal\dog\Life(); //A2 [; W4 V* c& s X0 \6 w9 r4 C# w. {
: W" c* U3 ^7 P: q. U8 c( A/ K% N- use animal\dog; //a
& n j$ W" Z6 N3 G5 a; H" A - new dog\Life(); //B+ p P0 C( s q4 o
- 0 f$ O! c% u9 p! t) h( m+ h
- use animal\dog as d; //b) u+ k4 G3 D" [: ]
- new d\Life();
复制代码 7 W0 ^( W! t9 q ?: G' [% ~
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 4 S& c0 H1 e3 R) d4 r+ @
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: : R' E. \2 P( F" `2 L8 @
相当于
5 g: ~# @* v& g2.namespace后面不建议加类名,但use后可以。 \/ l- Y3 c/ o/ Y' B4 z/ N
- //name.php3 ^. M! D! ~. Q+ @% ]& k
7 s! n. l g/ @. E$ q/ W- C- namespace animal\dog;* S$ |6 X3 q% ]
- 9 Z( v; g/ s' O; ^+ ^% j o6 b
- class Life{
- R: g3 A! W7 e - function __construct(){0 p4 ~! p; A; h m, \- J
- echo 'dog life!';$ L) H" s0 E! t! ]
- }1 [1 O% a. g2 O% c
- }
~; L Q9 `. c* X2 M- x - o& ^" T- s* M- F2 [, W
- namespace animal\cat;1 u" p0 r2 w: U8 ?2 e
( b. d9 r0 r1 I% K- class Life{ i& g' p" D: u( h' @' q* U( L
- function __construct(){4 Z5 e$ h1 N/ ]9 b
- echo 'cat life!';$ t1 ~; _6 R4 @. Z; }( Z; `
- } t% c% i7 r* n
- }
5 V! n5 I" q6 w% @! M: P
4 N0 b- w" _; a( J: i& T2 a- use animal\dog\Life as dog;
8 P5 `; [1 X5 V }- V9 K/ g - new dog();
复制代码 0 H* P q, }. y9 j
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
v0 g8 s( l/ \* R) v, m+ E; F( r因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php( L7 Q" Z2 A2 X7 ^, d. N( v1 `
1 x0 s7 |; X" i4 T. [& o+ T- namespace animal\dog;( k' ]1 f0 u/ b0 y
- $ \* y# }9 Q9 y9 X& W
- class Life{& k {. a. l; U! k+ Y' ^
- function __construct(){
! S* A/ s/ a; V; A6 [ - echo 'dog life!';& ]6 Q- r* D& t% [4 r
- }5 Z' z, a& ~1 N" o5 x2 A1 I- E
- }
$ X+ u. i0 T6 m6 B# s$ g! w$ h - class Dog{/ B2 S% b( M' h. F
- function __construct(){
# H6 ?, r0 z) \$ \1 x& C6 K - echo 'dog in dog!';0 l9 g4 v( k' Z1 W) e
- }8 m; Q1 b2 ]6 W
- }
4 q1 }) L" L& x4 B2 w- b4 [- N
- U; h G" J G4 |1 V7 e P9 S, e- namespace animal\cat;
6 }+ ?/ a4 g% Q7 p; O/ m - 5 D% x. v+ H. Q
- // class Dog{3 @& X2 c% I5 I Q* o! J1 J( b
- // function __construct(){
; d' v" ?$ a4 N+ V' k! p& E6 w, f1 i - // echo 'dog in cat!';5 M& M8 U6 D1 M& W1 \
- // }
% f* b; B( G$ |4 R5 A5 ` - // }
8 L0 v5 V- e. f( C" ]9 `" b: v! u6 p - class Life{
9 {1 n5 M2 Z$ @* I1 C: X$ U [+ W - function __construct(){
, t# D7 @1 p Q1 Y# L( X2 M - echo 'cat life!';8 u! o1 G0 W" ^! U5 V
- }8 J( J! p7 \! `3 I( I" A
- }
4 a ^: t7 i+ A8 L; u3 ?; U - 8 R2 Z* `9 A: J$ b9 t
- use animal\dog;
7 b* u) o" v# }0 } - new dog\Dog();
复制代码
7 O7 C3 }' ^1 D- Z4 H) J如上,使用了
, Z' [: L r# s" C/ P/ R& Ecat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
9 _" R4 w. i% j' n+ o简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
! P ~2 g3 }2 H! z d8 X o. w0 @: U. F5 b ~+ _: y
5 G5 m* N& E- Z/ v; j, ?
9 c8 e9 v: @: Q! E' S0 f t/ \& L2 D; p* h* ^* v
|