您尚未登录,请登录后浏览更多内容! 登录 | 立即注册

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

PHP命令空间namespace及use的用法实践总结

发布者: admin | 发布时间: 2020-7-1 23:37| 查看数: 7290| 评论数: 0|帖子模式

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
6 X; R2 b& D2 ^
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
3 N0 Q/ `1 X; m

- y9 M) g. `: K使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
4 N9 N, ^- [0 h: }
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

" h0 I* x8 ^- d" }结合使用方法来进一步理解它的使用目的吧。
2 b" B' f2 i  ?

  E$ f0 j% v5 T1 K+ Tnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    % m7 x- D# V" f) n" `/ l
  2. namespace One;# A& @+ I* _2 p  d; N7 N- J9 l
  3. namespace ONE;
复制代码
6 _- {% b, U# X, q2 W& C& E
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

9 O2 D" b, d8 P6 m' F2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    7 E! J9 D- {! a4 v0 H) d
  2. class Person{
    ! F6 [  S; Y4 ?/ @5 c
  3.     function __construct(){
    0 p$ ?  _" k! X- M, F9 P
  4.             echo 'I am one!';
    0 D( {% T* [0 V
  5.         }1 J" C. e0 c& D! Q" a; L2 d
  6. }
复制代码
  1. //name.php
      ]) z6 T7 G- L  d2 w. n' N. g
  2. require_once './1.php';9 D1 Y7 u( ?- }0 ]- Y- |( K8 J
  3. / j4 f6 C2 J: i/ \: e3 w% i7 o
  4. new Person();     //输出 I am one!;
    + ^7 `8 Q3 ]# o
  5. new \Person(); //输出 I am one!;
复制代码

7 w9 Z& M2 |. y- v: q8 c: p" e3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    - W7 K9 ~6 ~1 Y
  2. require_once './1.php';( J! L! M6 X+ x
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

9 T# I6 }5 v1 k' J4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   * V0 u0 ~+ y* a4 ~5 _- `6 ~) G2 r
  2. namespace one;
    . d( c$ E9 S+ O; j; d* `; G
  3. class Person{
    / N; M. F+ v' i" B5 }* j
  4.     function __construct(){3 Y9 }8 d, ~% A& N, A3 R
  5.             echo 'I am one!';
    % Z* f7 ~7 C& B2 w: L' m- C) X; ~
  6.         }
    " G" _% I3 @0 A
  7. }
复制代码
  1. //name.php
    & Q6 Z7 R. ^) Z1 D, W) }
  2. require_once './1.php';
    . f1 m; K9 `8 h# e
  3. new \one\Person(); //输出 I am one!;
    ) ~; d: c# S, c5 A9 o, J
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
/ y7 d3 B8 A' {$ ~% c# G
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

: `7 ?- |  @" @9 A9 @6 Y  |3 ^5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
/ Y- h. J+ ^+ H, N7 `) g& V
  1. //1.php   + q* K3 z# `! D3 R1 F4 m1 e
  2. namespace one;) \- {: X  |) _  Z0 I
  3. class Person{
    " I) ]# e+ E; Z! U
  4.     function __construct(){
    & i; m9 i" U7 G( Q* }6 n, v
  5.             echo 'I am one!';
    . I9 N$ i% Z7 v3 @9 ]+ a
  6.         }
    . U. k3 X" [  k1 E  J% d/ C
  7. }
复制代码
  1. //name.php6 B: X! s; @% q) }: @: p7 F
  2. namespace test;
      S: \. L( J5 q0 a% `7 ]% K
  3. require './1.php'; ( A- ~: t' @# t! H2 i3 S
  4. new \one\Person(); //输出 I am one!;0 e3 ^, |3 A5 [
  5. new Person();      //这里结果会是什么呢,猜猜看" x- B7 `/ O' x8 X( `
  6. 最后一行结果报错:$ Z2 W9 a: ]. x) U, ^
  7. Fatal error:  Class 'test\Person' not found
复制代码
( K- F/ _% `) u* ]3 i  v5 M, W( d, l, y

. F3 r5 \" N" o1 i首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
* H$ |; g5 Q9 _7 a$ |1 c# {
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

! ^- Z/ k$ z  @9 M3 p& i
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    , K! F$ z4 j% o. I6 T' }
  2. namespace test;
    - y" s. E/ A1 h* y
  3. require './1.php';
      u: h! a  a2 U- \7 R! L0 V5 ~
  4. 2 h1 [  Z0 L5 P7 X9 Z9 d
  5. class Person{
    0 t5 h/ `4 Z( A: I* I3 l& O; j
  6.     function __construct(){/ f$ o8 }. T4 ~) E! U" W/ D3 ~
  7.             echo 'I am test!';5 l, p, Z  n  b+ c* h2 t7 [
  8.         }
    8 O2 j0 W# `( T# M( q6 p  {) E
  9. }: L3 f# p( S4 K: O9 D0 Z
  10. # }. P3 M, ?+ ^; v, f9 \' q/ A8 t
  11. new \one\Person(); //输出 I am one!;1 ~; D' r8 T3 `& @
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

