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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
( m5 H2 t' A) X  f7 W1 \
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

7 J3 x  F3 d, d
0 L5 d0 _/ ~& i6 o. d使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

& ~& f9 U! T2 ~' o
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
; c6 Q; q. r9 [5 J: T# c: f" U& r
结合使用方法来进一步理解它的使用目的吧。
- @2 v' l9 j+ I
7 J, J* `* {; X6 i4 D+ b
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    + e: {  o( t0 T* l1 [' N
  2. namespace One;5 O' A. d% x) O# `: b: J. q
  3. namespace ONE;
复制代码

0 I" P5 ~$ i6 i6 }) g- @& S1 t
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
: p2 G" M; Z8 d, F3 c4 t2 e  s
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ! W) w8 R" L2 X% [
  2. class Person{3 d* X/ o3 g( k2 r! y* _1 q# X4 v
  3.     function __construct(){7 B0 B* I$ [: R- Y6 x  i2 G  N
  4.             echo 'I am one!';. J" z" q. n4 i1 U+ ^0 a4 {$ y8 l
  5.         }
    6 n2 X, H1 b( a$ q: L
  6. }
复制代码
  1. //name.php9 Y0 q5 c5 r+ h" ~
  2. require_once './1.php';
    : B) L" q/ z: g  j0 G/ ~$ m# x
  3. - N8 U8 t3 M: {# L/ _
  4. new Person();     //输出 I am one!;. J9 o( p0 h5 ]
  5. new \Person(); //输出 I am one!;
复制代码

; a& b' R' E: M3 F1 R2 {' Y3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php) \% u4 ^; j5 p3 }) k
  2. require_once './1.php';' R7 ]- C# q1 Z! C# K1 @' E9 ^. d/ l6 I
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

/ b6 q2 \: |6 o* z  d+ X: p& ^4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
      ~! C0 D' K$ |- F& s
  2. namespace one;
    5 q% z4 s7 S$ ?( Y
  3. class Person{7 s/ ~1 I0 V4 J3 h
  4.     function __construct(){
    ; |- S' M3 B' W+ v8 `- l
  5.             echo 'I am one!';2 i' m/ u) J' k4 Q/ x  |% A* u
  6.         }  S8 M0 ?! D  q8 x1 S4 ^
  7. }
复制代码
  1. //name.php. X, L. \& x* ~, q5 D! e, T9 p* k
  2. require_once './1.php';0 f* M# J6 P# |( ^' y( l$ G& D
  3. new \one\Person(); //输出 I am one!;& N" f  w. b& _+ h" Y" h. L
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

: F3 q8 n; J  R& `
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

9 P2 S# a5 {4 _  J. G5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。" m6 F8 x) l# h& _$ \  G
  1. //1.php   ) y5 D9 P2 }+ z; S8 k/ m5 U
  2. namespace one;; K8 {7 m" i) b- J) F
  3. class Person{
    " g, Q: q2 @: h
  4.     function __construct(){8 i7 c" a0 X$ J7 U# N2 S+ s
  5.             echo 'I am one!';
    1 d# {$ _# ]4 N1 n3 q2 o; ^. P
  6.         }
    3 x" z3 L; O. T/ x1 N; i
  7. }
复制代码
  1. //name.php
    ! g1 w3 ]* v* B) g
  2. namespace test;
    . n5 |$ s1 J4 ^8 O, d1 d
  3. require './1.php'; # d9 B- F6 m1 K! l* g1 B
  4. new \one\Person(); //输出 I am one!;
    ; d6 G" ^% k8 N9 G, u/ z
  5. new Person();      //这里结果会是什么呢,猜猜看
    5 f0 r" h9 t8 k/ ]1 E
  6. 最后一行结果报错:- v. x  x/ p1 w% w% R- f- X5 e
  7. Fatal error:  Class 'test\Person' not found
复制代码
  z* r( v& x5 L' L, D* Q& d6 {

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

5 i6 D9 R5 e( l' O
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
" o$ |! W' g5 E+ Y
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
      T$ e( R4 b- n
  2. namespace test;* o) h: b% ]$ Y( B
  3. require './1.php';
    ( a4 E: m2 c! I, k. \8 D0 G$ ~0 T

  4. - n( t' x9 ~+ S  [5 u3 G
  5. class Person{
    # C6 G+ I7 b* G1 k% g0 n8 p2 o
  6.     function __construct(){9 D- E, h) _% K6 Y3 @
  7.             echo 'I am test!';
    2 R  [/ G; v9 e. y5 D, k  Q! K3 J' J" U
  8.         }4 c; p6 M: z$ o
  9. }" D; Z! v! [# i8 z4 g' @
  10. : Q4 H6 Z) X7 _, B, S
  11. new \one\Person(); //输出 I am one!;
    # N. ~) ?8 p* r/ X
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
* E6 O9 M# Y$ z4 R7 S, \6 p5 O, ?
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    / R& p9 k3 c% s3 E8 |
  2. namespace test;
    ! T* T9 {* J( q8 X
  3. namespace one;
    1 ~( b& e0 e* T9 D
  4. class Person{
    " r3 b  N  H. ~8 I. w; @
  5.     function __construct(){
    3 M: V0 f" J* X0 E' i  W3 G. u
  6.             echo 'I am one!';8 f* L# A6 i+ m& H1 c
  7.         }
    4 ]# W  _# F% P; n  s  d
  8. }/ `2 N8 N) Q' q; q4 e. K

  9. ! X  i/ ~6 F( `% k* z4 G6 c, E
  10. class Person{
    * K# k0 b  }5 H6 k9 Z
  11.     function __construct(){
    ! n( |6 d- U$ v" p
  12.             echo 'I am test!';
    ; z1 I7 |0 O, l  B. q1 X# j
  13.         }( c$ G6 T, D* k/ o6 e
  14. }
复制代码
$ ^* T. p) G% ^
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

/ k- X# {4 ?* a
看来简单的把require理解为替换,在这里行不通。

% f6 R8 j' R9 d4 n6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
0 ?$ @3 G- h$ |2 s- g1 t7 g& r0 I
  1. //name.php" e# W" E# Z/ \4 P1 g
  2. ! ^/ u( ?( h2 r0 n
  3. namespace test\person;) I0 f% T9 m2 i9 R  A

  4. ) `6 l1 |* Z8 T: r- z
  5. class Person{
    * w& c5 e5 H$ J3 j9 P
  6.     function __construct(){
    - _+ V7 ^2 N7 C" p6 O) {
  7.             echo 'I am test!';
    + G$ @+ v1 J& T6 N- ~+ {
  8.         }
    + L3 X- u6 ^6 N; S2 ]6 U
  9. }
    ; Z( Q% |+ o: a4 O- E7 O# n: \5 D
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

3 L: Q# S3 l& N* g9 e
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

% V' {$ n# Z1 k7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    . T8 ]( d9 E, D( ^7 b
  2. 2 _% m& |$ I4 X; t. H
  3. namespace test;
    ; E- a5 v0 s0 t% a" U: d
  4. echo 'zhai14';- `/ b. {3 D+ g% Q5 g0 [' W: m
  5. namespace zhai;
    4 B7 u- I: ^& c! \4 U5 ]5 K
  6. require './1.php';
复制代码
- u7 e# s: \6 B. w( z; m' E+ `, p
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
& P( J: ?$ y6 h5 q; ]0 N, s6 I
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。3 Q* m. L' S/ g( k
  1. //name.php
    * O- x+ _. F. c4 J  X
  2. 5 q$ u2 i% T, Z
  3. namespace animal\dog;
    & T, o0 S/ U) S4 F7 y" H2 e+ l

  4. / h) N; M; w+ x* t
  5. class Life{
    ; [* ]( r) l$ P$ A& ~; `0 z; L
  6.     function __construct(){" E; u* a' `* a' T# B  g% Y' o
  7.             echo 'dog life!';5 Y# V* T( Q  b- A
  8.         }/ }4 R  v  f5 B( f* `
  9. }
    , [( x' p( x! v; D5 J
  10. $ D2 m! d7 M$ n, c
  11. namespace animal\cat;
    ) p' C! y1 ?& X

  12. " f$ Z) m0 R$ d* B! y
  13. class Life{/ u: {7 z& {1 p
  14.     function __construct(){
    ( c% U! v$ j6 d5 f& {( h: S# J8 {
  15.             echo 'cat life!';, Z1 c( }7 |4 O  i, T; q( w# Q+ L$ c
  16.         }6 D& O* v7 J  a) c; {9 y1 @1 H) w
  17. }. H8 J& o$ r9 ^

  18. : I8 x! @3 m8 P# u
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    * p- ]/ i4 |; `# D- V# l6 v
  20. new \animal\dog\Life();  //A, v0 P4 i4 a! X4 ?

  21. ; _9 U7 e3 N" p$ b1 c& B+ H
  22. use animal\dog;  //a
    ( q- c3 q' M, B0 o& P! \# ]! ^
  23. new dog\Life();  //B
    ! _3 L, R; N% V7 ?
  24. # E8 |2 c1 j9 s/ N# ?
  25. use animal\dog as d;  //b+ D! j0 D9 W$ P) b
  26. new d\Life();
复制代码

% v* c2 s6 L, K' Q, P$ [
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
7 M0 W( u9 ?8 _+ }
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

5 H0 C# `1 A3 Q: T
相当于
  1. use animal\dog as dog;
复制代码
) c4 A5 q9 D4 L- {* H0 B& I6 H- [
2.namespace后面不建议加类名,但use后可以。
  P! G/ ?% {# a: ^
  1. //name.php
    * Z/ A8 x4 j1 r3 N% {+ A
  2.   _) R; I4 `0 N/ W/ O1 z
  3. namespace animal\dog;( J! |/ [* ^) u
  4. : C" d5 f9 s1 w. Z3 o  g1 o& T
  5. class Life{7 \/ @/ |; |7 X  B4 x4 H% c4 G; R
  6.     function __construct(){
    * C) |9 J0 y, P9 d2 L6 ?
  7.             echo 'dog life!';; a% S( @- R4 w$ z4 t
  8.         }9 t0 L' k. p2 z9 U
  9. }
    4 Z# i' I$ i# ]' t3 e
  10. 2 _  @& v  X2 X! |. i7 V
  11. namespace animal\cat;
    4 A- Q: {" Y% w% T3 M3 \

  12. % o8 {3 L: ~1 X+ }. `2 w1 A' {
  13. class Life{
    : X2 V  q* J$ c3 E$ k/ J; D
  14.     function __construct(){
    2 _. q7 c& P" v% j
  15.             echo 'cat life!';) Y: }2 @/ A# e- V. s5 h, @/ G6 b
  16.         }
    7 o+ F  m. G- b: a
  17. }
    . U5 Z2 B0 R. I5 f

  18. 5 j1 M! F6 ^. _0 a* y+ Y
  19. use animal\dog\Life as dog;  
    7 k: G4 i7 w, g* E# L% S- z$ Z
  20. new dog();
复制代码

* {% ?4 y' e5 G5 [
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

) V! y  ]( D% {+ u
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php+ d% C* Q6 e( Y% F4 k' j) }1 S5 R1 _
  2. + b- h; p# s6 i3 O( v) z* c
  3. namespace animal\dog;
    ( s! ]8 n/ y; W; I7 D5 l

  4. ! I# r. c+ `, |. M
  5. class Life{
    , v$ y- v0 w0 x
  6.     function __construct(){
    . c  n! k7 ~+ e. U% ?7 ^
  7.             echo 'dog life!';
    8 i, c4 q$ ~+ f# k5 V1 C
  8.         }
    6 G/ G9 G4 l3 S4 u) A2 U
  9. }
      \9 I: ~, n! S1 y0 A9 _
  10. class Dog{3 ~5 ^4 U) z+ z
  11.     function __construct(){
    ' R  U; m& q; U2 @. y0 C
  12.             echo 'dog in dog!';
    0 r! u1 D/ Q4 O% Q7 P0 T: k, [
  13.         }
    8 B' ~; F: k/ W- w" ?2 S
  14. }
    ; e# W) m( U; _: ?# F
  15. + w" V+ r  c# j7 i. }& T$ k5 C0 g% \  W
  16. namespace animal\cat;
    ) n# y! v" c1 `" T9 J
  17. . O1 y$ K1 I, w/ ?0 g3 q9 W
  18. // class Dog{
    7 ^9 c7 k) d& h4 e3 r! k, [6 f
  19. //     function __construct(){
    # Q0 M5 N1 {5 g
  20. //             echo 'dog in cat!';
    - W2 J4 Y0 M' X9 x/ V
  21. //         }
    * L6 l8 g$ _4 q& O
  22. // }
    4 o/ K9 f! w  ^8 t6 _8 r
  23. class Life{
    5 \( P0 ~; s+ D8 Z  Z3 ?/ |% f
  24.     function __construct(){+ ]+ E$ l5 J: U) d3 Z
  25.             echo 'cat life!';& {6 x+ l6 ~% _1 N9 h
  26.         }
    ) w) h  A5 Z% z$ s# s
  27. }
    # J, N# \8 v0 _! _5 Z8 M$ Q' l# a

  28. $ e7 L/ h1 k9 w
  29. use animal\dog;  4 p: Z3 B( l& q: |; \
  30. new dog\Dog();
复制代码

: o1 l* \) A+ ]! z/ i  ~1 ~
如上,使用了
  1. use animal\dog;
复制代码
8 w* \5 q6 G5 d, I! x* D" j
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
# |* M: f" a3 j1 m1 Z
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
: Y* C! ~* F& g7 B4 e
/ a9 Q$ b; S' x0 O
) q& Q) D( _! B9 Z
7 B4 r! N. d" H" k

& [  v# U7 p+ p  e: @; p) y0 l) A
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 13:03 , Processed in 0.050402 second(s), 20 queries .

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