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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
0 t/ h, x7 I: S
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

# [. b' ]0 p/ `+ H
3 a+ X& d+ I  L$ s使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

2 f8 j7 G% R# U# R( }: e$ w! n) J
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
1 u7 e. a1 t& D6 P" i, e& J- i& v& b" K
结合使用方法来进一步理解它的使用目的吧。

& P- d2 o0 @+ d( }& ~7 ~
, y& g6 b# U0 [, ?+ d0 T1 G& Unamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;; |& ]* w9 h$ j* @
  2. namespace One;* V3 v) R/ o8 i# @( u, }$ e
  3. namespace ONE;
复制代码
# _% Y9 ?9 O* d$ Y! j
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

8 H  y& \4 J  h0 M3 s- |2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    0 q$ [# r8 R) x9 A# I/ \) M$ U
  2. class Person{, i4 W2 b6 T( d$ `+ a( v0 k
  3.     function __construct(){/ `. Y# q) q6 N; Y8 ?/ C
  4.             echo 'I am one!';3 l, E$ x+ O* d* e) E1 W$ @# x
  5.         }$ J) s* d6 f6 X$ K9 |
  6. }
复制代码
  1. //name.php+ r7 I$ o9 T. T' V9 c
  2. require_once './1.php';: L) q0 C; s, t9 I0 n

  3. ; i5 l, J6 F! @3 b4 U
  4. new Person();     //输出 I am one!;+ Y# _6 L0 D; {9 @  D6 F
  5. new \Person(); //输出 I am one!;
