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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
1 C: T* @. k! r6 a. x5 C7 l
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
6 G( w- F. ]) y& `4 N+ n

* K6 U4 x$ [$ I+ K使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

4 L+ V3 m* r1 G1 m, ]; E4 f结合使用方法来进一步理解它的使用目的吧。

, X( V, ^$ G* _3 k2 R: p. h- N( p9 G4 q
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;( }* }; R9 H" d/ a6 t2 L: J# v
  2. namespace One;& F2 _- e0 \9 v& G; @! R
  3. namespace ONE;
复制代码
# t) z# E8 z% ]* j" }* Y6 |8 Z
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
8 m1 q9 {; E+ A: X; t8 i$ T+ C' U  v
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   1 @6 E5 C" U2 Q" p* q
  2. class Person{( E, D/ ]; h' L
  3.     function __construct(){1 b( i0 p' D$ ~/ h
  4.             echo 'I am one!';
    1 v" a8 Y8 Q6 h6 x: h* d
  5.         }
    4 d7 r# w/ R. q9 }
  6. }
复制代码
  1. //name.php9 i$ a1 n4 _6 u" t, \
  2. require_once './1.php';0 J7 k1 G9 B8 s* U3 Z( U
  3. 2 ]% C2 n' n2 p. M
  4. new Person();     //输出 I am one!;
    0 U, \( G( N5 b  I$ L0 x
  5. new \Person(); //输出 I am one!;
复制代码

# W! x; |# L, V/ w2 _9 n# W3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    ' _  k6 P. F; D9 y7 g9 z
  2. require_once './1.php';
    8 s7 `/ m5 p: y+ @; N/ _7 x: b
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
  J- R0 `, u% N7 @/ j: Q% X
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   , b  \" J0 |" `* y! |! ^! ^. X' L
  2. namespace one;. j; d4 d- e* Y( c
  3. class Person{
    ( a5 _0 B8 Z! s* `, `- U  ?
  4.     function __construct(){: L  N3 c# G  e! ^
  5.             echo 'I am one!';
    1 N+ {1 J! _) I2 @* b0 P/ e: L
  6.         }
    8 Y% L' L4 r- t
  7. }
复制代码
  1. //name.php
    $ h* e  G0 _- e/ k% Z& t/ b2 [
  2. require_once './1.php';
    . v5 L3 l1 B: q$ A5 p3 X" G
  3. new \one\Person(); //输出 I am one!;
    / L0 a8 O" \# z- i( w9 ~
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

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

  t( P, D! y. l9 J/ i* ~/ C5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。9 y$ U( g  e7 M# K6 U8 w, Y
  1. //1.php   
    $ L' r( W( J6 N, }, S
  2. namespace one;0 V$ e1 C7 K  R; ^
  3. class Person{
    2 p/ M! s5 _* N0 v) Q+ q3 P. [
  4.     function __construct(){; b1 a& V* M& _4 K; `/ M
  5.             echo 'I am one!';" n/ C/ {! b( \' e' V7 o
  6.         }
    . d6 I6 K4 k. C1 A7 L4 K' t4 u
  7. }
复制代码
  1. //name.php8 o' u8 G- S1 \) k7 }2 J' d
  2. namespace test;; `5 A/ H3 n" k0 K+ B2 q7 R
  3. require './1.php'; 4 b( V6 q/ n) }' ~
  4. new \one\Person(); //输出 I am one!;3 ~$ U+ }: r- }4 e" v6 |2 R9 a
  5. new Person();      //这里结果会是什么呢,猜猜看
    ' ?( Y! t6 E, B
  6. 最后一行结果报错:
    6 ~: N4 o( T; E5 n
  7. Fatal error:  Class 'test\Person' not found
复制代码
+ K" F6 y+ W7 u! q

# d5 y5 ^) `7 q% H首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

5 A5 _* B9 u0 g! j0 v+ J
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

* O* c& v. q% t+ _: }$ V/ T
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php$ ^# c3 f# i( P8 z  P  s! j
  2. namespace test;6 s8 C  ~1 u5 o6 x0 h6 n
  3. require './1.php';
      U) ?0 p. c' N5 l( F
  4. - D" J! ?7 M7 m9 ?' ]
  5. class Person{
    % O* G" z9 _. P( E
  6.     function __construct(){- a& q, v9 o& Z2 Q( E) C
  7.             echo 'I am test!';
    # i9 N0 ~; Z& ]; B% Z
  8.         }, Z$ N& R: w3 G6 f
  9. }2 l' d4 Z* N! _( P$ s
  10. ; P! }) m/ E7 F1 g& D# }
  11. new \one\Person(); //输出 I am one!;8 c+ Y9 z! B& ^; _8 V/ l  q) t8 N# X
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
, U4 a; F; \5 r
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php- D1 x! u2 X+ ]9 K( J7 s
  2. namespace test;+ u/ c" ~; Y# R$ D; i
  3. namespace one;
    # @) M1 h0 t+ Z: N9 h
  4. class Person{
    8 b9 x% D, ~' ]+ v5 w  b, G) N4 R& n2 L
  5.     function __construct(){
    3 X( E2 e2 h! [
  6.             echo 'I am one!';
    ' U6 z& m: @! \) k' z
  7.         }  X: O- _) g; L! b+ T' P
  8. }
    6 ?# |+ Y1 ^" L# t/ S. i

  9. 8 X+ U, x* v9 V9 R0 u
  10. class Person{; W, Q  h/ f2 n0 X8 t
  11.     function __construct(){; I) [# L6 R1 L2 X1 J/ V  i
  12.             echo 'I am test!';3 j' F6 G: [9 k# @( k0 ^% v
  13.         }% `, W7 l& P1 F/ Y0 U0 X# k
  14. }
复制代码
$ Y8 S, l) Q9 s+ ?' m" \) J% \
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

  z# o+ \- {9 K! w7 a7 y8 `3 W1 l2 I
看来简单的把require理解为替换,在这里行不通。
. Z. J2 t/ W. I* |
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
6 t8 M5 u) G+ j
  1. //name.php. a! \& x* d  Y  k) `" h. l

  2. ' }8 z. I/ m+ e
  3. namespace test\person;
    . K+ K% ~, q* O$ b' T" C
  4. ! p: ]$ N: K/ z; l* ]( R% Q9 _% H
  5. class Person{
    8 z/ ]" L. l. v6 Q! f" }- {
  6.     function __construct(){
    , a1 E& V5 P& M' b- O
  7.             echo 'I am test!';
    7 s- _$ L9 q5 }$ T' U; W
  8.         }; c+ M. y8 I( N7 V0 ]
  9. }
    . ?- L; l' b0 e& R3 K$ R( k5 P: y
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
* W- E( G7 \# p- v
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

9 l/ ^) ~, h. p# c; s7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php/ {) L: j* V4 H- X( o

  2. 0 p8 p8 `% M" m; H/ p- x2 Q
  3. namespace test;
    ! I8 M! b8 J6 @3 z7 f  p+ Z
  4. echo 'zhai14';* a9 P8 ~& U: M; V# W
  5. namespace zhai;
    ; D  o# {. C. w/ |" z9 N
  6. require './1.php';
复制代码

- ], j& ~; _/ J# l
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

# R& B8 s6 C; Duse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。" P2 t  _/ U( c7 X/ C8 h6 l* d
  1. //name.php
    7 ]8 _& B+ O6 w4 ~5 R
  2. 8 N, x3 P8 h9 T. V9 c0 Y% p
  3. namespace animal\dog;
    ; k  a& D7 @/ s" }  T# u$ x

  4. * I; r/ D& m: h- [! H" {, }1 t
  5. class Life{9 H  C- C. L( t7 l1 l$ M
  6.     function __construct(){
    ' P9 y; r2 w9 x1 @# r2 l: o9 p
  7.             echo 'dog life!';
    : ~- A) l7 e7 W5 r
  8.         }. J- |- K5 g) `
  9. }) C) b$ d$ Q8 r( X; r

  10. + X2 l& z" m& K3 x
  11. namespace animal\cat;
    1 h" |4 a/ I+ S6 _( _* n: H0 d
  12. * |  q. Z( n. s( U0 X
  13. class Life{2 M3 ]6 U, t8 Q$ j7 w2 H& {! M( u% ^
  14.     function __construct(){) b: o* S& c( Y4 C
  15.             echo 'cat life!';% S4 L) K8 r4 z6 N: C7 ?4 `2 ]
  16.         }9 z3 O5 h/ f/ K* n
  17. }' }4 u9 b* Y9 X: o) _
  18. + e* n4 Y+ N; r5 i$ T! z9 n3 U
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间+ }: C1 v9 P2 Y! j2 N" W5 T: V
  20. new \animal\dog\Life();  //A
    5 o. a3 _8 S& I% o5 t# H
  21. ( A5 K3 l+ K6 s! R* j
  22. use animal\dog;  //a/ R# q; B$ g( [2 y
  23. new dog\Life();  //B
    2 U- U# t4 s& Y7 g  m" n0 p

  24. : j2 z, R% E. O) n: f" o
  25. use animal\dog as d;  //b/ i( o4 R# g5 P2 R3 V
  26. new d\Life();
复制代码
9 i( w, r! P: }" b3 B, v6 R
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

$ @* x+ z0 X6 b4 h9 P/ n
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

4 n9 J& i& A0 D6 C0 J
相当于
  1. use animal\dog as dog;
复制代码
; Q; d: c: c+ I2 b
2.namespace后面不建议加类名,但use后可以。
  J0 Z8 F1 Z* I  i  U4 O! M$ ?
  1. //name.php" x9 q" K- y% Q8 t* D: `
  2. 0 ^+ B9 j/ H/ o2 H: M( S
  3. namespace animal\dog;
    ) }' L" G+ m7 h7 V

  4. $ V1 D  x' K3 N1 U* `* G; n- W
  5. class Life{
      u+ B% \0 n$ ~% }* r; {1 k( C- e
  6.     function __construct(){5 D9 q6 S( g: [: [, G; q
  7.             echo 'dog life!';
    0 F$ D. W# r2 A4 I7 u4 Z
  8.         }2 V$ A- B' @$ j" v( `6 H/ G
  9. }) y$ `1 T3 O8 {! {$ d) x# t
  10. 5 p1 o' `6 B  T9 ~6 Q3 s4 s5 G7 d
  11. namespace animal\cat;
    5 H9 U7 \: N) n5 u6 f

  12. 5 H4 @. J: t: u( ?
  13. class Life{5 R& Z* q  p% ^1 N& a1 e; I9 g2 a
  14.     function __construct(){4 X# K* c" E7 z7 I( ]
  15.             echo 'cat life!';4 m+ m0 P% u) W. l, a; ]
  16.         }6 |, F2 B! E' i$ F$ d. I
  17. }$ a& k% R( @9 g; D8 w

  18. - `8 G# Q) @* y( K" R3 U1 X0 |; ~
  19. use animal\dog\Life as dog;  
    0 c, b5 _: Y8 v$ m
  20. new dog();
复制代码
9 K- I3 u, g: H' d( ]) f
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

9 e9 u% L+ v- c
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php) B4 u9 O7 Z* _' W0 [: L8 L
  2. ) e8 S  l+ k2 b" f- e
  3. namespace animal\dog;( ~, X' r& a: m$ _2 t
  4. " ]/ a8 V$ J) F; B8 O! {6 _
  5. class Life{" e  A: b' n! @* {  u+ X/ u
  6.     function __construct(){1 t4 E3 v3 C5 b/ ]" U
  7.             echo 'dog life!';) D4 _4 }6 v6 W! I/ e
  8.         }7 E* z% @* z2 v% j, K5 w" Z
  9. }
    , Z" s* V* Q7 {* v
  10. class Dog{
    # m& c: T% Z. F, _3 W. c
  11.     function __construct(){: T! L% N6 u9 A+ R9 k
  12.             echo 'dog in dog!';8 o" C) R9 \+ ~  q6 U
  13.         }
    2 `8 n6 w7 J3 y, g
  14. }1 J/ l5 }7 d' ]# C+ \
  15. ; F0 a3 @. X& I. ]
  16. namespace animal\cat;
    2 {3 Z+ M8 f; s  V

  17. 7 }, s* y$ [" ?. B; m0 p( _
  18. // class Dog{
    / ~8 L+ {7 m$ `& T% w8 q$ [
  19. //     function __construct(){
    3 A+ D, C" F3 K0 @* ?
  20. //             echo 'dog in cat!';
    ! I$ z/ c3 L+ N, o' `
  21. //         }
    ! ?  v0 @% D" ~9 x8 @" {& U
  22. // }7 x0 c' N) d" ~# z1 y
  23. class Life{% N3 k3 \6 R2 X) Z: E; V
  24.     function __construct(){: E# B' P1 ]5 c
  25.             echo 'cat life!';/ g9 q( \! c/ [  J* R# o& N5 _
  26.         }! v( s3 ]( q: R; e) r6 l2 M1 E
  27. }1 x' j! f; B# F6 P
  28. ; G) k1 n) @) z+ k: _& _5 i
  29. use animal\dog;  
    $ }: N, }( S( m- Z2 m9 G
  30. new dog\Dog();
复制代码
- K4 w" D2 h! B- A$ q
如上,使用了
  1. use animal\dog;
复制代码

; ^. M' w# E, s' W
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

: t/ D0 o& P9 Q0 S7 U0 v- X2 y: o2 f
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
5 i9 v/ K& U  }
+ s3 R7 T$ J8 e9 W1 A
3 p9 l2 U1 Z2 S* _5 ~" G
. |) Z6 {! l- A- E3 a8 T
6 Q! H7 ?8 ^2 c' t
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-7-27 16:00 , Processed in 0.179684 second(s), 32 queries .

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