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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 6734|回复: 0

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

[复制链接]
发表于 2020-7-1 23:37:46 | 显示全部楼层 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。

$ j3 p7 S  D! G. h7 [
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

3 \7 s* A. {! P4 C
3 G5 e9 @* S) E. Q使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

5 T5 Y  ^! p, ^! [
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
3 I+ S% J% g0 I+ s! d1 s1 e/ y
结合使用方法来进一步理解它的使用目的吧。
- Q- E) d4 N$ r: e+ e
+ F& i) ^! Q# |
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    2 D% c- A* |1 w: S7 L% j: a7 ?
  2. namespace One;6 m& ~( L$ V2 |& I& u: [% B
  3. namespace ONE;
复制代码

, _' ^( N% x8 ]
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
- J3 ^, f" G( N
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    6 B6 F% V$ `$ x
  2. class Person{
    3 _; R/ T; u; [# c" Z
  3.     function __construct(){
    1 U% m* H  J0 T8 C% e
  4.             echo 'I am one!';
    2 c# k2 G0 m: d/ W5 I; B# {4 c3 D5 _
  5.         }
    ! N6 A- W1 L% h
  6. }
复制代码
  1. //name.php6 T* |" R$ m* N8 \9 k
  2. require_once './1.php';
    ) c' f& u0 g- e% J$ N
  3. 3 a# }. p7 n7 _( V7 J
  4. new Person();     //输出 I am one!;; n$ |" n3 w8 h
  5. new \Person(); //输出 I am one!;
复制代码
. ?3 B2 U6 [. L% ^
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php' @9 V0 A* Z0 v& c  W
  2. require_once './1.php';
    ' [- G0 m! P3 Y0 x! c( J% L
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

4 L8 i5 ?# j5 q" C4 \' T  [$ j  @4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   * G3 K8 ^. N3 G" l# G# T
  2. namespace one;" \( b! _# a2 r. u
  3. class Person{
    8 d) t2 G/ q5 d' G
  4.     function __construct(){0 F$ n" @% i. G6 Y! u/ C
  5.             echo 'I am one!';
    + T" A  [0 u6 X. _% U
  6.         }
    ' u1 X# E8 f' J2 }1 f+ x5 v! O  M
  7. }
复制代码
  1. //name.php
    ( J  H" t3 K; L, m/ h2 y4 |
  2. require_once './1.php';
    " ]0 `; M" A- H4 x: Q4 p4 T0 g
  3. new \one\Person(); //输出 I am one!;/ D1 w" R8 k1 ?3 l( W
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

3 c) l' {! v; t( Z# @+ F; L
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

+ \7 b# c) h8 K3 O6 k5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
7 d" W$ v, }6 a2 [
  1. //1.php   7 k" O4 @: _: E4 ~2 U9 _" x6 a
  2. namespace one;
    & n: o/ b5 x! V) X! R8 e) c  R  q
  3. class Person{
    2 Z1 A* r1 J% g+ c- S
  4.     function __construct(){; B) }' W  M( l
  5.             echo 'I am one!';
    % g. h* {7 g; E! L& ~0 u. a
  6.         }3 [1 a+ s% w: n# {: m
  7. }
复制代码
  1. //name.php- Z, \2 `9 n; h
  2. namespace test;4 n0 p! A! T0 S5 S+ r/ I
  3. require './1.php';
    + T* O  o+ g. c7 |( a; E
  4. new \one\Person(); //输出 I am one!;! Q+ R5 q' _8 f" ^8 t
  5. new Person();      //这里结果会是什么呢,猜猜看! K/ y+ @' _( s4 C  e# e* F
  6. 最后一行结果报错:" E% x5 v  V3 q
  7. Fatal error:  Class 'test\Person' not found
复制代码

- c) P: u1 ?/ C, C, V6 X# \4 n( C

