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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

PHP命令空间namespace及use的用法实践总结

发布者: admin | 发布时间: 2020-7-1 23:37| 查看数: 15138| 评论数: 0|帖子模式

以下皆为本人自我理解内容,如有失误之处,请多多包涵。

& w6 `8 o8 Q4 F( D
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

( t. F6 ~4 Y! N& e2 Q& k2 b& H% T! p; e1 ]
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

6 }0 A0 N0 o, a' K% f
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
2 D% y/ v. Z+ f  i; h( }4 Q8 O; ^
结合使用方法来进一步理解它的使用目的吧。
2 O3 h5 _# }  e' C/ k3 F
8 |( k/ h1 e0 G+ g
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;( L  F; m% B" {8 f
  2. namespace One;* H0 A0 M& k2 S. J5 d
  3. namespace ONE;
复制代码

1 V% q" A" H  K0 P0 J  d0 v5 ^" X8 A8 A
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
, M% G$ B9 h1 P- P$ T2 Q- W
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ; ]; S1 Q) J- E
  2. class Person{
    $ m" l) l0 j9 P( k, ]* c$ u
  3.     function __construct(){
    0 \% P! s( @- N4 e' g7 y
  4.             echo 'I am one!';
    $ g% M$ [% V0 l- ^4 u( D
  5.         }
    3 u7 ^+ B) t9 E2 d) A  q3 B' P9 w' f
  6. }
复制代码
  1. //name.php
    & C, d. r/ ?; n7 N: r3 O
  2. require_once './1.php';4 Q. F: c! e7 R+ s+ b2 P# ?$ Z
  3. * Q$ C0 {5 F$ H
  4. new Person();     //输出 I am one!;
    9 p' O$ S% {5 ]4 S2 `
  5. new \Person(); //输出 I am one!;
复制代码

4 I) D( R& W. U7 _, S, j2 ]3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php$ q" T, w8 t8 C& s4 j! `$ Q0 |
  2. require_once './1.php';  G+ }* v: @8 U7 z6 d. e" S: |" ^
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

' N- Y5 O# t' @3 L0 i/ m" \4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   " d' e. @* K# |; A6 s% K, @
  2. namespace one;1 h1 n2 ~% T8 M
  3. class Person{
    6 G0 o4 |( q$ c$ Y5 P
  4.     function __construct(){
    ) E. q  B; m0 \/ _0 g# Z1 W
  5.             echo 'I am one!';
    ( N- w* E: d0 Z5 r& @6 r
  6.         }6 k) h1 F) ]0 u: X1 W/ Q
  7. }