6 l2 K# \8 }" t# A9 h7 O5 x8 O* \
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php1 ^8 h/ c( {" {
  2. namespace test;
    2 t$ v/ h3 o; U! R/ R+ Y2 @5 b
  3. namespace one;! s6 L4 c0 L: V  g# J' n% t
  4. class Person{0 E) ]9 e1 ~( f9 Z: u
  5.     function __construct(){
    ' b0 Y$ Q5 e! Y% A" k- ?5 L
  6.             echo 'I am one!';% Z1 ?7 P. H% j/ E9 u1 [2 d
  7.         }
    9 w) F* n8 N, x' H+ w0 S" z
  8. }9 n! _5 U' V4 g" [- m5 d# ~' F
  9. * m) ]6 @# H* D+ ?! m7 k8 H
  10. class Person{& v' ~5 j( X7 q  j! G9 B' c. a
  11.     function __construct(){2 |2 N' |! E- K6 l$ t. s; r: `( J
  12.             echo 'I am test!';
    " ~- e/ s2 J) p# {2 O( n
  13.         }7 s+ U# ~+ K! V
  14. }
复制代码
# X, X; e# w1 u% ?& P; J
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

1 X, f. b. C+ Z
看来简单的把require理解为替换,在这里行不通。

  U* |; s& T! s. K7 ?4 `6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
# K: N: P( h# E( J  L7 o
  1. //name.php9 D. q& p( ]1 x6 ]3 k7 @: T
  2. % {8 N# p% f$ |6 I
  3. namespace test\person;
    6 U; r, h; _) ^3 B9 \: m) n8 x
  4. 8 A& j6 n( L' F: J4 D0 \; c
  5. class Person{
    ( G' V, e. P7 `2 }9 x
  6.     function __construct(){
    # [0 Q4 K5 D; J2 Z0 \# D2 T1 k) Q% P
  7.             echo 'I am test!';5 g  T9 W+ Y) u& N1 V
  8.         }5 z; _7 O1 S5 |% p" [* D
  9. }
    ( }9 ~( a6 q; U1 t: `& g
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

* w6 s% f* x: N8 q$ f& X
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
% `+ x) S+ V7 D5 `/ y  n9 V
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php7 o+ ]  Q9 B7 u. d

  2. ! p, U+ N. k* g# S3 X% u; c# F
  3. namespace test;. `0 q2 z9 u. `: K- @) e
  4. echo 'zhai14';5 q0 j8 X2 j6 H3 k" |! U) r, g
  5. namespace zhai;) D7 l+ H7 [) Q& E( y/ N! C
  6. require './1.php';
复制代码

$ H# d  m. H. T1 H/ c7 }! |- F$ F
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

$ [: D1 a/ x' S" C) W& A' tuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。) e+ x% F1 [* x6 t' K5 Q# a1 A
  1. //name.php6 P4 W0 ^( q9 r8 R8 ~  l
  2. 7 e0 f* }3 @9 ^) A) ^) m3 v3 B
  3. namespace animal\dog;" z" G! p& c7 {" R

  4. 1 J! \$ [. a: _+ [
  5. class Life{
    # R+ x# a& o' I2 W+ S1 T% C/ t. V
  6.     function __construct(){  @1 ]  `7 J+ U- T1 `! i0 s
  7.             echo 'dog life!';
    / Q! T8 C3 M, ~/ C! W
  8.         }; K' g7 g5 r% B3 P
  9. }! ?# X2 h* Z$ J9 O- N* k  o

  10. 5 z0 n. C9 x3 r
  11. namespace animal\cat;: k5 w& g, `0 x

  12. * S- g* ~  [" b9 o' Z% r4 Q
  13. class Life{
    ' ]( X6 `  O  y& k+ R
  14.     function __construct(){
    # G9 u' t: r6 b! R7 h' F' a9 l
  15.             echo 'cat life!';
    & q9 n. s$ |; T; e9 [: `+ o
  16.         }3 I" B5 `, @5 i' l7 ?( _( N
  17. }
    + {' m8 C4 ^: e' h7 r! [; N
  18. , B; ]% |% s# A  l
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间  ]! B8 i. T  p- s8 D/ C# z
  20. new \animal\dog\Life();  //A
    ' T9 T$ U/ `: `

  21. 4 X! V7 b  c, S4 N- e# j% t3 a
  22. use animal\dog;  //a
    5 G/ [: T6 o( ?
  23. new dog\Life();  //B
    # g7 R, {- R& ?6 ]" x/ u6 m

  24. ( j; D" {) V( d# s2 E5 y; f( M
  25. use animal\dog as d;  //b# D& {; ?& }% w, w: J; K9 W( ^" J( y
  26. new d\Life();
复制代码
; }4 f" x! s4 F" O' S4 T) E" t
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
' e$ X7 }/ f" D1 {" r  o- N7 _+ @
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
: I( T8 ~  ^8 `  }: Y$ w6 Q$ d
相当于
  1. use animal\dog as dog;
复制代码

/ }  I- D" P$ `- C2.namespace后面不建议加类名,但use后可以。& l! J' e/ v8 f' m5 l
  1. //name.php6 H% l1 i. i* ?( L9 ^6 d
  2. 8 B& r/ E! K) p& a5 O
  3. namespace animal\dog;
    % {' s3 ^" s! f. g; o, A

  4. 3 M0 d* @( f+ b  D
  5. class Life{" W! @, X$ X3 ?- M2 X' k; a
  6.     function __construct(){& n- o% p) s8 T) d( Y- t5 n
  7.             echo 'dog life!';' F' Q' \9 V4 g9 i# V
  8.         }
    $ U, U3 R6 a6 J: x; |
  9. }  \$ b1 q& d' h6 u; y4 M2 J

  10. 2 i" ^: K3 W9 M! M
  11. namespace animal\cat;) N! @) M7 T) z) G! k* j
  12. / s  l$ S8 e9 t6 Q0 N
  13. class Life{0 v+ J: l8 Y# U& r2 F6 C( w8 z/ p
  14.     function __construct(){
    ; W7 w; w) [# v0 l) Y  N  y1 v
  15.             echo 'cat life!';
    9 X' O  u" Q% N/ Y
  16.         }: t8 [0 i& P1 K0 Z! j( f3 a
  17. }- m. J5 W" Z! ^  m" M0 o

  18. ' T: s3 O% }& b7 X
  19. use animal\dog\Life as dog;  
    ( s) v# w# t& ]7 t
  20. new dog();
复制代码

& B. L! [7 w1 b/ f/ o- n) c& D. w
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

- j& [3 |. `7 [: J1 H4 D2 k% v
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php/ y' c& d! I7 k% x4 b5 C0 d

  2. * d, r* S; |5 b/ \$ F) _
  3. namespace animal\dog;; d/ D  {* S9 t

  4. & T; ?) K9 `( `: {+ [# ?6 C
  5. class Life{
    / B) m( v% H0 M
  6.     function __construct(){9 y8 @7 |( h% P$ v. D% j  G
  7.             echo 'dog life!';- a+ K. g0 \3 G+ N! x' r! k# G
  8.         }
    * ?8 `5 r. g* M
  9. }
    % o8 g2 S) O' B8 |/ Q$ P1 y6 B# A
  10. class Dog{
    9 @5 d/ V! z) v
  11.     function __construct(){
    8 s1 z8 V2 X1 g7 a% `
  12.             echo 'dog in dog!';
    $ U0 j+ X- v6 f6 W6 S! Y- C+ O0 ^
  13.         }# y) d8 ?$ G* @' |8 O
  14. }; m* h+ s; G& P

  15. 8 T, O7 @& a# F( s- M
  16. namespace animal\cat;' F7 h$ h% B" N

  17. 1 L$ g/ i+ I# ?( w3 I
  18. // class Dog{
    9 a* ^9 z6 J: L" @
  19. //     function __construct(){0 J; j1 F0 n4 D; Q5 r3 t2 |: N
  20. //             echo 'dog in cat!';) I3 x: H. d7 t6 o/ y4 y
  21. //         }
    % v; w: ~8 B" m
  22. // }1 w- k+ s: G/ B4 K5 i9 ~
  23. class Life{" @" o8 ?4 O* w, R3 g% [. m
  24.     function __construct(){
    4 \" W% j6 O8 |+ l. R: h
  25.             echo 'cat life!';& `8 a- G; q6 |" u+ K) y
  26.         }7 O& w. O3 s+ V- K* W. Q4 b' C/ j( C
  27. }
    ) f6 g# K6 y' o% ?% n/ T3 }

  28. $ ~( u: n4 ^" `9 @6 o' ^8 q3 [
  29. use animal\dog;  2 v* M/ m) a) s2 z9 |
  30. new dog\Dog();
复制代码
  ?  Z& i: Y7 I; ^, {, R* `1 J
如上,使用了
  1. use animal\dog;
复制代码
" E3 ]  A! Y6 W1 j2 Q8 z" U
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
. v+ ^" P9 |/ x6 b! t, a1 V# \! F2 Q- a
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
' z, K& V0 w. k  p4 n: D, e

- K& b. l: }" X* E
* u& `: V4 X* h' |
/ U8 O6 Y8 y8 Y
; z( n% z1 V2 U8 i. I2 w0 c9 c

最新评论

GMT+8, 2023-9-30 06:51 , Processed in 0.125640 second(s), 22 queries .

Copyright © 2001-2023 Powered by cncml! X3.2. Theme By cncml!