$ H5 F2 Z1 H, y; S% W首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
. w- J. T( ^7 O+ i5 P& \
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

  q* D  r9 p" L% k7 g5 n
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php2 E) d# c/ ^0 Z+ R
  2. namespace test;0 h6 ~; J" `  |# o; a8 i
  3. require './1.php';
    2 d3 \% g# @  i$ Y

  4. & |/ K+ k6 I( z5 {3 M" a: @
  5. class Person{
    : E0 l, ~: R! |8 ^! i, V/ t5 I' ~
  6.     function __construct(){
    # i: h* w, [+ d' n+ N
  7.             echo 'I am test!';
    * h" z4 x6 C' `( @3 c
  8.         }
    : ]8 S% a% F* F; @7 o4 Z" f
  9. }  J  P+ ]$ P, l( g
  10. 6 Q. z7 x% O$ ?$ Y. c2 ^, M
  11. new \one\Person(); //输出 I am one!;
    0 I1 H4 j0 h, h, `! Y
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
5 D) n6 D7 [/ [- A% N- C
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php; V% e, o3 h/ k! ]' a4 c, H
  2. namespace test;
    - M8 H0 X  }/ W/ @, d
  3. namespace one;
    3 I! B& {. j8 x$ O$ L
  4. class Person{
    ; [6 [% R1 ?: B, F3 K* w8 M5 A
  5.     function __construct(){+ B/ d1 }: u- b2 e% e, L7 F! L2 S2 ~
  6.             echo 'I am one!';
    , X& _. C% a3 |/ e6 E
  7.         }
    : p; m. r* X2 h/ D8 d
  8. }
    ' g# H5 O& g* V) O  U

  9. ) m/ a. X+ T5 s( |  W3 s% ^
  10. class Person{
    2 D) u5 l8 _1 D
  11.     function __construct(){" Z7 T+ s8 D% _6 X
  12.             echo 'I am test!';
    % P0 X9 n8 ^! C
  13.         }
    0 {/ g  r: t& W# J2 |/ m
  14. }
复制代码
% B) ?5 y7 H# `6 m0 J6 ?! a
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
1 f" {4 y1 |  J) R& Y, i8 C
看来简单的把require理解为替换,在这里行不通。

& ]! D% o6 i! {. D5 U6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。7 H5 @$ ]" v- u9 w+ B
  1. //name.php) k' X  K+ P$ ?; u3 r& u0 [
  2. - w$ w( i2 D% s5 }; L
  3. namespace test\person;
    6 F- q3 I+ S0 p
  4. # x; j) X+ j. ^, l6 T- g
  5. class Person{
      x. a8 S. I" M9 K" `' ~9 f* U) Z
  6.     function __construct(){6 D2 E# {: T! y+ ?
  7.             echo 'I am test!';* u4 K6 r7 ^8 [/ O
  8.         }
    2 H) T/ S! j! p
  9. }# j6 q/ j+ _/ B! x7 a" ]
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
" w* i' K, z# B. P7 x
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

/ X. d( u% Q/ }7 Y3 i7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php4 w2 e+ ]6 e" w1 ]0 h. `
  2. " U8 g* M% L/ I& K! J7 E. Q) Q
  3. namespace test;
    * k8 S. L0 V- a8 t6 W2 M
  4. echo 'zhai14';; |! l* a  A( j- N- h+ r- K7 c
  5. namespace zhai;" I/ O! {3 n+ c0 l
  6. require './1.php';
复制代码
. R# r, w9 q& v8 _$ [9 w- i" k
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

0 X/ L* u) n# o7 U4 tuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
2 y$ \" @! ^" E* P. b
  1. //name.php4 x4 Q; G  u. R! k+ E. t

  2. 9 G' U9 G! Q( ^  l. ]) S- ?
  3. namespace animal\dog;
    . \% |% a, ^: O. n

  4. : ~% a$ L) x9 S: G4 r
  5. class Life{( q6 r  d& q" H  C5 f/ M5 n% v7 I* c2 j
  6.     function __construct(){
    " a; w4 ?' S7 }* S, C: B' j
  7.             echo 'dog life!';3 ^# I; D( `) j/ D9 y: S
  8.         }
    " \$ n- n8 u9 X, Z" y0 M( S
  9. }8 O$ f! ^0 W" L0 G0 O6 r1 P0 W
  10. 1 V! o) O) R- ?. d6 k' D! ?5 |: b
  11. namespace animal\cat;- u1 g) G6 {  s2 p
  12. 4 O& `; p% ~* j# @: s
  13. class Life{
    7 ~1 s$ a2 I, W5 b
  14.     function __construct(){
    $ J* S3 n1 z6 B
  15.             echo 'cat life!';1 k8 F# l9 |1 R, d+ F; P
  16.         }+ U- q* v/ A3 W9 R$ P6 z
  17. }# Q# h4 a9 }' s" p

  18.   x( g, L; y& k) H* t, n8 ^/ t
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间8 `: V( `% _1 T  [4 N" F) s( P
  20. new \animal\dog\Life();  //A* K7 F* B: X% M  s

  21. 2 y; M, e3 K, D2 I
  22. use animal\dog;  //a/ C& u0 M1 R# |0 r+ Y+ K% x4 m5 @/ x
  23. new dog\Life();  //B* z. ^4 m% P2 r! s7 Q4 |

  24. , ^. X! _! n- t; f, i! Z5 j% O( v
  25. use animal\dog as d;  //b0 @6 p% k% x6 ~: k; S2 Y( }
  26. new d\Life();
复制代码
5 |6 M- g1 y5 Z! g) \+ t
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

0 j0 p' o/ `+ Y% m7 K' C
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
) b, f+ g, y+ A- g0 k9 g; \: F
相当于
  1. use animal\dog as dog;
复制代码

1 c2 x  c. F5 z- r* W+ e7 O2.namespace后面不建议加类名,但use后可以。# r8 H" ]- B( [9 y( h6 Q$ V
  1. //name.php9 W9 r  `! Q( j
  2. 9 W" _! V5 I  p' X1 O* A
  3. namespace animal\dog;) b+ A& [$ T* r
  4. + L5 K) ^. T- h9 F; Z& r; w
  5. class Life{
    0 U# ?( x/ Y5 W. z+ _9 ^9 |
  6.     function __construct(){
    $ Y1 `7 A8 R2 q- e1 T! ^
  7.             echo 'dog life!';! u8 `& `/ z5 p" S1 P7 y9 `
  8.         }) b0 R: c3 l- h% X
  9. }6 h9 L  O+ }$ B

  10. 3 t7 B0 m  o2 W( K2 m2 T( L  c7 B
  11. namespace animal\cat;
    5 K, Q, v  I0 o
  12. + X1 i" L& B% A- b5 |& U
  13. class Life{
    6 o- ~9 r! ?4 B/ B, l) }: }
  14.     function __construct(){
    $ \; T& I0 x$ J2 [: ~
  15.             echo 'cat life!';
    1 b, b; ^" z% k" U( d: ?% f
  16.         }1 r0 ~0 w! H1 ^( z9 U( p" W
  17. }
    6 N, w" ^; L, |$ l, S. y% Y: h

  18. + i& {8 w% X2 }, Z7 g$ C
  19. use animal\dog\Life as dog;  + ~. A) r! @5 `
  20. new dog();
复制代码

2 m5 Z, t! x* Y, D7 k9 R
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

' n" A( p! P6 i! D# l$ {" B, T! [
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php4 r# n- O, S  B# ]) ]
  2. 7 c$ P& v1 O3 x  a$ [4 U: p1 n
  3. namespace animal\dog;( {  x+ f( z/ \' X1 R$ j( `

  4. 9 W9 Q7 k- N3 |# J$ f, ^' T
  5. class Life{
    - l9 C) _) ]! T( j7 S: F: l
  6.     function __construct(){; E' A5 T, O& p9 U8 M# L
  7.             echo 'dog life!';" Z. f; Q6 b7 J7 Y1 S" v: N
  8.         }
    , y* t8 J& h- b! v9 v
  9. }) B& x  }1 J0 G; x
  10. class Dog{
    " O3 P% G# k: ]+ r
  11.     function __construct(){9 D# I0 p$ [% {6 J3 I5 T% m6 x6 y7 ?
  12.             echo 'dog in dog!';+ _+ o) H! L* U5 N2 K  Q
  13.         }
      e4 C+ M, a6 l
  14. }
    + u( \! M; x# x6 Z6 \( L

  15. 7 h, x/ \8 ~4 P0 H# I5 I2 ^
  16. namespace animal\cat;
    3 w" m, {( j0 b7 u6 a& U
  17. + Y5 Z4 I# }3 X6 c4 ?/ @
  18. // class Dog{
    " x5 v1 g% Q9 j, l9 a! g+ |
  19. //     function __construct(){
    / s8 F2 x7 |! @( L" e
  20. //             echo 'dog in cat!';
    * J9 X% z2 Y( R/ G
  21. //         }" x2 ~2 `7 Z  C6 X; R+ r
  22. // }
    7 Z0 `; e! U( H, p( l5 t! L
  23. class Life{% \9 t/ e5 F1 ^9 f8 p, `
  24.     function __construct(){
    2 G. ^+ v1 c1 E$ T6 t2 y
  25.             echo 'cat life!';9 Y' j3 y$ N( X
  26.         }+ u/ P+ {" J7 ?) w" N
  27. }
    & q* ?" n1 J- B+ E' s

  28. , p+ O; ]" ?! a) I3 M
  29. use animal\dog;  
    6 w8 x% u3 m" x
  30. new dog\Dog();
复制代码

/ A% d5 Y, _0 Q8 Q* d5 y
如上,使用了
  1. use animal\dog;
复制代码

, q7 a/ H1 u1 Q7 F2 a
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
0 H9 @4 M$ t8 t
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

7 t3 a- n5 W6 T  O0 C8 K8 R9 s4 B( x' x3 P
3 {$ q% T8 e. f1 Z+ k( b

1 @% y* d/ N* z% Z
  p! v6 D' z9 j3 M0 I  [% I
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2023-6-10 05:07 , Processed in 0.136521 second(s), 20 queries .

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