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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
  L  q  D7 @' a& {
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
6 a; d8 T' F$ y3 k
6 Z. [( F& ~' p1 v% k
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
% d* `& m" z1 l* G0 x/ P1 J$ d# J: l5 u
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

3 ?0 J' g" Q- g' P  ]结合使用方法来进一步理解它的使用目的吧。

5 e& k$ {. A2 J% b% P, P+ L; J
; c3 B( u6 X1 }8 A, Y# j6 [! l. X/ snamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    7 [, o- s! {' K' L
  2. namespace One;# {0 H: Y: _7 f2 d4 |
  3. namespace ONE;
复制代码
. q9 b$ \& M9 E. {- P
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
, h7 i' C, {" X% s# F3 t8 k
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   / F) T/ R8 M* [' Y+ z
  2. class Person{
    * O* F5 \" p  L- o3 v
  3.     function __construct(){1 g4 l: \  e' t* ]6 M5 Z. o
  4.             echo 'I am one!';
    . F$ r1 a7 b& L; \+ `6 B9 m
  5.         }3 E) m2 e# k3 ~7 g8 X' B" }
  6. }
复制代码
  1. //name.php
    ( B( v" D  b9 q5 }& @
  2. require_once './1.php';2 \" _( M8 ~( ~3 G2 l9 ^4 T
  3. ' t  Q% i6 `5 P8 R: `$ _
  4. new Person();     //输出 I am one!;# E/ j" r. Y7 P. a. D7 c' {5 D3 a8 z
  5. new \Person(); //输出 I am one!;
复制代码

7 |+ `: }) R  W3 r! P' {3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php2 d) f6 }0 [, m
  2. require_once './1.php';
    ! b2 ]" K: t1 z' X2 `. E
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
/ N, U# I" r* v8 M  s. D
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    & k, d1 S5 [2 j, \
  2. namespace one;
    ( U: Q  g. Z9 R1 R+ S$ M6 \, s
  3. class Person{* z, p1 r: e4 ]; _; ?) X2 u" Y3 M
  4.     function __construct(){
    , o  `$ ]. {0 I
  5.             echo 'I am one!';
    ( y8 ^, {0 f$ u9 `( A
  6.         }
    1 t  f- z3 j2 \# Q1 P
  7. }
复制代码
  1. //name.php9 g: H1 G+ f5 K7 H0 C( e. W' B* v
  2. require_once './1.php';  f, v9 X' S0 z, s/ ?
  3. new \one\Person(); //输出 I am one!;% G1 N& G- ~; l
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
) c( d& w  u. I; }* @. [5 M2 C+ [+ |
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

4 O; E' r4 m4 V9 i0 k  c/ q! N! c" ?5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。0 l/ \; {7 b+ P0 U' H# R
  1. //1.php   
    " C6 P/ `+ }4 R- }! G, C% C+ A
  2. namespace one;2 Q8 Y; g( E" g" B! `. q
  3. class Person{
    + f& _* ^6 @3 `& Z
  4.     function __construct(){
    8 @; B3 i. z- d" ~# s
  5.             echo 'I am one!';+ s9 g8 w) r' N- G. m
  6.         }
    1 p1 O/ ~- @0 _) v8 e$ O' T9 ^! b
  7. }
复制代码
  1. //name.php
    # m5 w1 S8 ]5 P
  2. namespace test;
    : c; A+ b2 ?: @. f6 s
  3. require './1.php'; 1 @, p4 ~# x, e4 v" c
  4. new \one\Person(); //输出 I am one!;
    " f* s' D1 H5 c# F0 o7 N
  5. new Person();      //这里结果会是什么呢,猜猜看  k" m2 W- l; [! Q
  6. 最后一行结果报错:3 _$ J2 l: M, u4 i9 i# F) p: h2 |
  7. Fatal error:  Class 'test\Person' not found
复制代码
5 a) s( b; @# d0 [

, T7 s0 p2 I9 H! W- |首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
0 |% v$ [, a1 P$ W
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
" g5 ~5 O1 \5 |# e1 W; m9 T* J) u. S
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
      J1 j  {1 R  t4 Z; B' f
  2. namespace test;
    - s4 r6 ^% Q! p5 E6 W
  3. require './1.php';
      z) ^/ h  F9 }* t6 Q0 s% D
  4. 3 S9 r' i5 C8 `  x
  5. class Person{
    ) j) Q& J! K& ?0 m" ]1 [& }6 s
  6.     function __construct(){8 P/ O- ~5 i; l. p/ j
  7.             echo 'I am test!';
    * I# @% r5 y# j5 m
  8.         }, {9 A2 \# w# h: g, p* A: N
  9. }
    7 z( |4 g3 R% R! O  V7 z, B$ C7 z
  10. 0 m, U4 j% L, |' g2 k  {
  11. new \one\Person(); //输出 I am one!;2 C/ b/ t- \) z3 G  e; X* U- A
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
$ e7 K. B+ E; n4 e8 ]
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    4 @$ B; }/ k0 f( q& U& _3 `; N6 [
  2. namespace test;2 r" s+ M. k$ q6 x1 F
  3. namespace one;
    ; D0 R& Z7 s4 ~' _
  4. class Person{
    9 s$ B  J3 V  \
  5.     function __construct(){
    ) A3 q6 W4 j7 _+ k" }0 o
  6.             echo 'I am one!';
    7 m1 K/ l: x6 z, {  w8 k9 ]
  7.         }7 ~0 C" e" s- A
  8. }2 N4 Y- I+ V* J9 x

  9. 5 H6 [1 Z  v- Z" A4 ~- f
  10. class Person{
    ; C7 {% j! z5 o& L6 t- y  F! y
  11.     function __construct(){
    , c8 G- ~/ R# m5 z
  12.             echo 'I am test!';
    ( j: w( V1 d. M5 \
  13.         }
    ) I/ d5 V  f0 ]; R/ ]
  14. }
复制代码
6 d$ g! L4 I& ~; w! p. |0 M
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
2 ]" p% e6 n) d) X# B" Z& d
看来简单的把require理解为替换,在这里行不通。

, k; n( `8 g& l" R- Z1 o6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
  W$ U. @4 Q5 B* a9 j+ U% p
  1. //name.php
    8 J  A. f: G% O' u) ^- r
  2. 7 B$ Q! ?6 X$ q. G
  3. namespace test\person;
    6 }0 n, m3 U" e  n
  4. 9 ~- t. Z. t! d' b% I
  5. class Person{
    0 B' [" r% R. d) K
  6.     function __construct(){/ q4 R; k" E5 o' ]- N, `
  7.             echo 'I am test!';
    6 c$ x% N9 I! P. P- T. O
  8.         }
    . y3 B; g7 e  u8 p( e! A2 u' s
  9. }
    1 Q1 L" ^& D4 |
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

& b/ c; B' @& ^2 u5 |$ a! w
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

* D# m+ F; L) s2 O* X% l6 x! C7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    9 {7 e3 ]7 {/ S, T0 U1 F3 U5 B: m5 E' Z
  2. , s5 g  R9 v6 n; M, Z+ E
  3. namespace test;
    $ e, P% U( z2 n% g5 s) x% M
  4. echo 'zhai14';0 w5 ^5 r1 L3 F$ {& t3 y
  5. namespace zhai;
    ) N9 D6 q* M8 m4 S( |7 o" D; d
  6. require './1.php';
复制代码

8 c: f2 p1 {  e: ]' o/ O: R
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

7 V, |! b* h8 i1 g% H' Y8 |use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。, v- M; a% `( q4 C9 W
  1. //name.php
    9 t$ Y. B8 V' F0 L
  2. ) A7 A" t: X, y, u: R, M- `
  3. namespace animal\dog;# o2 y$ `. I+ @! q

  4. 8 P* h% I, ^+ u
  5. class Life{
    1 R+ R# P9 k. ^2 B+ r8 L: T
  6.     function __construct(){
    8 J7 }- W# Z7 Z8 P9 k6 B/ y
  7.             echo 'dog life!';1 t2 I/ J" h- X; o
  8.         }
      s, b+ b- p2 @1 @# A; q: T2 O
  9. }
    7 E# U3 ~5 e& |) e' c' H( u
  10. % M/ V9 L; G! X7 v+ t! [/ l
  11. namespace animal\cat;: i) }2 z8 s/ i) ^: ]8 B  L, D- o

  12. , ?8 v8 y! s, s/ o7 o
  13. class Life{
    8 W' L* @3 y( T. V
  14.     function __construct(){
    9 \4 Z1 D/ ]* w$ Y" Q6 h8 L
  15.             echo 'cat life!';; k. H4 Z* Z8 E- c1 G
  16.         }' w) [/ D  P, Q
  17. }
    & I+ M; K( V0 d8 Q* Z

  18. . r3 M7 M# y; C4 E! j+ g" }5 |+ O0 y% u% F
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    & C$ l. D/ _# L( W. S- y
  20. new \animal\dog\Life();  //A
    2 _" L1 v0 }& M" M
  21. & w; B! y2 ?, ?' A8 x+ _' y1 ?4 D
  22. use animal\dog;  //a
    3 U7 y% j. _' }  Z) U
  23. new dog\Life();  //B6 Y( V+ b. C6 q6 d6 \
  24. 0 ^+ ~2 a1 Y+ V: h" n' Y, E
  25. use animal\dog as d;  //b+ d+ j0 |- {3 X! g  t3 a8 ~
  26. new d\Life();
复制代码

* u% z. j+ U9 }, t
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
& ^. C: z  x; S8 X: i. _7 }
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
; k4 T0 I7 h+ e( s% {" g2 E' w
相当于
  1. use animal\dog as dog;
复制代码
2 f0 w. o( v% K% w0 o: ?9 `
2.namespace后面不建议加类名,但use后可以。; t6 A; @+ C3 U5 I( r
  1. //name.php- A& L. L' w$ e& h
  2. $ m/ @7 c8 Z' g+ K0 J
  3. namespace animal\dog;
    7 {, L) q0 p6 |- M

  4. 2 R, h) y6 o$ U2 E) E: C
  5. class Life{7 {, U% G4 Q$ n7 Q! W; t. G
  6.     function __construct(){
    + Q9 D0 z! T9 d3 J( I0 Y, o5 F
  7.             echo 'dog life!';2 x& _( s" N( t, x( M' R
  8.         }* i+ ~- g% i, k$ r* D& ^2 d
  9. }! j$ S8 g9 M0 \
  10. ' ?+ ?* Z8 }% a- l5 s* l
  11. namespace animal\cat;! f6 S3 A$ s, W4 I
  12. 4 ?, R) \' G2 y  \/ P
  13. class Life{
    $ j6 V* K5 a  k2 H) i
  14.     function __construct(){6 f7 Q$ O  R8 E- f, ~) w$ e* Q
  15.             echo 'cat life!';7 r% v  C! ~% L' t# m
  16.         }
    . w$ |2 D$ l" o% ]0 o' T6 t$ }
  17. }- m# H: ?3 k/ e" W8 p, P. m$ p
  18. . ^3 _& l! j7 s% V
  19. use animal\dog\Life as dog;  ' \+ }$ }% B& J/ N
  20. new dog();
复制代码

* y% r, {7 A! V& y
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
+ D( Z) h4 P$ ~2 k! ^+ r/ M6 G
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php! I7 R* E- E3 ]

  2. 4 h+ j; f: C2 ]5 i
  3. namespace animal\dog;
    % m0 j, y# W( I( J5 W$ `' C

  4. . h; b9 i4 A* t4 c
  5. class Life{
    ' u+ J, w' e' n+ `; d
  6.     function __construct(){
      [/ w4 [9 E& P' g7 R. U
  7.             echo 'dog life!';
      B. X/ r9 w8 s4 |  d
  8.         }- D, ^3 c( Y/ N+ t: o7 J/ ^
  9. }
    ( Z6 j( ?4 F1 |, @
  10. class Dog{! v) P) A! F% |8 p* e' t* S
  11.     function __construct(){
    7 B) m  V( a. j" u# {% Z) x  a* K& ~
  12.             echo 'dog in dog!';% ?5 S  k, }  f: Z) m& V- Y/ J5 i
  13.         }4 v7 E3 U7 s5 ^: @0 ]  j  ~
  14. }/ u% @* x0 Z7 _1 i* b! T
  15. + D/ L& l0 B+ J1 i$ v
  16. namespace animal\cat;
    6 @( k. [$ y& j2 G

  17. 1 d8 [4 I. y7 j
  18. // class Dog{
    + `# B1 n% S+ x4 u
  19. //     function __construct(){2 r) f- Z, F; T$ Z5 C* N
  20. //             echo 'dog in cat!';+ G2 ]! S2 I; s4 _8 L6 u
  21. //         }) g# H+ n3 T' R4 ^# G6 D% y
  22. // }' a, H- Y3 m/ c  ~  M
  23. class Life{
    , n0 k5 j' m4 N$ n; ]1 n( ^2 v& \
  24.     function __construct(){
    ) e% @$ c/ D4 g. l! @
  25.             echo 'cat life!';) W4 n* }  F4 _: C: k; o; I
  26.         }
    ; M. _4 e* ]' b( E! i
  27. }
    8 X" {, |1 f" m: u3 ~& V" `7 f: ^
  28. 7 x9 W: r; a% h0 c7 `( W8 E
  29. use animal\dog;  + z% B: [# c& t+ X6 v
  30. new dog\Dog();
复制代码
  B" t* f7 {  \. p7 a* l) ]
如上,使用了
  1. use animal\dog;
复制代码
% B+ q+ S. d+ d; ]
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

6 k; O& ]" H0 w! E0 x( O
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
% P. C. r7 Y$ p2 l" T! x# f/ O
, `$ J! B' q% d6 U8 o
* \. @8 p8 ^* t+ R( o

* S! |! j' R# y0 J4 h- X0 ?. D1 Q# W- N" k; h# s) k1 z
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-16 15:03 , Processed in 0.055231 second(s), 19 queries .

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