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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 8498|回复: 0

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

[复制链接]
发表于 2020-7-1 23:37:46 | 显示全部楼层 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
1 h( _/ y, \8 N: g) V
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

: u9 G3 w. i, h" B+ X2 l4 I& l7 o
/ }+ h- r9 p- R7 H使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

2 y) X) @4 Y7 P* G" A3 \- z/ h
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

6 W! k7 O5 y1 X% n, v; F& j# v结合使用方法来进一步理解它的使用目的吧。
$ o1 V: N- m  b0 w
" Q6 ?- C  Z6 H) m2 o
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    6 Z1 `1 k( s9 m. O; @! y
  2. namespace One;
    8 Q' o) w5 i2 T/ i3 O- D1 e
  3. namespace ONE;
复制代码

2 N% o. K5 m/ ]6 Y$ i+ L& e
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

# v$ O0 X2 t$ s) G( I* A9 f. u! O# |2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    ) b1 ~- t. }! `+ W6 |
  2. class Person{
    / W! d. R& A' Y" U4 g+ `  J
  3.     function __construct(){/ y6 W+ z6 x7 o+ T" n2 K8 q
  4.             echo 'I am one!';
    % {, ~% M' G% I4 l+ n
  5.         }6 i1 X. i- G2 F4 v. B# X% ?
  6. }
复制代码
  1. //name.php
    9 f+ W/ J9 _, E
  2. require_once './1.php';! {" Z+ {& t  H
  3. ( R- N. X5 I% J$ Y* ?3 L2 {
  4. new Person();     //输出 I am one!;
    % R1 a1 R  G1 w% w# p7 }* c" N
  5. new \Person(); //输出 I am one!;
复制代码

2 w4 o# @; O8 z8 U! o2 ?8 Q3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php) y4 V) i# I2 G, ~
  2. require_once './1.php';7 [' [& J+ t5 i9 @- u. S, m4 {+ I8 ~
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
! M5 T& P' r; L
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    & }  P7 l" X: A* ^+ E/ |
  2. namespace one;: I4 O+ j/ f0 v7 \
  3. class Person{
    $ F$ s) {/ h$ U, Y
  4.     function __construct(){
    # ]8 q: `3 |" N! I
  5.             echo 'I am one!';
      {/ `1 Z/ I* [) c
  6.         }7 r7 E) a, N  p: G1 M
  7. }
复制代码
  1. //name.php# D9 Q0 B& X! I1 s: s
  2. require_once './1.php';6 U$ u: @; F* E8 m
  3. new \one\Person(); //输出 I am one!;8 a4 P5 e( k6 J$ z' W: q
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
! r2 C* E2 @* |0 U' ~
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
  K* ]5 O) _5 A6 z' c. w9 K
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
2 G1 a% I& N/ k* l( x7 c
  1. //1.php   
    1 b2 T" m0 E2 Z8 C, k* N: P* K5 ]
  2. namespace one;
    ( A4 k2 d& N& e) M! Z- s2 m' b7 u
  3. class Person{! f5 m0 `( {" @' T! x/ ?
  4.     function __construct(){! s- X! d6 z+ W8 i
  5.             echo 'I am one!';' e% h4 j  _  l, l0 f, z7 Z5 H/ k& P
  6.         }
    7 n: ?* g) g% T0 d0 n" ~- H+ w
  7. }
复制代码
  1. //name.php% J8 j! A$ k2 M9 z; G
  2. namespace test;
    2 z! z  o+ `# [
  3. require './1.php';   _+ W* r% m  y( l; S
  4. new \one\Person(); //输出 I am one!;
    + ^  E2 f6 |+ }4 x# W. n
  5. new Person();      //这里结果会是什么呢,猜猜看7 H/ D) n( _* u* a# a, F0 V
  6. 最后一行结果报错:  O1 Q0 X3 e/ O0 @+ L8 s
  7. Fatal error:  Class 'test\Person' not found
复制代码

$ E/ ~$ e4 Z4 f0 J1 w7 t% `  {) d

6 x: B- a) _; V/ ~首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
# H- T) U8 ?+ `" s" K
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
  A, Y6 [% K! b$ [
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    0 c# L0 N# X& m- y+ y
  2. namespace test;
    $ r9 N. X( s/ X/ p, {. i
  3. require './1.php';
    - x% D  p' o. z! g' R" b* t

  4. " c6 L& [5 }# Y5 y. U
  5. class Person{
    & a3 _# I; P& w2 l* \
  6.     function __construct(){7 B) }( l9 C# C4 o
  7.             echo 'I am test!';
    8 x, M- d+ m/ }) @/ B
  8.         }8 t0 D% M6 |  [/ ?7 W7 a
  9. }0 {1 ]$ X+ y  d% N' f% k7 E( W

  10. ) @4 @* g3 i0 x! [# v; z, J  a
  11. new \one\Person(); //输出 I am one!;% ^  l, P/ U7 [3 q/ P% M2 ]
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

( t2 p2 g/ d+ I( c8 [
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    - e8 V" c; f5 q, ^9 n6 w
  2. namespace test;
    ' R) K/ S7 ?: u
  3. namespace one;* X) j4 Y- m) A) p! u/ f
  4. class Person{3 g) \) {7 x( N, A/ W, N
  5.     function __construct(){
      i/ M, b( X# w: ]1 X
  6.             echo 'I am one!';
    ! \5 K: o$ i8 Y7 P3 A0 Q& J* G
  7.         }  Y& P" L6 q" j' _- G: Q& A
  8. }& O- e% ^' L$ y& i( n

  9. ) f  ~5 S% [# K$ Y$ B; j* J4 n8 \
  10. class Person{
    $ j7 a0 x4 G7 j! v+ L+ L0 h
  11.     function __construct(){4 t, I0 A0 Z+ x# ?" D0 ]
  12.             echo 'I am test!';
    0 H1 M% v( [' t+ ?- l& L, {. |
  13.         }
    " p  P9 C6 q: ]4 j  A5 E; g( `2 {
  14. }
复制代码
6 K( V" Y) x  J0 a% I7 w
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
+ n/ j  _, c$ B% [6 ]; I
看来简单的把require理解为替换,在这里行不通。

7 K3 ]0 Y7 i  ^& B6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
* q3 Z( M9 n; K% l) r" d; \  G
  1. //name.php
    9 y$ ^. G  o7 s; c  O
  2. # ?* J5 l0 G3 v* P. ~
  3. namespace test\person;
    % J* d* [- C# ]
  4. : h' z# {2 `; b4 @# Z' ]
  5. class Person{
    $ J$ m  W1 F9 Y& z  T$ H/ D
  6.     function __construct(){) y1 `+ y$ d0 m
  7.             echo 'I am test!';8 X0 E; s2 S+ T, ]# W$ U3 e4 m7 x
  8.         }
    * Z% X) p( }* Q+ d7 X
  9. }5 r' Q7 J2 q  G5 i! t
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
: D2 L- i0 N% b$ H! [; J  a" q
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

9 C8 @4 s9 M7 |+ R* E- f* u) t7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    , ]9 f9 p, K2 ~0 w
  2. " D: P( |- X- e$ @7 }/ F
  3. namespace test;! ^  o/ h& ]+ _7 |
  4. echo 'zhai14';! J) `- L8 e2 r4 m$ V
  5. namespace zhai;7 H, T$ o+ n' W
  6. require './1.php';
复制代码
9 ^, w/ X6 ?6 i( V9 C' n
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
( W& w1 h: u, B& h/ s5 ?
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。0 u$ \- `' z3 F4 s1 h$ r3 g+ j
  1. //name.php
    5 ]- x; `8 C; ]/ V0 B# v! Y

  2. & b  [! {8 ]& b" z. ]( I
  3. namespace animal\dog;
    1 Y1 H( q1 t7 |) w  L8 U

  4. " }% l0 I" W% \0 r, M3 v, R
  5. class Life{: X, F& i) u' q0 O* F4 q
  6.     function __construct(){! F% K7 ^7 C1 I1 A% E1 Z, [
  7.             echo 'dog life!';
    8 J% r# z7 j/ ]2 h' @. f! s6 i
  8.         }4 e1 U. N5 p% Q8 i9 ?
  9. }; W3 g* ~9 t; J# ^" u: G
  10. 2 Y; t2 I* Z% C
  11. namespace animal\cat;
    5 j+ ^; A) G1 ]& ~

  12. 8 ~. r; B% T" a% r/ a( Y+ Z
  13. class Life{
    $ R; @" ?+ k/ @
  14.     function __construct(){
    6 S$ h2 q+ K( W" b: A) h' H
  15.             echo 'cat life!';2 t  G, F( q  U5 N) u+ b
  16.         }
    / g- o3 f0 j" K' T# S$ r
  17. }$ P- Q$ t( d* A( V( U

  18. 4 h! R/ w) n2 V8 y) Y" |
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间1 |- j3 N9 U2 p
  20. new \animal\dog\Life();  //A" i+ Z: g  V3 U1 o. r5 F* E( S; Y
  21. / Q0 |/ ~4 I4 u
  22. use animal\dog;  //a
    5 h' G8 q) V4 s0 e% n# S# w! B
  23. new dog\Life();  //B
    : x: t( P8 ^  H( D6 R, w; y9 n

  24. ! ~; M) f# x2 ]8 P+ ~
  25. use animal\dog as d;  //b
    ( r1 y. b" K! y" N  P
  26. new d\Life();
复制代码
2 ~) h# b! F% k8 e
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
/ l5 D" b: r9 \7 ]. D
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
4 a" ]+ c0 z1 u: g" Q* z" d
相当于
  1. use animal\dog as dog;
复制代码
6 F7 k8 i" v1 l( V
2.namespace后面不建议加类名,但use后可以。/ f* \# ?2 \) D
  1. //name.php, E! Q: M. h6 Q' r
  2. % o* X3 u' C( k# I+ Z! r
  3. namespace animal\dog;: f  R4 S1 ]6 }) e6 {/ u; D

  4. 9 F7 h  K0 ^1 B: w
  5. class Life{2 m, z7 C" P& \' g- x
  6.     function __construct(){0 @; K" j0 _! t/ G6 Q
  7.             echo 'dog life!';
    2 Y, _% L: R' Y, X
  8.         }, T) J, s2 o8 Z9 O) w- G7 ], L- j
  9. }" b, s2 u. Z5 a+ B2 N( _6 M

  10. , J- ]6 X+ e) o0 p9 n
  11. namespace animal\cat;1 j! g% {9 x" \

  12. " R8 F0 D8 z, T6 k: W0 S5 P
  13. class Life{
    1 Y% D/ y1 G" g' c# }
  14.     function __construct(){
    7 w' ]  Z& F* }9 R( n/ }
  15.             echo 'cat life!';1 v0 |! n0 M* f! v0 }
  16.         }) m, Y, a4 h; w4 h$ _" f0 C+ I; b
  17. }9 o' ~9 a! p1 w9 }; ]9 W

  18. % m' a5 ?5 s3 a4 R
  19. use animal\dog\Life as dog;  4 k, W, W- I0 A3 \6 r% v
  20. new dog();
复制代码

! L) \$ ^! s& B+ y# s* M7 g
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
7 M; t, b: E6 e8 K( K
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php1 S" z5 v) {- R  w

  2. ' j# y2 m/ o: \' f/ Q
  3. namespace animal\dog;4 I# ^( X( l+ _! k- G
  4. 4 Z) ^: o" v5 l& L# t
  5. class Life{
    % Q; S' L$ S" [
  6.     function __construct(){
    , ]4 q1 D' i/ E; M! f
  7.             echo 'dog life!';  w* K6 ?  I3 G9 R; _+ ^2 G) D
  8.         }
    5 G8 C0 {, u4 c& u
  9. }5 ~0 x+ F& s& |0 n: q: l2 ^
  10. class Dog{
    , ^/ G$ h- `* u- g/ Y5 e
  11.     function __construct(){& K' Y- R& |2 P
  12.             echo 'dog in dog!';
    ; @2 s, x7 E+ z* W8 Y
  13.         }* \( v- q2 s6 F
  14. }8 F5 n0 J, X# \9 |

  15. 7 A1 m  y, a8 m* e" H& ?! t7 h. z
  16. namespace animal\cat;
    ' [+ N" a  \4 e
  17. ( |/ h  u! t$ W# |/ b
  18. // class Dog{
    - W6 x+ w+ h/ R; [) Q6 h6 n
  19. //     function __construct(){. G. C) v; [7 @0 E
  20. //             echo 'dog in cat!';6 M, b! `+ v8 o2 T/ Z, j
  21. //         }
    ' O" k- O9 r( |' W: q) Z5 |9 J
  22. // }
    2 I0 V1 Q+ W# c+ q$ l) R
  23. class Life{
    ( I4 c: I8 d& |# `$ e
  24.     function __construct(){: s1 U3 [6 M& c# I  ^7 U  l
  25.             echo 'cat life!';
    1 b* a3 R6 {" `7 ^
  26.         }, e6 M8 L! X7 B/ v8 ?1 ^
  27. }
    / j& n' _! b3 G
  28. / M2 y7 c& m6 j) R
  29. use animal\dog;  
    0 R0 ~0 v; ^+ i
  30. new dog\Dog();
复制代码
7 M4 k) w5 f' ~, D5 G
如上,使用了
  1. use animal\dog;
复制代码
5 p0 B: I; |& A. p
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

3 I$ [0 h7 t, E1 H
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
! j: v. B. R4 _- b- F- y& s3 c

+ U+ H: i, G0 @8 c) l9 C" K( H- x; y; G

- R& m! \2 H2 N7 E0 H% s6 Q8 s' x2 i! b6 k; A
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-3-29 19:48 , Processed in 0.186994 second(s), 22 queries .

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