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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

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

( J& G3 {; R1 n6 e! h7 y! ]
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

; }5 v: {8 W2 i  Y
9 V, T  \3 z. p0 k使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
$ e- g9 J  I! P% P! A& a
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

9 l* U( n# F) g* f7 y结合使用方法来进一步理解它的使用目的吧。

. ~# ^' x( ]; H. e( j
; {) d8 g/ q; p' |/ ~namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;1 H& `1 p) b1 n6 E
  2. namespace One;
    9 G  w  [( d. ?; P/ o
  3. namespace ONE;
复制代码

0 Q. V4 S8 d1 B4 ?2 a" O9 C. U) o
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
. Y7 O* Z- i% W; w' _2 _7 g
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   1 e8 v' v1 t) j+ e: e
  2. class Person{
    ' }- x% [) C: k
  3.     function __construct(){
    6 o4 C! K5 {: c
  4.             echo 'I am one!';
    " t- @3 f& p) O# F' V2 |  ]) }( E, x
  5.         }
      s/ Q, A% K; N* d1 o2 r/ Z
  6. }
复制代码
  1. //name.php
    % c/ W8 \6 F7 m. k
  2. require_once './1.php';" f8 C7 V9 L+ m: A% ?6 `

  3. ( m3 H2 J& N& W1 d1 W9 o4 e
  4. new Person();     //输出 I am one!;
    3 o. o7 f& u- N/ Q4 h$ ]0 X
  5. new \Person(); //输出 I am one!;
复制代码

% U5 T$ H+ X3 R: @, l) {9 ]0 X6 y3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    4 L* d5 F# b9 n% J1 ?. A) i1 `- ?8 d  C
  2. require_once './1.php';" z8 |' I2 v7 q) l) u% G4 p
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
: x2 x, B* `! f1 v
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    - J% |. ?! X, D+ v: _
  2. namespace one;
    * N/ }$ ?" s& Y* E. g) p
  3. class Person{" n6 J1 Y6 h$ [1 I9 t
  4.     function __construct(){6 m/ Y, [7 q& x$ ]0 Q+ n8 C7 h8 C
  5.             echo 'I am one!';
    0 j9 ~% B, i5 n" Q4 M+ }
  6.         }2 H* P# w, |: b9 z( L
  7. }
复制代码
  1. //name.php
    $ A( T/ [& m' U" w5 \
  2. require_once './1.php';
    ! i0 Y$ R& x% x: [1 G
  3. new \one\Person(); //输出 I am one!;
    7 e/ F( y) c+ @7 s1 s9 w
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

* T0 F/ u* k  Y: F+ {6 p. ]
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

7 d5 \- ~; u, h5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。+ O% h* W+ u0 A2 f
  1. //1.php   
    6 m# r( R, g9 L3 |5 f0 x8 T- _
  2. namespace one;% ]' J9 R2 a5 K% Q. f# c! z' M
  3. class Person{
    2 I" s' o+ D; \  ?
  4.     function __construct(){; R. H, m3 h1 L8 {0 _
  5.             echo 'I am one!';
    $ F3 }% \! [8 k# I
  6.         }
    - s; o* _- g6 E4 ~
  7. }
复制代码
  1. //name.php
    # ]7 f( n) ?" ]$ R8 _# A
  2. namespace test;1 O4 \! ^8 Q  |( i* }5 a$ @& M: T$ O
  3. require './1.php';
    . d; ]; N9 O8 d
  4. new \one\Person(); //输出 I am one!;$ [+ }2 Q, s; K1 g# p) s
  5. new Person();      //这里结果会是什么呢,猜猜看
    9 Z* S6 z7 q( I* e3 Z: E
  6. 最后一行结果报错:! W* Y5 {# ]' @
  7. Fatal error:  Class 'test\Person' not found
复制代码
0 R; f" B: a8 [$ Y# T9 b) F) ]
6 \# B+ k* ^' ?9 G2 ~
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

/ p- V' E; L  e5 D/ `$ D
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

  M5 N6 @7 R! S# `
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    3 b6 b1 h" {$ d( o
  2. namespace test;- e: ]( ^/ w1 V  |& r
  3. require './1.php';
    . b+ }6 V! S1 F( s4 E; q1 U, h6 t+ {
  4. ! w  s! H: J) w/ d1 ?  j
  5. class Person{: [1 ?" d* h; w3 `3 ^3 w
  6.     function __construct(){" L" @% j2 t. W& v- E7 G4 T
  7.             echo 'I am test!';
    % g* y" g. }6 U) a2 I- i& H4 ?. b
  8.         }8 H7 D/ ]% B' _/ E2 F# g. }
  9. }+ W( }7 p  t" n- D5 w2 m. T- S2 v
  10. ! a+ V/ x' F/ X6 p$ Z
  11. new \one\Person(); //输出 I am one!;; K( _# t  X( p) Y
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

# ?0 o, Y% \% L; I  n' ^) G
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php1 {& L" _+ A$ F0 R+ x
  2. namespace test;, N5 C8 M% f( d/ H1 o
  3. namespace one;
    6 m! i0 U0 \! Z* B6 l; V, R
  4. class Person{; ^! c/ \7 f( v+ s' F
  5.     function __construct(){
    , ]8 k5 K5 v* }% g4 P6 f2 F0 |
  6.             echo 'I am one!';7 o$ D2 r9 C+ T! g
  7.         }4 u- m3 R" N+ p) }$ Z& j
  8. }
      M3 B7 f% H" c! K+ ~" T: j% F# r
  9. 1 L) ^6 f9 y3 ~, a% o. T' S
  10. class Person{9 S) W1 }+ Z' u1 o- j( c- W
  11.     function __construct(){
    & f. O  f7 B" `7 ~
  12.             echo 'I am test!';! P: z0 e8 i; X) C4 q0 }
  13.         }- c- }8 O, t; r. e% X
  14. }
