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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 8209|回复: 0

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

[复制链接]
发表于 2020-7-1 23:37:46 | 显示全部楼层 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
5 P7 r! Y; \1 A" q+ Q6 Q
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

( ~2 w# N" Q6 a: y0 ?+ D/ x0 k; t* D; U2 f! {, X8 x: v' B
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

7 K/ F# V+ g* `/ t% T
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
# Z  D! j. T$ l2 r& [# j7 E$ t
结合使用方法来进一步理解它的使用目的吧。
% c: Y6 J8 F7 w* m; @2 g3 V+ O
( v1 N3 Y0 z: E5 P1 n
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;" T7 Z0 C& K7 j: ^% a' o; D5 M
  2. namespace One;# O+ J- r/ B* H# R* B! \; U
  3. namespace ONE;
复制代码

) W0 o4 B: O0 f& `9 o$ R$ T
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
1 }8 @0 N" ~1 ?' ~8 z
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   # P; i, A3 f, N( x5 T! e) t! P
  2. class Person{
    ; w* m6 V3 R# \
  3.     function __construct(){4 k; z5 r. g0 \8 I6 T/ F
  4.             echo 'I am one!';8 Y+ I2 c4 T2 O
  5.         }
    / k0 e, u  R$ H' ]( p: m3 X+ `
  6. }
复制代码
  1. //name.php
    ' n( d8 N* O, P9 K) N
  2. require_once './1.php';  V0 i3 D/ D7 N" n  A
  3. , [1 m* s8 _/ G/ x
  4. new Person();     //输出 I am one!;/ r& `9 G7 w; `8 x3 }3 u& o
  5. new \Person(); //输出 I am one!;
复制代码

& o: H# g2 v5 ~3 y2 f* J3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php+ _+ s5 v+ Z* C; O/ @
  2. require_once './1.php';# T4 s* u) s; D- L
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
) w. ^: q7 G' T. n8 v
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   4 h3 D* f- {) S( G# M$ h. g3 b
  2. namespace one;- ^0 l. w* o  x2 q
  3. class Person{
    0 {) Q) E9 j4 C
  4.     function __construct(){
    3 D0 M6 z- K2 p# _2 q3 t
  5.             echo 'I am one!';$ g6 v* i! B+ p' \9 b, e% A8 K9 {2 d
  6.         }9 n" O* R2 V$ u# Z. X' g
  7. }
复制代码
  1. //name.php# l) v7 T" R- M2 J. m% W( r& ?
  2. require_once './1.php';  `; T7 P- n7 c& L4 O! l$ |& g
  3. new \one\Person(); //输出 I am one!;# @5 a8 l$ ?( t
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

2 T+ k) p% ^, _, k6 `1 u
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
( B1 L& R7 i' p9 I0 o" k3 x
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。9 i6 S. G/ O  X  ~
  1. //1.php   
    5 n- M. E; q; ?+ M& b2 V
  2. namespace one;6 |, U" W2 t) V' V8 a& z5 g
  3. class Person{
    ; c: L! l3 t. ~6 p8 E/ v
  4.     function __construct(){
    1 i# q4 U- w+ l# a
  5.             echo 'I am one!';
    1 O# s) @$ w5 c' u' K2 c) K
  6.         }
    + {/ K2 B, b- o; s' W$ h
  7. }
复制代码
  1. //name.php+ h7 u: T2 D2 B( k8 o$ d8 i
  2. namespace test;8 a# K. T1 d/ x1 ~7 H# B, \. S
  3. require './1.php'; ) v; _" t& g; }, R- k2 Z7 N( h
  4. new \one\Person(); //输出 I am one!;+ r0 @% n* G2 z9 U3 f; f
  5. new Person();      //这里结果会是什么呢,猜猜看+ q. Q6 k& }, R
  6. 最后一行结果报错:
    ! r0 {% C& e$ W+ ]+ S' L( W
  7. Fatal error:  Class 'test\Person' not found
复制代码

* v9 S$ k. c% l' n  D$ |: C! S  k& F

% D) I% q0 F8 C, E首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

