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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

2 F) S9 G/ w; a( L. I# x; u
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
2 R6 \/ Y8 n  A

+ |8 W. h: A5 I5 Y使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
+ t5 ]3 h. N8 J# I
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

+ s* k7 u( B% W5 @, P2 p结合使用方法来进一步理解它的使用目的吧。

" J- V$ U+ |3 i8 e* n. E1 {$ G7 [$ u: Q# M5 O1 V
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    , T' _- L0 Z7 O2 R% N
  2. namespace One;
    : P+ c& Y  [  e1 r
  3. namespace ONE;
复制代码
2 G# `4 S$ [+ A/ a
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

" ~% L1 I5 E' a! j0 }; i+ j2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ( {8 F0 Y$ V9 S9 E/ i
  2. class Person{
    1 {) M8 [/ v. `
  3.     function __construct(){6 H. g& }& `0 A7 `3 A- ^7 Q
  4.             echo 'I am one!';
    7 J* g1 `: b1 A5 U- G2 e1 f
  5.         }# ]9 r0 j6 \( X7 B" e6 B  M5 b
  6. }
复制代码
  1. //name.php( o! o) h- ]" X
  2. require_once './1.php';
    4 U# `7 T$ q9 u! |: Y' W1 D0 `- W

  3. ' d& [- ?( F- j" l, ^
  4. new Person();     //输出 I am one!;8 ?! M6 [0 K$ \+ H
  5. new \Person(); //输出 I am one!;
复制代码

. k, K$ a. v2 y4 R: n1 H' m3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    & N1 j' X+ S' e: S6 w& Y+ D
  2. require_once './1.php';
    ! r" M  M1 P5 w9 A: y) k; s
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
6 L+ j# J. o* F6 [$ @, l  w* A5 h" T: g
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   ' w2 Q) C6 v, Q/ c. A' x1 S
  2. namespace one;
    1 w- s, r" Z0 E
  3. class Person{( L7 ^5 y9 g/ P: S
  4.     function __construct(){1 `6 M& z# a6 M+ e! @2 A: k
  5.             echo 'I am one!';
    ! O/ }, G# T7 C( g5 A6 X
  6.         }1 V& C0 ~: F/ I' G* U
  7. }
复制代码
  1. //name.php
    5 x6 ~9 A6 F/ Q) O
  2. require_once './1.php';
    9 X% k4 x( g  d- s- }* A8 H
  3. new \one\Person(); //输出 I am one!;
    : N$ r- t$ ]; U' a
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

9 D# ^9 K3 I, u# E
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
& N" G* C1 N7 }3 k/ S& K# H1 R
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。* j' O5 r% c8 R  T( m3 C2 D
  1. //1.php   6 _; q2 V# a) j* [( V9 g( G2 Y: }
  2. namespace one;! U) Y1 e- S: X+ B* E7 R4 G" ~& x
  3. class Person{% E7 Q& w7 y& ?, O/ @+ v0 `5 h; |4 f
  4.     function __construct(){8 z' p* J: Z8 K
  5.             echo 'I am one!';$ b1 N/ U  C2 \- z7 c
  6.         }1 m  b0 M7 ?  @* a" b
  7. }
复制代码
  1. //name.php
    % w9 x  r2 E0 R* ^% k
  2. namespace test;. V2 C7 P' m# \
  3. require './1.php'; + O3 n7 p* Y6 i- @5 _
  4. new \one\Person(); //输出 I am one!;% C$ {8 H$ z0 B# A8 |+ q1 T
  5. new Person();      //这里结果会是什么呢,猜猜看5 ~3 Y; E6 T. f4 R7 Z% V7 t
  6. 最后一行结果报错:
    0 k$ l0 N+ T+ a6 i- ~7 g8 r7 ^
  7. Fatal error:  Class 'test\Person' not found
复制代码

& Y; t8 X* i# f2 @. Z5 X5 b
3 s. j+ L# j6 W* y3 x" s
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
& P$ u; E* `0 I3 B! h
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
4 {* y$ X- R2 ~  f, p0 h; n9 q( L
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php: E4 m0 v  q( i) X
  2. namespace test;
      P' C2 w7 {1 O$ o2 V
  3. require './1.php';   `# b. c4 N& [: e

  4. + T' @& k& f8 f' W4 d% B
  5. class Person{$ W* h' W$ U. Y% i& D8 a6 U/ O2 ^
  6.     function __construct(){
    6 z2 S) t) S  n1 C8 T; s
  7.             echo 'I am test!';
    ' Z) g8 Y; N3 m) k: d- W( |
  8.         }6 N7 u6 x4 Z( O
  9. }& u8 {% q- a# x- g+ M! e) N3 x
  10. + A( L- r" p% c2 c* Y
  11. new \one\Person(); //输出 I am one!;# g/ d+ ~4 u7 Y
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

* O, ]% ]' F8 _# Z3 ~
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
      T& c; F- c7 @9 q. U, Y
  2. namespace test;# V# t/ T, y6 M% R
  3. namespace one;) b$ I; c( j, }  q
  4. class Person{
    # h- Z& p: v; t. w
  5.     function __construct(){
    & n) E7 I# |/ E( A
  6.             echo 'I am one!';
    4 @  ~1 y- ]4 t& H* J& X
  7.         }0 Z3 R$ O' [7 A2 e$ ^
  8. }5 f( {- q( m2 L( w% A* h+ g. m/ d
  9. 9 b5 m3 L# J* ~+ T) D, N: d0 N
  10. class Person{
    8 o1 v* o8 G& i' Z/ K0 I2 ?
  11.     function __construct(){
    ) v) j% H5 |6 A0 ~
  12.             echo 'I am test!';
    ; O5 e# o7 p0 ~
  13.         }
    ! y5 V% n$ b5 _& d& H
  14. }
复制代码

$ [( `0 g3 ]5 y3 |6 h+ b
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

5 f! L6 G) }8 T( d
看来简单的把require理解为替换,在这里行不通。
( o  X3 l9 {) n7 Y
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。" f) J5 {6 b1 O6 m
  1. //name.php2 x% V6 ?4 A8 ?& v4 x
  2. 1 X* G* V) [% ?; {# D# e5 Q
  3. namespace test\person;8 G/ _0 h: s' r1 _& H) j

  4. % D  {) c; s8 @9 ~4 U! J
  5. class Person{2 Q! n9 Z2 u' X
  6.     function __construct(){# \# `; M# p& e
  7.             echo 'I am test!';
    " J8 w3 L' l) U* Q
  8.         }
    5 L/ |5 C" J" j
  9. }& {2 ]( B5 V  J" ]0 u- Z) h3 y
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
" R  d- n  U6 V6 r9 Z
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
; i0 N3 U6 w6 F$ Q( J. H2 R9 \
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php- O: v' J4 }2 x8 [
  2. 1 F# U$ a! A, @& j
  3. namespace test;- ?9 q- n% ?3 J5 @7 U2 }
  4. echo 'zhai14';4 \6 n. O/ x$ f
  5. namespace zhai;
    - c7 g. ]1 h5 {: H
  6. require './1.php';
复制代码
2 ^$ c" z- E- n8 L* w0 @3 Z
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

# ?) R9 q% {8 z  X9 ~use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
( G/ T6 t1 ^1 r% W: D' y
  1. //name.php
    $ a9 z) H0 T! i4 b0 Q7 X( n5 J" b  w. u

  2. 1 B$ f. n3 z# W
  3. namespace animal\dog;
    & o+ Z* F8 d  c# z7 g* g) N7 z

  4.   U" J6 b6 h+ e. J
  5. class Life{
    ) t# o. s2 P0 T" r3 O
  6.     function __construct(){& k0 o8 x7 L& R$ D  I
  7.             echo 'dog life!';; i% r8 j; }0 b1 e- g% @0 @. P
  8.         }
    # b0 U  u; i+ c: g
  9. }
    1 ^, u# k1 }' r/ C$ ~! W
  10. + l7 ~9 h7 v  O0 z7 F
  11. namespace animal\cat;
    3 j. I- m# ~2 K. E4 g- Y
  12. 0 C- {. E4 ]* @( ~' S
  13. class Life{& S4 B4 X$ D8 q: p. Z5 k
  14.     function __construct(){
    ; u, S8 e; }; s2 u, d! k3 [
  15.             echo 'cat life!';
    & f5 P, m, F$ ~6 ]
  16.         }
    1 }& u* k+ i. I8 y1 M( b
  17. }5 d1 o. p& ?; R) t' o) [

  18. : B& l4 X4 f8 h
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间/ J+ X. Z9 f6 ~( J% S2 J/ `% I' C4 @
  20. new \animal\dog\Life();  //A
    0 B5 A( [4 c* H

  21. 9 E$ L4 ^2 f/ K# N: G1 B2 s
  22. use animal\dog;  //a* q1 L+ L! j9 h2 |: Q. `
  23. new dog\Life();  //B
    - K! \! d- P: P& `0 T
  24. 6 U* d! n: o: Z
  25. use animal\dog as d;  //b
    2 @0 [' A& |) x: N6 ~) n
  26. new d\Life();
复制代码

: r0 S6 r2 U% N7 `4 E
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
: m5 b. Z1 ^1 H3 y
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
, s% \. ?% h% W  w8 l  j
相当于
  1. use animal\dog as dog;
复制代码
# {4 }6 P9 p" H. h
2.namespace后面不建议加类名,但use后可以。* [' }- G$ [( l" t+ t# {1 ~& F
  1. //name.php7 ?0 c8 z( @' w$ B" F

  2. * A$ X: _7 u0 E
  3. namespace animal\dog;+ t. `( c# ^6 {/ s1 p9 N7 ~
  4. 3 J, }9 V4 N" Y% q2 X
  5. class Life{! ~; A7 D$ M! n2 Z
  6.     function __construct(){* b5 N: O0 W8 c- q# _
  7.             echo 'dog life!';$ N8 k0 A* }- i. D1 e1 a
  8.         }# t" e: y0 _5 X" @
  9. }
    & K( Y0 ^5 _  g, C% O4 [, ~2 W$ R: t
  10. $ t$ @# e6 N$ k3 S$ ?
  11. namespace animal\cat;
    4 T8 l: Z2 d7 x; G/ Y, a

  12. - n+ o3 n3 I1 A$ y) y
  13. class Life{! r6 k* N  G6 i# k# _
  14.     function __construct(){
    . L7 |' a. h: ?& J; f
  15.             echo 'cat life!';; W! z2 v8 e( m2 q% w2 ~' }7 L
  16.         }. h7 a3 T. \6 q( B, Z' X3 N
  17. }4 u1 D# Z' e# p& N- N
  18. 7 `* l% @8 ~+ {! q- G' R
  19. use animal\dog\Life as dog;  4 b) J' H# \% d  l5 ?6 j
  20. new dog();
复制代码

1 Q# ?. U- s9 w( _5 W2 }- e
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

1 U2 A8 H* t3 |- o8 ?9 C
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    & Z$ i+ d, k. W8 x* A- C
  2. 7 r+ Q7 U5 B) Z$ r) r( {) T
  3. namespace animal\dog;
    # S. P- g; s" [, Z  {
  4. 5 ~3 [0 y! W. E* |$ O: N( k
  5. class Life{5 u  X- n7 c& V3 Q0 X+ F3 k
  6.     function __construct(){+ ]( K: y+ z7 @3 E1 ?6 S. A
  7.             echo 'dog life!';
    ) k$ O* [7 Z' R+ o
  8.         }8 a- B' n0 z/ N5 m; t
  9. }' `% g% H! b& Q, h. L
  10. class Dog{6 Y3 @" }% a- k5 j% |+ S8 ~0 r
  11.     function __construct(){# }# f4 g$ C5 j' E4 J& e. [8 u  V
  12.             echo 'dog in dog!';8 ^# x, b* y3 c1 e9 Y6 Y
  13.         }" U- E% N& J0 D' q0 I* C
  14. }
    ) K/ c" E" S1 ]0 m/ v  Z* R

  15. + L4 H" q8 u4 }: A7 G* Q$ D2 w& g; ^
  16. namespace animal\cat;! q- s* D- ^: B& j
  17. 4 i7 I9 N, ^. R- f& o2 ]6 [; M5 d, W
  18. // class Dog{; Z- e5 G+ Q4 V: i# u! Y6 K
  19. //     function __construct(){2 [( w' T4 u) |6 G+ S- [# B
  20. //             echo 'dog in cat!';
    1 F8 S0 T- E: m8 }! O& m
  21. //         }3 \, Z& [. t+ s& U
  22. // }& V  V# X0 ~9 ^' ]9 t+ d7 C9 h3 X
  23. class Life{
    # B( L0 W2 J- ^7 ^0 h
  24.     function __construct(){' Z9 o4 D% ^0 ?
  25.             echo 'cat life!';
    ! z' z+ o8 W( G& P3 a
  26.         }4 }- J9 X8 V0 P7 h4 `. J
  27. }2 Z6 W( `  [# y1 f8 I0 o

  28.   T1 \6 d- \5 c9 P2 q) I1 O
  29. use animal\dog;  & o' L" S+ p  y# K+ u' O
  30. new dog\Dog();
复制代码

" R7 q# e+ T. o+ `; L. _
如上,使用了
  1. use animal\dog;
复制代码
1 H6 q3 F& w3 E. m
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
( }9 L6 ^! A& A( o4 W: i
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

% ^5 O& M7 n+ P' O- V$ {2 P7 D6 N" x8 \5 N) \: T; p- [" p! x

# B2 ?- {: L3 C" p8 i- w7 M' b! k4 G0 B$ p( q# ^. h; D+ |) {

( c" _3 P3 h# @) @
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-12 00:33 , Processed in 0.119088 second(s), 20 queries .

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