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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 9021|回复: 0
打印 上一主题 下一主题

[php学习资料] PHP命令空间namespace及use的用法实践总结

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
1 `# W1 p" v! q, S& g9 S' Y- d
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
4 F2 L' C" k6 ]3 H% B! s

) D' R: z/ x( S2 ^; Y使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
( F9 J$ C# J7 t  C+ `( s4 L/ i8 f! t
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

9 v/ N* F2 v/ T4 d结合使用方法来进一步理解它的使用目的吧。
+ X' Q+ R! @* K/ p+ ~* I0 [
/ W' \& }3 z6 y  o  a# ~& O0 E
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    8 F* N& M' H4 z; M% ^) W9 y
  2. namespace One;
    $ {4 F# z% @5 R$ e, b6 K0 H2 C2 N7 g
  3. namespace ONE;
复制代码

# j1 C3 J) y7 `0 f
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
. \, [6 p) V" I# }, s" z
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php     [9 b1 C% d" }2 w5 J. g$ A
  2. class Person{
    % l1 e  b2 [5 R+ C. h0 S
  3.     function __construct(){
    1 j! C9 K6 N! n, e% u
  4.             echo 'I am one!';
    * G# ~5 h- M% }9 N5 z
  5.         }$ v* K8 l0 W; R& o6 \! c
  6. }
复制代码
  1. //name.php- B4 u1 |6 Y% p# N+ L& ^
  2. require_once './1.php';& [7 V& e8 |+ B" S' B
  3. 4 A% h1 U! j: D+ q' ~* U
  4. new Person();     //输出 I am one!;
    ! l( b, x- x. L, E% a
  5. new \Person(); //输出 I am one!;
复制代码

9 O9 X  f( ~$ C' B1 M3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php* z4 D9 h( l7 e+ K& x
  2. require_once './1.php';
    ' ^# w+ q5 r; [4 s& P4 k
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
- d' W+ G3 ^0 X3 g
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    / b7 {0 x/ Z, L
  2. namespace one;8 f, d. F  N# a7 ^  [$ P& X) h! N
  3. class Person{
    ! Q3 {' D/ w) u& H$ D" \
  4.     function __construct(){3 c6 g/ f& }. z5 {% s+ k! G9 i
  5.             echo 'I am one!';
    9 b7 i, M2 K! }
  6.         }
    ; Z( X$ x, t8 G1 N% l# D
  7. }
复制代码
  1. //name.php
    . c( @+ k% Z1 X$ }* ^' |
  2. require_once './1.php';5 _$ \0 f4 q- v
  3. new \one\Person(); //输出 I am one!;
    # u7 y* l* @3 m, }
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

" c5 m( V( R3 w. m2 e% O
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
9 Z4 }: k% b3 T
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
. K# O2 q; V5 v" O; F9 w  S
  1. //1.php   ) D% {0 ]6 v$ p  I
  2. namespace one;
    " r/ h$ n# i- S( ^( O
  3. class Person{/ }7 A  }3 B/ c% d, _
  4.     function __construct(){4 `) g& r! b% T. a2 _7 d
  5.             echo 'I am one!';
    0 i4 n" [- \! R% a6 l3 \6 ]
  6.         }- _3 R2 e. P8 _1 b" \
  7. }
复制代码
  1. //name.php
    * e1 e" v4 ?7 C1 x7 U& m9 w
  2. namespace test;: }) s  ^+ X5 V7 J3 m: A! W0 n& w
  3. require './1.php';
    + `( i' a$ W/ q
  4. new \one\Person(); //输出 I am one!;
    + U% S$ p2 h  ^- P/ |2 e8 Q% p5 `
  5. new Person();      //这里结果会是什么呢,猜猜看3 ~% E% ~1 _7 g: J% i( g  s: a$ n
  6. 最后一行结果报错:) Q( @! I; u, {0 Q# n7 s" H; T
  7. Fatal error:  Class 'test\Person' not found
复制代码

& K: {; v1 V. b3 u; Q1 t. I

0 M- X5 P6 `( O6 S8 e" x7 L7 }首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
- x$ u3 s& M7 K  [; a& g
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
& b5 ]# Q8 ?: @" y( u' P. N
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php$ U' b7 K0 c8 x+ q. N
  2. namespace test;9 A$ D3 N0 F5 A% W; B* Y+ N
  3. require './1.php'; 0 d& }$ v  Y* \$ M

  4. : E! k$ Z1 [3 A" x2 t
  5. class Person{8 W) ]# B8 h) D1 w; F* q5 @
  6.     function __construct(){3 ^; P; @3 {. L! g% L
  7.             echo 'I am test!';
    / w0 M* G+ Z/ e
  8.         }. }; l3 I* ]# w; d
  9. }
    ' g7 Z/ X% P- G2 c' H
  10. 7 Q8 F) d9 g7 E, R2 O% h
  11. new \one\Person(); //输出 I am one!;6 F  j# t: E4 v, T1 Q/ T
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

0 y4 I+ Q8 Y; Q- F' v* _8 U# f
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php- X) ~" u9 E5 N& M8 E
  2. namespace test;
    / r& u4 v: l4 a, m' h; W
  3. namespace one;
    4 a( n% _4 ^% B5 v
  4. class Person{
    9 ~* K% l! ?; h6 K
  5.     function __construct(){
    * L) ^) ^- T; N# T2 \! e7 }+ [
  6.             echo 'I am one!';8 ^! _) t  t+ O% o. m! V, Y/ \! ^
  7.         }
    * G. f) Q- N  a9 A4 V0 s5 @3 Z3 O8 X
  8. }
    / ]4 x+ V2 ^' y+ X4 _8 B
  9. ! ]' I2 t4 U; c6 A) ^5 j
  10. class Person{, ]( o9 X! @! q. ^/ M: [! t9 V
  11.     function __construct(){
    5 C9 i4 z2 n" Y, N# X: T& o! e
  12.             echo 'I am test!';
    % A5 m6 `9 ?1 w+ [8 }  }/ o
  13.         }) I$ D' k' j* Z
  14. }
复制代码
/ }; v' O% L' j6 k
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
0 N4 g9 _1 {% w  L5 U
看来简单的把require理解为替换,在这里行不通。

& [/ ?8 f* E  v& A. X2 g6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
! `" |) i3 F; Q% ^
  1. //name.php
    , b+ w1 }* u8 A1 D6 A$ F

  2. - G& W" {5 w1 _$ A+ B1 x9 a
  3. namespace test\person;: K; i2 T# F2 T/ F8 O2 _

  4. 4 F7 z4 T1 q; b8 R) [% E2 l
  5. class Person{7 e. }5 ?$ p+ t5 Y/ P( P+ L" F
  6.     function __construct(){0 D% D% Y9 ]+ g: I  q- ^' h: f
  7.             echo 'I am test!';
    % w* n" D& s3 Y+ a+ e9 J2 S
  8.         }8 Y8 y' w; E3 W
  9. }
    $ d% Z( B$ B0 s7 G+ A: s
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

8 [8 z  ]- x; {& t
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

8 m1 p# Y/ O# N2 ]/ ?* N  O7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    . O0 {9 h! y. n1 _+ N

  2. 3 T' e, u; ^$ q2 k
  3. namespace test;# d( h$ j2 O+ b' z1 t
  4. echo 'zhai14';/ @4 G3 Z, L. U7 D9 j3 P
  5. namespace zhai;7 T/ ^: o* o, k3 C9 s
  6. require './1.php';
复制代码
( d* Q2 q$ x) a- n/ z. f  g, d, p  q
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

( L" p4 e7 R' {use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。, g$ Y# t% T6 S4 R& E% A! ]
  1. //name.php4 m3 R7 d  }$ V+ u3 Y

  2. 2 Z3 ~! o( |( j4 l5 X+ h2 R: J2 i
  3. namespace animal\dog;: A1 C! L! C2 ^- D$ J
  4. * ~$ L2 B- R9 ~) S# b
  5. class Life{, o" V+ d! B& D8 w8 {  W3 V. p
  6.     function __construct(){2 u+ r' L" d8 l  N5 E: j0 B6 A
  7.             echo 'dog life!';
    ! k) B' U  l" `0 Z. r% i
  8.         }
      T/ P) b' I5 n7 n
  9. }+ K* X) N# {$ J8 z
  10. 6 b2 _5 F* e4 ~: m" H  g  f6 G
  11. namespace animal\cat;' T8 o- m6 O. `

  12. + `) o' s9 W) P' d5 D! ?
  13. class Life{
    # R% e& ]( l" h! p1 e; |, o
  14.     function __construct(){- w  d' h4 F5 G; Y# K
  15.             echo 'cat life!';
    / q3 ^0 r0 B6 i8 X2 ^; y( Y
  16.         }5 r- G2 _& S9 J6 \
  17. }
    ; U, F1 U8 P/ k1 c9 {' J, K$ _/ J

  18. 8 x1 [7 x* M: I+ L- o
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间; l3 Z6 h# S4 r  `' E8 Q' h' z
  20. new \animal\dog\Life();  //A
    2 x7 w2 G( B# O# R2 |6 y( V8 ^+ ~

  21. & E" f8 Z( d; x
  22. use animal\dog;  //a" Z& e) e* T- s
  23. new dog\Life();  //B. o9 W3 k8 {$ G' k' V
  24. 0 C3 X/ I$ ]) Z, L/ k
  25. use animal\dog as d;  //b
    3 ?9 i5 G( j; k# G4 D' o
  26. new d\Life();
复制代码

8 ]- X4 Y" H5 u1 y" T: M& ?. B% u
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
$ `+ G3 u) A; x+ P$ ]
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

' L, s" p* @2 q* I
相当于
  1. use animal\dog as dog;
复制代码

7 A1 [- J8 I: e0 r% V! h' c- J1 h2.namespace后面不建议加类名,但use后可以。
) N. r9 v3 y6 Q3 A' ?
  1. //name.php+ B* K/ \* S1 d

  2. , f* B& b$ {# p  N0 H4 e
  3. namespace animal\dog;
    3 L: Y. x* G( Q

  4. ) A- f* Z+ e  y# b
  5. class Life{
    * r2 Z( S4 L) b4 g+ \7 r
  6.     function __construct(){
    " B1 Z; t6 U) N; B/ t$ y! u
  7.             echo 'dog life!';0 e: M+ ?6 G( \1 F- j1 E( v
  8.         }
    9 Q1 S5 i/ @, s% `
  9. }
    " t( [: [4 G- ?  h4 Y2 |6 N

  10. + |! {, a( x" i+ Z4 G& \
  11. namespace animal\cat;. S0 F6 w) F( S' \
  12. # H2 j: F1 l  u& l! v3 n
  13. class Life{. j# B3 V7 H/ b1 d% ^7 B* V' `" r/ U0 h& P
  14.     function __construct(){
    * {. P, V+ |' r# t4 M
  15.             echo 'cat life!';
    " h$ ]/ K9 |6 \* H5 U9 D" J
  16.         }) _7 E8 B( `4 v9 l5 u/ W
  17. }0 ?! T7 U! F8 c/ i. r# K6 J1 a
  18. ' P: |0 X* j. a4 y, D; h
  19. use animal\dog\Life as dog;  0 h+ @+ B2 ^4 s0 T+ [, k1 ?
  20. new dog();
复制代码

8 J6 o6 {" X4 u
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

  P- @7 T( l; L( P$ F6 J: h9 Z
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php/ p6 P3 R: j: K/ s% q4 l8 c
  2. : E8 M& L  U* f) Z2 B+ r
  3. namespace animal\dog;& e" Y/ D+ D  {+ m8 N

  4. " u7 e3 c1 w' f" n5 m; ?
  5. class Life{6 U3 K$ v, N4 h" p- r5 B. z
  6.     function __construct(){
    6 L7 @9 T0 d: e) B9 b
  7.             echo 'dog life!';! j# ^% J6 q$ x% K
  8.         }
    ( U: z6 j* A3 R5 \, J  C. Z
  9. }$ o. Y* g8 ~6 t/ A2 A) A
  10. class Dog{+ M4 \' L% v. D0 H* ^6 s
  11.     function __construct(){
    & m* `4 d/ H- |
  12.             echo 'dog in dog!';
    ; l% W( [0 Z% h5 f6 Q1 X( X; _
  13.         }
    3 T' Y. B2 C: H
  14. }
    ; {8 O" G' P& ]3 p: z# W
  15. 0 m2 L. k; J8 x+ q8 K
  16. namespace animal\cat;
    5 \5 ]. _5 W( T; V" n
  17. 4 `2 i: \+ ~: l. g( ]
  18. // class Dog{% U& d3 S/ m: Z( ?4 W: L9 r
  19. //     function __construct(){6 c$ Z2 i) V& I
  20. //             echo 'dog in cat!';! I. B, t! u% Q% n; @1 d
  21. //         }- m' _! h% Q5 B+ _
  22. // }
    # Z- I/ z6 S4 l# O
  23. class Life{
    , \0 H% N" t& I6 j/ N( f. _
  24.     function __construct(){
    : R; u0 z  s; e7 C" m: K# ~% s
  25.             echo 'cat life!';
    ) |8 w- N9 x% U9 G! s
  26.         }
    + k0 d, Q1 q8 D* t) j* t" o: j
  27. }
    ' i8 _1 t# [5 e5 d* `+ z; I; r

  28. ' \3 Y$ G% p7 _9 U
  29. use animal\dog;  
    " ?& L" J% [  C& x. B3 w8 L, i
  30. new dog\Dog();
复制代码
  O& k6 p. b5 O# t4 J
如上,使用了
  1. use animal\dog;
复制代码

, n! o% p2 z6 O8 \) y. b$ u
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
7 k  M  ]' t! }
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
! |) P6 Q1 g2 ^6 _& Z
8 D0 V9 J* J) u

8 h% \. b  M. j2 j2 L! R0 @4 ]. R8 F% f
- B( w" X2 b, d0 h, k0 D3 Z
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-9 06:46 , Processed in 0.118742 second(s), 21 queries .

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