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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
5 C9 a7 W. _: v+ s* Z" L: q
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

" W5 O- E8 q4 C* f6 k
% G* R: o( Z5 \% F) n# G使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
/ C3 b, e9 J1 q# C" e$ [- \
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
  e9 `8 U/ |6 Y' q) f' c
结合使用方法来进一步理解它的使用目的吧。

$ `  h& A7 u' `3 H. y7 L+ n
8 O4 |" G, G0 Jnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;; f3 k- W6 u+ {. X6 a
  2. namespace One;
    ( R+ `9 B% o% r( E3 }) |
  3. namespace ONE;
复制代码

) L( Y& z% t! P% f/ z. Y
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
& ]4 z9 w( E  ?! y
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    4 y3 m: U% P" _( E. S
  2. class Person{
    + e) z1 O4 p) y" t
  3.     function __construct(){
    ; n1 o+ \/ C. {% t3 W, _0 z- V
  4.             echo 'I am one!';  }8 U9 s2 b6 O, O
  5.         }
    $ }0 f) O2 b- T! J* E+ ^4 @7 \
  6. }
复制代码
  1. //name.php! H/ g& \- S* W/ X
  2. require_once './1.php';! ^# u( V+ x3 ]! ]' n/ p
  3. 5 {1 p% X- g& R% h. R
  4. new Person();     //输出 I am one!;
    , _3 a! _) T( Q  I" Y4 V" j- w. e
  5. new \Person(); //输出 I am one!;
复制代码

' T0 G) P) [; Q9 f9 {( }5 b3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    " o1 G: ^5 S+ I6 y+ m/ a$ [+ N
  2. require_once './1.php';4 V5 M, o/ h) |' x% R* v$ s5 t  z8 C
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

/ u2 v$ m0 ~! `- p5 U9 w4 ^! T' @4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    * Q* k" I3 f4 o7 O( B5 S3 P$ W+ O" x
  2. namespace one;
    * {" A* F$ P* F# c
  3. class Person{
    . p/ Q! v- q: o- V) v
  4.     function __construct(){
    $ {7 t. v' n. y4 w& n
  5.             echo 'I am one!';
    9 [7 d/ I# B# s4 c$ H, m/ _7 M6 W) a
  6.         }
    2 a4 `; l: x, s: v1 I) x
  7. }
复制代码
  1. //name.php
    % E2 P) a2 l& S% C7 W' |( O
  2. require_once './1.php';
    ) V' H+ I7 c# H9 o1 i7 d
  3. new \one\Person(); //输出 I am one!;- k. S& u" Z" w# Q( o
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
. i7 g4 Z$ Q( f' S2 N
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

) a: S4 W& ^, S5 u( T: a5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。  Z% p3 a' G+ G
  1. //1.php   3 j1 n) s& h6 L( C1 Y& _
  2. namespace one;. J5 [0 w+ t8 E; a$ Z
  3. class Person{
    5 P2 n6 E* B, D2 w: |/ s7 w
  4.     function __construct(){
    9 k, d& }4 u$ t* X( X9 g
  5.             echo 'I am one!';- A9 U5 @! X8 b: V( f/ T. D
  6.         }8 p& h/ ]0 g. a* n3 p; P, K
  7. }
复制代码
  1. //name.php& e4 ?7 ^5 |  s7 _5 G2 K8 A% C
  2. namespace test;
    / w" H9 v: _; P
  3. require './1.php';
    7 b+ @5 i: G* h* s- Z
  4. new \one\Person(); //输出 I am one!;
    / \# e" f& M% k: q' ^3 m
  5. new Person();      //这里结果会是什么呢,猜猜看
    3 m7 U* D+ w/ x
  6. 最后一行结果报错:
    9 L1 H; \9 O4 _+ o$ }; K
  7. Fatal error:  Class 'test\Person' not found
复制代码
# U- a- `9 n& [) R: L: p" I

- K7 R  c5 p8 G9 Y% E8 g! }! o首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

- j# J3 R. H. V" @
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
# h7 [, Y- y+ N, \6 u3 q. j3 I4 K
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    ' J( M2 p2 \2 d
  2. namespace test;
    : \; n, ~& Y' g( ]* v
  3. require './1.php'; " o) H- B  {, N/ e! V! @8 a
  4. " c2 \0 b8 _/ J' c# b4 [4 j! p! P
  5. class Person{
    ( }: ?! X# v& U5 o
  6.     function __construct(){; [- O. ]% T8 M: q5 O
  7.             echo 'I am test!';  M9 G" `# s6 }- v0 F: i6 F  v/ G
  8.         }
    / N/ c% F* {; L
  9. }
    / n0 |) v& j/ z+ T. r2 b
  10. 2 Q8 x2 E8 R, ~6 ]: `
  11. new \one\Person(); //输出 I am one!;  O- j! H. ~  B
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
5 K+ U1 E7 W, R; Z
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    & o* P/ n5 q* T' O" x
  2. namespace test;( v8 e6 V. n5 T5 M# C" u. t
  3. namespace one;
    0 g5 I- l0 q6 j! I7 h' v' s2 ]
  4. class Person{
    - l8 @, W, J# \' r3 P# W- _+ Z
  5.     function __construct(){& P, L3 m; m: M6 u# t  J5 I
  6.             echo 'I am one!';3 z; ^, Q" K" ~# K% `( M
  7.         }& [, V, J% g$ H9 P0 ~, K9 A* P
  8. }
    2 a( q+ V# Y3 E# l3 K
  9. + |* @2 @, K+ G! m! Q
  10. class Person{; F- U. y' ^& ?
  11.     function __construct(){
    & Z$ R- X6 [5 q# ]+ ^; v) S: v2 Z
  12.             echo 'I am test!';9 _4 n* L! J4 H6 b# p$ {7 U
  13.         }
    / o5 f) o4 J) x' y! I7 A& r! F2 ]
  14. }
复制代码
! s+ j% Y4 G5 J  N4 s  A1 i! R' I: B
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

: p3 D  r% J* i& E/ b
看来简单的把require理解为替换,在这里行不通。

1 A6 T5 m: \: L( n. C. f6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。! @- M" i4 ~' k) o
  1. //name.php. o% H! e- ~4 n3 ^. R

  2. 5 u0 n4 a0 c! h) i" S+ I; N
  3. namespace test\person;1 ^( {- ]1 P7 b5 Y0 J
  4. 5 P" x3 o: L8 [. S: c
  5. class Person{! {. e" H: _, J
  6.     function __construct(){+ A: }5 @5 l! m. X
  7.             echo 'I am test!';- a* ?6 A2 J  K' u9 ~0 \; h
  8.         }* E, ~( }0 ?) @9 r. `2 X
  9. }
    6 T2 `  I: X% F: @* ]
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
8 ^: s' d* D# [
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
/ H' d3 u) V2 y4 q7 n; n
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    , n, Q  I2 C5 F  q( `% l' |! A

  2. 0 O5 Q3 w" N4 R7 T( c3 d
  3. namespace test;; h& H0 H( S6 t  G
  4. echo 'zhai14';
    : a9 x9 |0 V/ H8 ?) @: {0 K
  5. namespace zhai;9 Z9 W! x& c0 O# T0 g( o2 H8 {
  6. require './1.php';
复制代码
7 H: ~* ?6 v6 R; ^. ^
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

# X4 T# |0 n( @use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
  h1 e& {5 H$ P& p; Y
  1. //name.php3 v: x. K3 |- M: g+ ?9 _

  2. 0 F- b5 Q: m2 d" ~6 S" g, {2 d
  3. namespace animal\dog;. K8 d4 K  {/ C) M9 _9 `
  4. " u( S9 H. b+ g1 G& n; [& b$ Q
  5. class Life{; V2 U, y: }7 N% Q8 F
  6.     function __construct(){
    2 B  y) Z( e9 M# C+ O) m
  7.             echo 'dog life!';
    ! J) ~: j- L. C( ~0 D
  8.         }
    0 p& ^! h4 G4 r' o6 g, w8 W
  9. }8 M, R4 n1 M  n5 t1 G) p& h: u; v

  10. ) k2 s4 b4 Y, m) P- d
  11. namespace animal\cat;
    7 C2 y0 p/ P6 y- H+ w# |. Q
  12. & y* t& S9 ^3 ~3 G; ?. O
  13. class Life{
    ) Q7 Z9 B6 R' p% Y, l
  14.     function __construct(){4 ?, i  X& }2 z  a7 F$ S0 I& Q
  15.             echo 'cat life!';
    4 k% Q! G% B) b" K
  16.         }5 k. @. d8 Z0 T( h, M% c
  17. }
    1 q9 ~: \* r" E$ Z4 o
  18. - K' \: \2 z" ~' X4 f
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    8 x( C: H" V8 y5 m
  20. new \animal\dog\Life();  //A
      i9 _# I! t( X5 d& o( M

  21. 1 o2 M) h: p/ u2 Z$ @' d
  22. use animal\dog;  //a% f/ y; K/ U( V; B( p" p6 f5 ]
  23. new dog\Life();  //B5 v4 j  R  N3 F/ C8 m1 {% U
  24. / ~# t4 r; T9 M- D. U
  25. use animal\dog as d;  //b5 K' N; v* g" a  F& c
  26. new d\Life();
