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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

: v2 a# W" O" ^4 G+ e6 i
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

/ x0 V4 n5 N- K3 I4 s$ L0 y3 ?8 N# x1 f& |- h/ m
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

0 v- n2 |3 o3 J1 L% M7 m: s& B5 c
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

: I0 c% _# ?' x* A结合使用方法来进一步理解它的使用目的吧。
4 u4 r. F$ X2 p  o$ T

( A/ V7 U! `5 W0 Q+ inamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;% i* r2 `3 J. \" S4 ?. Q( @6 u4 I
  2. namespace One;' F+ T6 {/ R" T, ], v6 l' @
  3. namespace ONE;
复制代码
" }. S8 f" S8 x2 |1 Z; h. l1 @: s
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

* e( b) ?# X* I! G" H2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ) \' e( ]9 q9 t& i2 M  r2 ~
  2. class Person{* t2 ~3 x' |0 E3 f; T1 s% U' D5 V, }6 W
  3.     function __construct(){& Z1 L- Z" I" e0 M, z) p
  4.             echo 'I am one!';
    % ?% q6 t1 g9 O+ k% }
  5.         }
      }. C' Z/ Z0 z: k2 e
  6. }
复制代码
  1. //name.php
    ; s! I" J* P( w5 i* q5 b& k. V
  2. require_once './1.php';
    - n% L9 z# ~( _/ Z: Q+ ?7 B) J

  3. 4 W4 v4 B2 G; @: N4 \
  4. new Person();     //输出 I am one!;
    7 u0 f: D" T2 p4 X
  5. new \Person(); //输出 I am one!;
复制代码

% D7 r/ `# x3 U3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php9 D) P2 V! N4 f
  2. require_once './1.php';
    ; R  C3 W. v! H4 x  M% K
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

' R8 \0 [! P( H- ?" \) p  f3 {4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   % k4 `4 l2 O. U( D9 ?! m
  2. namespace one;+ s! p5 U5 H# s
  3. class Person{: Q9 S/ _) r# s& S& [& f5 H9 L( Z
  4.     function __construct(){. a9 U/ m0 Z8 ~+ q
  5.             echo 'I am one!';
    $ T! d8 |0 S! ^; Z2 H2 |4 F# S3 s
  6.         }6 l2 e; Q1 _0 z" x0 S7 G2 V
  7. }
