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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

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

* C- Y* i! [8 F
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
, O" i) ~( S5 M/ ]7 d
  {- o6 @& H! i/ ~
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

! ]4 s1 C' h  _4 E( w- J0 B结合使用方法来进一步理解它的使用目的吧。

/ S8 s, j4 z, G5 ~, x2 u# E7 t- `( {) \
1 H7 t4 a. [* T3 D$ O' jnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;7 N% T% d# l: e4 Z8 c' r/ k
  2. namespace One;' E9 z+ q  B1 ]/ A6 W3 A" d
  3. namespace ONE;
复制代码
; Q  S. p' L. _  F
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

4 L: d1 y" s& r" u2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    0 u/ l' ]7 n4 N6 Q* L8 f
  2. class Person{
    6 w+ R  @/ a. E; c" ]  Y  j
  3.     function __construct(){
    : Y* n+ F/ L3 \$ w( |4 g. q$ O# W! b
  4.             echo 'I am one!';
    8 N& ~9 g( p' ]+ Q. ]8 v
  5.         }
    & {" [4 `. B( Q( j( g; p# z. v
  6. }
复制代码
  1. //name.php
    - ?" ^  E, c8 c5 e# I
  2. require_once './1.php';" o& P; v* i! O

  3. % ~. `5 O8 `4 _1 _* f
  4. new Person();     //输出 I am one!;
    + C0 R5 u( s. ^
  5. new \Person(); //输出 I am one!;
复制代码

' [5 L9 L9 a0 |0 P- k3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    ; [9 G  t; C" H) v! U* Z
  2. require_once './1.php';# i5 N) e- K8 L  J" S
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

. q* ?! z4 m& H; B* C: v3 }4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    9 v8 Y) S3 X- t8 f1 u' s$ \# B  F
  2. namespace one;" C; f0 k- p) K7 j4 @' n5 ~9 W2 [
  3. class Person{! p  K* [$ Q( Q0 j8 z
  4.     function __construct(){
    $ W2 ]8 Y* k! }  }+ C1 d5 I
  5.             echo 'I am one!';
    . Q8 J: [8 r0 d& p
  6.         }# q  f/ T' j. _0 F5 h; a
  7. }
复制代码
  1. //name.php
    " l& B# J6 t! A8 A
  2. require_once './1.php';
    . ~5 m) N- Z- R4 ]& Q  a( x
  3. new \one\Person(); //输出 I am one!;
    & f: Y$ J+ L" H0 r, ?' t6 }
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

1 C+ \8 F2 ?6 B4 F; p5 `
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
  }' }* J+ B! R& x  Z
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
% M; W( K5 ]8 N. o' n
  1. //1.php   1 a8 s: ?+ G$ l/ w4 z; i* ?
  2. namespace one;
    9 H' X* a0 s" v
  3. class Person{# i* y4 n3 {* u' S( w% f& ]* k
  4.     function __construct(){/ y* s% ^" I8 `9 x" Q$ J
  5.             echo 'I am one!';
    0 b  J% |" H( s' B
  6.         }
    ; E! r# G6 k6 c/ [+ o" [* |
  7. }
复制代码
  1. //name.php& L7 p+ \, j: t) i# h
  2. namespace test;
    " B  A4 I* G( H+ _. n' O2 _2 a
  3. require './1.php'; / m0 w) y. ~$ A& u# v9 w/ x& z
  4. new \one\Person(); //输出 I am one!;2 v# W+ M5 E; R, G
  5. new Person();      //这里结果会是什么呢,猜猜看9 `, Q& i# X$ I  q# f  r0 F) ~( J
  6. 最后一行结果报错:
    9 S& C  B! @3 s+ j7 t
  7. Fatal error:  Class 'test\Person' not found
复制代码

8 h6 D- x4 `6 z
" J  O! D/ c. t) l, m
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
; f8 i8 T3 b" w
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
4 K/ @5 f* N9 C
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    , H( L  r* g- G, A$ y9 n
  2. namespace test;
    4 k9 Q$ \3 L4 T! }$ @6 D* D! z
  3. require './1.php';
    4 @+ U+ B$ d$ }# r# u

  4. ; p/ m  q- [1 }3 }- w
  5. class Person{
    + i6 i- k3 z' d- t! h- d
  6.     function __construct(){
    ( \  M+ W& r: l& H
  7.             echo 'I am test!';: v% f5 F. ^. j
  8.         }
    7 A8 g, X* g( c" U! r
  9. }
    4 a! D- V$ S# w4 H5 F' B

  10. - ^# `3 v7 S' ], p7 w' V
  11. new \one\Person(); //输出 I am one!;# y" k6 N9 w; Q4 a9 o) w4 O+ u
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