复制代码
$ u6 K2 o2 ?. F/ A
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

7 v: C4 N. R* u* r- `4 m+ f2 x" D. x
看来简单的把require理解为替换,在这里行不通。
5 r1 v) ~0 H6 Y. C" o
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
% g7 B9 s7 a% A4 C
  1. //name.php
    # f2 B4 S* D2 Y, p& w" `
  2. ! N' ?6 w8 ~, k( `
  3. namespace test\person;
    # Q$ r6 Y! |9 _* l  k8 o

  4. ) M! ]5 v. S) C9 U- @) d
  5. class Person{0 F! H5 c3 f7 i1 H
  6.     function __construct(){
    1 P! L7 ?, c. _1 a) E
  7.             echo 'I am test!';
    - B* r) O. b: g9 S0 h" e
  8.         }/ P, M& t) l. ]- B0 u
  9. }
    ( Z9 q6 `- {9 G# w( B  }
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
) l& c) n" `- G+ B7 U: K
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

, N4 [( x( U! e7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php0 a+ C6 M) L0 q1 V# Y
  2. + n  f. U) s' R+ b* U
  3. namespace test;
    * B( D- @8 z- A; N, f
  4. echo 'zhai14';
    2 k& o0 g) W- j
  5. namespace zhai;$ {+ X9 w7 X' M! q3 P& r, L. e& x
  6. require './1.php';
复制代码

% v" `) G6 o7 k  t
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

4 F0 |  v* f& a0 C% Z  guse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
  H! M2 e4 a# @7 i1 ]
  1. //name.php
    % e2 V4 k/ Q+ A0 M+ k

  2. 4 y. l; _7 Q# Z, K
  3. namespace animal\dog;
    2 x. G: @/ w8 d# f, M0 i( j% l
  4. / b$ m& F( w! t$ l: ^
  5. class Life{
    0 J1 ]* \; O/ B) b5 X+ l0 n
  6.     function __construct(){/ G1 N3 B/ {) e- }
  7.             echo 'dog life!';* u. \+ O5 i+ q: I
  8.         }1 X* H- Z4 {  J
  9. }
    + b# n* o7 i$ W# D+ t
  10. % a1 h  @! ]1 Z9 n/ \# H2 i% M
  11. namespace animal\cat;8 W9 }& o9 E2 c3 q. G
  12. & E1 s! Q. c2 C) A
  13. class Life{1 x$ B% O' D- |
  14.     function __construct(){
    ) ?1 t  e! q8 q
  15.             echo 'cat life!';
    " @3 F9 N' D7 n* b) n& O0 T# f# f
  16.         }8 C7 N- i% G1 P$ G
  17. }
    : s7 }! v( T, f

  18. 9 n% F* ~' E% P
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    ' x2 Y+ R, b! r- e7 P  v
  20. new \animal\dog\Life();  //A
    4 g4 m2 A" m" D2 a9 w  W* y

  21. . j' N3 I; C, J$ A4 j2 J) p
  22. use animal\dog;  //a
    : ~) U/ y1 k9 e0 d+ N! I3 x
  23. new dog\Life();  //B$ {1 D3 e0 s) }& g

  24. 1 v+ A) L' t. o
  25. use animal\dog as d;  //b
    " Z! f# q. a" o  U  P% z# W/ v
  26. new d\Life();
复制代码
" m- k0 Q8 v, J
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
6 T9 V( ]& E# O, M: O# [+ m
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

