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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
# T* M4 E( |/ w
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
. f; E: K7 r& ~) L- h, ~0 f& [4 X

- p" F* ~3 j- [& y4 e' ]- y使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
- x, W3 n- v) @9 f" M* Y9 R
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

$ }7 j$ W: D( I结合使用方法来进一步理解它的使用目的吧。

- z- q6 F' e* R) a1 [; C; L- ?3 T! Y* Q
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;1 |- l  X# q. X$ h+ L4 N4 D
  2. namespace One;
    ! j. \$ R+ z( E) o+ h
  3. namespace ONE;
复制代码
: \! r$ s; P/ X; |
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
  G+ w) ?! L* Z, R
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   / q8 S3 B; ~5 ?5 q9 g' c
  2. class Person{+ Q( l" L9 D& w$ B; S" E, J; v' _7 ]
  3.     function __construct(){: v4 w0 u5 u# n  Q% {
  4.             echo 'I am one!';
    0 T* [0 [/ Q* }/ ~2 s( C4 b0 \& M4 ?
  5.         }: g$ m2 {7 Y3 X# f
  6. }
复制代码
  1. //name.php' b3 B5 k  k4 ?: v. `
  2. require_once './1.php';
    & {5 @& p2 w& ~+ D; u; u  k

  3. 8 A: s8 p3 T! p! D
  4. new Person();     //输出 I am one!;
    ( w5 I( q( p7 N
  5. new \Person(); //输出 I am one!;
复制代码

) C" W. d1 ?2 ]" d0 H3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php3 o, t( Y6 q2 w
  2. require_once './1.php';  X( i5 U  B" E) y$ e! W0 Z
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

6 T; b$ \) h5 J8 p6 a4 w9 H' H. u4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    2 B! D' z) T( |% P0 D1 n, t( Z# s
  2. namespace one;
    7 r9 G- D5 o5 e* M0 L+ y& k
  3. class Person{
    - d0 K4 J: W+ L- p% x6 q. S# ]$ r
  4.     function __construct(){
    6 f, `, B. L% J6 |; r! ?
  5.             echo 'I am one!';, b! ^; V9 q8 e$ S# I6 q/ p3 v, {* l2 F
  6.         }1 S9 s! ~% Y9 t1 ]; o; m
  7. }
复制代码
  1. //name.php" a1 j' B, n5 z& X: d/ J
  2. require_once './1.php';
    1 L  R! |4 T! r) Y3 x1 M& `
  3. new \one\Person(); //输出 I am one!;% \& ^2 p- c4 w& _% u9 T- D; Q
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
* ^+ Z0 [1 H5 U, r0 j% \
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
& |" t5 q% w, U6 ?$ }
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
: p7 @; R% U  L, @8 X! I% |5 S
  1. //1.php   % C2 n, V/ ^& [& g. r  Y8 B
  2. namespace one;
    : Q5 Y: Z# b! m8 i( X" t/ O
  3. class Person{
    9 k, u. B0 S. y4 B# r6 z) \+ x
  4.     function __construct(){
    - F" |, e! |$ ]
  5.             echo 'I am one!';
    4 R5 T& g% A9 y; B/ v+ _1 S
  6.         }. A& @1 o$ G; X6 a1 @7 \' P
  7. }
复制代码
  1. //name.php5 D, j3 r! V7 T$ N  J2 @% e( S# o
  2. namespace test;8 Y6 }$ Z1 x2 C9 m; a, B4 p
  3. require './1.php'; 6 y; E& W: f: O* V& ~
  4. new \one\Person(); //输出 I am one!;( {3 r7 J& S$ v0 c% V
  5. new Person();      //这里结果会是什么呢,猜猜看
    7 O' T/ g" m4 l6 x! g4 O7 [
  6. 最后一行结果报错:
    2 t5 P9 @& N! d
  7. Fatal error:  Class 'test\Person' not found
复制代码

4 {! I( i4 [: \$ Z' h- n, g! T

5 p5 X! ]7 M3 D6 @0 y0 E6 M9 _首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
) N, N3 k, g, w9 Z( d
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

6 m2 v; f# ?* v3 D
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php8 X/ Z  i$ R( f
  2. namespace test;2 o' |+ m' t  v# F9 A' Y  \$ }
  3. require './1.php'; 0 Q6 Z5 ^1 R! n5 j1 v) i

  4. ! W# b9 I# Y; V
  5. class Person{" m9 _! \  Z6 v, P
  6.     function __construct(){
    5 r0 C. J- H, b5 r% L) J
  7.             echo 'I am test!';# x# p$ t8 b3 A7 \+ @( f: d! G
  8.         }; k3 T) a4 U6 S8 W: V1 V
  9. }
    ! p% ]& p( r% U+ ^/ V
  10.   e8 r0 i  k$ O+ B7 k8 T( V
  11. new \one\Person(); //输出 I am one!;4 n- a2 _6 P( B7 x" c7 J
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
/ j: \% B; W6 n( C5 c* e
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    $ s6 V+ N8 V8 O3 Q9 O
  2. namespace test;! m7 ~+ E: A) s- I1 Z
  3. namespace one;
    ! K3 D" K7 h+ t! P1 t
  4. class Person{
    / ?4 Y! E7 i+ t: E: b
  5.     function __construct(){
    $ `5 o2 Q/ U; B1 t) @1 O  [  X
  6.             echo 'I am one!';
    8 w8 T8 h% J2 Z. d& W
  7.         }
    * O9 Q4 Y3 K: k3 r
  8. }
    6 _0 v" C0 T6 |/ ^/ n

  9. + T: P+ f7 u- d0 F
  10. class Person{- C& R/ r0 A- @2 C  G+ V( y3 A1 ]2 ^
  11.     function __construct(){
    * T* M, a/ p& C3 j# ]. }4 j
  12.             echo 'I am test!';
    . c. R" f, r; r  X& V
  13.         }
    & B* L4 u0 d5 v4 B: ^* C! K
  14. }
复制代码

0 t$ O. [8 {- j# K) G$ ^' m2 M
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

6 y5 ~6 m. |, g1 S
看来简单的把require理解为替换,在这里行不通。
4 R9 w8 W. s# Z1 X& D
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。2 Y1 l! |6 ]4 W3 @9 z5 V, R5 `: w
  1. //name.php
    ) w9 T: n- m& Z8 m) ~8 K  Y

  2. 6 z+ b4 m$ ~& e; F! f5 L3 K
  3. namespace test\person;% }( L6 b- s' z5 J

  4.   W$ h& b/ X0 M3 z, ]( x3 d
  5. class Person{8 Q# V2 {4 H7 |$ Z9 U9 p+ M: Y4 s0 w
  6.     function __construct(){
    % Q3 H% n0 n  W$ X. q( b
  7.             echo 'I am test!';/ ?5 c, c, l( Y9 s: x: |3 ?
  8.         }3 {% i$ M+ M3 g  b
  9. }& x: J+ _$ d# ~+ g0 L
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
2 `2 L. R* ~+ p7 S- _
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
, a- t3 C: B8 q0 R9 O
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php7 N, ], s8 M& {" k6 l

  2. 4 ]3 D  L! D: t/ Y. v6 c: W
  3. namespace test;% n2 m- ?* Y3 x( ^/ l! r3 S
  4. echo 'zhai14';
    7 ]! v# _4 w$ D* T( q; }4 i
  5. namespace zhai;% f1 j, ?% l! Y/ {$ I
  6. require './1.php';
复制代码

+ x$ b4 G# g5 o$ }8 I) Y; U
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

9 \9 K7 [8 j! j) k' G2 B' Nuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。' c7 d3 k/ v& f, f; w
  1. //name.php
    2 @4 g/ \7 {1 w' ^5 o, S  k8 P3 G# _

  2. : h6 W; t+ S% o# U/ L
  3. namespace animal\dog;
    ) I; y& y- [: \# Z: y
  4.   v# t2 t6 A* K" B, c
  5. class Life{) d2 v: `8 c' N
  6.     function __construct(){* y- j, K) b) \. |
  7.             echo 'dog life!';9 H) S! P/ |5 j. v6 `0 A
  8.         }+ V1 n& Q' D( r9 [- m
  9. }+ U: F  K1 f( U* F" M
  10. 9 W! U) r' e5 |1 @, f  z
  11. namespace animal\cat;) q) |8 Q0 B2 z8 L" r4 U1 g9 [0 v
  12. ! K4 y. k2 M% F& b* v
  13. class Life{3 y! c( X& q5 g! j4 w& w. R0 L
  14.     function __construct(){( [' f! F4 t' D" N6 z1 J
  15.             echo 'cat life!';- u; J8 i+ m8 u6 E8 P9 |1 @
  16.         }
    $ A( U, h0 F" X) n
  17. }
    % |6 N3 O2 h- u. e8 {' \4 P

  18. - j" r9 B; h) @0 m/ S! A
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    * S! ]$ [0 t0 F. Q
  20. new \animal\dog\Life();  //A) l9 }5 Z4 ]) a$ r% b
  21. / T; x9 B4 [" @* @$ a9 G; Q
  22. use animal\dog;  //a+ v5 x: t: W2 Y% {* a; ]- B
  23. new dog\Life();  //B/ w4 G6 i1 Y$ z0 g+ U5 F0 \' N

  24. : P* d! i8 C- R
  25. use animal\dog as d;  //b, D! R1 ]9 @) ?0 `( z
  26. new d\Life();
复制代码
8 M$ Z6 Z% l/ b2 K3 M, L
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
/ \+ k1 {+ w, E
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

5 g5 }1 k3 ?& s3 I% S  ~. I
相当于
  1. use animal\dog as dog;
复制代码

/ `- k9 I8 s, s; ^% H2 z7 E2.namespace后面不建议加类名,但use后可以。& x6 @4 A6 N8 `$ ~/ i" d4 j4 y' w
  1. //name.php
    8 h+ F$ N3 W  L( |

  2. / _8 X- p  X) ~  y. x. k
  3. namespace animal\dog;
    8 x3 A* ?+ @6 \0 |

  4. 4 x4 m5 ~3 B; ]6 z; `# ^
  5. class Life{
    - e4 R2 F. F& {7 C' W2 y
  6.     function __construct(){
    ; V) T- C& m" p7 {" q( G9 h8 `
  7.             echo 'dog life!';
    - H! N* ]" N6 f2 k; E* ^$ y
  8.         }
    # J9 N( n6 i+ v0 I" m8 @" N
  9. }
    2 O! k; k( T5 B, x: X9 W

  10. 4 M$ U3 G7 d6 A6 N# `' m  a- z
  11. namespace animal\cat;
    & L) F. e0 t) ^6 z4 A

  12.   r! b2 r0 j2 o
  13. class Life{
      Q; f# h' C! D& ~
  14.     function __construct(){
    ; k4 z4 V9 `+ ]- G# Y1 g9 A& b
  15.             echo 'cat life!';
    # U, J5 T1 y) V  D* B# |. a* O
  16.         }
    - X1 _: l! j1 I3 X
  17. }9 `% D' ~4 |% i7 X+ [5 Q
  18. " t2 N. q) W6 `% ~% e# a! m
  19. use animal\dog\Life as dog;  # a5 G  H2 J' d3 N
  20. new dog();
复制代码
' q! X8 u& e' d# @+ O
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

9 v  ^) B; b* a# X
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php$ E  L0 g/ h+ ?: L" a1 n4 [" p

  2. 0 x: ]9 F+ U1 o5 R
  3. namespace animal\dog;; u4 ?; \6 T3 T+ w

  4. 0 x+ M1 \" g) l' U5 N
  5. class Life{: c/ \" U3 c! n
  6.     function __construct(){) g5 a4 x! ^2 o
  7.             echo 'dog life!';
    # ]  S+ K$ i- [% f& N! i
  8.         }
    : P' d1 X1 P. H
  9. }
    . z" b- A) ]3 T, T+ G# X9 t
  10. class Dog{
    $ X7 N0 O. j% U3 j- I. a, V6 t
  11.     function __construct(){
    % Y4 |% p& Q' ~6 g
  12.             echo 'dog in dog!';  Y$ n  ?8 N4 I+ Q. J
  13.         }$ q4 |0 L9 e% I' E7 H# c+ g3 d
  14. }
    / L8 m0 {, x: i8 g! _9 Y- X( z

  15. 3 [/ B+ E, M5 F1 N( O3 g" h" ?7 ]0 F
  16. namespace animal\cat;+ c* R: i* M. q

  17. + U/ o8 p8 t( J' a! K$ N
  18. // class Dog{
    , F& A* |; K( o
  19. //     function __construct(){
    5 l( P& w4 H" `) z; x* D+ _
  20. //             echo 'dog in cat!';  J# m9 r+ {' z! _' ^0 P
  21. //         }
    3 x8 w% x5 {3 n* w1 [2 R, D
  22. // }: @, x, Q/ N, X
  23. class Life{
    5 k/ z3 ?( v$ @" |8 q) F8 `% y
  24.     function __construct(){- v0 q8 x. G: C  Z7 @, E% l# c
  25.             echo 'cat life!';8 e, s$ |: q6 `+ S! i; ]
  26.         }7 v" E& W* Q, v# u5 }6 D. q$ t
  27. }
    $ ]* V+ O  A; N# x. q+ ^

  28. / p" W3 r1 ?  Q; d
  29. use animal\dog;  
    9 G% t- X/ N! O7 h
  30. new dog\Dog();
复制代码
  d; t% H( d. T3 R1 a% c$ I6 D6 c7 o
如上,使用了
  1. use animal\dog;
复制代码
8 s8 B4 Y3 O8 B( q- H
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

& q$ |% |+ G  j( P: x
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

% S# S7 f! d- S# x2 b" ]$ A( l4 S
+ S2 {: n+ n; a! y" J9 K( o/ E3 A! g" h6 k/ C" U

& b$ d) I1 ]9 i6 q
; z  a7 I* d0 s; e) ^
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-6-18 20:56 , Processed in 0.115857 second(s), 19 queries .

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