复制代码
' N7 ^$ j# W0 f4 {$ g/ Y0 a
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php: D- [, y  y0 A" l* Z
  2. require_once './1.php';
    9 j" E% g% W* X
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
& O! v; q1 a* N3 u5 N0 {
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    2 B7 y+ r$ b  ^8 X6 C: X7 y5 T
  2. namespace one;
    + r' T: E4 y5 c7 [" w# q) K6 g
  3. class Person{
    0 M" }; x) _% s7 `( B" Y+ h
  4.     function __construct(){
    - X0 m+ R/ m5 b6 @9 Q) A
  5.             echo 'I am one!';
    & |! e3 m* V+ e4 Y* a7 q; j
  6.         }
    * q' U; z  K- I9 s* B/ `& ^
  7. }
复制代码
  1. //name.php+ E+ @. J( f. x8 ~1 V% u7 M: d1 _) D
  2. require_once './1.php';
    8 L! U" o, N% |* @
  3. new \one\Person(); //输出 I am one!;
    4 c# j4 y1 ?2 Z. M
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

" w( ]/ u0 I2 B* Q3 ]6 g% n# ]( _
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

1 P7 h* e: S& ~% R  f, z# q9 K- u  j5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
- V6 f1 ~7 Z' R/ Z! G: H
  1. //1.php   
    ' t. T7 |' F: E( g, U# q( p
  2. namespace one;
    % h9 ]( G! z5 d
  3. class Person{' }: j7 j0 r! P
  4.     function __construct(){
    $ k. f: t( X2 ]! S8 M  ]8 `
  5.             echo 'I am one!';5 ]" Q& i- X, J
  6.         }
    6 E" n8 s# I' b8 U
  7. }
复制代码
  1. //name.php* ]* M( J; @- q; J
  2. namespace test;( T* r. m. l( J  l) g/ f
  3. require './1.php'; # H) P9 ?, e- I2 R% t7 X& l
  4. new \one\Person(); //输出 I am one!;4 I: z8 I) R' B% F  ^& X- ~
  5. new Person();      //这里结果会是什么呢,猜猜看
    : p" R5 K/ q& T/ b. }
  6. 最后一行结果报错:
    3 |! Q5 i4 E7 [3 I
  7. Fatal error:  Class 'test\Person' not found
复制代码
$ T- Q/ s0 V" D% B8 z" `

/ N3 Z4 J( S7 K8 S. `- x; _" y$ l首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
$ ~0 Y. W: p' g. e
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

: i0 Y% u% s1 v* N0 R0 ~
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php  a# S* R4 k* h$ B3 G" h& U
  2. namespace test;  ~. y2 t0 Z3 A
  3. require './1.php'; 1 l. U9 z% x1 H- s# f
  4. / L! r5 l3 q- X2 ~
  5. class Person{/ w% U  q9 ~9 x& t
  6.     function __construct(){4 ?7 J+ o0 G# N
  7.             echo 'I am test!';+ z( z: |7 C8 P" v- ^
  8.         }7 H6 r, b. z6 f3 n7 C+ U- A- ]( P
  9. }
    ; J# G' c+ ?7 Y, y. P/ k

  10. $ J* f' S3 g8 s4 `2 f8 c
  11. new \one\Person(); //输出 I am one!;( f5 d; d, B$ g5 @% ]
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

8 g, W# f3 s* z) r$ p- ?8 f2 ?9 p3 h6 R
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php0 B$ T0 Y2 p+ b7 m# D
  2. namespace test;& ~4 H  T5 ^- n8 H6 R
  3. namespace one;
    3 _- A) {# X$ l. h
  4. class Person{
    5 ~. O; D5 @' H
  5.     function __construct(){. T6 f$ H7 i0 l+ m. E* c- l/ [
  6.             echo 'I am one!';+ N1 w. ?" J3 w) }+ J
  7.         }
    9 \; l4 {4 P0 x9 Z: y0 j$ r. H
  8. }) o4 }! D9 U+ A0 N% g8 P
  9. $ D! P9 L0 v9 A  p
  10. class Person{
    - l; e" l% V$ a- P6 [
  11.     function __construct(){
    ( T% A# c# U+ A3 F$ r: X; o
  12.             echo 'I am test!';: L5 f; Y7 D0 p' _) R
  13.         }! V4 Y* R+ K1 m
  14. }
复制代码
/ o) l1 O" p9 O1 I4 A
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

9 v; L+ \: x2 }# t* F  ?. B7 {% q4 {
看来简单的把require理解为替换,在这里行不通。

- A, {8 t: I8 o7 u/ o8 b" m6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。) ]9 V: R) D) o5 s2 {0 b/ F! @
  1. //name.php8 a' H2 a% D) D/ b4 F

  2. 5 V# ?4 d/ Q7 i% r8 O! o1 u
  3. namespace test\person;
    2 K0 p; N5 B; H& ^4 J$ H
  4. * F, R4 \5 Y8 I1 x& w
  5. class Person{4 X: O' U' ~) q$ O" {" h6 T
  6.     function __construct(){
    " O6 |9 U) x- R% @' f
  7.             echo 'I am test!';2 M3 t! f1 x$ [& r
  8.         }- f/ H  H( b3 ]7 X
  9. }
    ' ]  s" O4 ]4 {
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

8 |6 d) W; ~# X0 U7 X: V
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
+ J' S, I; o, Y1 k
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    6 C& m* Z+ P  p- V
  2. 1 \8 e# n: B& b! a* C% _; L; I7 N3 W
  3. namespace test;" x4 S- S: T# x5 b7 Q
  4. echo 'zhai14';; s0 [1 t" A6 S
  5. namespace zhai;" }5 d, M% ?/ [2 |9 G! V; \1 H
  6. require './1.php';
复制代码
1 C6 w5 D# o- Q
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
$ U2 l. W3 p( [, K7 a
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
8 v& [6 p3 W" k7 j+ [- j) U
  1. //name.php! k1 Z: u# G- a- T- V+ J, o: x
  2. . T( H; i' {- U+ I! D% N
  3. namespace animal\dog;
    8 W9 g; l2 R2 }! y
  4. 6 V; q. h9 F5 O) \5 l& E
  5. class Life{7 d4 \% I- {; t
  6.     function __construct(){
    , U( G& ^! w% [; w
  7.             echo 'dog life!';* M$ _: O, Q4 u/ j  {# V1 F" E
  8.         }9 a! h4 A. V' ~  d% \( w
  9. }4 G% M- x9 u) c5 C$ _/ e$ t* D
  10. & ~' T3 H; k: P$ x
  11. namespace animal\cat;
    : o2 O6 L0 u& N& t

  12. : i) U/ A/ H) S/ U4 @8 @
  13. class Life{1 M5 h. P$ @" u
  14.     function __construct(){
    * ?& f2 q. n2 q7 a, f6 {# O0 q4 r
  15.             echo 'cat life!';
    ' _) o+ h7 B/ L" c7 R
  16.         }  @7 v0 Y) w! O. T- L0 w
  17. }5 }9 k: i- g$ l6 a1 ~' a1 O- |' c

  18. $ G- ~1 h6 q/ ?+ `7 V
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间; x, u! \5 c- F
  20. new \animal\dog\Life();  //A7 Q4 E0 R; d& Q/ D* R: q+ |, b
  21. 8 c; j' L3 ]- J$ D. p
  22. use animal\dog;  //a
    ) u& y9 {, C/ N' G0 u7 G. ]' b
  23. new dog\Life();  //B
    ' {& g- O! {7 h! A9 J
  24. " L  C. v5 t: K# w$ u; Q8 i  r6 ?
  25. use animal\dog as d;  //b/ x3 B- O& M( K
  26. new d\Life();
复制代码
. A" P6 u7 q% a+ k4 }# L
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

9 m& V: F! y$ ]+ Z1 K
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

; f; t$ m9 N2 R( u  y+ T
相当于
  1. use animal\dog as dog;
复制代码

' i& Q: m; \! H1 W3 m  H4 o2.namespace后面不建议加类名,但use后可以。- N2 F8 `8 J9 N! {
  1. //name.php, A" |; |! ]. m

  2. 7 @/ T4 X# `4 g
  3. namespace animal\dog;7 H' |. C/ j7 h) b* t

  4. 8 i' v7 [3 t" T" }! ]
  5. class Life{! j- }! T/ _- t7 h( K! {  Q
  6.     function __construct(){2 q# ]( z. K* n8 J1 j0 v
  7.             echo 'dog life!';
    + H0 A* @7 r( K& @, \/ `4 ~( }
  8.         }
    7 `6 X" Z/ a2 _
  9. }
    + C$ x* }0 a* g# ?5 B1 g6 O# C4 A
  10. " p6 M; b4 S1 P. l. G
  11. namespace animal\cat;' B; A" X5 ]9 Q, D# G: c& I& v
  12. 3 l* R; |* }. ]4 k/ D
  13. class Life{
    ) z/ {. y" g7 ]0 L- C
  14.     function __construct(){
    & R- f; o- x6 ?/ `0 E" C
  15.             echo 'cat life!';
    ! ?: M) m) R- x) K
  16.         }
    % B. Z7 M  W5 X6 B& Y, `9 k
  17. }
    0 s" F( }" U* U9 c* [2 W9 W6 M3 g6 r: G

  18. - S) D4 X( G. b3 c! C& t7 G6 R
  19. use animal\dog\Life as dog;  1 L+ Y3 e5 }$ _+ S; J  U  Y
  20. new dog();
复制代码
8 M6 r! }$ M$ Y7 q
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
0 H( [) U" d+ D# f( g' I4 r& H" M5 b4 h
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    1 T; Q6 ^- Q2 y, e- k; a9 g4 X+ t

  2. # ^6 p- k- d& o% F/ a2 N2 w
  3. namespace animal\dog;* n% G' J4 }8 o4 l3 d$ N# B9 l1 f
  4. 1 D  }$ h* n# O% o: E% O: M
  5. class Life{: p: b* J6 ~' T1 m
  6.     function __construct(){6 M+ b3 t0 ?6 ~% G2 H( I! Y2 J
  7.             echo 'dog life!';$ U, u9 _9 c* p! B0 I9 ?
  8.         }
    . Q  W* j, v0 M' l
  9. }
    ( P3 s) Z! a4 j! d
  10. class Dog{
    6 V- b5 g! A# K
  11.     function __construct(){
    : b% f5 Z" L' A. L2 ]3 b' q5 p; f
  12.             echo 'dog in dog!';
    7 y- s5 e$ K) h' o6 T3 a5 z
  13.         }0 @) V) a; }, F. \- A
  14. }
    ; [! C- ~: H9 d- |6 Z7 N4 e- _
  15. 5 `# Z+ s: x$ i1 ?, u, s  y( [
  16. namespace animal\cat;. _  l  X& P0 f9 X3 `5 [
  17. 8 X4 ^0 M, p( x; P+ X7 }, V0 q
  18. // class Dog{
    0 C2 a4 {3 C- Z: J. G3 I. D
  19. //     function __construct(){
    # h6 s* N/ O4 Y% N1 O) O
  20. //             echo 'dog in cat!';
    " @: G6 ?8 x" n. Q& K
  21. //         }( B8 r1 @6 U1 `: x- Z
  22. // }
    5 ~& X6 x& m# ~" y& e1 y' N
  23. class Life{
    - j6 K# U4 ~: f9 Y1 a2 t/ Q
  24.     function __construct(){2 _% v( P4 D9 S- n# k5 b* p2 F" y
  25.             echo 'cat life!';8 ]% Z' q7 {% A8 A: r- p2 ?8 U/ P
  26.         }
    5 M+ B) R+ ]% P. B8 o
  27. }3 O" Z3 P% A! Z8 a( B

  28. 3 H, X+ I3 w7 }0 i
  29. use animal\dog;  1 G% M( J/ ^% x/ u+ {; G$ `
  30. new dog\Dog();
复制代码
' p5 ~+ N9 w4 k" F- c
如上,使用了
  1. use animal\dog;
复制代码
- V) b' F  G, B) E; k2 Z4 j: j
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

0 ]8 R2 v( W/ ^. U# T
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
0 g9 w' C( o' J4 ?5 p" Y) N

5 W9 A0 ?3 f( A1 Y
" [' x7 w' a9 I# u
0 |% g% o8 H% I, x  i% k
5 t7 I8 |" p) H6 P) l* \/ z
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 08:14 , Processed in 0.081783 second(s), 20 queries .

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