复制代码

& p% ?( E0 Z8 d( O4 a8 q/ e: U" F
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

  Z) k, k" N$ z
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

* W. R7 E3 W) d! `, K
相当于
  1. use animal\dog as dog;
复制代码

+ i  Q. U8 x0 k7 `' b6 l2.namespace后面不建议加类名,但use后可以。  x; h; [6 U4 n
  1. //name.php+ F% P3 `2 z2 W$ L

  2. 6 y9 ~5 j, }/ l7 i5 X4 O
  3. namespace animal\dog;
    $ k5 A1 J. M; z. y+ N# ^0 Y

  4. " {: L/ G) t, }$ ~
  5. class Life{: u7 v/ L& F' z0 l
  6.     function __construct(){6 `* h. j- K5 a. \
  7.             echo 'dog life!';
    ( `5 K3 _$ g4 y' P% q7 ^7 k5 m
  8.         }
    ( _* T) k, @& j+ c" z5 P$ x
  9. }8 h+ a' k' y& C# x! i( a; [  v
  10. 4 }2 k0 h/ z+ R4 L! `; h3 N% K9 b
  11. namespace animal\cat;0 Q  l+ t# }+ X% }
  12. $ A- i+ f% p8 h7 ^" @
  13. class Life{
    , O5 D1 L/ C3 H% L
  14.     function __construct(){
    ! n, w' l' U  Y! m& X3 m
  15.             echo 'cat life!';, E5 ~, M. _% p+ f# `, V- o
  16.         }* x( I& C2 j6 n( u
  17. }
    . C2 w0 f9 ?: f7 s2 s3 D: X9 u% y
  18. ! }6 O9 D8 V. d2 _
  19. use animal\dog\Life as dog;  
    9 d  k5 M+ B! Q; Y
  20. new dog();
