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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

: t; i+ D1 G, L. K
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
+ Y1 `; g* u+ }4 E% k3 e7 o3 R
# V& g6 c$ {% \' J
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
: D% E3 q5 f; Y& D% ~; b1 P) G
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
4 u  d1 v' Y) b3 I5 h9 j1 w
结合使用方法来进一步理解它的使用目的吧。

. ]" X" |5 r/ |$ \0 N8 O2 }7 \* J+ @5 \8 {
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    / g+ P) O4 f' Q5 o) X6 R" R
  2. namespace One;+ S! I/ B7 X2 U3 U
  3. namespace ONE;
复制代码

/ }, U0 T& B7 J
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
0 a  E! @  I* \$ [8 h! Y% e
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   5 z* A. f6 K# a8 h$ W/ q
  2. class Person{- H6 Z# j7 [2 S0 V$ h: N4 W
  3.     function __construct(){
    % R( v8 r0 E! v  L6 q
  4.             echo 'I am one!';0 W- C. a2 k8 D5 q- ~5 B
  5.         }: M8 t6 d4 [6 z  y- H' Q! F
  6. }
复制代码
  1. //name.php
    2 U/ j2 `  @' M/ P
  2. require_once './1.php';
    1 o4 \. q6 e3 t% u9 J7 o

  3. / E# D4 H$ y- p: e& W( C
  4. new Person();     //输出 I am one!;" L  S9 @0 L  [
  5. new \Person(); //输出 I am one!;
复制代码
* ~3 b, N  O; j0 c0 Q+ S
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    / j% y! [6 q4 a1 D9 }  v+ N1 v3 h) q
  2. require_once './1.php';. X0 M$ ]; A" ?. X: m
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

