|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
( J& G3 {; R1 n6 e! h7 y! ]文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
; }5 v: {8 W2 i Y
9 V, T \3 z. p0 k使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; $ e- g9 J I! P% P! A& a
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
9 l* U( n# F) g* f7 y结合使用方法来进一步理解它的使用目的吧。
. ~# ^' x( ]; H. e( j
; {) d8 g/ q; p' |/ ~namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;1 H& `1 p) b1 n6 E
- namespace One;
9 G w [( d. ?; P/ o - namespace ONE;
复制代码
0 Q. V4 S8 d1 B4 ?2 a" O9 C. U) o如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) . Y7 O* Z- i% W; w' _2 _7 g
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 1 e8 v' v1 t) j+ e: e
- class Person{
' }- x% [) C: k - function __construct(){
6 o4 C! K5 {: c - echo 'I am one!';
" t- @3 f& p) O# F' V2 | ]) }( E, x - }
s/ Q, A% K; N* d1 o2 r/ Z - }
复制代码- //name.php
% c/ W8 \6 F7 m. k - require_once './1.php';" f8 C7 V9 L+ m: A% ?6 `
( m3 H2 J& N& W1 d1 W9 o4 e- new Person(); //输出 I am one!;
3 o. o7 f& u- N/ Q4 h$ ]0 X - new \Person(); //输出 I am one!;
复制代码
% U5 T$ H+ X3 R: @, l) {9 ]0 X6 y3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
4 L* d5 F# b9 n% J1 ?. A) i1 `- ?8 d C - require_once './1.php';" z8 |' I2 v7 q) l) u% G4 p
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 : x2 x, B* `! f1 v
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
- J% |. ?! X, D+ v: _ - namespace one;
* N/ }$ ?" s& Y* E. g) p - class Person{" n6 J1 Y6 h$ [1 I9 t
- function __construct(){6 m/ Y, [7 q& x$ ]0 Q+ n8 C7 h8 C
- echo 'I am one!';
0 j9 ~% B, i5 n" Q4 M+ } - }2 H* P# w, |: b9 z( L
- }
复制代码- //name.php
$ A( T/ [& m' U" w5 \ - require_once './1.php';
! i0 Y$ R& x% x: [1 G - new \one\Person(); //输出 I am one!;
7 e/ F( y) c+ @7 s1 s9 w - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
* T0 F/ u* k Y: F+ {6 p. ]可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
7 d5 \- ~; u, h5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。+ O% h* W+ u0 A2 f
- //1.php
6 m# r( R, g9 L3 |5 f0 x8 T- _ - namespace one;% ]' J9 R2 a5 K% Q. f# c! z' M
- class Person{
2 I" s' o+ D; \ ? - function __construct(){; R. H, m3 h1 L8 {0 _
- echo 'I am one!';
$ F3 }% \! [8 k# I - }
- s; o* _- g6 E4 ~ - }
复制代码- //name.php
# ]7 f( n) ?" ]$ R8 _# A - namespace test;1 O4 \! ^8 Q |( i* }5 a$ @& M: T$ O
- require './1.php';
. d; ]; N9 O8 d - new \one\Person(); //输出 I am one!;$ [+ }2 Q, s; K1 g# p) s
- new Person(); //这里结果会是什么呢,猜猜看
9 Z* S6 z7 q( I* e3 Z: E - 最后一行结果报错:! W* Y5 {# ]' @
- Fatal error: Class 'test\Person' not found
复制代码 0 R; f" B: a8 [$ Y# T9 b) F) ]
6 \# B+ k* ^' ?9 G2 ~
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
/ p- V' E; L e5 D/ `$ D结果报错: - Fatal error: Class 'Person' not found
复制代码
M5 N6 @7 R! S# `接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
3 b6 b1 h" {$ d( o - namespace test;- e: ]( ^/ w1 V |& r
- require './1.php';
. b+ }6 V! S1 F( s4 E; q1 U, h6 t+ { - ! w s! H: J) w/ d1 ? j
- class Person{: [1 ?" d* h; w3 `3 ^3 w
- function __construct(){" L" @% j2 t. W& v- E7 G4 T
- echo 'I am test!';
% g* y" g. }6 U) a2 I- i& H4 ?. b - }8 H7 D/ ]% B' _/ E2 F# g. }
- }+ W( }7 p t" n- D5 w2 m. T- S2 v
- ! a+ V/ x' F/ X6 p$ Z
- new \one\Person(); //输出 I am one!;; K( _# t X( p) Y
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
# ?0 o, Y% \% L; I n' ^) G最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php1 {& L" _+ A$ F0 R+ x
- namespace test;, N5 C8 M% f( d/ H1 o
- namespace one;
6 m! i0 U0 \! Z* B6 l; V, R - class Person{; ^! c/ \7 f( v+ s' F
- function __construct(){
, ]8 k5 K5 v* }% g4 P6 f2 F0 | - echo 'I am one!';7 o$ D2 r9 C+ T! g
- }4 u- m3 R" N+ p) }$ Z& j
- }
M3 B7 f% H" c! K+ ~" T: j% F# r - 1 L) ^6 f9 y3 ~, a% o. T' S
- class Person{9 S) W1 }+ Z' u1 o- j( c- W
- function __construct(){
& f. O f7 B" `7 ~ - echo 'I am test!';! P: z0 e8 i; X) C4 q0 }
- }- c- }8 O, t; r. e% X
- }
复制代码 $ u6 K2 o2 ?. F/ A
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
7 v: C4 N. R* u* r- `4 m+ f2 x" D. x看来简单的把require理解为替换,在这里行不通。 5 r1 v) ~0 H6 Y. C" o
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
% g7 B9 s7 a% A4 C- //name.php
# f2 B4 S* D2 Y, p& w" ` - ! N' ?6 w8 ~, k( `
- namespace test\person;
# Q$ r6 Y! |9 _* l k8 o
) M! ]5 v. S) C9 U- @) d- class Person{0 F! H5 c3 f7 i1 H
- function __construct(){
1 P! L7 ?, c. _1 a) E - echo 'I am test!';
- B* r) O. b: g9 S0 h" e - }/ P, M& t) l. ]- B0 u
- }
( Z9 q6 `- {9 G# w( B } - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 ) l& c) n" `- G+ B7 U: K
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
, N4 [( x( U! e7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php0 a+ C6 M) L0 q1 V# Y
- + n f. U) s' R+ b* U
- namespace test;
* B( D- @8 z- A; N, f - echo 'zhai14';
2 k& o0 g) W- j - namespace zhai;$ {+ X9 w7 X' M! q3 P& r, L. e& x
- require './1.php';
复制代码
% v" `) G6 o7 k tphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
4 F0 | v* f& a0 C% Z guse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
H! M2 e4 a# @7 i1 ]- //name.php
% e2 V4 k/ Q+ A0 M+ k
4 y. l; _7 Q# Z, K- namespace animal\dog;
2 x. G: @/ w8 d# f, M0 i( j% l - / b$ m& F( w! t$ l: ^
- class Life{
0 J1 ]* \; O/ B) b5 X+ l0 n - function __construct(){/ G1 N3 B/ {) e- }
- echo 'dog life!';* u. \+ O5 i+ q: I
- }1 X* H- Z4 { J
- }
+ b# n* o7 i$ W# D+ t - % a1 h @! ]1 Z9 n/ \# H2 i% M
- namespace animal\cat;8 W9 }& o9 E2 c3 q. G
- & E1 s! Q. c2 C) A
- class Life{1 x$ B% O' D- |
- function __construct(){
) ?1 t e! q8 q - echo 'cat life!';
" @3 F9 N' D7 n* b) n& O0 T# f# f - }8 C7 N- i% G1 P$ G
- }
: s7 }! v( T, f
9 n% F* ~' E% P- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
' x2 Y+ R, b! r- e7 P v - new \animal\dog\Life(); //A
4 g4 m2 A" m" D2 a9 w W* y
. j' N3 I; C, J$ A4 j2 J) p- use animal\dog; //a
: ~) U/ y1 k9 e0 d+ N! I3 x - new dog\Life(); //B$ {1 D3 e0 s) }& g
1 v+ A) L' t. o- use animal\dog as d; //b
" Z! f# q. a" o U P% z# W/ v - new d\Life();
复制代码 " m- k0 Q8 v, J
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 6 T9 V( ]& E# O, M: O# [+ m
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
/ i5 k! r! B9 I/ n& l/ @相当于 1 i& n) X2 D" |0 h4 k
2.namespace后面不建议加类名,但use后可以。
! f8 U3 V* @- Q( b+ _0 z' k- //name.php
' Q! `3 P G8 f2 v) o - * A3 N6 @/ h& F) E8 R7 r" |
- namespace animal\dog;/ ?2 h) }4 S/ G7 C# \
% O5 q$ _' P# ]- m- C* s9 H- class Life{/ r! `+ X+ a8 ], h7 _, `" y& b( i
- function __construct(){
& E' x8 J* N% Q: v - echo 'dog life!';
) M* o; z" o" d! k - }, z* m8 |' R: [! d3 K+ z
- }
, ?6 y5 n0 Y' J3 w: c2 t E! K
' V p, ^, X J4 W0 d. ?4 I- namespace animal\cat;8 \: d7 P7 T% v! a' a" Q7 i
* j5 @/ Z [) r4 c s- class Life{
/ h$ ]$ c; d' r) M/ ]7 N - function __construct(){
6 e" b2 m7 h4 {+ Q" T - echo 'cat life!';
/ z7 Y% O; L, d. l& P - }& E. c" f7 K! y$ k& [) B5 o
- }( o- z+ |2 R4 _1 O6 L; e& [- ^
" }9 q1 S- C- Y' c8 f/ t, e- use animal\dog\Life as dog; " ^/ i$ s" l3 E: `
- new dog();
复制代码 6 r+ U# w: {8 T4 e2 |5 X$ d
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
4 N/ c$ y1 y2 A+ B9 R因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
5 v9 [0 j; h9 ]. a - 8 y4 v9 _) ]+ w
- namespace animal\dog;
0 f4 ~4 q! t0 `7 n% Q
3 J, h0 R2 x% t" W5 K- class Life{
2 @0 h8 ~# T1 C - function __construct(){
0 f8 f& e/ M9 s$ {' r2 \ - echo 'dog life!';
9 E, Z9 j# s2 K) M' Q! q - }
+ j; t( C% ~: k$ W - }0 K5 L( F, W2 x; O9 X7 b
- class Dog{9 }: {+ b, l- {& _
- function __construct(){
% l& X: ^7 a7 J& k# j5 M - echo 'dog in dog!';
2 ?5 `7 m1 @) V% z" l - }) t( {, i c( s0 g7 x% d; [
- }
4 W" M1 S% ~. f
' C1 z8 e5 _& |! o. C8 Y- namespace animal\cat;1 o0 [6 x, w6 j! h k2 l- ?
- 6 a1 _3 \" J' q
- // class Dog{/ j- B& G7 k2 ~2 u7 u0 R
- // function __construct(){; R- Y( x0 g) I: b o8 t0 f
- // echo 'dog in cat!';% A6 e/ M6 ]7 r6 o0 t
- // }3 L$ R( G5 a3 V% |/ e
- // }: b$ r8 }( A' T/ a, D. }5 t! i
- class Life{8 f* J6 \4 S' y! g
- function __construct(){$ p9 ?% r4 i: |2 u, I. y1 S
- echo 'cat life!';
: ~6 k+ u$ h, I" j6 j2 e' ~5 H9 s4 T/ t - }5 O3 {5 j$ U9 O( _4 _
- }2 m& F; q- k- |2 J& G% J7 y
- + W7 J T, a9 M/ c( ~5 c- ?( O& C
- use animal\dog;
$ I4 {* C) ~# c2 ^ - new dog\Dog();
复制代码
! Q& K, m/ K9 Q; b% F如上,使用了
* u3 B F1 h/ R4 ocat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
+ o# v& F& x& A9 Q- }简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
# T% a5 t: B" X
4 `7 R2 K! F8 h4 o3 Q" [1 S
3 o9 q' v0 I/ i! U+ \* f" R3 E
* m1 }* P9 X* ]. {5 Q0 i! _
. A" g3 T2 N0 t- @ |