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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
* X+ h( s* `- V7 E2 Y' D
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
$ ]4 P8 L4 |7 a/ Z, }$ t3 N0 r
: K8 E* l% B! d2 j6 s. r. ?1 E) k
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

5 a+ J8 B/ d7 s9 g' a1 ~% y) j
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

. N" E! ]; n0 n3 N结合使用方法来进一步理解它的使用目的吧。

; G) S* n; J0 W! S" s% m3 v; g
. X* W: M) w5 _' ?/ Jnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;! T2 ?2 r1 U8 W" N& q' Z) t. G
  2. namespace One;
    5 l9 t' C% M$ R5 k
  3. namespace ONE;
复制代码

( {, `6 D$ M; e/ k9 v; Y3 o- J
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
  D+ y& k# R8 y/ U1 t# `2 y0 h
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ! {, i4 n- x$ ~) ~8 z3 K# Z
  2. class Person{
    0 I. i' K. _% Y/ G! h
  3.     function __construct(){
    5 ^! _2 S) t: X4 A; G( G: o7 ^) ]5 L
  4.             echo 'I am one!';3 w& r0 r# r9 r7 `& e
  5.         }
    7 Q  O) P' ~+ L1 x
  6. }
复制代码
  1. //name.php
    ' H9 W2 G* n9 X9 ^5 N3 H) Y5 ?
  2. require_once './1.php';6 b$ X9 g8 r' q- P4 ?( f$ u' K
  3. ' ?' G( @* x  X: p" E
  4. new Person();     //输出 I am one!;. z! S# A/ C1 _) \& T8 Y3 u
  5. new \Person(); //输出 I am one!;
复制代码
4 J2 v4 i) v' L- c+ y* o- w+ Q
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    ' M4 m9 ~5 v0 p" @5 _- g7 @( {
  2. require_once './1.php';, x, i; ~( ]7 T
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
1 j; d- @7 j5 a' |
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    % p) O! ?1 g$ K- Z5 J
  2. namespace one;/ [8 s. m1 s8 {8 j' k  V* k
  3. class Person{! k9 u5 E7 O! d# e# ~9 n/ J* B$ ]
  4.     function __construct(){
    7 H% w, j5 I6 ]
  5.             echo 'I am one!';8 Y4 h6 g% F  o: Z; q
  6.         }
    " D, N8 D9 q: H9 D; W& E+ v- V1 E8 i
  7. }
复制代码
  1. //name.php. J7 Q$ j) [# j0 I4 O; w$ T7 p5 R, r
  2. require_once './1.php';
    7 p9 d3 }0 o' V3 A: u# T# ]
  3. new \one\Person(); //输出 I am one!;& N$ Y$ H% {9 g/ }& N8 J1 K
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
3 u- t; P0 ~) @* U( v, R$ j
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
8 S8 N) n& w3 r
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
+ Y' ^+ V3 T' o& G8 ]& ]& h1 a
  1. //1.php   
    ' z. X0 r% K4 D6 @5 i  |% Q: u
  2. namespace one;
    . b+ g: E1 D5 {! b  H
  3. class Person{. [6 C- I% h$ [
  4.     function __construct(){, C, b+ u2 x5 h9 i  }
  5.             echo 'I am one!';
    ' n5 [* T2 v& t, x6 \9 c  D- c9 Y9 I
  6.         }# y. i, s/ S- Y
  7. }
复制代码
  1. //name.php
    1 X) }, u+ K3 d/ t/ }
  2. namespace test;6 R, Y) K& E$ L; K* {5 a
  3. require './1.php';
      r+ s, w) Y0 ~6 |# D8 t3 w
  4. new \one\Person(); //输出 I am one!;5 b4 _  j% b- ]4 a
  5. new Person();      //这里结果会是什么呢,猜猜看; i! n2 ?4 u# t/ q+ w6 x
  6. 最后一行结果报错:# e1 D* \5 P% t* t2 R
  7. Fatal error:  Class 'test\Person' not found
复制代码

3 u3 ^+ W& k5 B# Z6 X% G. }& B

2 M4 @7 o. [) r3 m6 t  M% v首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
6 \$ m# }9 ^: X( ]! N( |) O- y# u
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

/ O; h5 v5 i. Q; W# @
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php# P* U% S6 I. N" R
  2. namespace test;
    7 N' c/ s4 T$ ?$ s- S8 n
  3. require './1.php';
    0 i) t/ J' w! F% F/ W- y7 {
  4. ! M* K" V- W* G7 Y+ ?
  5. class Person{5 {9 B" l- z' r% J4 y
  6.     function __construct(){+ e6 ?" F. X) V* A
  7.             echo 'I am test!';
    $ |7 ?$ _* b1 m  R* h2 A
  8.         }
    ) w& P: J& V# U2 n4 H4 i* s# H
  9. }
    0 g4 ?  z* q' B$ W# ?* h! \$ b

  10. 6 v  D; V' N) S& Q5 j0 R( x
  11. new \one\Person(); //输出 I am one!;" |' I/ R& L, p7 u6 m) v8 `& G6 Y% ]
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

