以下皆为本人自我理解内容,如有失误之处,请多多包涵。 / h# b* |% A, {3 Y
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
9 j3 m. v" u: I, O" P4 b
$ ]- w6 a: Q, r% L1 P使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 2 @, f5 s7 e4 j, {1 i+ S* l) g0 x. k& e
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
% G0 T& o% }8 y结合使用方法来进一步理解它的使用目的吧。
3 Q6 c* W2 m* N0 A- q" {; k, R
|; y: G1 O& R' [0 [ l: znamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
6 O, C9 z4 B) ]. v! M; M - namespace One;
3 }* ~8 B1 o& U+ f! o% K) G - namespace ONE;
复制代码
) x0 H5 `& Z \如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
5 O! O7 H' Y/ U! h% R2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
* U1 g6 o- P; Q - class Person{
2 `% T# n0 L: ]3 Y t! E& ? - function __construct(){
8 N9 M3 X2 `2 o$ j3 v - echo 'I am one!';
' e! ^3 ~, {( J! J1 q - }
8 a) Q# s$ c- F y3 m - }
复制代码- //name.php
$ a0 S, C7 K- [ - require_once './1.php';" G9 M7 B# K, g
- # K6 ~( a5 @6 a/ q6 ~
- new Person(); //输出 I am one!;+ Z& i W3 C+ }' n( ^1 s. t$ m* c
- new \Person(); //输出 I am one!;
复制代码
* l* U! e" G: s9 W3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php. k; R" U" T8 U t8 I& W A
- require_once './1.php';' }) u( c" D Y! `
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 . `3 X5 a$ \6 C1 l9 K+ V2 P
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
% N+ E1 K1 W3 `2 |, E; l - namespace one;
. V7 m9 V+ D& f* Y m( z - class Person{6 u* q; [* D; m/ f. S- ?) }
- function __construct(){7 j' j6 ~0 y) i, y" Q3 u
- echo 'I am one!';* J$ \, }! E7 `* u) M6 }$ X+ _, r
- }
) x2 g. Y: l8 E" r - }
复制代码- //name.php
$ x4 H8 \; N6 P3 A( N! q0 |+ r - require_once './1.php';3 }# M& ~5 @$ X W- ]# y7 y: ~/ ^" c
- new \one\Person(); //输出 I am one!;* t H+ b) \- h* `5 i: E" Q) D
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
, S o( q9 U' w可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
$ a- s6 X/ l% p! A/ z" k& S5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
6 V4 l+ a$ H% T( ?1 x- //1.php
- [; y3 Y/ s6 l& g* W7 d$ x* e8 w - namespace one;* K. @) Y( I2 d" a! e ^0 d p
- class Person{' y" j/ Y8 i! \) a7 P" X- N6 l7 w
- function __construct(){
: ?( Z* Z+ h% l7 [$ n& w - echo 'I am one!';) Q* ?- A4 n# ~4 q/ m- s
- }* R3 @% b" z+ B( k* h' T' g
- }
复制代码- //name.php7 L6 b& X; G2 W- ~( N' B
- namespace test;& x X v+ O9 m! ]1 p, e Y- H
- require './1.php';
: B; X6 L! g- G4 k* F7 b. ^' Y - new \one\Person(); //输出 I am one!;) `( m- P, q' P
- new Person(); //这里结果会是什么呢,猜猜看* q/ s! D+ P$ R Y' U3 u
- 最后一行结果报错:
) m/ N @4 S% c8 E7 o - Fatal error: Class 'test\Person' not found
复制代码 0 u0 q8 v2 k& S0 b
' B. }7 Y, c" c; P
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
! F5 Q( H% }. |" O/ Q( d: ~结果报错: - Fatal error: Class 'Person' not found
复制代码
9 \- r% m5 L; A: y* O2 W- t. |接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
9 X9 v3 \* ~. C6 K$ h% B. }/ n - namespace test;
% a& k- [; g9 P2 K7 h. }3 ] - require './1.php'; + |+ b/ `9 r* |% T9 S+ u
9 b6 Z& V- v. p# | W7 C* t( E1 z- class Person{+ b$ J8 y5 d) E7 f/ D! i- U
- function __construct(){. \7 S$ x: N* V* m/ C: F7 g
- echo 'I am test!';
4 ]$ }$ u! R# ~+ H - }( S) j M3 d- \/ Y% G
- }
/ k7 n( M; c, l- P% A4 I
- l" b" y/ T; [& M/ S- new \one\Person(); //输出 I am one!;& w* c/ M3 O7 z. F v# j6 _" X o
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
* @' K2 t( K' q最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php( P' @2 H0 n4 A+ `3 x d5 T8 b
- namespace test;
1 W! @$ i# c0 e" c$ F# O. c - namespace one;- c+ i- A$ | e% L# T6 E2 N# J
- class Person{8 l# k! k/ Z( H9 D
- function __construct(){5 a# d4 Z6 _) ~3 P# R% w( G5 }
- echo 'I am one!';
, H2 V7 y/ g- D. H( I' W - }
7 Z, T5 Y8 l E. o) r/ x: a - }
- l$ D" a% h/ E* Q
' Q' {# a, b" Z: d) f4 x- class Person{
) f" z% z8 K9 s) _! y - function __construct(){
# ? S4 T. A- G3 o - echo 'I am test!';* z( R4 K0 @# V+ G
- }
1 r" p3 t* M$ Y% \7 ^% c# `+ } - }
复制代码
$ C# M$ V/ _, V无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
5 p. z$ ]) ~0 g3 Q) C看来简单的把require理解为替换,在这里行不通。 - D- d. r U% U5 |& @
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" |% ^% S% d$ |4 i; c2 S/ W2 {- //name.php
/ u/ G) k+ f3 u" k7 t% u8 S0 p% I4 D - . Y6 m) p v/ x6 @0 d
- namespace test\person;( ]0 F! Z t0 ]' p% K
d Y7 }7 ]" Q) D# H' ]- class Person{
" _. i+ `* {$ R. Q2 C- R: p8 s - function __construct(){
0 M1 @0 ?: d# u( {6 X) ` - echo 'I am test!';
8 b& r) E& |7 L% b- A* w [ - }- _# ^% N1 q: p; }$ w* x9 C
- }
+ @" F a& ^2 s5 T; Z) s2 d - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 ' h) z7 C( n% b
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
3 a# F+ S2 ^5 y2 b$ I7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
! s2 F+ W& m: F5 S' n - ! g' a# r/ Z3 B/ j1 r
- namespace test;- D) w0 M/ p. R* x0 R, W
- echo 'zhai14';
! H* m7 z8 V- |. R; u- n4 ` - namespace zhai;" B. g! G+ C) o3 v( M
- require './1.php';
复制代码
$ Q5 D/ U/ x# o$ X* e: w' I: q( Dphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 / H" t( `' n$ {4 \' b8 H1 C
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
9 z! l/ R0 k! j2 Q0 h- //name.php* Q# k* V0 \6 m, t2 {
- $ z5 C- ?2 {6 j7 j1 T
- namespace animal\dog;- i. q+ K9 z7 S3 m- r* t8 k: s6 P2 t* u
- 1 ^/ |. A' N! A: N0 z( i5 P* M
- class Life{
: q& v: J5 G; u& v4 @: j% v - function __construct(){5 n4 h |# ~: G8 @( g& i+ v
- echo 'dog life!';# m( ^9 i8 X& d3 T- |& X
- } \+ F1 G- V* O
- }
5 ^. W" {3 p+ v$ k
2 E$ ]. r4 B# Y# ~9 Y6 U, R- namespace animal\cat;' y5 B9 N# G* w! Y4 S
- 0 `+ {4 j8 ^4 R: W' g$ Z$ Z% O5 F
- class Life{
1 y" U& G+ S5 k* I* b( a+ X! d- v- G2 ` - function __construct(){
4 l) d/ B+ W) C" I - echo 'cat life!';
8 U- W# U; i. W8 O* K9 S. Y$ g - }6 h. ]* _+ Q$ |1 O5 `
- }2 p; j0 J7 d# \- }4 y' q
- & N, N& I- x, b4 S0 f
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间 W* w4 z( a2 h6 x3 H
- new \animal\dog\Life(); //A" K$ k; a2 L) j! I1 n }2 F( \
/ t7 n p; `5 }3 p. v- use animal\dog; //a) q! T5 k S, D5 L% _3 @
- new dog\Life(); //B
! |1 M+ P% v1 ]! M4 w& Q# r - 0 H: v- m8 f- ]. p3 X/ o
- use animal\dog as d; //b
0 C& B' S& ~6 p* b) Z" H - new d\Life();
复制代码 * a, s3 Y/ N4 ?* l
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 : Z u. I9 }# D* T; b |+ X- F
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
: H9 ?' q2 |4 K+ B) Z. c8 m相当于
) A, X* t$ N/ D+ r5 Q* }2.namespace后面不建议加类名,但use后可以。' o. q; K; V& _% h w+ B% g! M
- //name.php* G8 _: j- x9 ^7 n! |
* G$ j; E3 y4 M3 p- t" S- namespace animal\dog;
& s% x2 z, ~3 q* M& D& j$ H - 2 b7 E* }* L% m d1 Q
- class Life{
% Z7 ^2 Z; e' I3 F* r% Y& d' c - function __construct(){3 D* B! A( ^& P$ w
- echo 'dog life!';' C& z2 z9 h1 T5 @
- }# K3 H2 h3 y& a% w- \
- }
3 `% ]7 A% c( E) o
0 \9 h0 k7 ?0 k: {5 M7 [7 D- namespace animal\cat;
\ j3 Y) n7 Y& k4 r( { - 5 K p6 v5 I: Q |' Y
- class Life{
: U# z" N9 N) O) j - function __construct(){: _* Q0 P* m; J# I! V7 r2 s
- echo 'cat life!';7 `, T# `% q4 _2 o) ?/ C o
- }7 d( [! i" h& D0 G5 t
- }
; }3 f$ @/ d) A0 g3 w4 n: X2 h- W
# D3 b) N- v: s1 M- use animal\dog\Life as dog;
# r* B7 f W0 K2 q) q" ?8 Y2 J# O3 C - new dog();
复制代码 $ e- e1 N# W9 V( T4 e
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
7 z2 ]* R0 |- O9 K6 P& T因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php/ r* l# f, z! Q( w3 v
% |, o [" B5 b# l/ {/ i- namespace animal\dog;
" g1 o$ M* D/ e F - 9 `! Z5 s9 B" S2 R p0 _: U
- class Life{
& Z1 \/ w5 e }' z0 ]6 V - function __construct(){/ f: L# H" l) E L& a9 s0 ` e7 r
- echo 'dog life!';
+ a9 ^" f( Y0 W$ ]% @ - }3 L7 H9 R1 {) i- J
- }
& `. v! x( O" g - class Dog{
0 u% Y5 l; y9 H3 a& K7 a: ]" b - function __construct(){
8 K3 H3 J: \4 [% t% ?& E - echo 'dog in dog!';
3 Z2 S# G# t9 O: Y - }4 Q' ]+ `7 y' _4 |& R
- }
- ]. L' l0 r/ y1 t; i/ Z; A, x - 6 x0 K$ S0 ?0 k9 a- l9 b" w
- namespace animal\cat;
8 U' b* ~* R' K
2 L- ?( E# b3 l5 Q5 a$ H- // class Dog{( p9 D3 h" [. Y' _5 O
- // function __construct(){
6 o9 U8 r8 P/ I- L7 r - // echo 'dog in cat!';
0 C- U% q3 w* f6 c" o7 W - // }
; b8 w, K9 I, d - // }* p! D% \1 n+ l- n% c
- class Life{( ?* [ H. `% i3 o" N
- function __construct(){ U* x8 p L/ D" n
- echo 'cat life!';
7 {' s( A; m6 e1 i8 ^3 g D - }- M3 F( k& U: j& _( D( T
- }) o* t1 a0 K o8 J
0 G: z. E2 o# @, K t" \- use animal\dog; $ V! Y& k1 d9 a A5 u0 _
- new dog\Dog();
复制代码 ( g4 s, m | n+ D+ [
如上,使用了 ' F% @- T# e9 M' n+ `) ~% h
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
: @+ A; Y0 D/ ?) B) B2 N简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
# m2 K" T2 h" J- z1 M& f* q7 Y9 Z) }4 i& F
: o' W# b- Q' v, }" U5 A% o
6 H% W4 F' a; `4 P; T2 D
+ U7 w. |, k- U! O6 G: ]& U |