# a" |: E7 S+ U9 w- G
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
; H- R0 g' g  a) M2 U
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php  }9 K/ g- b+ l+ z, y3 Y% T
  2. namespace test;
    ( r4 e. K* J. N& j( i
  3. require './1.php'; - U0 O1 `7 f; R" E; l) o6 I( v

  4. 2 w, |$ J; h' O
  5. class Person{
    % K. w( a  s9 u  p( T: L
  6.     function __construct(){. c+ z6 A, x. v# j" D; E0 Q; w& P
  7.             echo 'I am test!';
    . \1 o0 Y, X2 W% I) e
  8.         }& y% {3 i+ l/ |! Y
  9. }
    6 w# F+ K) h1 R" @
  10. 4 N# Z. D% Q' j
  11. new \one\Person(); //输出 I am one!;
    9 f' V" @- A+ W+ N
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
6 @9 N6 _% Y+ Y) ?: |4 t+ ^
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php# F( K  T7 K. X, E2 E
  2. namespace test;
    ( G$ Z; R' N0 Y/ z0 X* N
  3. namespace one;+ p+ m! |7 c8 e) S' c8 Q
  4. class Person{
    + I$ W" {' S4 }9 v6 M
  5.     function __construct(){
    6 N+ b5 u' I# z3 A; X" B' \
  6.             echo 'I am one!';7 P' a2 }% O0 ~6 W; F, s3 |/ R
  7.         }
    5 U' W1 ^/ d0 }" \
  8. }
    8 i' L1 \5 d! X9 W/ p
  9. 4 d3 j: h5 J+ g/ c
  10. class Person{
    - D$ n; O  }, }; {  ~$ F& J; K# v
  11.     function __construct(){7 ~7 @! S2 I3 s/ `
  12.             echo 'I am test!';
    ( m8 X' S( ^  e! T4 U2 z& F' _
  13.         }
    * l* t7 M. R9 W" R. c5 D2 v9 h, s
  14. }
复制代码

7 M& j- h4 h) ]: y; Z& D0 z5 Y7 U
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
- t! Q+ c0 G7 D2 F+ I1 i
看来简单的把require理解为替换,在这里行不通。
/ e5 b2 Z. @7 T2 x0 u
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
. _5 Q7 @+ O- Y
  1. //name.php, \$ u6 ]% H0 W/ D5 X) w
  2. . ?5 @# R. U* P. I
  3. namespace test\person;# }0 E2 r+ y$ O# m/ p  H$ ^

  4. 5 ~& f+ [2 y! W& W6 S
  5. class Person{
    5 X$ ^1 U# \: d( W7 ]
  6.     function __construct(){
    8 X5 M6 _; m# W# X0 e  b$ K7 {
  7.             echo 'I am test!';5 `! ]! C0 U; m$ m9 |2 L7 B
  8.         }. v0 E' }' ?% @- N6 h7 u
  9. }# r6 E+ f. S$ |. N
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
5 @- z  {/ B; P  k5 k2 v  w# ~+ |2 Q5 G
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

& |; _; H7 _4 Z7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php/ C' ]  O9 l* Y- D5 X# m

  2. $ @" r/ c7 ]8 {) ?
  3. namespace test;( H, I! S; J2 }& [
  4. echo 'zhai14';
      F" R& k/ O& _# b5 U2 B  m8 W+ L4 Q+ ?
  5. namespace zhai;" r0 K" v. k+ @2 W5 `. F6 K
  6. require './1.php';
复制代码

  R! [6 S) P) k' j, j! I2 w
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
' ~' N7 `! G" Y! q
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
$ o2 f$ p; {6 y3 O, t7 o
  1. //name.php' F4 e" n* n  ], \7 C, B
  2. 4 m/ C3 b( ~6 }4 u& H
  3. namespace animal\dog;
    7 W6 T; p! H9 w9 k' \: {

  4. 8 d  O3 H4 {, L$ \: ]  _% W
  5. class Life{0 [, m1 e/ g! ?* V+ f/ C. z7 Y+ @
  6.     function __construct(){8 }2 r0 Z4 C, m+ e  c3 w* ^2 ?  C/ N
  7.             echo 'dog life!';) ?$ @0 C/ U2 o- ]
  8.         }$ ~5 f  X& I4 G( |% s. B6 @
  9. }
    ; b& \$ I& f  {6 y0 l' e& {
  10. ) T% a6 O5 B9 B# z; S) w' [
  11. namespace animal\cat;
    5 |2 E& p: b1 C3 l
  12. , d; _* a8 F/ c% I
  13. class Life{
    , [$ _% V4 J, g( K( o  b
  14.     function __construct(){
    4 a, C+ K" W# A- I
  15.             echo 'cat life!';
    7 I7 R1 c0 |4 r" M$ i
  16.         }: o0 J& k) Q9 O. P4 w% S
  17. }
    ! j: ^, D9 a& N* I7 M' [" o

  18. ( }5 I% J) t* r* U5 X. X6 M
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间; l! p* A1 H8 A8 ~$ W- u
  20. new \animal\dog\Life();  //A
    * e3 _0 N& N% Z7 n$ `
  21. ( W* z  c, A9 T; Y6 D- ?) s
  22. use animal\dog;  //a
    # h# q/ D5 \! \- r& \# c! B
  23. new dog\Life();  //B$ G/ H( Q4 c* P* k9 i0 E4 m* H
  24. . ~, D6 f1 G: B4 \
  25. use animal\dog as d;  //b6 x* l9 ^( Z- ]! W
  26. new d\Life();
复制代码
( H" r( F6 Z2 ?- u3 t
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
* ~( a# N& C& }( f) u" F! \
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

5 o! M% x) y' w  ]# F
相当于
  1. use animal\dog as dog;
复制代码
4 E; C( L$ c) u
2.namespace后面不建议加类名,但use后可以。
; |/ Y' v$ r# Y: {( I8 s
  1. //name.php, p0 b1 }( {' V& }' J1 i! l9 y
  2. + r: b+ J7 G, C1 I  A7 ]
  3. namespace animal\dog;
    3 {1 M; h5 }$ C: B

  4. % S6 i5 q8 g2 _' E, w* V
  5. class Life{
    3 X1 Z3 y; g1 s  R- L% A
  6.     function __construct(){. D/ b' V5 j# Y! C; {3 o
  7.             echo 'dog life!';
    & I6 P3 S+ ^. i2 B
  8.         }
    ( B# @8 V0 ~4 X8 K+ Q4 X. f
  9. }5 Q; y: V# T( g; }  {+ I
  10. ! j1 N5 \8 s9 M1 K
  11. namespace animal\cat;; ?$ ^" Q' U0 f3 N

  12. & W* v2 ~& ~, l) l9 h$ j
  13. class Life{
    5 ]1 p& v: L# I2 B. P$ l* u
  14.     function __construct(){' Y& v3 s' V7 z) M7 @# T
  15.             echo 'cat life!';
      U2 D5 P+ T7 I0 N" k: X
  16.         }
    . A9 }/ R8 T( S( E
  17. }) a+ ]9 {9 U; w- w
  18. $ x4 j: T3 r6 N, o1 c
  19. use animal\dog\Life as dog;  
    ( H- t& A6 l" _0 m0 Z7 R
  20. new dog();
复制代码

5 }3 V4 {7 c" h  r5 }0 b
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
$ D3 D7 h9 u9 U% a
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php  b% K! h; b7 r% K* t; T

  2. , J7 f' E! Q6 W& w# `
  3. namespace animal\dog;
    . G2 y( {# t6 X9 L
  4. * I3 K; D/ e3 A* b
  5. class Life{* o* p& k) @4 ^
  6.     function __construct(){
    - j' I8 x1 D0 I& ]- ~# j) L
  7.             echo 'dog life!';
    8 O6 ?/ _5 e: Y1 `( h
  8.         }
    % g. b" O1 D+ V9 A
  9. }' N/ @5 @: b! T( @( P8 U  [* Z
  10. class Dog{, S4 Y- A& z; [: a
  11.     function __construct(){, p% ?- W* o5 O! o. V2 l( E
  12.             echo 'dog in dog!';
    2 X% g0 I& ]2 M( B9 \# w/ u2 z" O5 @
  13.         }. p$ J$ p% m  Q9 A$ q3 o; ]
  14. }
    " g: V% S: J/ m. H6 o& O2 J9 \
  15. : b8 I: n/ f8 E4 s
  16. namespace animal\cat;7 O$ Q2 N7 r4 ~7 O

  17. ' W+ o$ A0 n! b
  18. // class Dog{" T: H0 N" i& A& I, Y
  19. //     function __construct(){
    . u! }2 q  c! j8 U6 _* i
  20. //             echo 'dog in cat!';
    - t$ J, R/ |: l& I, x& ^
  21. //         }
    7 M+ a5 d% l; q$ L  ]  T
  22. // }+ _' U6 p  [0 m  M
  23. class Life{
    ! J$ F7 r, ~7 Z2 T$ k& w: h. n
  24.     function __construct(){
    % |6 W2 e6 i2 a) M  W
  25.             echo 'cat life!';" {. \5 ], s* |. i
  26.         }5 O; r4 `1 Y/ ]& s, r  d# T1 m1 K
  27. }
    3 I: A. b  c# l8 [4 F% ~% H
  28. % e, }+ T& k; h1 b! m, W+ @4 W
  29. use animal\dog;  7 E  s! r& n/ h- i1 y
  30. new dog\Dog();
复制代码
8 V- W5 h+ A' s) H% m- n& ?
如上,使用了
  1. use animal\dog;
复制代码

! \6 R( X8 i( @  Z2 s5 H
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
( h" K+ I, S9 a0 s# B. T, K  `
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

2 L) ]; U" \  f1 \* q6 _3 O1 r" \4 h0 ~+ X9 z0 }

; D2 M/ N% i+ w+ I! R+ [
* o" g4 L* P8 N# }6 J4 V$ h& ?5 N. e" `" ~! q/ p" J
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-3-4 05:54 , Processed in 0.140041 second(s), 22 queries .

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