: m2 M+ S" B) \9 g0 @. f% V
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    1 [$ A! F4 _4 `8 o+ |+ l2 e
  2. namespace test;7 S# ?0 z) e0 A
  3. namespace one;
    4 W$ J" t, I* Z8 _8 ]& W( t: R
  4. class Person{
    7 M% ~" t! t) p7 M! }% j% B
  5.     function __construct(){
    # Z1 Z+ N, D. a2 w, j
  6.             echo 'I am one!';$ u. F$ P0 N1 v6 Z2 ?
  7.         }
    * w' |" _8 R2 ^) W2 D  ]' T+ @/ P
  8. }3 `; e7 i; V* |" b" H0 z1 d
  9. $ T, e& Y6 t- s9 y( z, o- _% {. O
  10. class Person{
    7 ~* a8 t2 I1 H, P+ J6 U
  11.     function __construct(){
    & x% B) g) x$ Y9 C0 H
  12.             echo 'I am test!';7 B* N( O+ G- e; ^$ W- F9 w
  13.         }
    * ?  z6 x2 B) M7 }* ~
  14. }
复制代码

4 I2 p# y4 p* Z5 @8 s  E4 Y
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

5 t" Y: v5 R4 S2 R* M6 K
看来简单的把require理解为替换,在这里行不通。
! z; b6 O  x) [; m
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。9 f* J+ ]5 d7 D/ z# L
  1. //name.php9 T3 e) w( d) P4 ^' U5 P, \

  2. ) D' _) u  L3 T. v" b
  3. namespace test\person;/ q* H% ^$ X( F! j8 {% _( G' @/ |& i
  4. % s* G% g& Z. Z% l7 s
  5. class Person{: u3 b) e* @" S: U: ?% i
  6.     function __construct(){6 u3 a" W4 ]  m/ c. W' K
  7.             echo 'I am test!';: @  x  M* G) q" @
  8.         }, j/ J3 |  \/ c) A) B% ^( T
  9. }5 P. l7 X& N1 K) T/ N; e: F
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
5 W5 O, f7 `" B5 w$ d% e
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

( a2 R# u0 ^$ i7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    + E6 d' d5 K: N* J+ Q' y

  2. " `" d' C7 t0 F0 @
  3. namespace test;
    5 r8 Y# Z4 v- o# y
  4. echo 'zhai14';
    6 v! ]1 l- D5 O5 k: Z  u
  5. namespace zhai;
    $ j# O- G  Z5 q9 M/ ?' ?
  6. require './1.php';
