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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 11183|回复: 0

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

[复制链接]
发表于 2020-7-1 23:37:46 | 显示全部楼层 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
# g. T: a# C8 n% ]
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
# x! e4 V* a* i- n1 V) u7 m
% g, k3 t- y% t  R4 Y
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
+ g$ Y! v+ y8 J  |, N. m
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
6 m) s0 F" N6 M9 r5 e, m
结合使用方法来进一步理解它的使用目的吧。

0 F1 t7 o# ?" N  n7 f: J  E# q5 a9 z9 R
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    % O1 B8 W& F4 |+ S! c/ r
  2. namespace One;
    ; O3 {( q4 z" u! N1 n1 Z  Q! Z
  3. namespace ONE;
复制代码

/ y, r5 \5 Z# G$ U
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
% p+ ^; _$ y: J
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    * A1 g. `8 a: r0 T  `
  2. class Person{
    * U. q+ F) l* \& S
  3.     function __construct(){
    6 p6 n5 \2 G: R7 ]1 t4 K1 T
  4.             echo 'I am one!';' G5 O# a+ [0 e9 T+ g
  5.         }
    : S( B3 r- E8 ^$ W! s
  6. }
复制代码
  1. //name.php; ^1 l' H. N4 }( z. `  m( u
  2. require_once './1.php';2 h! D2 _) w( o7 S) H- T% L& Z
  3. 4 r$ N: X! ?. b- N4 \1 ^1 V1 `1 \' Z
  4. new Person();     //输出 I am one!;
    , ?4 ^6 H  ?3 F9 p+ K
  5. new \Person(); //输出 I am one!;
复制代码

& q* X. l' d& Q. k3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php; h4 e* c5 W6 T! h, v2 z! g; k: F' P
  2. require_once './1.php';9 B' F2 U. r2 F0 `; _3 @
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

5 ?) @2 ?4 A, \6 l* E; ]( N& N4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    & r6 M: H' M( Y% Q# d$ S
  2. namespace one;! A+ H: p6 M4 L) b2 Y
  3. class Person{
    8 e# ?( J* {3 F' m+ A2 u& i
  4.     function __construct(){  i! O5 G6 }( r" @# G7 F
  5.             echo 'I am one!';& i# N# s  t/ g* ^- t
  6.         }
    $ u$ O" ?& U( |9 I) X8 [, d" n
  7. }
复制代码
  1. //name.php
    : l, w4 b. R  T1 G
  2. require_once './1.php';+ c  I8 }  J4 O9 ^9 L: `2 u' k* ^
  3. new \one\Person(); //输出 I am one!;$ n  o0 @* `) U
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
6 A# U" D. u7 q* O# `3 s4 O8 t! ^9 Z
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

