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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

4 [/ D9 E8 k% A8 j, }  ?* u
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
/ k- B# ~3 U0 f2 ^! Q- r; j

5 j& O3 ?+ Z6 D; d) h- Z$ V, R! M使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
: Q: d9 f4 _/ r& V
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

4 k* U/ b: R& b: C( X$ E结合使用方法来进一步理解它的使用目的吧。

5 z. b9 r7 E$ S8 v1 R+ `' F
$ z# @4 M1 e2 w0 knamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;4 {4 J" \& l7 d2 J# _6 M0 o
  2. namespace One;+ G% w3 R' ~. R! h
  3. namespace ONE;
复制代码
& k3 }2 S" N  [" g
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

& R. L3 M  P& X9 Z+ m2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   . V9 g* @0 d- q
  2. class Person{
    8 Q* o& T7 U5 G6 G" `  k; R1 B
  3.     function __construct(){+ K) e" h, {% I- Y6 `+ U
  4.             echo 'I am one!';5 m6 l0 j' t3 z) P. ?+ Q
  5.         }7 _- e$ P& k) W/ U( ]6 ?
  6. }
复制代码
  1. //name.php
    . w; J7 `! r* E) n
  2. require_once './1.php';) U5 h$ x0 X  D+ ^8 G# e
  3. # A+ g3 X9 n8 H: Y. u/ @! D
  4. new Person();     //输出 I am one!;* T, `( H5 y+ @
  5. new \Person(); //输出 I am one!;
复制代码
8 n- y3 X5 X/ a0 t9 g7 E; p. c
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    , Q- f9 `9 Y  B$ w
  2. require_once './1.php';
    - q0 V4 e- I0 B+ F
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

+ }$ V2 U7 r. ]+ u) T" w4 T4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    : i* u7 C  ?1 ~  _) y
  2. namespace one;9 j! O# T& k6 D5 @
  3. class Person{
    , n6 m8 O" G( }4 c3 D
  4.     function __construct(){6 F% D+ Q# F* b3 s2 C# j0 q
  5.             echo 'I am one!';- m. o) {& H+ _. H  m
  6.         }5 M0 w0 W( J* E
  7. }
复制代码
  1. //name.php
    4 m8 E5 D: A. b  l- Y( r3 w0 q
  2. require_once './1.php';, q: s. v- j" }! x3 {
  3. new \one\Person(); //输出 I am one!;
    5 H8 O( A7 C" I% E8 j; u
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
- k6 I# @- Y: I0 S
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
' A; ?( ?. u8 d/ h$ N; n
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。$ A& F( t1 B. y; V+ r! _0 |* Y% l
  1. //1.php   
    0 e% y+ w/ L! g6 h, l
  2. namespace one;3 ?  T" }! l- d, Z- f% G7 [8 w; n0 L
  3. class Person{
    # U6 U' U7 t3 n+ c' e
  4.     function __construct(){+ E' J$ j  z. i6 R) r
  5.             echo 'I am one!';/ b- }/ N* e8 o. c" V, c( {
  6.         }$ H, _3 d2 u  ]
  7. }
复制代码
  1. //name.php
      ]. V) I3 H3 k! a
  2. namespace test;* \4 v1 i; f+ R/ `
  3. require './1.php';
      Y9 e- x/ W1 H1 k5 u4 b
  4. new \one\Person(); //输出 I am one!;
    $ \' s' w5 A; }* T- c
  5. new Person();      //这里结果会是什么呢,猜猜看8 f  {3 X$ Q; k) \" Q: a6 }; P
  6. 最后一行结果报错:
    2 ^; g, a& I8 Q6 @7 j' o5 n
  7. Fatal error:  Class 'test\Person' not found
