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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
* I9 }  v+ e% p' b* {& y
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

1 X! Q) w% v4 b7 r( j& ]8 j( k& g7 }" |  Q, R8 I: A, R
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
& O& b, R2 h8 O! f
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
. C. K4 w4 J, n" [) |# e
结合使用方法来进一步理解它的使用目的吧。
3 |  J4 x+ p% j, C

0 ?$ O( y* E- M- x$ `namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    ! [% F$ M, J! l* J5 H! h
  2. namespace One;
    4 X: ]6 `( y2 F1 h* x
  3. namespace ONE;
复制代码
. i4 K, s. i+ I. q" b( k
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
8 G. S! T; Z4 a& W+ @: n: T$ L
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    : E4 e; ~* |+ l/ e) V9 C
  2. class Person{) ?/ }& X# ^' P, _7 j. q% v% a
  3.     function __construct(){
    # ]. F+ A( u" S! ?6 C* ^; h
  4.             echo 'I am one!';
    1 I" T' c& K# |; C% }! \
  5.         }
    7 w! F2 P; h1 Q4 f7 n
  6. }
复制代码
  1. //name.php( J: V9 m- |3 f" I+ m8 {
  2. require_once './1.php';
    ! n) F! @9 e1 _' D( h# F4 {
  3. # J, h" l( G' W  J- s
  4. new Person();     //输出 I am one!;
    5 Y9 y- ^0 v9 W4 W$ O
  5. new \Person(); //输出 I am one!;
复制代码
# z" \, T3 p; p2 I  u1 b+ M7 [
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php$ X3 Y) E, E$ R3 Z! B
  2. require_once './1.php';
    4 m: a. D4 T0 z- q- w0 h6 y1 E: a
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

  S7 f+ _2 m" r0 f6 g4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    5 F% N2 t# I- j; ?# O& B! w
  2. namespace one;
    " J/ G" n9 G' i; F, n
  3. class Person{
    1 J: B. Z# |6 f1 @% Y
  4.     function __construct(){
    2 |3 h- [4 p$ A7 U: @7 W9 ?
  5.             echo 'I am one!';% i( X- e$ a+ o+ o" v
  6.         }
    & |5 i- w' o5 s. |  L
  7. }
复制代码
  1. //name.php
    : k& ]( L9 x) Y3 J7 C3 }: q
  2. require_once './1.php';
    * P3 O9 r5 k. e: o/ f
  3. new \one\Person(); //输出 I am one!;5 V" U( I8 j2 u. y3 u9 N) P& P
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

