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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
+ o4 j3 B- Q8 v1 V# n4 F6 k: |# v! o
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

  X+ K6 p1 ~0 ?8 B% d% X" [: [3 D# j. h
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
, l& p  f. |" W. G# u4 V
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
& d" d( a- c/ S" {( Y
结合使用方法来进一步理解它的使用目的吧。

3 z& O* E6 ?9 d8 Z6 z, n  [8 Z& b: S
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;% O3 X( z- A9 v/ B) e
  2. namespace One;
    3 ^' q+ z, o/ m1 E0 I) l1 a
  3. namespace ONE;
复制代码

0 V' F8 P1 l# v' f
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

. ?! @; R! {6 R2 U  D2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    1 `0 J# @3 u6 ^
  2. class Person{
    % |4 Z  m9 ?( ~7 a8 b* m4 t
  3.     function __construct(){
    6 R9 @1 v2 ]& Z1 O2 I9 |8 ?
  4.             echo 'I am one!';
    1 s5 U/ D6 P9 X" m- p  i
  5.         }; z- Q) d& A9 s2 Z
  6. }
复制代码
  1. //name.php$ y) y' S1 W! i, @' G- J0 a1 r
  2. require_once './1.php';9 A5 D5 [) `8 k# c7 B9 i

  3. 3 s5 |1 G1 T7 H. n- s4 A. t
  4. new Person();     //输出 I am one!;6 U/ `2 N( I% R
  5. new \Person(); //输出 I am one!;
复制代码
4 X% ~( |3 o7 q2 v. B- E
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php- n, o6 {  g9 V. x
  2. require_once './1.php';
    $ }5 z$ F: {; `, k+ j' L8 f) f. v
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

3 m9 g% q% u8 Q9 W4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   3 q# S1 r5 ^0 j8 f# M# @7 U7 u
  2. namespace one;
    : w/ U7 R) O) d9 x
  3. class Person{
    8 Z( c. N. g- v' ?
  4.     function __construct(){0 r# N( r  H4 V, p8 r! L6 j
  5.             echo 'I am one!';
    . Z7 h; t" j$ ^. f
  6.         }! g: g' T+ D/ }" }& c7 l: ~5 R
  7. }
复制代码
  1. //name.php+ ~% h+ M9 q4 \- W2 `/ Q
  2. require_once './1.php';& O/ h$ o' j: ~' z) }% S% m& k* ^6 D
  3. new \one\Person(); //输出 I am one!;# V% _8 n( [1 d* ?3 [# A9 u
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

& B* n0 s3 y* P# G
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
% C9 T( v/ [5 Y
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。. _- k# w) C' P  g' Y. G; d
  1. //1.php   
    9 `: H% r& w5 F4 Q2 G
  2. namespace one;
    - p! g! a, j* z' K
  3. class Person{  r' \) W+ |* K( M$ p$ M+ }
  4.     function __construct(){/ ?$ g7 f. p3 B3 _1 r
  5.             echo 'I am one!';7 \4 j7 k6 F9 t" ^9 o% I1 T0 v- M
  6.         }4 \' k- u+ V2 g5 u( ?
  7. }
复制代码
  1. //name.php
    2 L1 Y- `# C" N( }  L/ o9 F
  2. namespace test;
    ) _$ ~- K$ H- x  C
  3. require './1.php';
    ! M' ^3 T* L7 T
  4. new \one\Person(); //输出 I am one!;! k* Z8 O6 N6 ^2 R1 Y* {
  5. new Person();      //这里结果会是什么呢,猜猜看
    % D4 }# A* v8 @0 D; r
  6. 最后一行结果报错:, |  |4 t& g( f9 }! w' [
  7. Fatal error:  Class 'test\Person' not found
复制代码
6 B- Z: Y! n8 a8 |; d6 G& D* ]
' G7 D; Y1 A) [
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

  ?  s! [6 A+ n! d  _$ G7 n
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

2 O/ w6 v# X* ~5 J! j% n- {
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php7 f2 E+ w' D. S* T& T
  2. namespace test;
    2 J9 b! M+ o( X+ F& l# }& c# q
  3. require './1.php'; ! A* o% }/ {- x% t; E
  4. : M3 _- [" T) ?% r+ ?
  5. class Person{
    + b7 {% u/ |8 J/ b
  6.     function __construct(){( a2 L2 s7 X" d& N  L
  7.             echo 'I am test!';- i3 r# n2 l: V
  8.         }" R8 ?3 r! h2 P
  9. }' X; E. H6 R5 ]% u, Z
  10. 5 {6 }2 c$ v9 {7 J
  11. new \one\Person(); //输出 I am one!;+ J) H2 E. V( M  y% a1 b
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
' W" _9 U- A8 _" G
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php" a. S7 q$ T/ Z0 n6 ~! ]
  2. namespace test;
    9 q, p2 b+ B* l  C: ]5 W! `: c" n
  3. namespace one;+ x2 z1 S9 Q- q$ X$ G9 U. K$ w
  4. class Person{* j! }; {8 B4 E. ?$ w' f( u
  5.     function __construct(){
    3 D2 l$ o9 {0 U, f. k
  6.             echo 'I am one!';
    ; y; A9 M( `% ?* [' U
  7.         }
    % K: z6 L9 b7 H1 }, A
  8. }
    + S$ l" y5 M7 v. a( [# k: _, U

  9. $ w+ P" l- r; L) ^8 ]* P. c
  10. class Person{
    6 Y$ U8 x# \9 }2 n$ W! c9 w
  11.     function __construct(){, o3 h9 N& [# W: x# {" G8 `
  12.             echo 'I am test!';6 N8 \3 J. a5 ?& G% {  D) O
  13.         }# a5 X& |* u; n+ Z
  14. }
复制代码

( b; S% l* \1 L4 ?2 S5 t! G
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
4 Z+ R* x3 L! A+ N3 l( }# S* W/ m
看来简单的把require理解为替换,在这里行不通。

, Q$ F, k$ R( o' I6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
) w+ C& Z3 T4 W+ f& d
  1. //name.php3 j' R+ _" x; V* h

  2. ' u/ \. Q0 x+ E7 V$ ~) O
  3. namespace test\person;
    7 L6 ~2 F" |# r& \
  4. . a0 T: {* k: i  l( b# a) H# V
  5. class Person{6 o/ F! o+ T/ X
  6.     function __construct(){7 G- ]. [7 x" l0 C
  7.             echo 'I am test!';
    ) y4 H& ^6 V  D, n4 |9 U! [7 Y0 |
  8.         }4 H- w# T4 ^0 A1 q" t6 ~
  9. }9 b9 M1 e$ v" i$ y7 @# q/ }, c
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
5 ?, \- _, U: q' ^, Z% B+ W
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

# {, i3 y- _  i( J7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php2 ?- c, a$ y& i1 o
  2. 3 K% R1 A& ]8 Q' J2 Z, I
  3. namespace test;5 R# y% ^6 X( @2 |. V( P5 c
  4. echo 'zhai14';
    ) k( _$ g/ ^" R
  5. namespace zhai;
    ! Q8 w- F# V2 k, y7 F
  6. require './1.php';
复制代码

3 c) `$ p5 i/ N+ z2 I8 B9 U6 _
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
0 ]- i3 h( Z3 b. C
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。! `2 `$ Y) }* M6 |% F& v
  1. //name.php% P: W1 j. _8 L
  2. : y; `  |9 N0 _) y' L6 x' r
  3. namespace animal\dog;6 G7 E  Z4 E9 m( u$ V
  4. 6 K3 j! y+ j1 p* I  c% i+ r  W
  5. class Life{
    8 B9 c! \4 L6 N, {2 b
  6.     function __construct(){
    5 ]6 R! y# \( Z. P% K- d
  7.             echo 'dog life!';/ {* |- |8 M  d6 H" }7 R+ T
  8.         }
    . n  }+ q7 R1 y4 q+ C) j" @
  9. }
    6 N! }- y! b- Y2 |9 y/ @9 s- k
  10. + e  Z8 e8 I. q2 u8 x( V( M) ?2 k2 v
  11. namespace animal\cat;
    % c/ d1 z' M3 {; |/ B

  12. " O  o2 Z# z$ E. n3 [7 G6 {% V7 m9 t
  13. class Life{
    7 T6 L, V6 h& s& d/ C" F- y
  14.     function __construct(){3 ~' Q) O! T4 }5 f* r+ q8 O
  15.             echo 'cat life!';" k# U) C: g: x* e  {# `- g6 ?
  16.         }% a; y0 a# ?0 i2 B
  17. }3 Q: S" v1 s" G( o8 L8 k% T- ~( ^

  18. 4 M+ F! }$ g6 r" _) m8 [, q
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    $ H, A6 g- k' j# ?
  20. new \animal\dog\Life();  //A
    * m& V% D% {& E! y  ]7 R5 D' H
  21. . f& D  \" K% z# ]3 e
  22. use animal\dog;  //a
    6 \  _7 f3 o3 H" v7 s# `/ t( O2 s
  23. new dog\Life();  //B* B) ^# u8 i: a# l
  24. 5 _2 q$ K/ W* w+ q/ _( i
  25. use animal\dog as d;  //b7 @  f' q; f6 U4 Y( W  P
  26. new d\Life();
复制代码

" N& b) p* Q9 [' S8 B; q
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

/ S  N, B; A3 m: c3 U
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

. u$ k, E: B3 `5 a
相当于
  1. use animal\dog as dog;
复制代码
. f' v$ w+ `. G
2.namespace后面不建议加类名,但use后可以。
( \" a; G5 e3 g, z* k  G8 l/ E
  1. //name.php
    8 P- ^) ]0 ~+ S! D4 \( y

  2. 8 u, k" {7 T: F" r
  3. namespace animal\dog;9 M" u* P' C/ @

  4. 9 v& p4 }1 u* Y$ z3 v$ P
  5. class Life{" P' {) ^% v! j4 k6 b: t# f0 s* i
  6.     function __construct(){
    9 Z4 f% s: p; X) S
  7.             echo 'dog life!';4 r, P7 p9 h' r8 G
  8.         }
    : c) T2 D' b1 y+ w$ U
  9. }
    " a/ L* Z, @$ j, L8 n$ {" @

  10. ( G% {2 M) {8 x/ X/ X! o
  11. namespace animal\cat;: d; j4 `# E& [
  12. + W( S! Y. A& \! X1 o& u  j0 ^
  13. class Life{6 [. W- u' A) V! ~1 k7 [! }
  14.     function __construct(){1 s! }2 `+ y. }" X& l% Q
  15.             echo 'cat life!';( m; Q1 ^( q, a& k8 t' N3 I6 `+ p
  16.         }
    ! y# k4 C0 P4 s% O' k
  17. }
    4 l. |) G0 s- ^1 p6 w4 b  m) W2 X

  18. * M2 h& ~2 o! R
  19. use animal\dog\Life as dog;  
    . J2 N: w0 N3 ?& f3 t% B
  20. new dog();
复制代码
6 d9 c* T2 @) H) ~& M5 `
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
1 X2 X2 [" o2 w
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php1 V, G# P' W, b

  2. & I- ^( r0 V! @& R
  3. namespace animal\dog;: i& S; J# s  v7 u% r, m" q

  4. - z$ o; K2 Z. o5 a9 t+ m
  5. class Life{
    , z7 r( b; o$ v7 P3 D/ C1 B
  6.     function __construct(){
    " n1 t! f+ ^' G4 z" Q
  7.             echo 'dog life!';- Q! l! ?* Q* Q2 o) R+ d
  8.         }
      @& i" G  d. }3 V
  9. }9 w7 w7 h* J* F2 j5 j! L3 @& b
  10. class Dog{
    / N$ C& q5 G- l. d
  11.     function __construct(){+ g5 W! I  [8 z0 V  X/ E+ h
  12.             echo 'dog in dog!';- d: ^% |# ?7 y5 b* ~# G5 }: r
  13.         }
    " L* L! ]5 H' i8 d% k; X% A3 C5 ?
  14. }0 |3 T1 x, a. \0 u0 @* c
  15. $ g$ l+ s1 A3 S8 Z: `3 F2 d2 Y
  16. namespace animal\cat;6 |; g/ y' ]4 A7 j0 p4 K

  17. + s& l- w/ I+ l% n7 @2 B
  18. // class Dog{; L7 x9 e& o4 z0 o
  19. //     function __construct(){
    7 s' }5 n# ?6 u2 ^8 J# ^
  20. //             echo 'dog in cat!';
    4 y- l1 s: I6 r: j( J
  21. //         }
    * {% O9 x5 u3 S/ V" I
  22. // }
      A9 P! n% O3 h
  23. class Life{
    " X4 W4 j3 A1 S9 B7 q1 W
  24.     function __construct(){
    4 s8 F; e  y( {' E2 A$ T+ ?( x
  25.             echo 'cat life!';
    4 _& h% v6 j2 L7 z; s5 p8 z
  26.         }
    4 l  a2 p4 m: F
  27. }
    5 a* L3 _# ]* E2 @$ A3 _" o
  28. * Q6 ]% y/ h9 ?0 Z' K
  29. use animal\dog;    I5 C2 I) P1 f! i
  30. new dog\Dog();
复制代码
* A2 b* L( \1 N  O" i9 N
如上,使用了
  1. use animal\dog;
复制代码

0 g+ e2 w' M; t: L; a7 Z
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
- x+ S* ~+ ~6 A% `
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

! {: \. o/ |# Z, O5 F( j! q- F: \$ ]6 |7 u% f  l8 L

2 B8 c& Y; D6 I# l5 H1 t: D' M4 Q; ?% d' J
* g2 i9 k) z, O
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-10-25 02:08 , Processed in 0.113187 second(s), 19 queries .

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