复制代码
  1. //name.php" m: W! i; u. k; ^( M! M
  2. require_once './1.php';% Z( f  d6 M1 p- m* O) \
  3. new \one\Person(); //输出 I am one!;
    . o/ P0 ?7 x  d- |$ `1 x7 F" H
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
' c! W1 _6 m" J  I
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
: M. J1 r/ e: Q( {# Y- }+ m
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
2 U  @& C" P3 }9 {
  1. //1.php   
    % j, T# k% m) r5 s3 z4 }2 `0 N
  2. namespace one;
    ) z8 ^/ E. D# o  m' @* m
  3. class Person{7 m  m& Y) T: O( b
  4.     function __construct(){
    6 r$ _* T2 E6 I3 P$ D
  5.             echo 'I am one!';+ l5 B. V8 g1 A, s6 K
  6.         }( K7 G1 \, a4 K5 F+ x% z$ k
  7. }
复制代码
  1. //name.php% x3 ?) G# E1 Z: H: e' v% k
  2. namespace test;/ u1 ?+ M  y3 W9 B( W
  3. require './1.php'; # |7 D, ~; d7 j6 Y" D+ c, ]3 s
  4. new \one\Person(); //输出 I am one!;
    . S; b+ |: P" \8 X
  5. new Person();      //这里结果会是什么呢,猜猜看9 ^, S1 C, n$ s
  6. 最后一行结果报错:. w" ~: G/ o" W( z2 t  U1 K, ^
  7. Fatal error:  Class 'test\Person' not found
复制代码

# v) C! Y/ T3 [/ g  {

8 V+ g3 B# i! X' Q4 }首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

# r) Q: j% u4 t/ g$ t# T, }' a
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
" j) o' I! o1 _; l2 O7 ?
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php- u& B/ I& ]3 |9 P) Q3 \3 A4 L
  2. namespace test;' K9 R. O7 G9 g7 |/ ?" N; i
  3. require './1.php';
    ( q4 ?7 x( O6 h( r3 P% A' W1 `

  4.   j* T  o" a* d1 j, L( Q1 d
  5. class Person{
    $ _4 `* M" \' f( y, V. z2 [
  6.     function __construct(){/ d$ C2 J# C: O  Q
  7.             echo 'I am test!';
    3 U" n2 Q) a8 W3 j( I
  8.         }( J3 b/ c% ^- u
  9. }
    2 o, d8 m# r, O/ {2 |8 n2 G
  10. 4 w9 J) \0 A, {4 _; p  Q
  11. new \one\Person(); //输出 I am one!;6 L. s5 A* {& N$ y0 I% r8 N  V
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

0 k: p) V( w6 V+ H1 W9 [  I1 L
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php, R6 ~4 n: B% [8 Y1 Z6 p$ E
  2. namespace test;. e% @( B0 E+ c& ]% o2 N
  3. namespace one;
    ; G/ @6 [9 Q" S3 ]4 b( ?- p
  4. class Person{
    ' u; ~  X& m- p
  5.     function __construct(){0 D# B' y  Q* o' F" Y
  6.             echo 'I am one!';
    1 l1 \# i9 C" z3 j( W6 w: x: V
  7.         }
    + ?" \, e8 R* ]8 N
  8. }- A+ i- ?/ V) F5 z

  9. , x* N# |2 U: v' S9 w$ u
  10. class Person{' }, b7 x6 _' Q/ P# c! j: s
  11.     function __construct(){
    * |4 Z% _+ |  Z) R" q
  12.             echo 'I am test!';
    9 M2 ~1 Z1 ^% S) |1 z
  13.         }
    % t/ H! U7 j2 K/ ~5 g
  14. }
复制代码
  z( I0 ?! F# |0 T7 I: j6 I% Y
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
( Q6 X4 U6 ?, i2 m4 d& O
看来简单的把require理解为替换,在这里行不通。
0 t0 M( @: R% R! ]3 Q/ h: ]# [
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
, V% ?! r  f6 j
  1. //name.php
    * I. ]6 A# n+ U( {

  2. 5 ]3 h( v8 G9 e+ l
  3. namespace test\person;
    2 H: f, T% c3 P5 B: u4 i( `4 B5 \

  4. % {$ m2 Q' U' ^) d
  5. class Person{& X# V6 a4 T; G4 J4 m9 E$ `& M
  6.     function __construct(){1 b6 k  e! g, G! P4 I% u  C
  7.             echo 'I am test!';" D. ?: ]/ _0 v& c/ [" S
  8.         }/ b5 H2 h$ a5 |- r1 y+ w# o4 M" k
  9. }
      a6 W' Z% l; E$ c% T
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

0 w) L; U/ W$ `2 [) Y2 S7 ~/ J; }
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

4 {0 ~  y  B: U7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    ) Z/ y% o0 J  j( V+ n

  2. % v) J+ Z! o, `  H2 p
  3. namespace test;8 L( [2 C2 o/ t0 `
  4. echo 'zhai14';/ L: f) Z; M+ `3 w1 E5 S' O3 z
  5. namespace zhai;- t3 }9 D! K8 d/ c/ M
  6. require './1.php';
复制代码

" m; k4 N8 J, a% H$ \* h5 W
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

: J- h) K& [: k# g$ I# ?use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
3 d+ M5 b% l; T" f; ~3 p% T+ j" y
  1. //name.php: q; P' h8 N) ~+ u
  2. % {, S2 F& ~- u
  3. namespace animal\dog;2 X5 B/ y, k& [4 j' ^8 ]6 v

  4. 2 Q! J2 h) Y! h% f
  5. class Life{
    : m# a. Z. h: I
  6.     function __construct(){( `1 P0 U( J5 j# a( {4 F! S
  7.             echo 'dog life!';
    1 u# f# c' |) E; T6 Q8 H
  8.         }7 O6 ?5 R0 h/ j' v/ m
  9. }! A; M- W3 B* ?% c, _; G
  10. $ }2 S( Z3 Z9 c$ f# T
  11. namespace animal\cat;
    , H' t- v2 E9 Y  v& Z- l

  12. / c" |% m! C! a: L0 L
  13. class Life{7 L. @  z, w# p2 T$ \" g9 F
  14.     function __construct(){+ V; C/ o- b2 x  ?
  15.             echo 'cat life!';8 e4 e8 Z& d$ l+ E5 K
  16.         }: p  \. D' t- m4 E: {9 e* Z/ U
  17. }; D" U4 Y- H/ O, Z
  18. # F  f6 `1 p. L' U$ d& j# C5 h
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    - C: i3 w' [9 X$ V- X/ P3 V1 w, \0 w  o5 e
  20. new \animal\dog\Life();  //A
    * u! s' ^  x* E& g
  21. 0 `3 E5 O% k# m$ \& B$ y' {
  22. use animal\dog;  //a5 Z' d1 C4 q' N9 e2 T0 m! L; P2 w
  23. new dog\Life();  //B- q' ^- i8 c, {0 c

  24. 9 `3 _6 Q, b0 d, |) [
  25. use animal\dog as d;  //b
    ; k$ H4 |) J: d3 T  V
  26. new d\Life();
复制代码

' I* ]; s: N4 `5 ^) H" D
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

! \; {; g! V; Y( Z2 ^: I. D4 G
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
# c0 D+ D0 x' E( A  ^% b* b7 b
相当于
  1. use animal\dog as dog;
复制代码
% c: D: V* |' @# R( m
2.namespace后面不建议加类名,但use后可以。4 `, H1 q8 _/ _  y+ x) Q) k  p
  1. //name.php
    8 q- K5 l' z' ?5 k8 b/ i

  2. 2 u+ ]: K1 N9 z2 T7 p/ M( ~2 d
  3. namespace animal\dog;& Y+ D3 E8 @- W5 C- w& {3 B

  4. - ?+ T6 _0 ^6 _1 Q* e0 F3 i1 t
  5. class Life{' n/ W( A8 n2 e" C0 |
  6.     function __construct(){
    + c, ^; ]6 G0 b2 c6 j
  7.             echo 'dog life!';+ `$ ]* x( Z' z3 b; L; ~1 c) I* j
  8.         }
    ' }9 Q9 {4 a- C1 j. e
  9. }: H0 u1 I3 ?/ D: y' b. \

  10. ( X, N1 `# d4 V7 c* a7 S  L5 N
  11. namespace animal\cat;8 v( q" u6 p1 G0 P5 w6 }3 Z, ~

  12. 6 g$ J( U# H+ {  i% ^3 m, ~
  13. class Life{' l* S0 r( l% G
  14.     function __construct(){
    ! S% h! v) @  N  |
  15.             echo 'cat life!';% I/ _4 U  }9 Q2 n$ R* Q! \; g. R* S
  16.         }2 j! F% O  {2 t$ K# i' M
  17. }
      L9 w6 _4 r! {

  18. # y& _6 z# H5 @
  19. use animal\dog\Life as dog;  
      I" q) e8 Y& ~
  20. new dog();
复制代码
4 f9 g& i8 F0 x
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

- G2 ~* f- w1 H5 `0 L
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    % ]8 f! p, D+ h9 g  Z) m
  2. # c* ~" q! a+ l$ e6 y" d
  3. namespace animal\dog;5 v% ]8 z# F; K* r
  4. : u% q" y, L( N2 g& B
  5. class Life{
    ) t' U0 f- w: q7 W( I' d- e7 ]
  6.     function __construct(){4 Q, h! H' b/ o- d* z" A) f* {
  7.             echo 'dog life!';
    * m# m9 P" Z$ U; p3 ?
  8.         }$ ?  `/ I2 @( z3 g
  9. }/ G, v2 a5 T* u1 n& G
  10. class Dog{
    / {: z4 a! J/ g9 L, x& M
  11.     function __construct(){
    - j9 H' Y6 Z0 x% \5 q
  12.             echo 'dog in dog!';5 P4 D, z) E3 w8 S) A
  13.         }% _9 D/ G0 L! |' p! j% r
  14. }
    + _: ?. \# l0 J) Y  \2 j
  15. ) Z: J. h# ^1 B0 s" _8 `
  16. namespace animal\cat;
    * z3 c9 ^: c' g$ e; e

  17. 7 d9 J& D2 U3 j4 D7 [% C
  18. // class Dog{5 Y- ]8 R3 I+ ~+ J3 G. V3 h- _
  19. //     function __construct(){
    3 d, Y( a6 S* H
  20. //             echo 'dog in cat!';
    + A% B9 M4 @. ^7 b
  21. //         }: f) {' n8 a- D- T) X8 J) f
  22. // }" H2 v' _: Y% ~1 j# ~5 N
  23. class Life{
    # |/ V: a; W. ~, y& C" Q1 O" b/ _
  24.     function __construct(){7 w  J( {/ _; I' I7 n* ^
  25.             echo 'cat life!';1 Q0 D7 G9 ^( ~$ G4 {/ L* R
  26.         }5 ]5 V0 E9 s  O2 t' \) F$ [: s
  27. }
    , Z$ Y' r' C7 b4 Y9 \

  28. 5 t& |; S1 D. Z2 {2 j5 ~
  29. use animal\dog;  
    ! N" ]) h" h7 x
  30. new dog\Dog();
复制代码
2 b$ k1 k) G  C7 D5 V" x0 v' o
如上,使用了
  1. use animal\dog;
复制代码

3 b4 B& H& }; ~, ^
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

6 C3 e( R! q2 n2 k6 a+ N
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
* F+ W9 g7 a1 x

/ x9 G) W: X+ O1 R( j: c9 u
3 Y6 E! ?& k: M7 j" w& `( `( a( U. f

; `) G, e  ^/ Y4 P5 Z' `

最新评论

GMT+8, 2026-1-30 06:32 , Processed in 0.056329 second(s), 21 queries .

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