复制代码
3 H$ F9 R2 a" _- g
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

4 Y. D/ |( ]$ R
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php/ i" c7 q2 W( s6 ]% F( W
  2. 5 |, z+ h" p1 M  l
  3. namespace animal\dog;
    , U3 D+ E+ d: u( y2 q
  4. 4 S1 R. g+ s% b7 X. Y: m) I& x  {& c
  5. class Life{
    7 S. z* Z  C# \3 b+ d
  6.     function __construct(){
    , [' z% k% T% y) f- O1 }
  7.             echo 'dog life!';
    0 ]9 H0 e; I) @  N
  8.         }! j( j0 r  P& ^
  9. }
    3 F) ~* ]  g; R6 ~0 R$ C% ]
  10. class Dog{2 o+ f4 V( z8 i9 S6 l6 X2 S
  11.     function __construct(){
    ! F* V( j' l% o( _  H  t
  12.             echo 'dog in dog!';
    9 A" {% |( t2 r8 [! R( V9 P# D
  13.         }0 R' X: c4 e! X& K; i2 r
  14. }
    6 g. b4 ~- d+ G

  15. 7 n; x+ u. B% o( M/ T
  16. namespace animal\cat;
    6 Q" k4 L# j7 g) d8 L5 h- p# L/ ?7 f3 B1 X

  17. 1 d  ?# Z$ w, d  S- q2 t$ G
  18. // class Dog{
    $ o# L2 h) V  j
  19. //     function __construct(){
    5 [: _2 P6 p. K" C
  20. //             echo 'dog in cat!';
    4 U7 ~+ Q. j+ Q0 g
  21. //         }( j" R/ k  N' ]# l* G# E
  22. // }
    4 H: P& Z& ~2 c, D
  23. class Life{
    $ v/ @& |3 x; N7 W& y2 m2 ~; i
  24.     function __construct(){- [; @7 W4 ^1 c$ X( t" m1 P7 s; G/ s6 q
  25.             echo 'cat life!';: f. O" I. v( B- e
  26.         }
    % q# E- v  v# X, B" B$ D' N
  27. }* d, a% T4 z/ b
  28. * {6 J4 K) b7 J4 B3 p' J" v# X
  29. use animal\dog;  ; _0 E% X, p- w1 ?+ l3 \! {
  30. new dog\Dog();
复制代码
9 K1 Q9 T3 h# F& `
如上,使用了
  1. use animal\dog;
复制代码

2 n9 |! n: J. G9 l( G
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

3 j7 O- \( j8 ]2 S' Y
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
; j& H" _1 m$ ]* h, P9 d+ `5 v

9 I6 c* R9 b$ k( D/ a
/ B# `3 d0 ]9 i/ O& ]% n. H# A) a4 W8 w1 @- y( M
5 U9 }. C# q7 ?+ x; E

最新评论

GMT+8, 2024-6-23 21:44 , Processed in 0.139725 second(s), 22 queries .

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