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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。

  X$ \% m) R: }: o7 S/ p, P! T
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

5 P6 v' Y. K/ G8 f# D% G1 N, u1 z' _7 ~! N" g8 ]8 ~4 r
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
. M5 ^- U8 Z& H
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

2 c6 f: j% D0 t结合使用方法来进一步理解它的使用目的吧。
) O) w/ m1 ]8 u: A6 _

; a" C" P; z, m" a* K" Rnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
      y5 e; l7 S! g1 Q. H
  2. namespace One;
      i2 o9 d7 t: l! `. u4 X
  3. namespace ONE;
复制代码
' w+ M2 t3 ?: H* ]/ X0 T9 w- _5 ~9 V
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

+ Q; ^  n; L. `' W) y/ l3 z2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   " @: [& N: ?( K3 c) F* w
  2. class Person{
    * h3 _# ~" ^! }9 _' C
  3.     function __construct(){
    / u) w* }8 f& p5 ]" ~
  4.             echo 'I am one!';
    - U7 p" e" y- h+ ~' c. f8 i
  5.         }) u1 k9 k/ ~5 ?6 @2 ]; l& E4 H
  6. }
复制代码
  1. //name.php* X! H  @# E# M0 Y  w
  2. require_once './1.php';
    9 X: R& Y6 J* ?* ~: ?) D+ u: E% b

  3. 9 O. K- l- i* p4 R# t) p
  4. new Person();     //输出 I am one!;- T- D6 ]" Q+ S! \1 Z2 b
  5. new \Person(); //输出 I am one!;
