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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

PHP命令空间namespace及use的用法实践总结

发布者: admin | 发布时间: 2020-7-1 23:37| 查看数: 10139| 评论数: 0|帖子模式

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
$ C) J/ G* ?( e! s$ g
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

* r. k  k+ u" h5 O6 G' w3 y
* G+ A9 E/ b8 b& P5 ]; S$ m使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

% }9 }$ Q$ E: E" p
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

7 b9 ?8 o7 L' e  ]! f8 f4 k/ M6 Z9 S结合使用方法来进一步理解它的使用目的吧。
  H: v; ]: \# d( t% P4 @

$ Y: ^: W. E+ z4 u& o/ xnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    - q. C* g( L: E
  2. namespace One;
    1 V" F5 j" p: A" b+ F: z& i
  3. namespace ONE;
复制代码
  `7 h6 q8 p4 n3 \5 `
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
! V) N5 h' v3 U; {& P
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    & G' j0 z  t. C, B2 \* l8 V$ j! `
  2. class Person{
    ; Q( [2 K0 G( G# ?0 o
  3.     function __construct(){
    2 H: q9 z/ s6 H8 a1 R/ P: `
  4.             echo 'I am one!';
    $ B' A( q$ v3 [7 F* b
  5.         }
    6 Z" K# j9 A' w$ ]: z
  6. }
复制代码
  1. //name.php+ |1 Q% g  d, O) |, A
  2. require_once './1.php';
    3 s& z9 f' S0 a+ \, Y* H# }( {5 g4 r

  3. " R1 Q4 R8 v/ F) Y. H) |7 @
  4. new Person();     //输出 I am one!;
    8 `& E+ n6 q7 `# X9 V0 i0 |/ _
  5. new \Person(); //输出 I am one!;
复制代码
7 i  n; x, U- R6 x7 S
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php6 P9 z, h$ ^- G8 m2 _
  2. require_once './1.php';
    : X6 M3 e3 E( H
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

: d& o$ h, `0 m4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   5 A$ j7 E9 v& l! i2 O
  2. namespace one;& {- W  y5 e# c9 M: _2 r6 l
  3. class Person{" E3 `/ q- z! c8 l, j
  4.     function __construct(){1 C9 r" |* g: M5 g, c
  5.             echo 'I am one!';
    1 Q6 G/ f1 G6 T* p2 T& r" d
  6.         }
    ! M/ b) ^4 _5 a5 x# M( E3 x9 G
  7. }
复制代码
  1. //name.php: F* s. ^2 l! r
  2. require_once './1.php';- s) q: p; I  `! u
  3. new \one\Person(); //输出 I am one!;3 X" v: G% m, ?/ K$ f
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
) P9 o) _* W  O) l& l
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
+ d5 B& r9 j0 ^0 f9 U# g0 `! X
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
7 J! i4 ]% O. ]: w4 z- I' x
  1. //1.php   0 o+ u) n8 h2 j, \7 X$ I$ \6 Z
  2. namespace one;
    5 U& b: a$ Q  }; s; X
  3. class Person{
    0 ~# h# V# i$ p1 f% _' R
  4.     function __construct(){, }0 d- E' i7 Y" Z0 u8 ]
  5.             echo 'I am one!';3 U7 W* k- K" r) `9 a9 x+ ~6 ?
  6.         }7 |3 W3 i  x+ n
  7. }
