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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
! M5 M) j' Y. V& s
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
+ O4 Y, W) R1 z  |# Q
. ~1 x/ w! j' L) H% A
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

; r$ r+ s+ X4 k4 y0 _- Y
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
# @  S! o- z9 M# }5 r; v: F* U
结合使用方法来进一步理解它的使用目的吧。

, j# W& X: a0 r' m+ o9 C6 O  Q& v
- G! p; D" x- D4 lnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    - I1 w3 A( F7 o5 h" d
  2. namespace One;
    . X: v- f2 J1 B7 O* J9 Z
  3. namespace ONE;
复制代码
" g, k) e0 a' E: H1 c
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

7 |3 `+ g- f7 J- x3 s/ ~2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    . E: {9 p) [7 h2 g, @- K
  2. class Person{
    " z, F/ i; f% e& o0 c7 x  r$ r, r
  3.     function __construct(){+ U# u8 O9 w' }! E5 ~( z
  4.             echo 'I am one!';  u1 M/ A. S8 m+ _8 n
  5.         }
    , J( u- N% G4 [4 t1 {
  6. }
复制代码
  1. //name.php
    , q7 z9 b& |8 ]1 P: W% T# P
  2. require_once './1.php';8 u/ y5 R$ n/ R+ N( Z

  3. * I6 q5 A7 m0 ?
  4. new Person();     //输出 I am one!;
    ) Z' H9 H; u3 }
  5. new \Person(); //输出 I am one!;
复制代码

. \/ x3 l1 _. l3 t3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php" N& E- O9 U4 l3 n4 J: z
  2. require_once './1.php';+ Q" l( N8 q/ L0 T& O; w
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
  M: x% k  m* G/ B% n
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   ; c) p8 d" K: e
  2. namespace one;
    8 [& w5 Z9 N  _+ r. ]8 s! e  c* k
  3. class Person{
    ) [1 |+ R/ Z8 \3 ]
  4.     function __construct(){
    ) w; W( W' z0 x) u, _7 ^
  5.             echo 'I am one!';; `( c8 h- p' T$ p- z* O' D
  6.         }
    + d, C( k$ K3 v1 t
  7. }
复制代码
  1. //name.php
    2 @" ]  @* h( k  J; x
  2. require_once './1.php';
    6 n1 p4 P. {% e1 d( X  r/ J" t& g
  3. new \one\Person(); //输出 I am one!;
    $ y- l% P  X- f; }
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
6 P" O  r. Q# d* l" i
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

& ?+ ?8 K& X1 |2 ^) p5 D( ~5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。+ H& ^1 {3 _9 @1 o' u- G
  1. //1.php   
    1 k$ W& _0 c) m; g: L# W
  2. namespace one;" s, z( S7 v; Q/ D' a( d
  3. class Person{
    5 h9 l5 Z" ]  K/ }4 Z: |
  4.     function __construct(){
    , Q; h' p! B2 ]( W% h5 K" S
  5.             echo 'I am one!';
    " T' n" x* O0 ^" m
  6.         }# m  L5 O' O- e0 C
  7. }
复制代码
  1. //name.php) i5 m: ^1 B; Y, Z3 U; s! ^
  2. namespace test;
      _4 z# O/ W# y8 e
  3. require './1.php'; & f) Y; @6 E) f$ U
  4. new \one\Person(); //输出 I am one!;) q& ^8 ^; |8 J& S; [
  5. new Person();      //这里结果会是什么呢,猜猜看
    % o8 g% t! _. L
  6. 最后一行结果报错:2 r6 w" N5 k; J
  7. Fatal error:  Class 'test\Person' not found
复制代码

! c  ~7 C  ?$ x" `. z5 V/ W

' M0 |% L/ T2 s! Y首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
! O, k) w. n  F
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

