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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
. [/ Z' I+ U- n) w
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
" ?4 W- d+ q# r& m( \' k  L# G
: {4 e! o! [2 l. H  R9 r3 j
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
1 ]3 |  a7 Y& x6 M! p' O+ j
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
* p+ ?9 E$ a7 t3 ^$ i# [5 }
结合使用方法来进一步理解它的使用目的吧。

3 ?/ M4 T, m' {) R$ i! _3 H- c3 l0 `9 ?. R; p: `( G# r
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    7 H; Q4 x0 m" L. I4 d. z$ X
  2. namespace One;
    . \. p4 x" S: i' |. F# `0 l* t4 H: X
  3. namespace ONE;
复制代码
+ L0 a) l( [" v" t3 M; n8 b) A. \* N
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
5 G; L( H2 j4 W; E
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    . o4 u% q' V! i& E
  2. class Person{
    + j. I$ e5 ~+ k5 l# b3 l: b
  3.     function __construct(){
    9 q" {6 g5 @4 R5 R/ y
  4.             echo 'I am one!';
    ( `, W8 F' Z3 m/ ]
  5.         }
    ; G$ A5 x; P0 Y3 v9 L4 A
  6. }
复制代码
  1. //name.php
    # a0 @: m8 S% a/ l& n4 D% w- o
  2. require_once './1.php';7 r" f/ U1 z0 m& O1 f$ ?

  3. # v' R" ]) H3 F; q  b
  4. new Person();     //输出 I am one!;7 ?7 l6 V$ y, Y4 q" E* k
  5. new \Person(); //输出 I am one!;
复制代码
9 }( y! S0 ?+ o, k% r9 |  A
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    9 M5 Y9 Q* |2 x  E" A0 T5 W
  2. require_once './1.php';6 `' g) o% E, W+ F( ?+ G1 Q
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

8 t8 M; M; r8 q7 L( v  L+ X& u# Y4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    8 Y8 c6 v& M9 y% t3 H
  2. namespace one;
    . O2 L, b" ~) |3 C) [# V# ^
  3. class Person{
    0 E- n0 X# l( b+ W( S" e" O
  4.     function __construct(){' }- r: s+ J! D; _8 y
  5.             echo 'I am one!';
    6 m6 l, ~) V8 L/ K2 h) U6 e
  6.         }% y4 ]2 h* y  ?: {+ q3 V
  7. }
复制代码
  1. //name.php
    ( ]/ Z$ |/ G  r/ y; r5 o1 O
  2. require_once './1.php';
    / c# E9 u5 H4 m- r# U
  3. new \one\Person(); //输出 I am one!;- e' r" C* Y0 X7 E
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

0 e8 ^2 c4 a* y3 [; u* ^
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

; n! Q( P- n9 E) b5 f5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。" h) `! [5 D5 i: N* n
  1. //1.php   , M* u3 u: P2 e: Y; V7 H" k
  2. namespace one;  z3 n2 [+ ]( |- V; o
  3. class Person{
    & z! L) T& {+ r
  4.     function __construct(){
    : `4 _: s( A; Q9 Z  ^; h0 D( H( D
  5.             echo 'I am one!';
    ! ?3 N! `! S& }' A! b0 ~9 n
  6.         }" S2 j! T0 d1 x' \
  7. }
复制代码
  1. //name.php
    ; b- t9 J+ T6 k! ?* {4 n2 X' r
  2. namespace test;
    : d! R/ X9 E# s6 E' C+ ]3 T, U
  3. require './1.php';
    5 q1 o6 X) k+ n8 T8 H
  4. new \one\Person(); //输出 I am one!;
    2 ~+ I% {3 I1 C  T& V# k  T- m
  5. new Person();      //这里结果会是什么呢,猜猜看
    ! x# b/ U& H: ]7 l
  6. 最后一行结果报错:* W7 g' H+ q9 f& _7 n" ~2 q0 J( F/ `
  7. Fatal error:  Class 'test\Person' not found
复制代码

; S# e# Y% e+ L. t) s

: S( z: Z! b$ \首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
  g4 P( i5 W4 U0 a" ^& `6 |
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

2 P( a9 C: ^: U5 \
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    / E9 A# [" [: i# n5 @
  2. namespace test;% M, k- o: {; k$ V
  3. require './1.php';
    . G9 w4 f9 q' j( y5 b1 U
  4. 9 n/ @  s/ I1 _% I
  5. class Person{- p0 d2 [# a; I
  6.     function __construct(){! m& \% I' w" [: R, D, O
  7.             echo 'I am test!';
    6 e( Z1 j( o9 h# H7 L% C+ Q1 e
  8.         }3 [  e8 L# O5 c" A2 F! }( C
  9. }
    & |" W/ _4 c2 \9 m1 ]
  10. / [; [! C& U' g+ t
  11. new \one\Person(); //输出 I am one!;
    5 O0 \% T$ p$ w0 I6 \
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

; s8 ~. I  g' M/ X+ `$ q
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php' |/ h8 k1 n5 S6 d
  2. namespace test;
    0 O' @: a( F1 h% f
  3. namespace one;
    * r* m& a  h& _: D) M
  4. class Person{: A9 z5 T9 q6 K7 ~) {5 N/ H, }
  5.     function __construct(){
    % g! j/ M* o! N4 A
  6.             echo 'I am one!';
    1 W2 q- t8 ~; ^
  7.         }" @0 G6 e7 r2 @' c
  8. }
    " |- B1 |% H/ `$ u4 {. h& _

  9. 8 |7 n. A: [; v: n
  10. class Person{4 f" b  L+ j2 T3 m" N* c) ]
  11.     function __construct(){' ^4 K; k$ r" n) _7 z# ]
  12.             echo 'I am test!';6 U; p2 v- ]$ @
  13.         }1 L1 m0 `1 ]  C% r
  14. }
复制代码
# J7 e' M0 q5 Y& @
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
6 n  U( [! |# F1 r# d. k
看来简单的把require理解为替换,在这里行不通。
. f( q. ]$ w: W1 B
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。, Y5 P% y# y# q; \' f2 m8 E
  1. //name.php' N/ @! T1 _7 A
  2. & D3 o; q$ Y: `
  3. namespace test\person;- D, S1 o! O0 K" m# ~  p! a
  4. ) Y6 M: W' |+ L! u$ u
  5. class Person{: O/ H# ^8 b2 J& w
  6.     function __construct(){
    8 n. d+ U4 S6 [& @3 o+ {, C% w
  7.             echo 'I am test!';
    $ g9 }1 w7 b: j7 W
  8.         }
    $ s4 o. y3 p' l, H* ^
  9. }: H5 a! I  Z+ U/ j7 m
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
5 B* \  e1 s/ V* X0 |! j3 W0 i
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

# e, @! s# J7 L* a  I7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php% y5 ?/ i9 D" z5 ^: E: P
  2.   f: E+ H( P" W! D; q
  3. namespace test;
    # D0 ]% U; X! f3 S3 g  Q! N& j
  4. echo 'zhai14';
    * z3 R. i; @) j3 T
  5. namespace zhai;# I) m- q( X  v
  6. require './1.php';
复制代码
$ u3 f- N; e# c. e5 D0 R4 V& H- q$ I
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
2 v1 L% [% e" S( Q, e1 h+ N6 S
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
* r2 M1 C+ Y" G7 J0 O, c
  1. //name.php
    # z* P' R8 X  u

  2. - B6 r- y5 t" |2 i+ k  `  A
  3. namespace animal\dog;
    : O  c  _3 f& r) F9 k; f
  4. 8 O3 I4 V3 ~" |5 Z
  5. class Life{$ J7 A5 T8 k0 x2 C& w0 t
  6.     function __construct(){
    ' L9 H" a2 C. z2 L7 t8 J
  7.             echo 'dog life!';
    6 e' ^7 V+ k% b4 M7 `: ~( W+ V* w& L
  8.         }
    3 ]3 d7 K7 ]9 {7 Y, B
  9. }
    ! F, i- z% m8 k

  10. 9 J. U  I. X( t- o
  11. namespace animal\cat;
    ) U. }6 }3 \/ `3 t! \* d! R
  12. 2 w$ j: A0 w* i$ X2 y/ _
  13. class Life{8 P" P/ @5 f! m5 w
  14.     function __construct(){
    " v2 b  N* e! z
  15.             echo 'cat life!';
    3 X% F$ [9 m" ^2 w  B
  16.         }/ C5 w* j# r& k3 ~9 I1 u
  17. }* E3 b: v  u3 W* X* R* n

  18. / |- M! w( \3 h) M! |5 j! Y
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间7 i# H7 s3 \% g
  20. new \animal\dog\Life();  //A
    ! f! l7 M9 f5 w/ @, P) ^

  21. 3 _) r0 X. W8 Z7 r
  22. use animal\dog;  //a
    6 x8 X% j, P/ ^( @. f3 |. a# ?6 W
  23. new dog\Life();  //B0 O% n4 Y: N+ O! e$ g5 @

  24. ) z- r1 ?. k6 H+ M, J$ b2 f0 y: R) D
  25. use animal\dog as d;  //b0 a  s: x) ]) I3 R4 t/ y
  26. new d\Life();
复制代码
9 @. t6 _; B, R" p5 C, v
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
/ e( p* ^1 M, o% r4 [; B
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
8 A: A% N! V% y9 P5 \" H4 g2 U
相当于
  1. use animal\dog as dog;
复制代码
7 O# X1 M6 ^5 t6 B) u) b
2.namespace后面不建议加类名,但use后可以。" `# q8 w# w: t" M
  1. //name.php
    5 d7 O% w7 e1 a) u; V: b4 [: k
  2. : d( x+ @6 p% }0 E1 B4 z( P
  3. namespace animal\dog;7 Q: J- p; k: E. l. d) P

  4. 8 y; a  j9 j  D3 x3 v9 y% x
  5. class Life{  z7 M4 d3 {4 }) @1 z
  6.     function __construct(){
    4 S  C, E/ \9 B( K' ?0 e5 u
  7.             echo 'dog life!';6 |5 I; n6 r: c7 [% S
  8.         }+ T! o) G+ O, l( m, p
  9. }1 _2 e' e5 E) q1 W0 O

  10. 6 \" F; `4 W" U
  11. namespace animal\cat;# ^5 s# U9 C/ T' M# q3 W! U

  12. ! |7 I: z+ t, D% f8 @& ~" T0 n
  13. class Life{
    . S: N  s9 X+ E  F& _4 k$ o
  14.     function __construct(){
    7 E: R# I9 T! ?1 }- p
  15.             echo 'cat life!';
    % d! k  A5 `* j
  16.         }  n3 }  a# V8 O- C: g
  17. }
    $ U% [9 N( G: L
  18. 6 F, \8 g8 t7 O# k4 D' c/ Z
  19. use animal\dog\Life as dog;  
    8 t. A8 Y0 h# |7 i
  20. new dog();
复制代码

7 b/ t0 x8 r$ ?# U9 A
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

1 B- `  a5 E$ L9 L+ D% H$ z, J
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    + l( R, B# c1 e% X7 V
  2. / M8 @: f. |5 Q: V. k5 J
  3. namespace animal\dog;
    / T/ O4 {, E3 O' }( M3 b

  4. 0 U- l5 v+ K8 G! O+ H, Q* k# i4 U
  5. class Life{% Y9 e* e6 Z' a8 n1 c
  6.     function __construct(){8 J9 H  r4 m  H6 ~+ m1 A6 Y
  7.             echo 'dog life!';$ ^% {+ t8 D2 F3 D5 b
  8.         }
    " a" ]( b% Q$ \9 R: x
  9. }* K& R0 p0 }: n# c+ M9 ^; I
  10. class Dog{
    1 W* N- W3 s+ ]  x3 f- A: B' {
  11.     function __construct(){
    # ~5 U6 i6 g) T% z# z( Z7 x
  12.             echo 'dog in dog!';* l3 U; Q+ j/ B3 w& I# Z0 V
  13.         }
    * C6 F& N% ^# t8 @! X
  14. }
    ) M% P- t7 b6 P8 M
  15. ) @  ?8 A( d! B6 B) \
  16. namespace animal\cat;
    + o; T( R% x8 a2 c/ \; q

  17. 6 x& X! `$ T+ |1 ]+ E
  18. // class Dog{
    9 F0 u  O7 F, o3 S* N
  19. //     function __construct(){
    ! C9 G4 z9 q4 h- E* M) D+ s' M
  20. //             echo 'dog in cat!';
    5 C% ^3 X# s& M/ i9 d/ x
  21. //         }
    $ {7 V  H' ]6 j  V
  22. // }
    ' U* X" j' o7 m; i" R0 _4 n
  23. class Life{
    " [' D/ S1 }- T( [! S, B3 Y
  24.     function __construct(){9 s1 k4 A% |/ e
  25.             echo 'cat life!';/ M0 k. U# B! T9 _- U  r
  26.         }
    - G& R# N' }3 ?3 Y+ B  R
  27. }
    0 c# T! d3 \7 d3 a0 V9 m6 t
  28. 4 e$ L: K) b7 a
  29. use animal\dog;  
    6 s* ~* E1 v* Q0 i6 s
  30. new dog\Dog();
复制代码

& j+ e# i! }6 u& f0 y
如上,使用了
  1. use animal\dog;
复制代码
) {- {1 Y8 F  `% V3 |4 `
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

# g+ Z; X4 r8 r7 T% ?7 m$ J3 ?
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
% P1 o# F! s2 Y. f  G6 t
0 _7 {/ _9 g: {

1 d0 R- |0 ]% y7 h
  Q% s# R' t7 F, _/ T" r3 \0 y: f- b" f/ C: t1 [' Q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-5-2 13:34 , Processed in 0.059646 second(s), 22 queries .

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