复制代码
  1. //name.php) R- m! z, p2 J( g1 E7 L3 c
  2. namespace test;
    1 q7 D/ o' }' q2 k1 v1 }9 s
  3. require './1.php';
    ! j' C" N# E+ G0 p
  4. new \one\Person(); //输出 I am one!;
    , I; I1 A! R) C% \0 x
  5. new Person();      //这里结果会是什么呢,猜猜看
    % m! t/ ~6 }+ \5 _8 ~+ _, ~
  6. 最后一行结果报错:
    , ^8 N( J+ {  \" G# }" X
  7. Fatal error:  Class 'test\Person' not found
复制代码

2 z  o- {  a- Q+ B* C) Y" ~. R% p0 x
2 _- Z3 Y+ t0 {% I) @
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

5 U' D% h/ R6 G1 e6 l. j
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

; V' s& h+ p* K# ^3 d$ a) m
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    ! |9 o, M8 I* j* l9 S; X4 }+ ]
  2. namespace test;
    7 D$ U4 e* ^3 J- _
  3. require './1.php';
    + X2 N" V* f1 V9 n- N# a

  4. % P# Q/ F  p  I$ O
  5. class Person{
    6 G* E6 L* U8 a4 t+ W& Z
  6.     function __construct(){; k# a8 z0 ^: o- e  h
  7.             echo 'I am test!';5 @( q0 e& [; N# _9 k1 J
  8.         }
    / `3 ]& s! O/ P  @
  9. }3 G" n! t% F& ]" M0 M
  10. 7 |5 ?  S1 J, t8 U: o% i
  11. new \one\Person(); //输出 I am one!;" P, `* Z, j% p0 }0 f
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

0 D7 ~2 a) \5 d. w' d& u
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php& c' `/ v' p8 m7 q6 ~
  2. namespace test;
    . p7 |( r% v' W; p; C4 c
  3. namespace one;
    ; y# J' g0 Z2 j6 x$ y+ c
  4. class Person{. f2 X/ R# V  |0 t% z
  5.     function __construct(){
    5 @1 x/ [5 d  L0 B$ e
  6.             echo 'I am one!';/ T' g" N7 w# f' V6 m
  7.         }
    * e5 e! J) {9 S# v
  8. }# c+ D- q: Z, j) G1 y( |% Y

  9. - I' f' `7 f' D$ q1 ?
  10. class Person{; D/ Q) v1 G/ k* j4 a; v7 p( |
  11.     function __construct(){
    - N% P7 I/ F! C" I8 h
  12.             echo 'I am test!';" t9 K0 H% x4 _( G9 X8 m: p* z
  13.         }, D3 X( i5 r1 l
  14. }
复制代码
5 F. l: E' l) e+ i5 S0 @& j) B) h
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
- b8 T( P; y( [7 e7 M' o8 h
看来简单的把require理解为替换,在这里行不通。
% e3 N- p( z+ D% t) i
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
$ a6 D' s# |+ e$ O9 y
  1. //name.php0 W# |! _: }3 l7 j

  2. 6 E: Z: `2 g8 H6 _& _# c# u7 s
  3. namespace test\person;
    + m% [6 _! j) F' _3 h. C% A. G

  4. 4 ^. V6 l2 j. J
  5. class Person{
    ' \# v  t& Z' g; E( y! v
  6.     function __construct(){
    / K$ T. C1 [$ D
  7.             echo 'I am test!';
    3 ^; q  k: d: f6 {  ?
  8.         }
    - C$ E8 q0 d- \. V! m9 T, N2 F) A
  9. }
    0 v% G# W# F/ T, O% ?
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

2 H: V- u" w$ y# \$ I
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
0 n% G0 T: B* ~
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php; ]) r4 `0 Q/ Z; R& H+ X
  2. 8 }" Y7 F7 g0 \
  3. namespace test;. X! p: x' A$ E5 ?1 E0 K
  4. echo 'zhai14';- [5 n1 Y! B' M9 n, Y7 {0 x! \
  5. namespace zhai;3 E7 w+ n# G2 k2 n4 ?$ T
  6. require './1.php';
复制代码

8 e( K# I9 U8 |0 ~
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

$ k1 y/ y' d; d4 v( u$ T1 m' kuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
; J0 v7 t, j* e, I3 \, z
  1. //name.php( Y5 M# \* j- k, w7 e2 O

  2. & Q, F( i9 P0 u7 T  d
  3. namespace animal\dog;8 q5 s* p, h! K$ |
  4. & F. L5 x2 P9 d! v& Q  f
  5. class Life{
    & p% |( [1 v% _3 W+ A8 x% F
  6.     function __construct(){
    0 V  N0 p* [# e; T# A& J$ t
  7.             echo 'dog life!';
    $ v+ ~  B. c& Q- p) B
  8.         }; y+ n0 a$ P; F# }. U' F1 a
  9. }
    5 ]2 o  ~! ~$ }" h9 Q

  10. : [; j6 A1 _6 u4 b9 W6 M- I$ g
  11. namespace animal\cat;
    ) c5 n& e/ f, a+ t# r5 G

  12. 7 ?7 D8 e- @/ U2 K0 I" @
  13. class Life{
    ( D8 H5 g2 _/ @( @& I  g$ S
  14.     function __construct(){
    + F) I+ x( s" A5 j
  15.             echo 'cat life!';5 z8 T7 c8 F8 o, `
  16.         }* v! `3 L$ I4 D* w' J* y
  17. }
    % ]6 U( j& o5 A# N, y7 d8 o3 \7 |

  18. : \8 ?3 F" f6 F  y: O2 P7 _+ {
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间4 L" l$ f  T' @4 N5 T0 _% f
  20. new \animal\dog\Life();  //A
    8 F0 m# W3 @, {
  21. - m* {* Q7 a, k( N5 p' Z- `  ?
  22. use animal\dog;  //a1 W2 ~( u2 ~: J" R. C
  23. new dog\Life();  //B0 N& S/ X' [; F* A& X

  24. 9 t7 }9 G; d9 s5 W
  25. use animal\dog as d;  //b" u2 Z5 K9 q8 h% u3 O5 V9 [% F& M
  26. new d\Life();
复制代码

5 t; S% T& k% p; I
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

& O6 m: ]% H& p9 X+ Z
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