/ i5 k! r! B9 I/ n& l/ @
相当于
  1. use animal\dog as dog;
复制代码
1 i& n) X2 D" |0 h4 k
2.namespace后面不建议加类名,但use后可以。
! f8 U3 V* @- Q( b+ _0 z' k
  1. //name.php
    ' Q! `3 P  G8 f2 v) o
  2. * A3 N6 @/ h& F) E8 R7 r" |
  3. namespace animal\dog;/ ?2 h) }4 S/ G7 C# \

  4. % O5 q$ _' P# ]- m- C* s9 H
  5. class Life{/ r! `+ X+ a8 ], h7 _, `" y& b( i
  6.     function __construct(){
    & E' x8 J* N% Q: v
  7.             echo 'dog life!';
    ) M* o; z" o" d! k
  8.         }, z* m8 |' R: [! d3 K+ z
  9. }
    , ?6 y5 n0 Y' J3 w: c2 t  E! K

  10. ' V  p, ^, X  J4 W0 d. ?4 I
  11. namespace animal\cat;8 \: d7 P7 T% v! a' a" Q7 i

  12. * j5 @/ Z  [) r4 c  s
  13. class Life{
    / h$ ]$ c; d' r) M/ ]7 N
  14.     function __construct(){
    6 e" b2 m7 h4 {+ Q" T
  15.             echo 'cat life!';
    / z7 Y% O; L, d. l& P
  16.         }& E. c" f7 K! y$ k& [) B5 o
  17. }( o- z+ |2 R4 _1 O6 L; e& [- ^

  18. " }9 q1 S- C- Y' c8 f/ t, e
  19. use animal\dog\Life as dog;  " ^/ i$ s" l3 E: `
  20. new dog();
复制代码
6 r+ U# w: {8 T4 e2 |5 X$ d
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

4 N/ c$ y1 y2 A+ B9 R
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    5 v9 [0 j; h9 ]. a
  2. 8 y4 v9 _) ]+ w
  3. namespace animal\dog;
    0 f4 ~4 q! t0 `7 n% Q

  4. 3 J, h0 R2 x% t" W5 K
  5. class Life{
    2 @0 h8 ~# T1 C
  6.     function __construct(){
    0 f8 f& e/ M9 s$ {' r2 \
  7.             echo 'dog life!';
    9 E, Z9 j# s2 K) M' Q! q
  8.         }
    + j; t( C% ~: k$ W
  9. }0 K5 L( F, W2 x; O9 X7 b
  10. class Dog{9 }: {+ b, l- {& _
  11.     function __construct(){
    % l& X: ^7 a7 J& k# j5 M
  12.             echo 'dog in dog!';
    2 ?5 `7 m1 @) V% z" l
  13.         }) t( {, i  c( s0 g7 x% d; [
  14. }
    4 W" M1 S% ~. f

  15. ' C1 z8 e5 _& |! o. C8 Y
  16. namespace animal\cat;1 o0 [6 x, w6 j! h  k2 l- ?
  17. 6 a1 _3 \" J' q
  18. // class Dog{/ j- B& G7 k2 ~2 u7 u0 R
  19. //     function __construct(){; R- Y( x0 g) I: b  o8 t0 f
  20. //             echo 'dog in cat!';% A6 e/ M6 ]7 r6 o0 t
  21. //         }3 L$ R( G5 a3 V% |/ e
  22. // }: b$ r8 }( A' T/ a, D. }5 t! i
  23. class Life{8 f* J6 \4 S' y! g
  24.     function __construct(){$ p9 ?% r4 i: |2 u, I. y1 S
  25.             echo 'cat life!';
    : ~6 k+ u$ h, I" j6 j2 e' ~5 H9 s4 T/ t
  26.         }5 O3 {5 j$ U9 O( _4 _
  27. }2 m& F; q- k- |2 J& G% J7 y
  28. + W7 J  T, a9 M/ c( ~5 c- ?( O& C
  29. use animal\dog;  
    $ I4 {* C) ~# c2 ^
  30. new dog\Dog();
复制代码

! Q& K, m/ K9 Q; b% F
如上,使用了
  1. use animal\dog;
复制代码

* u3 B  F1 h/ R4 o
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

+ o# v& F& x& A9 Q- }
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

# T% a5 t: B" X
4 `7 R2 K! F8 h4 o3 Q" [1 S
3 o9 q' v0 I/ i! U+ \* f" R3 E
* m1 }* P9 X* ]. {5 Q0 i! _
. A" g3 T2 N0 t- @

最新评论

GMT+8, 2026-6-19 19:38 , Processed in 0.054611 second(s), 19 queries .

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