复制代码
$ W% G0 T% G+ H5 R, f2 Y2 H
* y% [& P) B  D( m9 b
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
: w2 d1 Y7 y- _: i6 f2 S0 Z
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

! Z* [" |# a& W# X8 ?0 ]& O9 j
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    0 M' J9 [; D  X& V* K( D8 f' J
  2. namespace test;( c% W6 U8 B+ |9 a/ b1 ~0 h
  3. require './1.php';
    & ?5 s! j" R2 Q  C- x6 X! }7 C  G# S( @

  4. & I; `- s8 M. r, Q
  5. class Person{) L3 Y' h! |  ?! @, t  E
  6.     function __construct(){
    & W- A/ `3 J0 ?1 O& @) x
  7.             echo 'I am test!';- |2 [1 s$ Q  N: D0 F, V
  8.         }6 ^8 \/ J* h9 j; y9 n
  9. }
    - _) [; u. U% U1 M0 g/ r
  10. 9 u2 F  E' n& Y2 V% k- W5 N7 h
  11. new \one\Person(); //输出 I am one!;
    ) U( D5 {3 m+ b  C9 d, v- C
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

/ w0 G" c1 X( O# Y$ C5 `6 X
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php+ D" }$ F8 A. f- ~
  2. namespace test;' [9 @* a: W$ S6 L/ @" O
  3. namespace one;
    2 A: N5 _% s9 [+ A" {
  4. class Person{' [6 ^: N8 Q, b( ^8 c5 g9 q( ^3 K
  5.     function __construct(){
    / H8 q5 B& Y/ W
  6.             echo 'I am one!';& @- g$ Y- P" q  \; Q% J
  7.         }
    ( z" |: v& J( A/ y
  8. }0 F0 A4 H  `" B
  9. ! t" Y8 C# |3 i1 P
  10. class Person{: T0 E( }  [. a* f% ~/ p6 }! u5 @
  11.     function __construct(){
    & _6 u1 _' L' l
  12.             echo 'I am test!';" U9 m2 a- L* r) z+ ^+ j
  13.         }1 D! I& F% K! a+ o2 m+ a
  14. }
复制代码
( e4 K" _. G! Z* O/ U6 f3 q
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
. d: @0 u& J- s4 I8 @
看来简单的把require理解为替换,在这里行不通。
7 ?( ]3 m0 `9 u: p
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
- \" l  O$ f4 M' k
  1. //name.php
    0 h! ]: E: n* S0 P

  2. 6 ^; p; G7 |' c7 u4 Q( |
  3. namespace test\person;
      }/ B6 v$ z+ W+ i

  4. 0 l' D1 B" |6 S# n, B& v
  5. class Person{; W. B7 U& X( h5 z0 ]7 I% A1 ?# O
  6.     function __construct(){4 \9 b3 Z  ^- `6 }* X0 b
  7.             echo 'I am test!';
    ) A- c9 I& y! p) ~7 Q+ F
  8.         }
    % y6 k/ z9 w2 A; H- R% `
  9. }) y0 R% d& k( `& O3 s8 A- ~9 A
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
9 }  K3 L/ N" c. [: |
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
+ k; f3 }, W+ J3 V0 r
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php, C" p0 S0 ?/ f5 G
  2. + l$ a: a- l$ k
  3. namespace test;
    1 d* e+ R6 s6 m, r
  4. echo 'zhai14';& q& X$ O. Z6 g
  5. namespace zhai;
    % N# F1 k& u6 C- ~7 M8 m; Q4 |
  6. require './1.php';
复制代码
) F7 K' K  I# h
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
: B" W7 x$ p; l* }1 r
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。- b! y5 V) d' I9 r2 V
  1. //name.php
    ' ^, {8 [& [+ C) v
  2. $ o1 U$ k, S$ W$ M5 U8 T$ D
  3. namespace animal\dog;2 c  G- \* j, @6 k! n. q8 W% d

  4. - X5 T! n* y" m3 l5 L0 ], k
  5. class Life{
    / j6 k# r7 z' \) ^4 H6 J
  6.     function __construct(){/ ^6 ]+ d- n) n5 X
  7.             echo 'dog life!';
    ( S/ M" s# i3 N) Z! b5 G  H
  8.         }7 J. l1 n6 s0 n
  9. }
    ; M/ t, B8 T0 ^5 q' {& G/ H

  10. 8 }1 B  Y- G& y9 @% s; b* a- f% P/ G
  11. namespace animal\cat;# P. Y" f: ]0 B' g" ^! `: |

  12. ( z3 \8 k. D; ?9 m' c
  13. class Life{
    / x4 p4 ]4 ?0 C; T1 T) ^* Y3 t! \
  14.     function __construct(){
    6 L8 e, q9 [( B( U
  15.             echo 'cat life!';( A/ ^, m- s4 }) S6 N! h" [1 L; {0 A
  16.         }
    1 Q, X# _. L" _4 X) s
  17. }
    % F" i$ ?( Z* J6 `) t2 o4 q* J
  18. ; o! ^. K3 P, F' X7 Z/ w8 S, W
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间- N5 y8 R3 P' f! V( g5 x0 H5 I4 g$ f
  20. new \animal\dog\Life();  //A
    : y! r6 v( Q7 @- K7 S; E
  21. & ?2 W4 F  ]' g# L0 b* v
  22. use animal\dog;  //a
    2 r4 A! N$ E, a7 x" O
  23. new dog\Life();  //B
    $ t" ?& r2 M' b8 v, w! m3 r  [- y4 ^

  24. - g* N7 n6 D+ [. d% p0 D' i
  25. use animal\dog as d;  //b
    ) \) c9 d# H, u
  26. new d\Life();
复制代码

9 @9 J1 I* I$ N# s" i  ^) N
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

+ F2 i  Y. [! I5 |% X& O
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

3 S: Z" y/ K. c1 Q5 O! G
相当于
  1. use animal\dog as dog;
复制代码

- D) I! m' J$ a! Q+ q' \9 r- W: Q2.namespace后面不建议加类名,但use后可以。1 X4 J0 f& x% o
  1. //name.php9 s' i, b7 ~8 \. @
  2. + r" ^3 ~: j8 e6 p: A2 M2 m  h) R
  3. namespace animal\dog;
    7 ~7 J/ l5 B' h* N- C) H! I" H

  4. # G# u2 j6 k6 i
  5. class Life{
    ' c- \. k' }# w, a3 A& V
  6.     function __construct(){" E1 q: P! m/ k. c, X$ O, I1 X& Y
  7.             echo 'dog life!';3 z6 Y% U* F" r' E* s) `
  8.         }, C2 |) }8 h% i# i7 t0 }1 i1 q. v
  9. }! t' r  G* [* g1 S% X

  10. " ]- i7 {* {, D4 [4 r
  11. namespace animal\cat;) g! \3 T- |- q' v
  12. 0 T+ r" U, t3 P" c2 t7 D3 E" N
  13. class Life{
    / E7 s( U8 w  _
  14.     function __construct(){. u2 e2 B) b2 E: n. r
  15.             echo 'cat life!';% T: }2 m2 Q- o7 `8 L7 D4 R- k) Y
  16.         }
    + y) Q% y2 [1 g+ C& N
  17. }6 e2 p% }9 X/ x9 t6 b$ ^' r+ D* D

  18.   l8 \6 g# G4 z
  19. use animal\dog\Life as dog;  
    6 u" Z3 K; ?; K; g: L; Q$ v0 ^% a; R; S
  20. new dog();
复制代码

$ _7 V' i8 {8 X  {' V3 \
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

7 Y; N# e  V* Y; `% t
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php' V: x: z: B; @1 p4 H

  2. 4 s& s0 m) y8 x5 @" H& P
  3. namespace animal\dog;
    - i- k0 d4 P- X5 G" n3 k+ \
  4. : ?" D5 C9 q* y; n3 M  _) K
  5. class Life{3 ]* H( g1 L* V
  6.     function __construct(){
    ; e& {# \- @2 t* }. X) q; R
  7.             echo 'dog life!';
    $ `7 R6 L' i9 D) p: y2 [
  8.         }
    9 A. t8 E: K4 N6 U5 N3 T  g
  9. }2 J9 k' K( _  {+ G! a# N
  10. class Dog{( O/ y6 Z  N! ?$ N* Q# K7 M
  11.     function __construct(){2 V6 L4 e( U& W2 V
  12.             echo 'dog in dog!';2 t( {, P! E6 \6 A6 k# m( M& {4 f& v
  13.         }" A2 `9 c6 C! O4 Z( k# k
  14. }# X/ _8 S4 A, D5 g
  15. 2 _: _$ s# l# Q- A" `) o; D
  16. namespace animal\cat;- R+ [3 ~% B- K2 P/ ~" D7 Q- ~9 v; m

  17. 9 b; r" s4 q5 s  o
  18. // class Dog{
    6 A0 V5 ?8 {+ y
  19. //     function __construct(){
    " L* O- r# L6 w2 [
  20. //             echo 'dog in cat!';/ w' N& R% n( |9 G" C
  21. //         }
    ' F% e9 K  S& }( X9 L
  22. // }+ Y! c2 k1 E1 `. q
  23. class Life{1 R! z! Y' C" s% o" Z
  24.     function __construct(){
    ; @6 A0 s- z# u" h$ j
  25.             echo 'cat life!';7 f4 `. y8 j" A' q8 Z" z3 X) h& ]7 C
  26.         }' R4 C" x, N( a+ `5 e
  27. }9 c6 f( `. d( Q+ X

  28. + Q7 w$ L' v* n
  29. use animal\dog;  ) S3 H# J" q/ U3 e4 o; w
  30. new dog\Dog();
复制代码
4 F: L) i7 N  U( B) Y' L
如上,使用了
  1. use animal\dog;
复制代码

$ Y4 `4 ]6 L8 i9 X# t6 e$ y, d
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

$ V# _2 V) h2 U& ]8 F5 a
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
5 v; q+ _2 C, F; B- @$ N6 ^/ `

* Y0 C5 U5 t" b% [  u) P, g2 T/ \) B( G

# V  O  x( x2 J/ e/ f7 a; {' e8 i+ W1 a; v7 s
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 00:13 , Processed in 0.063896 second(s), 19 queries .

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