$ n. v! J5 ~2 _6 b
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    % M" X+ y% K& I& M8 m9 m
  2. namespace test;
    . E+ c& R6 R% j, \' C  D3 V; r" s
  3. namespace one;( t) B" j4 U& e5 h- w' c
  4. class Person{
    6 F0 z1 w# {  H
  5.     function __construct(){
    & i* N# ]2 _: A
  6.             echo 'I am one!';
    4 V( T# h' m  D  f# ~1 E6 e
  7.         }
    " L* w, Z: ~- P" M' g
  8. }, |- a3 L: i/ L' f% V6 e6 [5 i3 Z
  9. " y4 J  M" J  }  `- |4 H3 L
  10. class Person{# W4 ^7 t! {! r8 {; c
  11.     function __construct(){
    + k8 u6 v6 X  P# _, y6 K! L
  12.             echo 'I am test!';5 i+ _7 B2 I: w/ Y9 W7 [$ h9 a
  13.         }  W. ]- Z9 w; K- X1 h& S  i6 U
  14. }
复制代码

- `5 y) {7 o6 a/ W! O* o/ p
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
; K  W1 M- v7 _! D; m" Q
看来简单的把require理解为替换,在这里行不通。
+ g" W/ s  g' ?5 |3 _- S
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。. O% L4 J0 W" `
  1. //name.php
    4 `* x: K9 H! u- Y+ C

  2. 7 O' H' x# `( q" Q. |$ k% g9 @" w7 [
  3. namespace test\person;: e2 b4 }4 K9 ^2 D( K' n5 q7 K

  4. % `# g" L) Z: I) r
  5. class Person{
    & z0 B/ D3 x3 }* u- o
  6.     function __construct(){
    * r  D3 o9 ^* Q( _
  7.             echo 'I am test!';
      m; q, @+ h  ?
  8.         }
    6 N) ^/ v3 E6 c
  9. }8 i% d' @3 i' t
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
1 |1 y* e' O4 n. q- Q
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

8 }$ k, L& T! q& s1 u" }7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    " j/ |: }2 ]8 X

  2. 8 A3 p7 x5 Q3 y( R7 X2 G
  3. namespace test;+ O6 S2 j. x7 p- G8 `! s6 R( H
  4. echo 'zhai14';3 t; H5 g( ]) P' l) \
  5. namespace zhai;
    ! ]& H6 f+ I! S: _2 ], b
  6. require './1.php';
复制代码

4 \  H; {9 J% C* H
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
5 n, D+ v: S) K% r
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
5 u% E& k$ D$ G2 A( v& X# G$ B
  1. //name.php
      D0 w* ?2 {' `+ {+ ~
  2. ) z5 q# e) |% u, b
  3. namespace animal\dog;
    / U6 \+ w6 P) K9 S# C3 w) _
  4. 1 v0 r6 ^( E* C8 v1 L, r4 [
  5. class Life{" j1 T- Z0 H& [
  6.     function __construct(){0 ?' c# _' v; L' l
  7.             echo 'dog life!';
    , B- r0 \/ p2 D4 ]9 Y
  8.         }
    ' X! U' s$ R- G6 w* ^( O
  9. }! {9 d& Y4 k" L% u4 S% N

  10. ! X; b% o9 ?3 V; d* h
  11. namespace animal\cat;
    7 T& c0 O( M7 k  R8 G0 F' P" Y  Z

  12. 0 N8 D6 l2 C7 b. v
  13. class Life{
    3 h/ _  w. q: t2 T
  14.     function __construct(){
    ! t9 M: {+ V; j+ S% v
  15.             echo 'cat life!';8 p% w2 c8 h3 }# w4 L) K
  16.         }
    6 J! C8 v8 b* j# G6 G7 h
  17. }
    : H& `" x9 H" ^+ j. V

  18. 6 H6 y2 g+ N5 `9 M& G
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间' J% n3 Y  y& c; H, S5 i0 T! l
  20. new \animal\dog\Life();  //A3 w( d% f' ]: O, D2 N0 V

  21. 7 v9 R( M: E3 p
  22. use animal\dog;  //a
    2 H- }+ k- S( K* g. Z
  23. new dog\Life();  //B& t+ ~7 j* w# k! ?/ \
  24. 6 B6 e5 o! m3 K4 E! D1 c5 ?
  25. use animal\dog as d;  //b6 u: ~% J1 k& X0 {' r
  26. new d\Life();
复制代码

! Z5 S$ n% D6 ^# ]
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

# T- w" ]' d# u  W; r6 {$ y
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

% G4 w" z$ _& [8 x3 ^& R: p
相当于
  1. use animal\dog as dog;
复制代码

. F" |3 v5 P7 m& k( D: y( L0 f2.namespace后面不建议加类名,但use后可以。
6 S. c0 G+ E0 K8 m# K9 D
  1. //name.php  |: ?/ a/ o- x' N

  2. ( ^, X. x) ^& c* }3 u$ Q) A
  3. namespace animal\dog;- Y" W5 D/ ~: Y7 a  @+ b, `- U
  4.   T: D* e& C! Z) @4 P5 Y$ m
  5. class Life{$ z8 ^' h* O6 {+ s" s6 B
  6.     function __construct(){
    5 k( B  g; r* ~8 G
  7.             echo 'dog life!';
    4 k; J0 ^* U/ |/ q6 h* A) _. `0 ?
  8.         }4 L8 t1 W' ^0 g2 e5 P+ X
  9. }
    5 Y5 p  o$ |6 n, h/ W3 I
  10. : A# F  B& X' o/ y
  11. namespace animal\cat;) A) E" z3 ^# F% ]/ d
  12. , X: N7 Y1 ?3 X. q! X
  13. class Life{0 U* K( S  J$ _. }. U
  14.     function __construct(){" [9 j6 i- L4 X$ C; I. V" T
  15.             echo 'cat life!';
    , R+ r# h. o$ Q2 `* h. c; B$ a8 W3 C
  16.         }& m2 p0 l+ ~4 ~: z
  17. }6 S( l% M) D2 C: a0 S0 T
  18. ; B; I: e1 ]1 ?0 Z
  19. use animal\dog\Life as dog;  
    9 `8 x, t4 S) O) Z
  20. new dog();
复制代码
$ d7 V8 z% h, d* r
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
3 D% J, x& A. J  h
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php: T6 a3 M2 E( T# h1 F, ?

  2. 7 O' @% \0 E) m- a# U( d+ S5 u( _
  3. namespace animal\dog;. B* Q  U1 S7 J/ z! w

  4. : u0 ^' H% m" R) M! X9 N
  5. class Life{, W% U5 E# f$ W: j- O6 B1 x1 ~
  6.     function __construct(){
    # N9 R' F) V$ r* f; Z
  7.             echo 'dog life!';5 Y4 q7 b0 Y2 W; A# w4 n
  8.         }; z: z0 i  a, o, g
  9. }
    ! G' r7 U' f# f
  10. class Dog{
    1 @5 c% d+ r. N2 o3 a( ]
  11.     function __construct(){5 o' `. H0 g4 |8 j* j/ ]
  12.             echo 'dog in dog!';
    . y6 ^5 z3 m; q' c1 j9 k! y8 Z
  13.         }
    4 |# e8 N# t3 R$ A
  14. }5 [5 z- Y- K) Z, j

  15. 2 G. }: u% y) ~' m3 W' O
  16. namespace animal\cat;& g% X) S9 [& \4 N# V  _2 S) v
  17. * Z  G  x. f9 z- T; L
  18. // class Dog{
    , |+ T- h9 J9 ?  J5 z
  19. //     function __construct(){! k6 e! Z8 h  i* v4 t
  20. //             echo 'dog in cat!';
    5 {# n5 s' v! O
  21. //         }
    ' y1 q  ]2 @3 C" Y2 B5 ?
  22. // }1 F! f8 [* P; M8 v0 P' [2 k
  23. class Life{/ v0 \$ `, ^# u9 i1 }
  24.     function __construct(){* X& n' R% ]) x  O/ W; L
  25.             echo 'cat life!';7 o+ C' F6 [1 q$ A# W/ N
  26.         }
    + m: N& y! u' a1 u
  27. }  |' q/ u, \+ o+ P# w' ?6 q1 C/ a

  28. - [" k0 W% ^+ y6 W& s* Q
  29. use animal\dog;  ( K0 l) [4 ?* J) s2 z/ m0 d
  30. new dog\Dog();
复制代码

* _+ {; B( N6 {9 z9 d( A+ q
如上,使用了
  1. use animal\dog;
复制代码

# X$ }. J7 H" L, D: M) ^7 J7 U
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

- k% ~* r2 |& j/ k
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

9 X$ c6 \' q5 L3 ?/ N( G: b& C/ }

! Y6 Z4 F% B9 v! {
2 k7 _; ^. p3 m0 o. T& E& h  }
, l' i* I: k1 q, F4 E9 a+ S

最新评论

GMT+8, 2024-10-25 02:12 , Processed in 0.101748 second(s), 19 queries .

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