9 b$ p# l. b; q4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    : W# A* c3 w. x9 f; [2 x
  2. namespace one;; U; w% L4 U6 |
  3. class Person{" y) p6 t: }9 }
  4.     function __construct(){
    $ a" N) b1 a) W! ~% E
  5.             echo 'I am one!';
    1 A, e7 V: r" j  I' \- Q
  6.         }
    ) ^. `: l& D0 B3 v1 I
  7. }
复制代码
  1. //name.php
    : I! _$ Z& T; ]( ^3 k7 P% r
  2. require_once './1.php';
    7 ], g7 Q- a9 N# `1 _! U1 ]
  3. new \one\Person(); //输出 I am one!;
    ' @9 _7 Y. G( R  u. p
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
, M3 d2 c, s( M' _$ [# H& W
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

4 u7 R% g0 T4 e0 W* u- F; z5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。4 L) X0 W( i( S5 _% Z
  1. //1.php   " H  m8 |7 H- M1 W3 s( V8 M( j
  2. namespace one;5 z& }, L. a( g. _& R8 h
  3. class Person{
    5 y, u+ n- V# v5 _5 b: r/ e
  4.     function __construct(){
    0 N2 t- S) [3 {1 P% _
  5.             echo 'I am one!';
    ) h# @8 [  S* r$ A5 E; ?" N
  6.         }
    : s7 @& o6 c0 p- H7 S4 g
  7. }
复制代码
  1. //name.php
    2 S7 I( N4 O4 y; P
  2. namespace test;" v' v+ j8 C' u( l
  3. require './1.php';
    5 i0 {3 Z5 A' q# n: @9 ]
  4. new \one\Person(); //输出 I am one!;
    - I  N2 o  ]( f5 u
  5. new Person();      //这里结果会是什么呢,猜猜看. `& a2 o' b  d: K6 ?6 y9 O" _
  6. 最后一行结果报错:
    * `4 W: j( z' v& O( G- f2 P& j
  7. Fatal error:  Class 'test\Person' not found
复制代码

- O- _5 h. ~1 {2 q4 V

- Q2 a: n8 U' P! c/ q7 n2 _7 F首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

9 t7 E) b6 E& [( Q
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
5 a! ?! `( R( Y1 O9 C( j
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    9 c6 f* D6 m# K! b( M4 \" H
  2. namespace test;
    1 @( l  `2 W- i* s
  3. require './1.php';
    - C% J0 g1 x% D4 I

  4. 3 A  _, \7 ^. o& G  W
  5. class Person{
      W5 E" J+ I9 P: i. \% N0 p" S
  6.     function __construct(){
    # J8 B; N& q+ U* V0 v7 ^/ U: h' N
  7.             echo 'I am test!';% V7 j6 `. Z. \
  8.         }' L( M$ V4 b9 x" h: x' [
  9. }
    - E, V7 U5 _. K, {6 G9 i: [% @

  10. , J, N8 s- u4 ]! [# C7 o0 E9 r# V" E
  11. new \one\Person(); //输出 I am one!;
    5 u0 f# s! J0 ]: Y' u% u5 {/ N7 k
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
6 ~6 L" n6 _9 v3 C9 L
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php. ]- {( O  b6 v
  2. namespace test;# ?$ i4 e7 U! b
  3. namespace one;/ K) P' _% m- F( O. P8 ^
  4. class Person{
    ; d* c; h5 L; W  v( Z6 A" F
  5.     function __construct(){4 j& A% S8 \. G6 T
  6.             echo 'I am one!';/ @! p4 q+ X" n
  7.         }
    : f6 Q/ g1 ], e; F
  8. }- b( [' F! H# A) ~( i
  9. 1 I$ @0 ^# a6 a& I: \
  10. class Person{, n& J; r8 Y: k- G- k8 L& Q4 }
  11.     function __construct(){
    5 L: F9 L' `" |& \  P
  12.             echo 'I am test!';9 l8 t$ O" L5 l( J
  13.         }
    3 h. z1 [! o0 Q, K$ O4 b# ~0 }; x
  14. }
复制代码

7 {+ @# M: o5 [3 z
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
- V+ U3 z/ B% ~4 Q
看来简单的把require理解为替换,在这里行不通。

/ y# f; ?  l2 I6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。  a: N2 O8 A3 G2 h
  1. //name.php3 T2 |+ I9 d9 J2 v1 P/ \

  2. 3 G5 @* l2 T( e. M1 _
  3. namespace test\person;
    . g% `' \! A& V( R

  4. ' g, p: Q4 q; a
  5. class Person{
    : ?* `# t# x  W& t' p
  6.     function __construct(){2 x3 q  H; _9 G. k& K) z- F
  7.             echo 'I am test!';
    0 N0 i0 t; Q4 A. v5 I+ A
  8.         }
    ) U* P' B  |8 q6 b: j* n
  9. }
    ' W1 C' Z# ?) S# I# o! \6 c
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

2 B; |) e/ W7 E$ ?
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

8 k# V' _: C7 r( ?, ]7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php$ k4 P$ z0 [% N4 G5 w. y

  2. ' W, T5 n2 m% v
  3. namespace test;
    $ g) @8 ]0 P& t; y+ i$ ?
  4. echo 'zhai14';
    4 `: Y$ q! y, K
  5. namespace zhai;' O0 c, x2 i# v; O' |  W
  6. require './1.php';
复制代码
& i+ ~  b" t& \8 E( i+ a
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
& z/ w- E' |) u3 z4 a: ?
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
" h+ c2 b4 A) [- M0 {. n
  1. //name.php
    ; ]: J. J. \! u9 T2 [( f1 G. y

  2. 0 _+ c* Y) u7 k% Y% m  s
  3. namespace animal\dog;* r! [4 s) ~6 n1 q: N- A3 `

  4. 9 V0 P; P$ x, m+ n$ d
  5. class Life{
    0 x  Q' F( ?: ?* M: k
  6.     function __construct(){2 H* L; z% o* l( ~- t9 f
  7.             echo 'dog life!';
    % K$ h  w& W, b
  8.         }" K4 V5 R% s% c, _, B6 O
  9. }+ i. e- x# k' A9 u6 F! a

  10. - L( }/ K. i/ ^3 |% b$ n) p, q
  11. namespace animal\cat;
    1 |( B4 ^9 g- ?" L! V/ N/ ?

  12. * N5 V$ S/ z! p$ z
  13. class Life{. Y  I  _; H4 ~) G* L/ f8 o6 Z
  14.     function __construct(){
    + E  x5 D+ X8 {  ~) T: g! N
  15.             echo 'cat life!';
    / {/ u2 ?# P/ s- k% K  ?4 \
  16.         }$ [# Z, Q3 f7 V+ \
  17. }
    # c' E0 u* I5 R" T! p) ~

  18. # H9 c, \9 W5 N: |
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    - q9 s: G$ W( z# Y; U# E
  20. new \animal\dog\Life();  //A% G& I$ Q/ p3 u. i
  21. 8 ~2 o$ H1 M% h% ?! Y0 x# I
  22. use animal\dog;  //a! z% s! P2 j) s) g5 ?  `
  23. new dog\Life();  //B
    . O* j$ Y0 j  C1 Y/ d: p9 _

  24. . Z* K6 J% t, C" d" M7 V, c
  25. use animal\dog as d;  //b
    2 B! u" X4 D' q% _- h, p& N
  26. new d\Life();
复制代码

( j% }1 L$ k  w& k2 K
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

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

- Y7 E, C1 {6 @, C( s3 H  K% a8 w7 M
相当于
  1. use animal\dog as dog;
复制代码
! r7 I) \3 {0 x9 c% `9 _+ |  ~
2.namespace后面不建议加类名,但use后可以。
: q5 K2 a+ w# ]) A
  1. //name.php
    ' `; z) Y# ^8 d% h

  2. % k6 ]/ s: G& c, ^( d& n
  3. namespace animal\dog;
    9 B2 F  a( f3 D8 ]; ~
  4.   s1 `6 r/ q( y' V
  5. class Life{
    % \4 J  E; N# k) @
  6.     function __construct(){
    5 c1 A' m( _& D
  7.             echo 'dog life!';
    5 O1 y* S5 v( ~" ~
  8.         }' C& o% ?8 z  }, n$ G% |
  9. }
    ; z. J: `6 Y4 c! h2 a

  10.   m7 Z- S7 L7 f, n$ X7 M
  11. namespace animal\cat;
    ! C- H0 U: Q: z$ ?
  12. ) V- N1 b5 J6 u9 C2 Y% S
  13. class Life{
    / {* M9 V, M7 q( @
  14.     function __construct(){; P' r! d- B9 ?8 k- D
  15.             echo 'cat life!';
    6 N2 R4 Z; z( T
  16.         }% l. I8 F9 q1 I' \- ~1 \1 F
  17. }
    0 h* O5 ~6 L+ d$ X2 A
  18. 2 [! I  {/ \2 C8 m! k7 k7 J0 k
  19. use animal\dog\Life as dog;  
    * `% j4 ~  J" o) u4 `
  20. new dog();
复制代码

) m0 g" X6 `! C) U  V" Q$ F: R: o
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

8 E( M$ M' _: r% E& k
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php( e5 p( ?. o' f: }& n3 E9 O0 v

  2. ( l4 r5 z4 x7 L8 J
  3. namespace animal\dog;& y0 q4 X3 d" M5 K2 }
  4. 3 M/ b5 Z! O1 l
  5. class Life{
    1 ]! u" c1 I: ?, v8 ^
  6.     function __construct(){
    ( E* b; j; k1 u$ n0 H! e4 M( z
  7.             echo 'dog life!';% l9 x1 b( y9 Y7 b" M9 E9 {& N
  8.         }. g1 A# j9 c- }
  9. }/ R, `5 h7 }" L0 U: q. f
  10. class Dog{
    2 }! h  v9 `" M/ ^( H$ \/ J5 X
  11.     function __construct(){
    ' [/ O) _( g! m' E
  12.             echo 'dog in dog!';
    * m1 D3 N, I9 i" M$ D4 L
  13.         }7 m$ L) M+ U3 j  w0 j' i- A
  14. }5 r: f3 _: V4 h5 l: ~; [& ~

  15. , B! s, p2 k. Z5 W# b- D  G. d8 n
  16. namespace animal\cat;
    7 Z) z7 c; L) ^1 Y& o; k( v
  17. # H7 {: p9 C& q6 s: ~; }8 H/ g- K
  18. // class Dog{+ i6 }$ h0 A" h# t
  19. //     function __construct(){/ r* \, I# X% M8 b6 l  n1 P& o
  20. //             echo 'dog in cat!';5 q3 x! p( g" W: q% I/ i9 K0 l* w
  21. //         }5 \! L* u( z8 x% }, g. G* R- e" o
  22. // }
    8 _- ^  H( [' e7 p6 d
  23. class Life{
    + x/ z. L! ^& o
  24.     function __construct(){
    / {& z; r- H, `( ?' j; Y4 a) G
  25.             echo 'cat life!';# Q% Y* P$ \# n8 f9 e" Z$ y
  26.         }/ I6 D. A6 K5 U  J& g& Z/ C$ h
  27. }
    % s+ _0 T8 m/ d/ g+ B6 a8 k) u
  28. , x$ }5 n+ q% A' D$ A
  29. use animal\dog;  
    4 n& G1 _+ `5 B( O# B% h
  30. new dog\Dog();
复制代码
# S4 n( f! X  J% M) {
如上,使用了
  1. use animal\dog;
复制代码
/ t! P- [0 B- Z: L- j  ]
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

2 x0 C2 w% _2 z5 r3 S* s
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
5 k  G3 J8 N. B4 C; r; q* {1 `

! |+ U  v1 h' A' U! r  x  ]) M( k: ]- F

6 i$ P  q, p4 y# w& ^8 }8 f2 U
& {# \* k5 i$ E' f3 y
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 00:12 , Processed in 0.056181 second(s), 21 queries .

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