; b% L% R; M0 S2 O: a8 K% m  q9 k5 g
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
1 n  M7 B$ ?5 |- W3 ~8 F1 P6 w% c$ n
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
! c2 X' c5 h- I5 ^
  1. //1.php   
    + W( j4 W; V( l
  2. namespace one;
    2 C7 y  x- J: I
  3. class Person{2 t2 k. [: }8 C, i- C
  4.     function __construct(){3 |$ ~/ |4 H$ W. f$ t2 h' {
  5.             echo 'I am one!';
    $ t' j) g+ p$ E3 u% F; t* {) }
  6.         }2 s3 U: A: Q% u# R
  7. }
复制代码
  1. //name.php
    7 f  w& c' u6 t3 b: p5 H7 h
  2. namespace test;
    3 Y$ Y) i* ~/ |9 C/ ]! F" }
  3. require './1.php'; . F1 K6 ~7 {+ b/ M/ z- l$ D
  4. new \one\Person(); //输出 I am one!;$ T& b. `0 c# F% S
  5. new Person();      //这里结果会是什么呢,猜猜看
    ! C# O2 m& N" f2 E; k& r
  6. 最后一行结果报错:3 A* [7 q1 k- x  a9 [# W+ n: {
  7. Fatal error:  Class 'test\Person' not found
复制代码
4 X4 ]  N& A4 U; I& ]  {  c. P5 W! W- i

, U& C7 ?3 x, w8 z, _! W首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
, ?  M$ B  u4 G
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
& {8 a) T" f1 C% [
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    , M4 Y) Z  J0 j- ]) S
  2. namespace test;8 W  M. l$ C7 u; Q4 K: W4 g
  3. require './1.php'; $ s, j$ U& A& B# Z! Z6 X5 `% T3 b5 R
  4. # o0 X; B# E/ R; [
  5. class Person{, Q7 b# u9 T. Q0 R/ e
  6.     function __construct(){3 K8 ?9 {2 h; {% U3 t, S
  7.             echo 'I am test!';
      q6 @& c  z" {  x3 y2 z) `; O! ?
  8.         }
    . V7 u, z$ `. ^+ g  _% i& W, w
  9. }
    0 e, p9 }+ q% m3 Q$ ]

  10. " x2 ^- u/ t) i. C7 Y, ~
  11. new \one\Person(); //输出 I am one!;- n$ m4 K: t% e
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

& o2 x- j$ ~& o7 I8 A( o$ v) Q4 f
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php( Q% z  J) J5 v# x7 e
  2. namespace test;9 v3 `) }7 K7 o- t' _0 ?  f
  3. namespace one;3 F6 N  I' j: n; {/ }$ K/ @
  4. class Person{
    & F% g$ w: U  Q) d: h8 Z. a
  5.     function __construct(){
    0 H; @+ m' n* a% L0 [3 ^1 Q
  6.             echo 'I am one!';+ B5 n4 ]3 F# v( y) i2 E  D5 s  l
  7.         }
    # j, q4 |3 X+ c2 E3 u7 r
  8. }
    0 S( B0 E% Y: w, Z0 G
  9. - j7 m& Y( F( Y0 A0 N) D4 Y
  10. class Person{, y0 \8 j2 Z1 V
  11.     function __construct(){8 j! T9 B1 L6 g5 P" r
  12.             echo 'I am test!';
      d; \- ~& q4 a. y
  13.         }
    $ }5 F3 n( C$ ?% C* K+ F
  14. }
复制代码

+ Z4 _* b: Q) r: k. b
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
2 L2 s8 Z& J1 l: e! _$ i# g( H
看来简单的把require理解为替换,在这里行不通。
# c8 H# B. l8 j5 S$ B* l: G2 l
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
; z) ]( {2 E6 S/ u; u- |
  1. //name.php& \$ g& H  @) X, o) n5 o
  2. 3 b# O" ?9 a% ]& m
  3. namespace test\person;
    + t. @% [$ H% s$ E$ {, F
  4. 6 P7 B' R$ N9 X+ F/ Y: t
  5. class Person{: e( B! E$ |, A1 N
  6.     function __construct(){
    5 B% p; R) X. I
  7.             echo 'I am test!';
      q( h% U/ u  b' [
  8.         }
    9 L% l0 v. k6 @$ O$ J
  9. }
    % ^9 O' J# C# S: b; I
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
5 r9 m7 F* ~5 g; j3 H+ A+ p
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
! q- L! k. }, U9 J8 y0 h
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    $ ?8 x8 g8 r1 F9 D5 h
  2. 1 u: q. v6 c% I. C6 e
  3. namespace test;8 a3 C' G- f/ O( i
  4. echo 'zhai14';. C( O$ `* _' l5 G+ p' Z3 @
  5. namespace zhai;# V: y; e5 n5 s- ~: p6 n
  6. require './1.php';
复制代码

% f# g# n, m/ X) l7 u
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
/ U4 n1 {9 ]9 C  ~5 L: {' e& v; q
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。. G0 P* ^4 P3 v0 a3 ]0 U
  1. //name.php
    + |& K9 a/ d& i

  2. 6 {1 A) j7 k8 B/ c
  3. namespace animal\dog;
    , i5 Y/ e% S. e: M5 p/ @5 N
  4. 6 U! ~- J  j+ n" C# M1 C
  5. class Life{1 |2 k  L9 L0 G% N6 k
  6.     function __construct(){
    + P) B0 f/ S9 A/ l' q! ^
  7.             echo 'dog life!';
    * }! g' ?( M! I! G
  8.         }
    5 A* I. C6 ~& z( `
  9. }
    3 C; ~4 [$ J+ \" f3 `
  10. ) C0 A4 }/ w; C- G! Q$ e1 K& s  p" p
  11. namespace animal\cat;; q$ F3 \: a, J/ F
  12. 9 w6 \$ n) |% T9 K
  13. class Life{
    ) j9 i; K6 ]& H& R" d0 n' ?8 ?
  14.     function __construct(){4 Q! {3 O( M+ K! F
  15.             echo 'cat life!';
    + J0 @- y, J5 R
  16.         }) h* u0 k. I& h; @. Y
  17. }
    : i' [0 U( E# K+ _& G4 z& a
  18. 6 U+ O9 B2 z. S8 j4 _4 @. V
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    / k# I% H3 Q1 e2 j
  20. new \animal\dog\Life();  //A
    ' p$ f& [4 ^9 q7 d: T) L

  21. ( s: Y; @& i7 V: z1 o' Q3 {
  22. use animal\dog;  //a
    2 |7 o' m% T; ?% I4 m* G1 H
  23. new dog\Life();  //B
    , h6 E0 |; g" S( v6 U
  24. 9 Q0 R! }3 c; @1 T
  25. use animal\dog as d;  //b
    2 k( W/ c: l2 O2 y5 c
  26. new d\Life();
复制代码
& t8 K& _4 c* s9 A' y8 ^9 s
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
6 b/ z. X7 N9 E! M7 }
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

& k0 a: }$ f3 D1 V+ H2 }3 x
相当于
  1. use animal\dog as dog;