复制代码
  1. //name.php1 N0 U" u3 i" L* w$ l/ e$ ]. N
  2. require_once './1.php';# ^/ [7 T9 p& a% x' L# `5 P
  3. new \one\Person(); //输出 I am one!;
    ; {# m# v0 Y# z6 ^) a
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
3 c% @8 u1 g5 f8 Q0 \- ^. G
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
% Q( p! {. T$ l& t
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
6 H' N) N, K% o4 M
  1. //1.php   1 D. {5 S% N3 E( h) `! b, s2 e
  2. namespace one;
    3 z7 b9 z7 R! S" M2 L: t
  3. class Person{
    3 Q6 {- B9 W* D% ]( |
  4.     function __construct(){
    0 ?* K  f! W% y+ z8 K
  5.             echo 'I am one!';
    3 S* X, h/ A2 t7 l
  6.         }6 }/ o$ U5 j8 C3 D
  7. }
复制代码
  1. //name.php) w. A  i7 Z1 P) s4 J
  2. namespace test;3 K' w2 b! n% \4 e/ _
  3. require './1.php'; 4 e" `. g! o- n  \
  4. new \one\Person(); //输出 I am one!;# u$ J+ t0 w/ Y" n3 l2 o
  5. new Person();      //这里结果会是什么呢,猜猜看& E( d$ w$ T4 a" A: M1 m
  6. 最后一行结果报错:. q" D4 @# V+ z$ _
  7. Fatal error:  Class 'test\Person' not found
复制代码
  K" s) e, D! D; y* q- z
3 h( m" ~( f0 A1 X$ d
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
6 G5 T. i. H' s. b) ~5 y3 p; y; ^
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
3 b7 I# ^8 T$ @0 N' a4 g+ A6 g
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php2 K- v* E) |( E0 C! \/ p( T; P/ U
  2. namespace test;
    ! h4 f. N3 [5 O! L7 w3 S# N
  3. require './1.php'; 8 a# M3 M$ s7 H. E
  4. : f! T5 L8 g+ u$ c* c
  5. class Person{3 m& n" _. y% {" y/ ?
  6.     function __construct(){
    , C) p) N/ D7 E  ~
  7.             echo 'I am test!';
    , v7 L2 o9 D& d; t5 M4 Y
  8.         }" y$ Y7 `7 P, a& S6 A0 C8 A
  9. }
    4 n- w/ i, K5 w( K5 I& r

  10. ; i) D/ z+ l# @* A2 L+ {8 A
  11. new \one\Person(); //输出 I am one!;
    + a4 |: B. y- c- V
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
3 X8 g4 M" ^0 b5 q
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php2 `; L$ W; t  m8 `/ l( X
  2. namespace test;- D( h3 o. n5 y- V" _% }
  3. namespace one;3 g5 b2 I3 J; P" y# a9 ?. E/ B
  4. class Person{
    ( L; u. @' f0 v9 J8 k
  5.     function __construct(){. n8 x! J4 G& h! M8 i6 ~3 ?
  6.             echo 'I am one!';7 i+ n; M3 E6 C# y$ A: X% l3 m
  7.         }
    # P$ A1 E$ ]3 e  l7 Y& r
  8. }
    . [+ U2 J9 q7 v
  9. ) T, i2 r. E  ]! X; g7 E. u) h* c
  10. class Person{3 w  @, F- [6 T" C3 e  [  F; \
  11.     function __construct(){7 q& S$ ^7 i& l$ t8 w' Y
  12.             echo 'I am test!';
    ; i. A+ ~% L, q) w1 b% R# Q/ u
  13.         }
    % D% c+ ]5 O$ z4 i$ l/ C5 c
  14. }
复制代码

/ ?* q( V$ Q0 x: a8 B
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
8 i$ e- [$ c, [. x
看来简单的把require理解为替换,在这里行不通。

# T" _( C6 |( c3 T% N, m1 _; ?6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
6 @0 }/ [9 ?0 d# h4 R0 N
  1. //name.php
    5 N  s' B3 D; o1 k% Z; Y" Y' l# }. Z

  2. 0 O3 g; p: u2 d' Y  S9 R
  3. namespace test\person;
    ! O& M9 r/ p" h$ x
  4. 5 r+ g7 R. C% o
  5. class Person{( H7 S3 y: Z+ ?/ C6 o$ v
  6.     function __construct(){+ d* ~- ]; B& ~: U
  7.             echo 'I am test!';; ?, z" }0 c4 d7 r
  8.         }' s- G, W$ g# a7 S7 \5 `
  9. }& g' w) R5 r4 x  G  a
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
1 k0 g1 V% ^5 s
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
- s, l1 g( w4 c- @& {
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php4 D! c0 c) i4 k: Q+ W0 n

  2. 1 N) f7 n2 Y9 E7 I( Q
  3. namespace test;5 K' }! W, s! u; C
  4. echo 'zhai14';0 c! V; ]% n7 p) v
  5. namespace zhai;4 {8 P9 K0 |6 G, F
  6. require './1.php';
复制代码
" J% ?( h& o% v2 ]
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
$ C. P- s5 @/ o) N9 e
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。: E0 J+ M, Z( L2 e5 r0 g# }
  1. //name.php* X/ Y9 E/ M; X' U$ P4 h

  2. & O$ o' i8 x. |, i
  3. namespace animal\dog;+ Q9 N; f# Y1 X% d0 W

  4. 1 e9 a( ~, T7 z/ X0 N
  5. class Life{0 C" m0 ]+ k- J$ Y0 `5 N' C
  6.     function __construct(){1 D* e  o) l: n7 S5 o7 h
  7.             echo 'dog life!';
    + E" N7 x9 Y6 m( y8 x' u9 H
  8.         }6 ^5 _0 D; q0 [; {1 N- y) e
  9. }
    . y0 j4 ?. p; G/ Z

  10. 3 W$ a+ S7 O1 \6 y7 w! ~! V+ r
  11. namespace animal\cat;
    0 o: ~  l9 u7 c0 T

  12. 0 K8 A3 y) z$ G3 c; N+ q- Y$ {- q
  13. class Life{
    + k/ z" C$ p! {- P' a" r6 d- _
  14.     function __construct(){& P% o. J' w. m  S; ^* ]
  15.             echo 'cat life!';7 D. q" _  B2 u" O) L5 z
  16.         }
    ! K% L- B* `8 h- W
  17. }1 u) E9 P9 n5 N0 f

  18. & Y8 y$ Z/ e4 n/ m+ c5 O2 K
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    9 R- G! ]1 D+ t* ]# i
  20. new \animal\dog\Life();  //A
    ! j. u) B7 r- c  r2 S: A5 m

  21. . H+ [, r: D7 v0 s) D1 F
  22. use animal\dog;  //a
    , ]; P+ E" r9 A2 n
  23. new dog\Life();  //B
    , H& H0 h  O- [# G

  24. " ~/ \8 T3 ?; Z1 t+ T! ]& M
  25. use animal\dog as d;  //b. U+ A8 r! Y5 ~
  26. new d\Life();
复制代码

4 I) ~( q/ @4 S" G+ ?
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

3 G! N% Y* O( I% L$ `! {' _4 P
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
9 l) [0 u6 {/ p& T* O
相当于
  1. use animal\dog as dog;
复制代码

# r$ r" @2 H+ Y' Y- M- v6 q6 f& {: q2.namespace后面不建议加类名,但use后可以。! I. S/ v/ F( Y- s  g* u- z
  1. //name.php! V; g8 F- w. d/ u
  2. 0 O( o0 ~7 @! [& z  M  F$ O- n
  3. namespace animal\dog;' p$ T& M7 i6 C/ L- ^: k

  4. ; t. c3 s( P, ^1 |
  5. class Life{
    & O8 G$ H3 B( v
  6.     function __construct(){
    $ J  k# q+ ?0 C/ {
  7.             echo 'dog life!';8 H" ?. L: P7 J( p
  8.         }* o) {' E: ^8 U  |$ m* x
  9. }) b1 A" O' g: X. g: P+ h& U8 A

  10. / n7 _( _7 }4 s1 T4 D; J) C
  11. namespace animal\cat;4 u5 g( ~  b: J% ], r+ _) z
  12. ( h# }2 q  X6 o* Z4 }
  13. class Life{2 t8 r0 @3 k2 T( `  O; s
  14.     function __construct(){" E! H1 N2 e) v$ i7 k8 m2 b
  15.             echo 'cat life!';( ?7 |) Y8 I+ `4 J) B
  16.         }" a+ H: @$ d- r& M7 [5 A- N% k
  17. }
    2 m; B6 l, Q& d7 N
  18. 0 c7 ^4 ]5 t+ U
  19. use animal\dog\Life as dog;  * x% w* F) `3 H/ o' l# b' D
  20. new dog();
复制代码
- d7 {" o: ]7 @( ?, P
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
* }: V$ P: Z- U: l5 X( X: Y9 V4 P
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php# ~' l( H! ?5 B+ i1 y
  2. ' t+ x& f- [  B; P. e4 W
  3. namespace animal\dog;& w5 G, d' J! W  a0 B" |9 X

  4. " N% }. K2 F; {6 H. \: {
  5. class Life{
    - q( }* K% X: @( \6 v; Y
  6.     function __construct(){
    * L" q1 ?1 w! l' \3 Z* j* ^
  7.             echo 'dog life!';
    ! N. F" z2 p! e
  8.         }! B7 {1 J+ }; G) C! {3 Y
  9. }
    1 V) a- S( ?9 b- Y4 Z2 H; [, @
  10. class Dog{- a4 a0 p3 x4 I
  11.     function __construct(){
    6 P- t4 D' O" h/ R2 F3 \2 ~- s! |/ L: C
  12.             echo 'dog in dog!';
    . Z0 i8 i! Q: d7 g
  13.         }) l- V4 E; x; ?9 O5 C
  14. }) n9 c. I$ M1 \% O$ f" ~

  15. 8 r) a2 c( k- @- ^0 d& l: {
  16. namespace animal\cat;
    - `0 Z" ?/ \' m8 u( k
  17. * j# h4 x% K. l/ K, w5 {
  18. // class Dog{- g1 C4 A8 P1 C
  19. //     function __construct(){
    / n$ R8 Z4 k  U- w3 I: U1 C
  20. //             echo 'dog in cat!';
    2 A9 v$ \# J5 T+ h% A" v
  21. //         }
    & W8 `) m5 O) t, W$ L+ L. l
  22. // }7 q( j2 w/ b5 W" q3 \/ l# d/ u% I
  23. class Life{
    ; p& M/ {: p# O8 H9 ~3 m
  24.     function __construct(){0 s' L' T% ~$ c3 K
  25.             echo 'cat life!';3 |" W; Y5 N+ U- v
  26.         }
    1 h+ _, G1 T$ n  f9 N# _
  27. }9 |, {/ F. K. x3 _- u2 g
  28. ' K. z; ?$ |9 w8 |- J
  29. use animal\dog;  
    9 {" L% ?5 }* _# R1 k1 ?
  30. new dog\Dog();
复制代码
6 t3 i. H9 }" P4 V* A
如上,使用了
  1. use animal\dog;
复制代码

! A" H) ^: o: U) U- _) {
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

; O2 n% l% `$ p2 B' J: s/ Y: [
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
  t# o- k! m/ ~* U! K
$ X* w  k  W) L; k* w' Y- p5 c% P
& H2 h$ _! V. m
) j6 w5 H- w( R7 ~- A8 R
) D7 Y; ^* n$ M. }% B- n& l
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-20 13:21 , Processed in 0.112416 second(s), 19 queries .

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