, r; i# c" F' Y0 V: s: J/ z
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    9 v' }' P! \9 N3 o0 c
  2. namespace test;
    ( e* \8 n0 ~$ z8 ?- \  D
  3. require './1.php'; , @! @) f" z6 u$ L( m* f, D
  4.   m6 R( n2 x  z; G, V) H
  5. class Person{
    9 a6 P) ]% O2 E$ `
  6.     function __construct(){3 Y- W$ {, j  C% _% w0 t1 z3 [
  7.             echo 'I am test!';
    2 V) d. y9 J, o/ }
  8.         }
    6 s5 _) p" J' w# f; L4 D. j6 m
  9. }
    - t: Q# F. q9 z/ C& R( R  l

  10. , x* o2 o/ m7 ^# m5 H% }- C, Y
  11. new \one\Person(); //输出 I am one!;
    # L8 N# |+ Y' I2 i2 n* O
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

$ `* Y7 e! F% ?6 d
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    1 C( T0 i2 d( r/ h% @2 g3 @
  2. namespace test;# w9 ]# i. r; c! ]$ D
  3. namespace one;
    ( {" w, s0 X' ?3 {' d% j
  4. class Person{
    - {5 t( v7 {3 g# i% o
  5.     function __construct(){
    / t, I$ {9 X2 S6 g
  6.             echo 'I am one!';
    0 }) _+ `, N: Y: Y" i0 v
  7.         }
    & J2 C( n1 k+ ^
  8. }
    - X5 B' b6 f" S9 x" C

  9. 0 u% R7 k* D0 d
  10. class Person{& |, g! r! e: `0 C/ G- ^
  11.     function __construct(){
    4 x1 ^+ }4 i2 E9 T
  12.             echo 'I am test!';
    $ L& }% |' ?2 X1 t5 l% v+ T% E7 |
  13.         }; ]# J, T5 [. s$ M9 P
  14. }
复制代码
6 }& p$ c0 X! ?$ X! N' ?7 O: R
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

0 V! \: B# n8 k9 W; t
看来简单的把require理解为替换,在这里行不通。
& I7 i& c4 _6 s% j, _: b( l  n
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。$ k% [( c$ [) t, I5 f& ~
  1. //name.php
    9 S  d' G. L% N
  2. 9 C+ `, Z0 {) d. n# E) @- X
  3. namespace test\person;
    4 q, [7 [( A) D5 D, L
  4. $ Y7 \: F; l6 V* O7 i" G. z
  5. class Person{
    5 e" Z1 ^' r6 {# Z) P
  6.     function __construct(){, ?4 ?, M9 A  x+ @% h  _' p. _
  7.             echo 'I am test!';2 A+ I8 ~1 U$ s% [, X; ~
  8.         }. m5 B) T3 q) }9 B! V' l  b; y
  9. }
    5 r  \# w% Q: n: y6 z+ A
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

* C4 Y7 K, M# ]3 E- F
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

2 v( g7 k3 L* _$ h6 g7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php8 i3 T8 M) W: p& R( ]

  2. 6 B) v+ I* B0 A2 r, _2 }' K% i
  3. namespace test;
    & X5 R, b8 Q. L$ |9 \6 [- Y
  4. echo 'zhai14';
    + y% ]0 d" D* L7 U/ k" n2 Z
  5. namespace zhai;# F$ L  s- F! x$ y8 B  k
  6. require './1.php';
复制代码

! y1 x' m+ i7 P+ X
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
. z' K0 i) c; I" P2 n) s& F
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
6 S& L: n8 `% m+ m6 O2 D* L" V
  1. //name.php
    ( J5 j1 q7 Q% e6 ~1 U

  2. ! o1 Y! P" O/ A3 ~9 M
  3. namespace animal\dog;
    1 A- g3 |6 e4 D% F7 E
  4. / `5 y& W9 g1 m0 X0 e6 S" H  f
  5. class Life{
    . O+ h7 B& ^( W) n& E( h. [
  6.     function __construct(){
    - ]7 F! P2 u# V; {% K8 J& t
  7.             echo 'dog life!';
    ( R! j) I( x) ?" h, d1 A  N
  8.         }
    ! |3 k( A$ S8 j- p& j9 x4 A
  9. }
    ! d, [+ f5 K/ Q4 ]6 ^( C
  10. ) [/ U3 l5 l% ~% \, c7 W
  11. namespace animal\cat;7 a4 V- L3 @( G$ C
  12. + ^: k! a; h6 p1 P( x9 y
  13. class Life{# m8 O" e8 o7 Q$ U
  14.     function __construct(){
    ( s7 l9 w. J) E8 W' j7 H- ?
  15.             echo 'cat life!';' J$ M2 W& P0 e0 T# y
  16.         }8 W9 C0 U1 u0 B9 k! P1 y% ?
  17. }0 W# ]2 x. B, D+ }1 ]
  18. ( d, G- }% F! U5 r& {2 n; G
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间2 s  [; y; t  x' e+ L; W
  20. new \animal\dog\Life();  //A, }. U( }, p9 c0 h2 _+ x3 h6 L. C8 U
  21. # j" Q: D1 W" t2 }( ?
  22. use animal\dog;  //a7 m0 n" _2 ^1 t/ t
  23. new dog\Life();  //B1 o- W& J* K& A; V. ^* N

  24. 5 x9 H/ y" [' G6 y
  25. use animal\dog as d;  //b" h, a# D0 H4 d0 P, r" a
  26. new d\Life();
复制代码
5 r7 Q7 f) Q, l
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
. w5 y  m# W% J* |9 U% r. d
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
6 L  Z5 i  w, _1 B! Q4 Z3 U. L* r
相当于
  1. use animal\dog as dog;
复制代码

, I' j/ A9 \7 b6 z2.namespace后面不建议加类名,但use后可以。) w. N' Z4 r: n2 {4 s: t, S
  1. //name.php, s4 G4 w4 R3 k7 [" Y' s( w

  2. % B+ Z5 R, M6 @
  3. namespace animal\dog;( l" T1 f9 b8 x  i* ~

  4. ( r  X) L* ~: R9 N) {7 I; a# l' k; D
  5. class Life{
    7 D! v3 ?6 P9 j$ T0 N/ J
  6.     function __construct(){2 V. X2 Q/ ~2 Z9 ]7 D
  7.             echo 'dog life!';
    % Y/ p2 I: m) w' Q8 q2 e! T
  8.         }" s: a; K, U& ~$ @) P
  9. }3 a, u0 ~1 r1 f! v  K) W
  10. 0 [$ X% J* ^/ E% R- Z
  11. namespace animal\cat;
    & S; ^  J# W' T/ q/ p8 C0 L; Z

  12. ! b# }5 C* w/ ~6 q1 e; t
  13. class Life{. h9 Y4 B3 }+ N' a7 Z
  14.     function __construct(){% y  h' N3 o: E% c
  15.             echo 'cat life!';
    / u& T7 j! Q3 a( W
  16.         }
    . G, T0 Y& ]- X! F+ x
  17. }
    : Z" I- E* `1 Z' \& |! g+ N
  18. + Z( ]" z; S8 A
  19. use animal\dog\Life as dog;  $ J7 r) V( _, N5 i( U8 B) y8 W
  20. new dog();
复制代码
3 `( F# i0 `! Z/ K: f7 R# ^
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
- g. c! @* z1 e; X
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php4 X/ ~4 G( @' g3 T! Y  }4 H, r

  2. 1 l; Q7 F/ p5 F
  3. namespace animal\dog;
    % `' i! D( {- h" N
  4. 8 ~( P2 @$ I5 E* i& R
  5. class Life{& ]/ h1 T, k5 K- F
  6.     function __construct(){
    6 T6 @3 ]; ~% _2 w7 {; R% t' e: J3 S) a3 L
  7.             echo 'dog life!';
    9 F/ x) E! I( T- g5 Q) I- ]6 G
  8.         }( i- G$ l8 E5 A
  9. }
    % \' S2 e+ P" l) ?2 w3 c9 _2 n9 G( F
  10. class Dog{, ~4 D) F. U1 D( c# w
  11.     function __construct(){
    9 n( g( G$ ~; v, E
  12.             echo 'dog in dog!';
    4 ?8 s8 G, b, c7 c6 y. k
  13.         }
    2 h& z+ w4 o/ p
  14. }) x8 L$ C6 [( O( b- ]$ |7 s

  15. / w0 ~: N1 Z# O# B* S9 z
  16. namespace animal\cat;6 `. U2 C9 J) q! H& ^3 ~/ K  |
  17. 7 H  S0 G/ q2 h
  18. // class Dog{" r$ l0 u0 l0 S2 _
  19. //     function __construct(){+ H, N/ Q  `7 ^! Q/ U
  20. //             echo 'dog in cat!';# R+ X( q' u9 `4 _! a, t' a
  21. //         }
    % K) w0 @% P5 g' K4 ]: l
  22. // }( ~! w# O' e: u2 w# D# V
  23. class Life{
    - ?, |/ y7 T  H. o" z9 L$ R
  24.     function __construct(){1 s) g1 P9 W" g2 @
  25.             echo 'cat life!';
    . G6 t: b# D* G7 X
  26.         }" f. [' h; w$ ]9 M) I% R! L
  27. }% @7 i7 C1 W' X$ y, F5 x
  28. + I) d- l, m* I4 X
  29. use animal\dog;  + K2 v7 ^/ I& i5 Q
  30. new dog\Dog();
复制代码
6 X9 p3 n+ M3 }) ~
如上,使用了
  1. use animal\dog;
复制代码
6 Z4 }+ r- N* L$ W4 `
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
, {) b' Y; j9 i& M
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

% h& Z0 B" u* c% N9 H2 V( `* h6 Q: [; ]: h1 D2 X+ m% V
5 R6 z3 m" }& H# h4 I# w: X2 p
9 J8 b# K: x( t+ h9 b$ j8 Y

* y+ s, ^5 Y' E  C; Q2 u. G
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-7-27 11:51 , Processed in 0.118008 second(s), 21 queries .

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