复制代码

9 Q' l) K; i) j5 c% P3 l2 |2.namespace后面不建议加类名,但use后可以。' @4 _3 z# K; g! V3 G
  1. //name.php
    4 E* _; o+ ~, w7 M3 C4 O

  2. : J' K, U8 D6 j0 l* X( D
  3. namespace animal\dog;+ ?3 }/ Z) c4 ^5 }6 N) K( j8 F
  4. ) D/ x# m  |! m7 m+ g
  5. class Life{/ ?& ]0 C# [( C% q
  6.     function __construct(){( w+ `) }7 y' w0 P: ^: A# @6 ~
  7.             echo 'dog life!';1 K) I% J; w! {. C4 I. G$ u. q
  8.         }6 f6 `. ?$ [- i" b( S- ^% u& S
  9. }
    ( l7 I- ]$ g/ A# `* J  p5 y$ t2 ^
  10. 2 M* A% E0 i. r& L/ p' ?
  11. namespace animal\cat;
    7 Z3 Q7 A; N- k+ a! ~8 d9 v6 ]' m

  12. 6 Q& Z+ |" ]4 P1 S' Q/ _
  13. class Life{
    & t( y6 c; ~6 f# C' t0 Y( h+ k5 p; M
  14.     function __construct(){
    7 g7 F6 U: c/ p) D( Z- R  S2 M
  15.             echo 'cat life!';
    9 ]4 o. G1 {) ]3 |" }- @5 u- a6 `
  16.         }
    , U0 _) J) K1 z: v" v& q3 Z
  17. }
      e9 ^# ]3 p( S- h& j  G- w

  18. ( j/ c3 S* W. Y/ A
  19. use animal\dog\Life as dog;  5 I+ ?7 D- Q$ \5 _6 u' Q
  20. new dog();
复制代码
' r$ }: a5 ]5 [. d, P
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

# b2 A8 Y1 ^2 j
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    $ t2 Q$ P4 {/ j9 Z, t5 _5 Z6 M

  2. 7 ?$ G, {7 w  o. c( |/ z
  3. namespace animal\dog;2 ]9 Q4 j$ b' ~, V
  4. ; P2 q/ n$ q+ z
  5. class Life{2 D8 d5 {8 }3 r( P6 F. ]/ Q
  6.     function __construct(){+ I: O0 |/ j! g& X7 |# T  H. V8 j" W. U
  7.             echo 'dog life!';/ [5 v, U# a# u! l- [) c, W
  8.         }
    : O& j6 t9 T) L6 A/ h
  9. }
    ) I$ R, h3 l0 S" D6 s* i& F
  10. class Dog{' B/ t4 W2 n! x( ~1 A- F
  11.     function __construct(){9 L) \, f: a+ `6 U
  12.             echo 'dog in dog!';2 v* n" r. k% D* W: w* `) G" ~
  13.         }
    , W  G5 `" e: J0 Y  J7 a. o% O- U+ E
  14. }
    8 p3 k- U  }4 S+ I9 {* b  O

  15. 1 b' F$ y# n/ B- _
  16. namespace animal\cat;
    7 a$ s  x: p. d/ H$ M' J8 z1 Q

  17. 9 R' \5 t+ q6 ?) n, }
  18. // class Dog{8 |0 c; R3 Z4 C! R, Q( u8 d
  19. //     function __construct(){& i' A, v2 C9 |2 z+ S( k8 m( K
  20. //             echo 'dog in cat!';# ?/ n* t! F, |6 [4 n+ z
  21. //         }
    ! u6 {3 w% B2 u! B
  22. // }# |" b! R. B+ H. @- w" A/ V# }
  23. class Life{. c- d; ]2 r( Z# ?+ ~2 n" S
  24.     function __construct(){4 M3 T  G( `" M; A" }9 m; s
  25.             echo 'cat life!';5 j- A7 i1 m7 m& \, V! {1 L# d
  26.         }; k' u3 `7 O! G
  27. }( Y" h: V4 i7 d- _+ A, M$ q
  28. - m% A) v  B  N/ ]+ x% z( m% Y
  29. use animal\dog;  6 i. L( A% j. H; e% s
  30. new dog\Dog();
复制代码
5 v. G0 |4 [- K3 a
如上,使用了
  1. use animal\dog;
复制代码

7 R' E3 E5 I) P0 u7 M
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
. V/ W( A9 |4 k# t2 G
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
) `. X2 B5 w/ I, s  o

/ P: c& G2 m- U0 p" V/ A" r9 N2 z, z; F* P: |" g% c

$ y  m; o1 \; v( W
; U% ?4 z* S3 U6 b2 V4 D8 G

最新评论

GMT+8, 2021-9-24 16:33 , Processed in 0.130242 second(s), 22 queries .

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