- D- x* M2 z8 B: [, g* Q
相当于
  1. use animal\dog as dog;
复制代码
4 V% Q- t. ~, |0 l) ~- E
2.namespace后面不建议加类名,但use后可以。3 `. k9 V+ M) h2 E
  1. //name.php
    # p( B2 R- ]* O3 _0 |

  2. 0 |8 b, M8 n  f( ]7 m" `* H
  3. namespace animal\dog;
    % {7 S4 D! U: I+ p

  4. ' Q# ]4 |+ _" c/ i. U6 E* C  a
  5. class Life{
    ( S1 s1 v8 @- L) ^4 v: x8 e2 V
  6.     function __construct(){; p( |" ]2 i- [5 E& R, z! |9 d3 E
  7.             echo 'dog life!';7 B! R0 W$ e, r" E) S
  8.         }
    % p3 i2 e  n8 r! L! ?" J, f  V
  9. }
    ' Z0 v( n, i2 k; a% C* A- U

  10.   l& e3 d( {- u& ^. Z; x
  11. namespace animal\cat;
      w) y7 @0 z6 \- _& G
  12. % f& t* H) n- P- a$ ]
  13. class Life{( @! @. f1 g7 {) f& W' @- p4 u
  14.     function __construct(){
    6 Z/ n- y( x& Q! H. D8 P+ q
  15.             echo 'cat life!';
    7 [/ {$ `! r5 s7 n
  16.         }1 {2 @5 Q% _- c
  17. }- Y" d7 l( s5 \$ A! t( Y0 I' X) g5 X
  18. ' ^; }( h, E8 J! u$ Q. ~: ?
  19. use animal\dog\Life as dog;  ) b% E0 U% R  C4 z8 p  B5 {6 y
  20. new dog();
复制代码

% N; Q% q8 |, }; p9 A8 W2 T6 b
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

! _- U; O: t7 b  U
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    3 w$ c0 k. R0 r/ ~2 H8 u
  2. , |. \# W* p! s7 A5 u% a. H8 s
  3. namespace animal\dog;2 o/ v( h& A" a6 d0 L4 {6 ]2 b
  4. 5 [& b% `8 J( U) J: e+ t9 `
  5. class Life{1 K, E$ C# Z  E% o* w
  6.     function __construct(){
    , w6 ~  }/ }- K8 f
  7.             echo 'dog life!';) H* S3 z& |; S( s/ @
  8.         }; G; I9 a4 |; n7 w8 Q
  9. }
    : E( \7 K6 W2 V$ O6 L1 u; b8 C
  10. class Dog{% _. E# e1 T! @4 E+ Q
  11.     function __construct(){
    # @8 u5 I# g' R  Z8 H# U
  12.             echo 'dog in dog!';, h) y$ O& Q9 F( ]; N" I$ t3 G  y
  13.         }
    9 o6 c6 z' Q+ t. f
  14. }5 a! p( h0 A/ l+ e
  15. . y9 V' C# k0 v  J$ M. ]" C
  16. namespace animal\cat;% z8 L7 ]- P! t5 k# f& Y- i
  17. 4 v: w) ]. S; N  a/ @* K  d
  18. // class Dog{. Q0 G+ F1 X9 ^5 S* f0 }% C( Z# B
  19. //     function __construct(){
    8 h2 K4 O7 |" }8 ?! n& ?2 ?
  20. //             echo 'dog in cat!';) v- t- Y- U( q0 P! u6 e
  21. //         }
    ' Z4 d2 t2 ?! r: a9 k1 w
  22. // }) |4 x! Z# s- v1 P) t, m. k( z
  23. class Life{
    & O& W/ P- ~1 U) g" j0 y8 ^
  24.     function __construct(){3 Y" A# _3 h2 }* |; b5 W7 y' i
  25.             echo 'cat life!';2 P4 O2 {& r9 S" g$ _& I
  26.         }# R' n  W! m' ?# `7 W
  27. }' H" p% P) x6 h

  28. ; p/ E1 P5 g4 A* M: [& N2 h
  29. use animal\dog;  
    7 H' x2 W% k- [+ d' T5 n, C
  30. new dog\Dog();
复制代码
+ O8 A* [1 Q! t. b/ a9 E
如上,使用了
  1. use animal\dog;
复制代码

  K8 a3 u* F: Y
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
7 t1 }2 E6 q% _
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
" H4 h* p1 A3 L

7 ]' `: s+ H" h
# L; U' ?# a8 T( E" \$ d; ?( u- ^( g8 q& j# F
6 y. \" V5 M( N2 V

最新评论

GMT+8, 2024-7-18 01:13 , Processed in 0.158627 second(s), 22 queries .

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