复制代码
: T& X- {& L5 p' Y, N
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
$ V1 O- [5 T$ B9 \3 G! h
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。2 i" X% \: H( \7 U+ A' D, m. b: c$ n2 u
  1. //name.php
    . g  ?3 w; |0 B  M: Y  o* Y

  2. 2 m+ w' O& r# R& S: @- u2 F
  3. namespace animal\dog;
    $ p8 V. s6 I' V* v2 i, E5 Y$ T

  4. 6 X: h; B  X$ M8 U/ g
  5. class Life{) [' N2 S6 @% p0 m
  6.     function __construct(){
    , l! b5 d) X. S' g
  7.             echo 'dog life!';
    * A2 L+ j8 n0 v$ J
  8.         }
    1 g! b" D" {% B  v3 [8 r: n
  9. }
    # t) x: {: o, g3 @$ W7 e
  10. 2 p1 v- {" ~/ S2 o
  11. namespace animal\cat;4 d$ E- R$ r; b8 Y# W3 g  v# e
  12. 5 H5 Q& Y, ]. E2 \
  13. class Life{' S, H/ K6 x+ T
  14.     function __construct(){' m6 T; i" Z7 ~; q- B
  15.             echo 'cat life!';; z  U* s) c$ M$ y9 D  O( J
  16.         }+ M9 ^* i  M. `: K
  17. }
    + a! g' P) F  \/ F/ E! I* M
  18. - }$ N% ^5 q" I2 d8 Y' Q
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间; F1 Y- y- {* L8 ?
  20. new \animal\dog\Life();  //A
    6 D0 i1 s9 C- Q
  21. ( a# H  f# G6 ?& b) W5 ~
  22. use animal\dog;  //a
    2 n$ v* {1 g- b. j0 ?
  23. new dog\Life();  //B
    " q+ a3 E# H- V- i
  24. - b1 z8 U9 M1 e$ L, p1 D
  25. use animal\dog as d;  //b
    4 l! l- z& g' ~- e! d$ i& F. d. W
  26. new d\Life();
复制代码

% _- I" a3 S. Q4 M( Y/ `
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
# [& m* V" K/ w6 E" e
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
6 J! u, [' C1 w1 T& `* X
相当于
  1. use animal\dog as dog;
复制代码

# d% u$ m0 m" l6 F2.namespace后面不建议加类名,但use后可以。
- y) a. l  z  |  e) b) S' Q4 S
  1. //name.php1 H! p' a1 \# F/ P/ P1 t# o! D
  2. % @8 Y2 X# `/ ~3 ?
  3. namespace animal\dog;
    1 w' o5 b, q/ a" v8 }8 q2 F! H
  4.   q  t7 ~4 J% m) U2 e, K8 C2 F1 h
  5. class Life{
      T3 T2 Q1 }, h
  6.     function __construct(){
    9 M1 E! i: ~3 M7 {5 n1 S+ ^0 G. _, M
  7.             echo 'dog life!';6 W" S0 C( M: g9 r' B: W1 G
  8.         }. W4 |1 P( n) G9 l5 a
  9. }& |. D4 A. U; ~

  10. & _" p" Z* z2 K7 s; b$ S
  11. namespace animal\cat;+ `2 O& |/ [8 d/ }& c4 r

  12. * d' D- n( r- z/ g
  13. class Life{
    " x. U6 V8 R0 A; R
  14.     function __construct(){2 U1 k; O  T! P- T& ^9 K
  15.             echo 'cat life!';
    . a5 _0 ?! X" a% o3 V
  16.         }
    6 c9 M: B. X  v0 z0 q9 c
  17. }3 a# D1 x, I) B8 \! I5 O
  18. & O1 P. k0 G; C6 t' p: D) v' q( ]
  19. use animal\dog\Life as dog;  
    6 Q+ E8 ~, [; U: o+ y
  20. new dog();
复制代码

7 P: N1 W6 \* C- i: \" y* j
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

/ f0 c' U' m: e5 F
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php: e8 h7 R, n* F4 @5 Z6 t; k

  2. & B. Y& S1 f! \" {  @  r
  3. namespace animal\dog;
    ! Z, w0 C- y$ r! Z9 n8 M$ T' t! Y+ l/ w
  4. 6 j% P  Z& x- I& x  w& D8 ^- M
  5. class Life{+ {2 b  i1 h4 W; Y
  6.     function __construct(){
    3 R0 U3 ?1 |2 f2 i  ]$ l3 X% P7 e
  7.             echo 'dog life!';
      L5 \. |* o: p3 V& ^
  8.         }
    " A. N6 `6 Q7 H4 |4 V
  9. }
    1 v: Z& }1 y$ z8 n7 X* l
  10. class Dog{" y, s6 M' x  I
  11.     function __construct(){
      T. K8 f7 L  B% X4 ?
  12.             echo 'dog in dog!';
    ( v4 Y; R) E3 D- j
  13.         }' w) ?& J4 Z; X; X+ E# f
  14. }
    ( M+ U- V0 ^. f" Z6 d2 @

  15. 4 g& g' e$ E, G6 m: `
  16. namespace animal\cat;
    1 }: {9 Q3 _8 a2 p

  17. " e. h' |( L7 J3 S) c, _6 v8 `
  18. // class Dog{+ d) Q6 b* I7 c5 _9 R1 B
  19. //     function __construct(){  l2 `$ X! t: ], \9 {- g# y6 v2 [. K
  20. //             echo 'dog in cat!';
    , y, r0 x" Q1 o. K( F$ I
  21. //         }1 A7 O. u8 m. S
  22. // }
    3 ?6 L! V8 Y" o. Y
  23. class Life{. k6 o9 ?' `7 i: |; f# V: T
  24.     function __construct(){
      E3 w: u; l" }1 w/ @
  25.             echo 'cat life!';% E* s5 ?* a6 _$ r" x
  26.         }
    2 z" d6 ], Q# g* j
  27. }& Z0 S& I: N! r

  28. : L1 j9 Y- r8 ^- V2 @5 O- ~
  29. use animal\dog;  
    , V' v5 ~# F& U: B! G3 ]
  30. new dog\Dog();
复制代码

; G9 I1 w: ]6 I! t
如上,使用了
  1. use animal\dog;
复制代码

# s8 i! t( I" z; H
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
6 R; j" f' A. q% I5 v
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

8 S2 J4 n7 U8 i4 ?
: Q6 U5 G1 K1 b3 j3 i0 M
  P6 S; }0 q1 ~% `. m4 b/ ]% f  X. {0 U

1 b6 J( U& l( A0 `- y& I# C
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 11:52 , Processed in 0.141619 second(s), 19 queries .

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