( c1 T# z, `8 b# D3 x5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。$ _! W* ~4 [( v# m2 B
  1. //1.php   
    4 K2 z; h% u" N; @4 }( O# c
  2. namespace one;8 g" M2 y& K' F/ s$ r  s3 f6 p0 [
  3. class Person{
    5 W8 A5 Q+ D- o
  4.     function __construct(){7 ~0 n) T3 u0 b* p, y( r
  5.             echo 'I am one!';
      S5 y, m0 m3 B( g0 y0 Q7 B6 S/ V- F
  6.         }
    ; I# K! E* y* g. a; h/ ~3 B. p4 t
  7. }
复制代码
  1. //name.php
    4 K, Q. H( {% q/ j, U
  2. namespace test;
    8 E, l0 F4 T; h. Y, {1 |5 w5 G2 q
  3. require './1.php';
    9 m* d# L5 ~; e
  4. new \one\Person(); //输出 I am one!;
    9 U3 N9 X9 p5 n& {& ?2 q$ n, |
  5. new Person();      //这里结果会是什么呢,猜猜看
    % ?) w( J2 w4 O& x: J, R+ x
  6. 最后一行结果报错:
    9 c  `2 S5 @! O$ ^1 N# o
  7. Fatal error:  Class 'test\Person' not found
复制代码

8 k& \- w, V8 T6 ~$ o7 I

8 Y# j' R- D1 }; @首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

  _2 z# Z; d$ {8 j% |2 T
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

, X4 \, a# D* _! M5 ?- }
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php( W+ G4 ?0 x+ a1 B8 G% d
  2. namespace test;
      b) ~7 R) s6 \
  3. require './1.php';
    & `+ @: Z! a8 u4 q7 [( t  S/ q
  4. / y/ c+ N# {0 Q6 b+ T
  5. class Person{, P6 O4 r5 A0 v, o+ H, v9 [
  6.     function __construct(){
    . V, u1 s" \. \
  7.             echo 'I am test!';1 w" O, f7 N9 L0 z  ]
  8.         }* g7 i4 k" T1 V- [. @
  9. }
    * E, [  }$ q5 s! _0 M+ d6 j
  10. / z$ C/ f& L( ]4 J0 a  {
  11. new \one\Person(); //输出 I am one!;
    7 T9 m/ c( ^1 W4 ]; D! |" u( {
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

  K+ Q5 \9 j2 A  B" b
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    4 p4 X/ e& R, l6 f
  2. namespace test;/ M: O7 ~  N" D; b
  3. namespace one;7 f' X& g: h+ H/ {4 \8 T) f
  4. class Person{: C. `. k/ V. b" }4 T" x" e, i
  5.     function __construct(){% b9 B6 P: n$ X4 j2 _9 q, O
  6.             echo 'I am one!';
    4 r; I/ v* i' D. V7 Q) U
  7.         }3 Q9 V7 V3 [1 {% H, l
  8. }
      B6 @5 Y5 O/ G% i5 ^

  9. * |" q0 I8 g% t; [2 i$ J
  10. class Person{% w0 v; y6 U' C6 N3 t( D0 J! P9 n
  11.     function __construct(){& a4 d: u% e, U
  12.             echo 'I am test!';& P8 y4 O1 R2 R( J
  13.         }: u% ?/ K. F  ~
  14. }
复制代码

/ h  {! e: L3 r" Z: _0 \
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

1 J9 ?3 J- ~+ E
看来简单的把require理解为替换,在这里行不通。
0 p! w" r) a7 h! P9 H& H
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
( @* R/ d- q' h2 w3 |) V
  1. //name.php
    1 n% L. W( }. J  k, X, Q

  2. * F' t1 E' e7 }# U8 K
  3. namespace test\person;
    . Q: |% N+ U# m1 a. x

  4. * `6 v5 k6 k9 t4 w
  5. class Person{
    9 m; D6 R7 q* `* S( [- H
  6.     function __construct(){5 B: [1 G1 W* p1 X$ D/ \$ Q; P
  7.             echo 'I am test!';
    4 n5 J, O) ~( G# |* Z( ^* d
  8.         }
    & H/ ?+ Y. C0 E3 |& h( ~! R
  9. }
    , Y7 Z% ^5 s1 s# _' h
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

: r8 `% s4 ]" Z5 K$ z( Y
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

. R9 R5 G; }+ `8 }! t7 d7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php* K9 R; ^5 N) d# u. Q' A

  2. 0 C; L+ {$ _9 `
  3. namespace test;
    + I& C& G5 Q! h$ R& C
  4. echo 'zhai14';' Q& C/ f) V- O" j- T4 X/ E% D! m
  5. namespace zhai;7 L2 v. Z' I: r  e/ ~
  6. require './1.php';
复制代码
( p% \" E' d5 y% C7 @
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
1 t4 O. j/ c& e& z( b( F+ n
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。0 q3 k8 W. t" U! y
  1. //name.php
    0 v* ~& t' C3 L/ T, r$ Y* \
  2. 1 a  ?0 U/ d2 Q* S. z4 M9 k" d& O
  3. namespace animal\dog;$ `4 L# K' u3 k# F  ]0 M& F

  4. 6 e+ i6 K9 J+ n& _# s
  5. class Life{
    2 g1 U5 ]. _% L6 [- Q
  6.     function __construct(){: S' M' p; A6 y8 e
  7.             echo 'dog life!';7 t! B  j! o" p2 ^" C) [- u* @  B
  8.         }
    ! h- U4 Q; T- ^) l# O, v" J
  9. }* u6 v+ Y% r4 l$ T) f. J
  10. $ v: N9 V9 a5 t
  11. namespace animal\cat;
    ! z4 H* y7 e4 F  H) g
  12. : F. T+ H( E- x" f2 f) G
  13. class Life{
    . l% D, B4 l+ V# G- ^) C
  14.     function __construct(){. G* c5 u/ Z: d2 w# ], ]3 N
  15.             echo 'cat life!';. F$ B9 I, T; L. v% }1 R
  16.         }2 W1 |0 h( F; L# `: Z" B# h
  17. }
    0 u. b: G7 D4 d2 s" A, m& n+ Z

  18. . D( T' z" u* }  d
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间3 ]5 l& q& \' p  X: u( ~# N: D
  20. new \animal\dog\Life();  //A
    . h* E! r) D$ k6 M% E3 L, O

  21. / k5 D, w- R! z1 Z' S# c
  22. use animal\dog;  //a( U+ q( ]0 \" v& O% B) y7 N
  23. new dog\Life();  //B7 B; q7 V+ ~5 `: G+ U, y' q

  24.   v6 C( O1 a1 X! H
  25. use animal\dog as d;  //b
    ( g1 f9 `9 w, O+ [
  26. new d\Life();
复制代码

5 ?2 R$ ]4 ^' M* d3 g5 j/ [& ?
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
# o9 `3 \! P7 h% P
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
) J, V7 g8 \" @9 \$ c% y; V
相当于
  1. use animal\dog as dog;
复制代码
+ P7 E( G' w0 q& i; F7 J* u  i( _  ?
2.namespace后面不建议加类名,但use后可以。
6 P0 O, X, P# \5 X1 J
  1. //name.php
    , s2 c3 t2 l  y
  2. $ B9 F; L' K# `  S- [4 D, g2 c
  3. namespace animal\dog;
    9 o2 C+ k& L! j4 D0 A; G
  4. : z6 V5 o" L4 \5 K: F4 q. i
  5. class Life{
    ( D: ~/ n) @  {$ _' c, |: t
  6.     function __construct(){
    . c+ i4 {6 D" V+ x
  7.             echo 'dog life!';
    . w2 \5 t2 Y  s9 }6 q# ]7 V; W5 q
  8.         }
    2 i3 Q+ L! i+ C# b
  9. }
    : k+ |8 }4 p% G' P- y/ G4 r/ u; r

  10. 5 |7 l, V; n# G# z! Y
  11. namespace animal\cat;2 R* i5 B( d/ V3 l( y" [3 n
  12.   j1 D0 f6 n+ i% v
  13. class Life{
    % J+ L+ |( W1 j( {0 M; A) }
  14.     function __construct(){  Z' M. M! Z' I2 W8 W+ R9 c+ K
  15.             echo 'cat life!';6 A7 w5 c3 l$ i( X4 `9 A
  16.         }
    ( a) \3 a2 ^% R. T3 H; R
  17. }) Z% N8 z4 M& A" {' \6 }/ y

  18.   z! m8 i, b' Z3 J* f+ I; ~
  19. use animal\dog\Life as dog;  
    7 l1 p, X/ `, O" w( Y0 j2 i
  20. new dog();
复制代码
$ I. ~- s6 B5 E6 x" A0 J
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
5 Q& G- z; S0 ~" j; \. E
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php; K9 }4 Q8 B: T/ O/ G
  2. : E. t0 M3 K3 K1 W( D
  3. namespace animal\dog;
    ( b. |" V6 G9 D

  4. 9 z/ ^% `5 {7 [3 e6 t/ E* R
  5. class Life{/ g4 {5 M& i" V- R' a
  6.     function __construct(){6 \0 V% F# n3 L
  7.             echo 'dog life!';5 I8 Y$ A  O, a7 p$ @+ e2 ~# O9 F. {
  8.         }$ j" `6 |, X4 Y5 w) Y$ B+ O
  9. }
      c: e( Z% c/ y8 m) G% k7 m* F2 W- s
  10. class Dog{
    " K3 j+ v6 M4 a0 \. H& Y
  11.     function __construct(){* y. N' `9 d2 p: q8 l1 K3 ~
  12.             echo 'dog in dog!';) Q3 I( @! U; ~& c. D: {6 \- g9 G
  13.         }* B) E( \* `( S6 ^; }( a3 l
  14. }
    6 j2 H& K! F: t/ W& c

  15. 6 E& e5 f) \  f! e& s' a
  16. namespace animal\cat;
    ( J0 n1 w0 [7 B! C1 m4 x

  17. 0 d% p4 {4 p9 |; F
  18. // class Dog{
    1 n. a1 @/ V1 j/ ]5 }  I, |( c
  19. //     function __construct(){$ @0 @- q" H: b
  20. //             echo 'dog in cat!';8 C8 z5 y9 I% }( e+ q& ]$ ?
  21. //         }
    . o4 J3 o. `' O
  22. // }
    " Z6 k( V" M% {4 [! |( a
  23. class Life{
    3 `0 {3 U* D, Y1 d$ e
  24.     function __construct(){
    ! Q  O( |* q# G4 P# K& C5 U( a
  25.             echo 'cat life!';
    $ F# J/ ]  T# u# f! P
  26.         }
    6 u, `  X2 z7 D/ ^9 ]
  27. }
    3 m  N6 S! P5 j' Y5 P' \" [. X  g
  28. ; m: @; |2 W8 Y; M1 ]2 {" q
  29. use animal\dog;  
    " a, V; O0 {, @- J
  30. new dog\Dog();
复制代码

' k+ r8 x& w# }* p* o
如上,使用了
  1. use animal\dog;
复制代码

. x* O  E# M" o* G2 ]
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
$ O/ R2 j- j8 m5 n4 x
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
, N# o" E+ U- V4 u  ~
- Z; H8 u. w+ d

% D3 o3 q. _' t8 Z3 [: Q. K9 M/ Q6 C+ ^9 S$ K6 y

, ~& ?8 ?2 O8 j% I7 g' T: M
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-11 07:34 , Processed in 0.115157 second(s), 20 queries .

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