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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
0 T6 ?, I2 l( h, [5 s
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

# f: j6 P1 w1 H
# Z* m5 j' e3 P% A( p使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
" s0 y% |9 [6 [
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

% U+ ^9 v3 x( n' u& F, R) t结合使用方法来进一步理解它的使用目的吧。

2 b# t0 l9 t/ S7 M5 h: B+ S7 ~! E* _) N1 N* D* L
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    7 k" u: w. _9 E
  2. namespace One;
    ! r4 `7 c) W0 [: @8 Y( A0 {/ V
  3. namespace ONE;
复制代码
9 C2 T" e/ v" d0 x
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
- D! n1 K0 y; Q5 [) I
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    & D% \- Y* L. t" j. e- o* K$ \
  2. class Person{$ _8 G3 b' W. E; Q' L  {
  3.     function __construct(){
    ' C" I- M. K  _- g
  4.             echo 'I am one!';
    8 B  l6 \) Q' `
  5.         }
    : d) q7 D1 v0 z: |& [
  6. }
复制代码
  1. //name.php* Q3 R0 F7 s- E+ l. ^
  2. require_once './1.php';
    # [$ S9 [5 a% X% }  W$ M) X5 D
  3. 6 G! z6 F0 X. y/ s2 t& \2 \
  4. new Person();     //输出 I am one!;
    $ W% r9 m1 b7 U( P' U
  5. new \Person(); //输出 I am one!;
复制代码

- A8 u- H, G$ w1 L" @3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    % L' B8 \9 C1 a1 e
  2. require_once './1.php';
    ' R7 ]" Y( K; ^) e. ], u' p) D
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

! I  d5 Y7 W% ^8 p+ {4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    4 h% j3 v& z3 W9 N- t
  2. namespace one;: Y$ i  u0 [% a* A1 Z5 v1 G9 |
  3. class Person{5 z& c: E% i; [2 Y2 [3 ]* r
  4.     function __construct(){
    ) o$ Y# E  V9 |4 y# r9 V
  5.             echo 'I am one!';
    # w3 f5 T# @/ i
  6.         }; u4 G( i, @; e8 O5 |
  7. }
复制代码
  1. //name.php
    % z# R  w: c: X$ |! L
  2. require_once './1.php';
    - z2 ~3 ^  r2 P5 {3 n7 v$ S
  3. new \one\Person(); //输出 I am one!;) Y# S9 J! y, g* @
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
: _, ~/ q8 B2 D4 B4 g
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

: @/ m7 O$ l: G5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。) o  e) x5 J0 _4 ?( A
  1. //1.php   
    9 b7 E& L: V9 R, H4 F4 q, P' Y
  2. namespace one;
    ! ~+ P- N" L' T2 n  e6 T
  3. class Person{
    & G" x$ T% Y6 D* v# R
  4.     function __construct(){$ P, t* d' c( ~3 N  q
  5.             echo 'I am one!';- f& @. y& s* Z: Y
  6.         }* C0 d! G3 D( r- ?# i3 o3 {- U+ `
  7. }
复制代码
  1. //name.php
    / o1 B5 e+ E  m3 ?4 r! l4 f' y
  2. namespace test;
    ; T- y# ^& A! ]# U2 V
  3. require './1.php'; : i; k4 {& r) u0 b( `# }4 L0 I
  4. new \one\Person(); //输出 I am one!;
    % D1 x) M1 v8 C  h- X: T- d
  5. new Person();      //这里结果会是什么呢,猜猜看
    9 x9 n, D: T( f
  6. 最后一行结果报错:2 J- b& l% Q6 Y/ l% n$ m/ O
  7. Fatal error:  Class 'test\Person' not found
复制代码
  K. R$ n  F' w. @- u. t

2 ]* R2 i, \3 F5 I6 l首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

- p; _( a# d3 [1 E/ {- C" W. ?
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
; r2 I: k2 k+ }
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    8 q  y4 G+ z: E: R1 {
  2. namespace test;' @0 ?1 ^+ [. |+ w
  3. require './1.php'; ( w' t5 Z  \1 ]2 @

  4. 9 \% K0 {4 t0 x5 L8 a& U
  5. class Person{' Q6 q8 T$ i: [9 ]% y
  6.     function __construct(){  s- _# c/ }' {9 q
  7.             echo 'I am test!';
    6 f0 L% `$ ~/ h9 E. M' {
  8.         }# B( ^/ G/ X0 N: j
  9. }5 T6 [1 |( g- Y" ?) S

  10. ; U, T: O/ |9 X9 X: E; {
  11. new \one\Person(); //输出 I am one!;1 |. [" b) f; e; A  L) \3 ?' m- ^
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
- l( d/ ]6 H; R) G- c
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php) |4 P7 D2 V' i9 N4 W
  2. namespace test;
    : z( D/ U' Z3 i2 G' m
  3. namespace one;
    , y" a! H6 y: z  i
  4. class Person{) J" h) |/ R! a
  5.     function __construct(){$ e: w( I+ G: e6 H9 C8 C8 p
  6.             echo 'I am one!';3 d  u) n  g" l: P9 [& r
  7.         }
    3 d, E4 |+ O. F3 C
  8. }1 V' D" U$ w5 v  n

  9. - ?* a- v+ R- U$ R7 U
  10. class Person{" p% @( z6 s/ J( G( o) f: ?
  11.     function __construct(){4 N6 Y3 C0 P7 k. |8 C0 h
  12.             echo 'I am test!';
    , V  X& v0 P7 t) x" S
  13.         }8 U$ Q# \' y- ]+ S8 ?
  14. }
复制代码
4 d3 K% z8 g' `8 M
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

) }) F0 L7 z% G5 d: H( D4 v
看来简单的把require理解为替换,在这里行不通。

5 o3 h5 t8 {/ G6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。* `$ |( F- `; K( y
  1. //name.php+ Y& O1 W3 F2 {: f
  2. 2 o  X3 E+ W4 R: K  F2 V6 }
  3. namespace test\person;
    8 R% M: y4 c, G4 n( i# v. V- N
  4. 1 w$ a4 b/ O! B9 G6 Z- u: @( _
  5. class Person{% ?5 Q, L3 t8 z3 _2 v
  6.     function __construct(){. V! C* Z3 a3 k! p8 N6 o& s
  7.             echo 'I am test!';
    6 |+ X* B1 g4 V; Y. ~
  8.         }
    + C+ A* M4 c2 d+ ?8 d% ]# L* w/ Y+ Q
  9. }4 i0 d4 L& p% d( @6 p! k
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

7 Q8 a3 C+ O5 F+ t! a% l* z- X
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

' g& a# Y, i2 s+ r3 |( ^1 ~7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php2 p1 v3 K- G- V; K8 b% M3 u6 u4 T
  2. / C* A" b7 ]* n$ T
  3. namespace test;
    3 n* r, {# b5 n6 o% M. \
  4. echo 'zhai14';. A% E( K% I: q0 ^0 Q6 ]5 A1 S5 {
  5. namespace zhai;9 s: U! Z7 H9 m9 J5 d: u6 M7 g8 ~
  6. require './1.php';
复制代码
: X- r9 C! d  q) v% Y  ]  P9 `
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

; L( n5 F) S" e& {6 t" z' ^use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
) {  w( F, T* c. p* C* g  ?' e# ?+ V& f
  1. //name.php+ c' H" U* T) n
  2. ; f6 |& N; q. \9 p4 J1 t$ K
  3. namespace animal\dog;
    1 ~) t! x8 J0 E/ b- w% t" p: i

  4. + G& }, X' F  K; {
  5. class Life{9 C( b6 S" }6 P* J+ @/ V5 u9 \
  6.     function __construct(){& V7 |. ?  i) W3 V; t' w
  7.             echo 'dog life!';
    ( P+ w6 o- H/ [! Z. h
  8.         }
    ' l8 r( B* ?4 k0 M% N: s
  9. }" N: l: K8 ]0 Y: v" C) C8 y

  10. 3 }  V2 p. P( F, E6 [# @  [
  11. namespace animal\cat;
    3 ?) j; L5 c7 x) N

  12. 3 M# {8 u4 T" i! ^6 t% V# l
  13. class Life{6 {/ }+ X. e$ U. G$ H; D+ ~
  14.     function __construct(){  a- c! S( o# j) ~8 ^
  15.             echo 'cat life!';
    " l$ |" b, r1 `# j' F. N
  16.         }
    1 l6 X  ~& F7 ?  v0 O/ q, Y
  17. }
    6 O, P+ w$ D! H
  18. . l% u: O5 G! i# D# D2 {+ O9 j
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间: [+ z5 x1 U( B$ e  C2 U
  20. new \animal\dog\Life();  //A
    % v; O& M0 F, |) p
  21. * O, _: q2 @+ G, }7 F1 t3 |
  22. use animal\dog;  //a: ?; Z: G" P1 `+ T& `& V
  23. new dog\Life();  //B' ]% w1 C7 E( r

  24. / y. m# \# e- ?& O) j- Y
  25. use animal\dog as d;  //b, D8 k3 l8 n! s* ^# I. t
  26. new d\Life();
复制代码

) G. g, M8 V* U( H% H9 k0 t* ~% F
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

1 L! L# Q& y5 I  Z
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

% S- Z" [% X& t# B8 Y1 L
相当于
  1. use animal\dog as dog;
复制代码

& m* ?6 ~& @3 X/ J6 p2.namespace后面不建议加类名,但use后可以。8 }+ {* a+ P' H, M$ q
  1. //name.php
      k6 T# b! I7 y) Z* v1 \* P; r

  2. + A7 d  @, g; o# M: c( d2 T
  3. namespace animal\dog;" C" }7 P" Z: v* F" X
  4. " U! ?/ w! |/ j9 k; X6 ]
  5. class Life{
    3 d" ~1 t# R! x
  6.     function __construct(){
    / x0 u* [; v* Z9 f; p  x9 Y$ J1 _
  7.             echo 'dog life!';
    ! ~: A9 K3 X( g- v- m
  8.         }  \' t& Z; ?, g
  9. }% N- i0 b: K8 s! J+ p3 o1 b

  10. $ j- |4 _/ c  _$ }+ D
  11. namespace animal\cat;  b, \! L+ {  T1 v5 s

  12. - i# _5 ?$ ?0 b& \5 h0 h. U$ _
  13. class Life{
    $ ~1 I' q; j. q% P; r% \  l3 p
  14.     function __construct(){" w! Y) u0 v( s0 b8 |
  15.             echo 'cat life!';
      B8 K  p* x! t
  16.         }
    / y% D2 H  K/ P+ D2 `4 i
  17. }
    2 N/ m$ `0 K3 m8 I
  18. 1 o& t1 H" y4 B1 ?+ J5 q- c; \0 }& u
  19. use animal\dog\Life as dog;  
    ( A1 a4 t! I% a8 P
  20. new dog();
复制代码
' d* ^4 s' A% b9 p; P) o7 \- [3 i4 \4 R
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

; m/ R  q4 n9 ~1 I. B, \0 G
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    ) S* [$ f: X: P, f7 @5 k' v

  2. * K* ]. P0 f/ C1 y
  3. namespace animal\dog;' Q8 Z+ P/ J; g  C( M5 j
  4.   |( Q0 o5 h$ ^; `9 v& x5 ?
  5. class Life{
    - `: I7 S% g2 D6 b
  6.     function __construct(){; P! E& l% {5 O1 M0 C# y
  7.             echo 'dog life!';
    3 w9 m. Y$ _6 [, \
  8.         }
    . t$ G+ ?& ?8 P) e! p) `! }
  9. }
    * E% s3 x$ k/ y7 ^" \/ V/ O$ T
  10. class Dog{
    $ O, G. d% w& r8 m' G9 w" @
  11.     function __construct(){% g, A! l  y" I! }
  12.             echo 'dog in dog!';  f% g4 Y2 i  ?
  13.         }$ b/ c. `; S- D, b
  14. }# g& p/ o7 p8 u
  15. # {8 z5 ]) n. |( w$ a: v
  16. namespace animal\cat;, J3 ?% Y' K5 r3 S! Q1 x

  17. : t, V8 W8 T9 ], B( d) k# p' W* d
  18. // class Dog{0 s" k8 E4 M8 W- [! ~' ]
  19. //     function __construct(){
    6 f* j6 y- V4 Q% M  @0 v: v/ ?
  20. //             echo 'dog in cat!';
    3 A( Q1 X/ V* {2 d5 b& T% n5 ~7 K
  21. //         }
    0 A# @. H3 [" n; `' K9 c( R; Z5 a
  22. // }+ q) m' _% G5 z" k  E
  23. class Life{
    : C1 I% R: o8 `' @
  24.     function __construct(){
    0 D' j, v  O4 c# e* c9 e+ W4 r* S
  25.             echo 'cat life!';
    - n6 [6 s1 m7 f
  26.         }
    0 j" A8 E5 D1 E# k, ?4 w
  27. }3 i0 r7 `/ U7 J$ p. v) S
  28. 2 v8 E' l! G/ e4 K
  29. use animal\dog;  
    - s( V4 A; T. w9 |% _
  30. new dog\Dog();
复制代码

( l7 y: z  e5 S
如上,使用了
  1. use animal\dog;
复制代码
* s+ Q* C- v' f
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
* Q  |6 {) _: |; O
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
+ R: z0 o6 |; F6 H7 n! ?
0 w- l5 j* m4 a: D' u
: f: `8 d0 a2 e; D1 b( |! |

) [: o2 r! ^( h# j7 W0 w5 K! G, m! ?& i

最新评论

        在线客服系统
    申请友链|小黑屋|手机版|Archiver| 备案信息代码:冀ICP备18019919号-1

GMT+8, 2020-8-7 03:18 , Processed in 0.153677 second(s), 22 queries .

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