复制代码
2 Y% l3 \2 @& D
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    ; n0 ]9 i$ {7 S$ r
  2. require_once './1.php';
    % v6 J- j* o: t- ?
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

  B, }) Z# c% U% `4 Z& F4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   * o( `" N* A0 d& h& Z
  2. namespace one;( E; F. J' L, F: H7 q
  3. class Person{/ p- k, S! A, q( X$ m! ]9 N1 Y* W
  4.     function __construct(){4 d; _+ S/ a1 W+ Z
  5.             echo 'I am one!';
    2 K+ Y0 z% g8 E7 f# X
  6.         }3 F- d" f& ^& B! a
  7. }
复制代码
  1. //name.php
    ( @" E5 I8 D0 C6 J, ]/ q
  2. require_once './1.php';
    / t9 |) o5 V6 g
  3. new \one\Person(); //输出 I am one!;
    / @& x. z. e, _: \
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
, J& [. U5 U4 t
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
. [7 W# x  p/ y, A( |7 Z7 k
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。. K$ t( w: ^9 r5 B: }0 W
  1. //1.php   
    % }9 p7 N6 p+ i, v2 q& I
  2. namespace one;4 @& S& w& Z" c; {, p
  3. class Person{/ r9 Z4 S; n- `: n" X4 V1 ^9 Q( L8 t
  4.     function __construct(){
    + }& s$ V$ g" s( v) s( o/ e
  5.             echo 'I am one!';5 V' \- h( G: Y
  6.         }
    - E& `" s% P% t
  7. }
复制代码
  1. //name.php
    9 o, [" ^: U: h- ?3 f4 Q% ^
  2. namespace test;' w) U1 b( [+ m- e6 M' K- _
  3. require './1.php'; / S9 D1 u/ }( y1 W7 U
  4. new \one\Person(); //输出 I am one!;
    $ E" F5 A$ A2 a7 B' U
  5. new Person();      //这里结果会是什么呢,猜猜看
    - k0 M& _' _  ^* Q* W" l) I7 _
  6. 最后一行结果报错:( i! S0 p* g+ E: @+ m- m9 X, m+ f+ S
  7. Fatal error:  Class 'test\Person' not found
复制代码

+ }, D$ ^" N3 a; Y, d8 q
5 X! H5 L# ^* k+ m5 f
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

1 s4 e9 b+ R4 f
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
1 C2 c9 I2 i+ _' F; M& u* m
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    . J3 d  `$ ]* E* b$ e" R% v
  2. namespace test;9 H5 |6 O/ B# q! k6 B( y% ^, z
  3. require './1.php'; 0 E+ I/ N( F/ T; T
  4. ; {7 H; W% u8 |1 Y
  5. class Person{6 X6 B; C& |4 x6 V9 P' R! k0 |5 c
  6.     function __construct(){3 d: {& w. T$ `5 o6 C
  7.             echo 'I am test!';
    ) J: I( z! ?; a- }# P( `
  8.         }" x, V0 A1 K3 `$ G
  9. }9 c: \  i/ m2 m8 W" N9 ~. G. i$ Z

  10. + H7 u* U" h* {2 O, ]% q" `  ]" ?
  11. new \one\Person(); //输出 I am one!;4 h6 `0 D: E+ S
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
$ U- a% J/ N. C% [9 t0 H. F
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php$ J: d2 s1 ?4 L
  2. namespace test;
    + }& v: s! {( a: N5 c
  3. namespace one;
    ; h4 l* [9 j9 r4 j! R. @* z
  4. class Person{
    - ]; S2 ?$ ^7 v
  5.     function __construct(){
    % k0 B+ z5 R7 N2 ]7 Z- P0 r* M
  6.             echo 'I am one!';
    5 v. C& U; @4 S
  7.         }! c4 u7 P! a4 R  ]
  8. }" v, r$ r4 {; m% `5 @

  9. ( L& f4 L5 P8 X1 R6 y1 p( ?
  10. class Person{9 B( u% @4 ?8 Q+ W, Q( E7 s
  11.     function __construct(){
    * g- b+ @6 v  A3 M
  12.             echo 'I am test!';* @( z5 B; q* O& Z4 Y& r9 i+ k
  13.         }3 h6 {0 E9 n* N5 ~/ q* D  M
  14. }
复制代码

- I" _) @) G) W; ^+ M6 c  V
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
% l& e& S# w& C/ C
看来简单的把require理解为替换,在这里行不通。

( X3 r1 z, w5 p' W$ Q6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。- i; ?* m- S- r: S, \1 i
  1. //name.php, x/ Q0 R: E; @0 c
  2. 7 b1 r" G, h9 {0 P- r# z2 B
  3. namespace test\person;
    / G! |. c- |/ v6 ]4 M
  4. 0 h! J. u. Y3 F3 I* t. E( Z
  5. class Person{9 b! h1 T/ @4 J' |# `  S8 a3 \
  6.     function __construct(){) u0 W7 T; l  ]: B
  7.             echo 'I am test!';/ J8 x/ j4 x* o* s; j
  8.         }; r$ Q# |* j/ ~' f
  9. }
    ; P- v3 U% F$ j# d: G1 D* H
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
. }& e& M& r8 V, l
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
+ u7 @/ [$ p: w; O
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    $ j4 \$ {* @. G% t4 y* ~
  2. - g/ J6 a# `/ l( [# P# A5 l+ A, X
  3. namespace test;4 V- L! m& e  S0 T2 h
  4. echo 'zhai14';6 q- E! P; ]# E3 d$ j
  5. namespace zhai;
    6 b7 Z$ ]; ]) \& v
  6. require './1.php';
复制代码
# F8 n( ^# d% J+ R
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

  e2 d% }  r' @( Xuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
2 B- o' X( C# i: G% a: ~
  1. //name.php
    ! K, z" ~3 q) Y# f: {* y

  2. * l9 K. R6 R8 A
  3. namespace animal\dog;- ]; ?1 k) R3 d5 G5 a0 |( K: a
  4. - h8 ^7 X; X0 m, [
  5. class Life{7 W0 |" B( E2 [+ n* Z
  6.     function __construct(){. O. R7 a8 `# |6 {- {
  7.             echo 'dog life!';
    " y' L  t( a! _3 e8 `
  8.         }5 L( y6 D- a; A/ K3 u  E  g0 Y
  9. }" k) H7 j' h& ?! I$ {4 e( ]

  10. 7 ~4 z$ P" G) `2 j
  11. namespace animal\cat;
    # C9 k) ^2 P. G  H; v

  12. ; }/ s  u+ Y+ n- p
  13. class Life{
    7 t2 p8 v( p6 g. f3 Y
  14.     function __construct(){
    9 ?& T* p- C3 v$ B
  15.             echo 'cat life!';
    " p! E: y  U5 g% z! J! k
  16.         }4 V! V" u+ X. G
  17. }
    - C' `1 E. @: }

  18. " o* D. A: B, F5 S
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    ( d8 m  U; Q! {# g6 |
  20. new \animal\dog\Life();  //A
    + X- f7 f9 p- ~
  21. * J8 \$ V- w) |! N4 S
  22. use animal\dog;  //a
    . X( g( T) J- f9 r7 J' x$ z" D
  23. new dog\Life();  //B
    + j5 v" V+ c9 F% X+ ]; p
  24. ) f: ^. d( c4 L* o
  25. use animal\dog as d;  //b
    4 V7 E7 _- ~. J: f0 }
  26. new d\Life();
复制代码

1 s# y0 x4 V4 B! u" N6 k% J
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
9 ^" ]/ ]& u2 Z& g3 r" @" J: C
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
* i! E6 U0 W7 u: e" J* a. r, P
相当于
  1. use animal\dog as dog;
复制代码
1 C6 D$ J% B2 x5 W0 r
2.namespace后面不建议加类名,但use后可以。
4 E) s/ j3 O  ?' C$ z; L' c
  1. //name.php1 x7 p  w, v7 F2 S% L/ }
  2. 5 s# F; w) a* L9 P* s9 u
  3. namespace animal\dog;. H( Y: ^9 e: ]" [6 E, T! M

  4. ; `. q: Y" ?8 {# q; \9 y9 a' X6 o
  5. class Life{3 X* h  N# S6 d
  6.     function __construct(){
    + l$ e, X7 Z! o
  7.             echo 'dog life!';
    / Q7 v8 O# z$ v7 b4 i- \
  8.         }! V$ _  [0 O5 E
  9. }
    % u# r- B1 E/ k) o+ O; n1 x
  10. $ ]; o$ ~$ ~4 _$ z8 Z4 `! p* [3 S8 \
  11. namespace animal\cat;
    1 ^% c3 \/ |2 R3 ~

  12. * W( n1 n8 P, d* o+ K9 _+ N
  13. class Life{
    , G9 w: A8 [' |' O0 n( O6 z; _* m" M
  14.     function __construct(){
    " S, s7 u" V: i* \' V% T9 D- X6 n
  15.             echo 'cat life!';
    * o: u4 d+ f/ T) }/ |# k+ Z: I* d
  16.         }
    ; ~: n$ s+ v! u0 ~% t0 D% ~& C
  17. }' A% k0 l, V! H; t5 s& G: g3 X
  18. ! n+ D+ S0 d. r
  19. use animal\dog\Life as dog;  - O  F* a$ [9 D* s1 `1 R5 _
  20. new dog();
复制代码
  ^! t0 n- v/ f9 A# n
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
. m, O: j( _( r3 e' X6 J
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    ; }! |( S2 ~5 V! E- F- o

  2. : Z- }3 g) t# k. z
  3. namespace animal\dog;2 b  F8 ^1 ^# U+ t

  4. & K. d0 z) @* C8 R
  5. class Life{6 P* g) {! Y6 d* l" [
  6.     function __construct(){% d2 q+ ~9 Q+ |. ]
  7.             echo 'dog life!';+ u2 s. R  x: \3 D9 j/ \: M
  8.         }
    9 }5 B( h; @. r- g9 K; D
  9. }7 ?- C' T: r5 J  M  d$ W" N+ O& v
  10. class Dog{
    ' B* g. F4 I3 f5 _8 n8 N
  11.     function __construct(){3 b, V. {; D  b/ P' H
  12.             echo 'dog in dog!';
    3 ?# k: _* G- f- e
  13.         }
    ' Y( Q3 l% U$ O6 e9 F) `* f
  14. }: r) v6 O6 @" `) [

  15. : I4 p! [0 D* l9 z% x: |& ~
  16. namespace animal\cat;
    + U- h8 B! ~1 c6 J
  17. ' X0 K! c" Z; A% f. O: o8 g
  18. // class Dog{: P1 F0 g0 ?  C' ~- d( h% r6 r
  19. //     function __construct(){0 f$ _* Z! V0 g: h
  20. //             echo 'dog in cat!';2 l, Z1 s/ M  ~% ~6 I
  21. //         }
    0 k; b' B- U. Y" ]
  22. // }4 m5 ], |5 ], P6 C, W, |
  23. class Life{$ [% }$ t. L. w' L1 C" J1 K4 Z
  24.     function __construct(){
    9 A/ H- |, r$ A3 [  u
  25.             echo 'cat life!';
    6 z' u, B9 n, l, ^$ r. D- e
  26.         }( Q) f" @9 @& S
  27. }
    1 W" y( c% L. ^& i
  28. 7 s1 Q5 [0 T# [) s* Q7 ^: `! f
  29. use animal\dog;  
    4 J; n2 o. c, u4 @
  30. new dog\Dog();
复制代码

; |$ M) f. |2 {$ g( _5 K4 T
如上,使用了
  1. use animal\dog;
复制代码

  W2 l* x5 t% @: L: V7 }
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

2 G! K# ]2 c! s& p
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

; ]( d1 @$ I1 _6 p: e4 l4 ^7 K. d1 g( x  q. j- w4 k4 d0 n, q

4 a0 T4 F3 n+ x& X! P
; E0 q4 F: {# ^* F  `
* }5 n% {! J+ P2 x* j6 g
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-9-29 07:36 , Processed in 0.117832 second(s), 20 queries .

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