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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
; Z& U7 \( p& g& x- k
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
3 v3 f" ?9 u5 y, J

) @- u( O5 s4 I2 y0 N* p3 O使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
. o! ?/ |0 t7 Q
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

& V/ ^' F, Q1 q# f: F结合使用方法来进一步理解它的使用目的吧。
4 H3 O0 g5 Y- T8 `% Z

8 Q$ w; M1 f; C' P' x+ Z, m+ knamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    3 S/ V2 g( y/ r* y7 Y# e
  2. namespace One;
    " w( B) \/ _8 L3 k( ~
  3. namespace ONE;
复制代码
/ J& ]; V, s2 B1 D- r
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

: d) q1 j% Z% Z/ U  L; \2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   6 P" ^+ O/ A# |" E* W" H
  2. class Person{1 K1 i% u! E8 |  C2 {/ ?9 a& q
  3.     function __construct(){' Y3 d  P. ~1 e+ s8 z) h7 l* Z
  4.             echo 'I am one!';1 z0 ^/ b( g* Y* n
  5.         }( ~; {. M  h8 V: f! b5 n
  6. }
复制代码
  1. //name.php
    " v; J1 l" H' m6 {% `  b' U
  2. require_once './1.php';
    " |; r  \& q; [" A1 w

  3. " ~7 u$ r( B3 Y* R! X2 q
  4. new Person();     //输出 I am one!;
    " _; l; t5 V* }8 _5 T
  5. new \Person(); //输出 I am one!;
复制代码
+ b$ l* A9 T) k: B1 H) _
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    ' T2 p- ~0 z' V- D" n
  2. require_once './1.php';$ @! K7 n8 n) K* q) Z
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
: b) u; v- y, M+ s9 z1 F
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    0 B( E' E7 n6 v* r- J5 @, e; L
  2. namespace one;
    : Z; V0 K2 W: Q, j/ h
  3. class Person{6 k2 k' M# j( c9 S8 a! |# k0 B; m
  4.     function __construct(){- _: P6 {8 U% m0 K  F7 O9 Q4 K& p
  5.             echo 'I am one!';9 W" {0 @: A) f: Q# v4 J' k& [6 Z
  6.         }9 E  R6 M" f6 w1 j; G! i, z, [
  7. }
复制代码
  1. //name.php5 x' @' Q  {9 R% m" A* _4 z0 Q! W
  2. require_once './1.php';
    1 Z9 a8 P& g- t$ O0 S0 H
  3. new \one\Person(); //输出 I am one!;0 M8 X+ k! c8 O3 q
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
; ^9 k% U) Y: l5 K2 g2 l
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
, e; L% a' x) S8 W0 j2 W' [6 G* [' V
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。, @1 I) K% T/ m- s- K6 l- H
  1. //1.php   
    % x" o. P4 e8 k* a
  2. namespace one;& v* B) L/ ?. D' p0 C
  3. class Person{
    . M+ l/ B, Z: {0 \- M. `! t% c, e
  4.     function __construct(){
    * p$ K& g- E  i+ C: D
  5.             echo 'I am one!';# w* g( @- @4 \1 l% B
  6.         }
    : K  }1 a0 n: ]: l) I
  7. }
复制代码
  1. //name.php1 |& N/ S; s4 |5 a$ B! _0 L2 }
  2. namespace test;
    9 }: X: i2 i) G/ s9 V9 s& L
  3. require './1.php';
    ; [1 Q6 g- ^; _( M8 {
  4. new \one\Person(); //输出 I am one!;4 i4 }( n8 [6 b8 A1 p; \; u+ U0 G
  5. new Person();      //这里结果会是什么呢,猜猜看- }: ~) t( s- |0 p0 ^) Z
  6. 最后一行结果报错:6 d3 a  k3 s# i
  7. Fatal error:  Class 'test\Person' not found
复制代码

# G6 T* m1 Z/ c
" V5 K! z2 d  K8 K4 M# x: ?& s
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

" F9 {6 I& f3 C3 P- R% l$ |
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
" u. P, B# L- Z1 w" L
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php, K& G5 u; c5 _! P/ E
  2. namespace test;/ l7 w: X3 F( K
  3. require './1.php'; 5 ^# E% ]  O4 Y$ w( _9 v
  4. $ n  K, o3 c0 I& u
  5. class Person{" O0 h. ~8 Z8 m$ Z
  6.     function __construct(){# F( t8 o# M, S' z
  7.             echo 'I am test!';' r4 Z% e' D: I  g( l$ Q9 f/ Q
  8.         }+ u: q) B6 Z5 e, v+ x' ^: Y
  9. }+ Y& V. R/ b7 U9 k

  10. 2 B3 m  J; c7 v/ Q% [7 o+ B0 c
  11. new \one\Person(); //输出 I am one!;
    ' n6 Q; m! o7 ]8 f
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

1 x1 o6 m. |6 m, ~- e7 C
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php4 b) N, d, R8 Q; s3 [/ |
  2. namespace test;
    # \* f  d7 _) x
  3. namespace one;
    . h: R" I& D8 S) t1 f6 ]
  4. class Person{
    1 t4 [+ s- x  i/ K6 R- G
  5.     function __construct(){1 J; W9 K9 ]* q! U, g- |
  6.             echo 'I am one!';
    1 e% J9 N$ a. ^8 u& J9 |1 x
  7.         }
    & C( K. f* b  ~4 M  X2 M6 ]
  8. }
    & C0 U9 v- Y; S

  9. 6 ?  d5 m, {- C. \
  10. class Person{
    8 R6 t" _$ q5 V& \( b3 @& u$ E
  11.     function __construct(){# x3 v  j0 V1 D: b1 c. _0 y
  12.             echo 'I am test!';
    ) L! t! ?7 [3 u7 w" i
  13.         }
    & W$ x! o# O4 U' x; S2 z
  14. }
复制代码

* z' a# o- F' T! K7 a+ N4 ]" o1 U
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
4 ~6 V4 e; s# |7 k( V! d
看来简单的把require理解为替换,在这里行不通。
6 [( `! ^$ E: L4 A; d  A5 V  n5 \
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
( M  `$ ^' q8 R5 @  Y& t5 I
  1. //name.php
    3 b+ V" s! L4 C. _) @
  2. 0 \, v/ v$ f; L2 h8 `
  3. namespace test\person;
    * ?; I  P3 _! X; Q

  4. ; E. A$ E) y( l; ?* d/ O
  5. class Person{
    ) Y6 y1 M* F3 L
  6.     function __construct(){
    ' Y6 t! P) Z, g  `
  7.             echo 'I am test!';
    * A- p6 h; N+ @
  8.         }8 r: L& z+ S# P  R9 u/ y& ]" k
  9. }6 y* ?. k: o# z' I6 Y/ R2 }
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
) t. h! c! f/ M" O+ w
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
. h* ~4 [: M+ ~" X& z- G4 O
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php2 \) c* @6 H% S! b

  2. 8 j- Z* d7 s! ]
  3. namespace test;
    1 C- z  t  g& @/ g- N/ C- y6 W
  4. echo 'zhai14';* O  @' B- _8 @& h7 O6 O+ J
  5. namespace zhai;
    1 ~6 z: Y% q( e' ^
  6. require './1.php';
复制代码

- J8 y8 b& \5 j- D: z3 h
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

" \# S/ B+ @( ]; }+ H/ {/ juse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。7 ^- o0 L* F- r6 l
  1. //name.php3 [4 T4 Z$ @. F9 e/ z" U6 w# a
  2. . s0 l  S- n/ f" Q2 b
  3. namespace animal\dog;
      L. U" ^! o$ s; D
  4. , W0 l1 K8 R, u& }* z7 i& G& Q
  5. class Life{8 j8 j! y3 J8 Z7 H2 h' `1 ^( W
  6.     function __construct(){
    + @' c# X( V4 h; g
  7.             echo 'dog life!';# M8 y) V# p- c( y
  8.         }5 a2 o7 X8 d" o4 Q1 Y
  9. }
    # x1 T5 `1 i" h7 p* R% z( F

  10. % W$ T9 [3 o2 ]. G5 [
  11. namespace animal\cat;
    1 ^, X! F7 y- N! O6 g: l* S
  12. # ^4 W0 c" I8 H( U9 _3 n
  13. class Life{
    " }/ I" V9 A1 t/ v
  14.     function __construct(){
    2 q$ U8 n3 ^2 g: m9 ^" c3 Z4 ~
  15.             echo 'cat life!';# a8 T" z( }* S: R5 a2 L
  16.         }4 O% V, \& l! F' {
  17. }
    - C3 ~9 D# f1 J0 C3 [
  18. " n" i9 Y1 k2 @5 _. @! k
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    : J4 x% X, K# W. G5 t
  20. new \animal\dog\Life();  //A; \7 j$ g  p2 h- L' x- D
  21. " Z! O! H" `  @; k6 m
  22. use animal\dog;  //a2 ?. O- U0 o, h' R% x1 L
  23. new dog\Life();  //B
    * r0 }: [' L) l2 V) A1 I
  24. 4 x# @2 d& }& l0 r* ?+ X# S
  25. use animal\dog as d;  //b. E( L- Q* z* ?% w6 c& q
  26. new d\Life();
复制代码

+ ~7 l% f: W3 |! Y6 }
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

# G& G1 M) _! M  [
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

1 z3 F/ K+ N) p7 }, f; m4 T
相当于
  1. use animal\dog as dog;
复制代码
; v  I) X6 {5 j" s+ @
2.namespace后面不建议加类名,但use后可以。/ O# I: Q. N9 s' E! {+ x
  1. //name.php; _6 F+ a9 P5 K# ^2 b
  2. - i/ ~: W' ]& z2 l+ _9 _
  3. namespace animal\dog;
    5 V8 @% Q  F7 K, L' e

  4. 2 e- D9 R0 u  X/ q7 y
  5. class Life{3 a/ X9 N. h( x0 T
  6.     function __construct(){
    - B0 G7 O; D9 x  p, A& c& b/ [( h
  7.             echo 'dog life!';
    0 I; e5 v5 N( E2 @/ z
  8.         }+ ?/ U5 ]8 R/ N7 ?% _7 ]1 E$ @
  9. }
    0 T9 P5 A. l  s$ a
  10. & X1 m% [  r+ R; f
  11. namespace animal\cat;
    6 C- |$ Y( U7 E6 {

  12. / Q4 b5 V- P, u
  13. class Life{
    * i1 ~% P. E  L0 r
  14.     function __construct(){& b  v0 b  b5 I* i) G6 ]1 s! V
  15.             echo 'cat life!';% A: e: k" t  v! _5 E
  16.         }
    : z: K- A0 V" ?$ n
  17. }! W. _7 ^6 V: ^3 h9 r: V1 w
  18. ! d! k7 h* s! I1 A" X
  19. use animal\dog\Life as dog;  " I$ H- W2 ~& ~, R! B2 P
  20. new dog();
复制代码
; C, \: ?: b* u! E- \6 \
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

* i& ~7 h# P' X
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php7 X& y0 n# N. E8 h. N5 N' p
  2. 6 {( x! K4 U5 _4 H$ Z: i: Y- m
  3. namespace animal\dog;
    / {! C6 g! W0 b; j/ |6 F
  4. $ S, G1 z+ \. c1 X
  5. class Life{/ H5 p5 `1 c+ m1 S* v5 o) V. n
  6.     function __construct(){
    ( W  o6 e; B" \
  7.             echo 'dog life!';6 S+ F# Z, i6 i2 p1 a  }
  8.         }
    + [' ?% F4 H( M0 t' R- O
  9. }
    ! Q$ I) }* z* s/ A7 z& i+ |5 O$ a
  10. class Dog{
    ' D4 u" j* r' s8 s6 U8 d
  11.     function __construct(){
    3 O0 {7 ]5 }1 Z* C& _; k! A* p# s
  12.             echo 'dog in dog!';
    4 j# b3 o( J7 l! [' W
  13.         }
    " q3 }: D. b6 o5 S4 @6 N
  14. }3 D& x6 y3 R& z( q. `2 ~# x
  15. 6 l, V& U! }. F6 E0 A- F
  16. namespace animal\cat;2 p% g- T; V$ r! G' g  V( H
  17. " X& |7 d+ L6 c4 T" y% _
  18. // class Dog{
    / U) k! h; E1 E
  19. //     function __construct(){
    & C( E# V; a! U
  20. //             echo 'dog in cat!';
    3 S% z; \/ n0 i  k5 v
  21. //         }2 h, d8 X! k: g& J( Q" L
  22. // }8 r5 |7 o3 r; G/ R
  23. class Life{
    , L3 |4 j/ Y4 @8 }- V
  24.     function __construct(){# e& c+ G2 W4 N7 n8 T
  25.             echo 'cat life!';
    3 `8 u3 Y( q$ I$ b3 d
  26.         }
      D8 p7 X6 b6 E! v
  27. }8 o' y9 z, `0 o4 z( B
  28. % o' N! ^* |: }0 a! ?& f: N
  29. use animal\dog;  4 i) h2 v# B  l/ s' i
  30. new dog\Dog();
复制代码
8 X" e" v( ^/ ?9 {6 h6 s
如上,使用了
  1. use animal\dog;
复制代码

) ~3 \, _- s' `$ D) e+ r
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
0 |/ F2 y2 _- e- N4 M0 H: T8 @
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

/ n+ _  o3 l$ L- L  }/ D! I6 o
6 e5 ^+ _$ R1 G$ ^$ C$ R0 O' N# v; Z  ~& E5 c# z0 b

9 p  o: n7 B; q: o4 o$ v/ r, ~9 M
6 S$ E2 u/ z6 t  V' i! y' `8 J  K
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2025-2-5 13:47 , Processed in 0.109302 second(s), 21 queries .

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