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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 11462|回复: 0
打印 上一主题 下一主题

[php学习资料] PHP命令空间namespace及use的用法实践总结

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。

0 b+ q& @- Q1 J8 K: a0 c, j
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
2 _, l  T. O/ u
0 n! V/ G% R& n$ k, c2 ?
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
1 k+ G0 z. I, q7 K) y5 s% i3 j
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
1 N1 H9 a) ]0 n3 F% r
结合使用方法来进一步理解它的使用目的吧。

8 b9 N8 J# s  Q' x
; T1 z# ]1 X+ ?/ V5 o( anamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;, F' J1 A0 n# x& b  f
  2. namespace One;
    " \  H% Y+ Y& ]( S
  3. namespace ONE;
复制代码
  |# k, {) s+ P9 |; B! s
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
1 S" ^- m: q0 y  }9 `/ U
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   / D5 Z! z# V0 e% @/ r/ f) u
  2. class Person{
    ( P: g0 F/ ?0 A" s
  3.     function __construct(){* o3 t" t" C- p# ^- l
  4.             echo 'I am one!';
    - C6 n0 i: G' J' m
  5.         }. z  ]0 {2 c9 A. S% Z2 H  c& ?
  6. }
复制代码
  1. //name.php
    * Z6 q) K& {5 T
  2. require_once './1.php';
    ; T8 ]  B& t) Q/ F# T! Z

  3. 2 \+ L) H( p/ y% @
  4. new Person();     //输出 I am one!;
    . g% R& L$ [6 q- I& x2 ~
  5. new \Person(); //输出 I am one!;
复制代码
1 O. r9 a8 Z' S+ ]
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    ' X9 }$ ~% b$ z) j; @: x% E' m
  2. require_once './1.php';0 H, u2 p3 C+ a
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

- @/ M# Q$ `/ n/ N5 X3 {4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   $ C0 D, y% E/ G/ g. [: w
  2. namespace one;
    4 D% T8 K) Q+ Y4 Q) p& |5 j* W# \
  3. class Person{
    2 P* ]+ o; G1 \# N" @# i
  4.     function __construct(){
    4 q0 w4 U- q3 s- t/ h. @; z
  5.             echo 'I am one!';
      z+ B5 A: n. s3 v1 Q" R: E* f: Q
  6.         }8 ?) A- e9 U8 L: M
  7. }
复制代码
  1. //name.php( E( P8 \2 e3 v4 R3 ~
  2. require_once './1.php';
    2 ]  r+ B# [+ F; j* ^6 J2 t
  3. new \one\Person(); //输出 I am one!;/ `0 q* N* ^6 w5 P( L  ^! n5 U
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
; F* v% `: x' X6 _( ?1 e
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
+ K4 u3 V% c' j- ^# l  K4 e: [' k
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
6 [5 |, a, X; L6 a
  1. //1.php   
    9 X2 G+ T: x' S- j
  2. namespace one;
    7 a5 [/ a+ y/ W( D
  3. class Person{
    $ D0 T8 }3 ]+ e' b8 G# L
  4.     function __construct(){
    0 }1 O5 y! G3 {8 X
  5.             echo 'I am one!';
    ) A+ T! d9 C) l2 ~, w. M
  6.         }
    6 H2 E& `2 Z. ^+ i/ D
  7. }
复制代码
  1. //name.php8 M7 j0 Y, R1 P2 O0 ?
  2. namespace test;- Q2 I" q! m; o; \9 M, F4 A( G6 k
  3. require './1.php'; 7 o0 a  }+ K, K8 o$ q+ C4 K
  4. new \one\Person(); //输出 I am one!;
    2 @- k+ y$ g! p; o4 O
  5. new Person();      //这里结果会是什么呢,猜猜看3 ~. J/ l3 K: g
  6. 最后一行结果报错:$ e* s8 a. n" s; |( W
  7. Fatal error:  Class 'test\Person' not found
复制代码
: J8 n$ ^2 r2 M; m2 N- M3 Y
, @+ B# |0 z& y2 z' t. b0 r* G/ o& b# V
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

& D5 R4 `& f, f6 o/ O# H8 H
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

- S* W8 A: ]: o5 e  b& C( L$ q* C
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php: m3 Y2 W! ?2 h; ?
  2. namespace test;; m3 v% q2 Y/ l# v
  3. require './1.php'; 5 u+ D1 O  Z# q1 e5 H, z
  4. $ }7 E5 {- b0 v6 Z* I
  5. class Person{( Y7 Z  `. r% e+ C. r% ?
  6.     function __construct(){! w/ d) Z1 d1 s6 \- y7 m6 i, X$ F
  7.             echo 'I am test!';( O$ A( s' q" R; z6 ~
  8.         }
    & u( c+ d/ A4 L& O
  9. }
    8 v1 t1 z( s: o- a( u1 T4 ]

  10. 0 i: K8 M7 G) u
  11. new \one\Person(); //输出 I am one!;
    8 G0 |+ o# `: k3 w% M
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

% A% Y- j6 n8 v* x3 S
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    . d2 x' S6 q9 {) p+ @
  2. namespace test;
    - c2 C9 S- E  l3 E. N" n3 r1 t
  3. namespace one;
    ; W% K3 t" S- b3 `" o
  4. class Person{6 @5 Z: p( h2 O1 o- x2 l
  5.     function __construct(){
    ! e+ C, V8 y( a. Z2 G
  6.             echo 'I am one!';
    8 R5 }" L6 X$ P' G5 P- |
  7.         }- m& R  x6 y8 a
  8. }
      T7 i  a. A: L) v$ z
  9. , A- L7 n, J& ?. u
  10. class Person{
    1 `9 C( ?4 v& j. q5 L5 T5 Q5 k
  11.     function __construct(){
    ( f+ S- v' Z  n* \( M0 u  m. B
  12.             echo 'I am test!';" E2 q: I9 h1 a7 T% E6 l' I
  13.         }
    0 G: v+ [5 Z0 `5 b& I2 W( W1 S
  14. }
复制代码

1 U  [+ F3 ?9 ^% F4 X# P
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

! C& r1 q2 x) U
看来简单的把require理解为替换,在这里行不通。

1 w, B0 j8 d& g6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
  K- f8 B8 J6 D: F' w6 E/ `# L
  1. //name.php
    8 l6 v6 {) E- t3 ~$ {! I9 u* k

  2. ) H3 b* H5 ^* n& Q$ H5 n0 S, A9 q, Y
  3. namespace test\person;
    6 Q% V3 s- ~8 n( N- ], ~% o/ j4 a3 \

  4. " [1 `. t% l7 t
  5. class Person{7 V/ o9 U$ Z- p
  6.     function __construct(){
    1 w( [; v% n* y% q
  7.             echo 'I am test!';
    8 g0 d$ A% f% V% [& P9 `+ h
  8.         }
    - X1 ~  ?4 s* E7 Z2 V: G) `5 N" M
  9. }
    . ]$ G4 w6 R! A: j3 [* v
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

# G/ L/ f% D% b6 o" E& {% p0 a
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
: F$ k5 o& F& P5 t- z5 H( L& t: ?
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php$ ]4 X9 x/ ^7 u' n2 {7 y8 K
  2. 7 H: ^) U3 s2 v6 ~1 W% J
  3. namespace test;# _+ `9 M" |0 f6 P
  4. echo 'zhai14';7 }3 s7 Z! R$ v4 v% Y; U
  5. namespace zhai;
    5 U8 j+ x% x5 N9 t, |$ [) b/ Z
  6. require './1.php';
复制代码
% l' S+ k, k  m: x
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
' @" }" Q8 d3 ]
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
# m' K% g7 \3 C" [
  1. //name.php1 S$ i: X/ c6 M7 y, r

  2. # H0 C8 ?5 c& ^# R/ J. L, u
  3. namespace animal\dog;
    8 n* F  ]! \+ n% h* q' W
  4. 5 @3 h0 k2 G# S9 Z6 ]
  5. class Life{4 H( O1 Q$ `  c8 n0 C* d  ?
  6.     function __construct(){
    " N% Y4 y8 ]/ D, G2 m
  7.             echo 'dog life!';0 ?% U6 Q% V; B3 G
  8.         }
    ! G; r. E/ q* R7 S7 K/ S9 Y
  9. }
    7 a  o0 c* S. Y3 ]1 ?9 w

  10. 0 z+ n$ R" f9 J4 l5 H7 c
  11. namespace animal\cat;1 h+ P6 F( C2 r& ~
  12. ( N- E  G$ s9 o* p% k/ `
  13. class Life{. S0 F! N& h; M: ], @0 a
  14.     function __construct(){
    / K7 Z6 @* z6 H& n) J9 `' K
  15.             echo 'cat life!';
    " p3 t1 R9 |7 t, z& o
  16.         }6 {; X' O$ }2 F. b& \  t
  17. }4 R# J1 J. k  l8 ~- @

  18. ( H9 C5 a7 V2 E
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    % k: P" K& l. H- B6 r6 A" d- o8 U( s
  20. new \animal\dog\Life();  //A1 ?" F2 G4 M" o2 y

  21. - x7 Y7 F- o! [/ J  y- b& X  I! i9 K
  22. use animal\dog;  //a
    6 n  W% e' T: r# M8 M1 [. L& G
  23. new dog\Life();  //B" k0 o( I& Y$ ]7 Z$ z4 H
  24. / E* x9 f+ h% N9 r# x
  25. use animal\dog as d;  //b5 S1 |% F& r  B# o# \
  26. new d\Life();
复制代码
! y# B5 c2 E) t! @$ d
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

. A) E/ }1 \5 ?) s& v3 p4 F+ W/ F
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

1 M4 U: p, v: [( c( {+ L& o
相当于
  1. use animal\dog as dog;
复制代码
, W# u; s6 |  e, J8 d- X
2.namespace后面不建议加类名,但use后可以。
3 j% E$ B& }) G& y
  1. //name.php, @% R) M7 G/ m( K/ q, g
  2. ! a% F1 i+ Q( S+ _' A3 B# b
  3. namespace animal\dog;* b) \5 m' \+ Q% D

  4. 3 x. k1 U, A3 G* H
  5. class Life{6 v0 N3 Y1 k. E; d- u% L
  6.     function __construct(){
    " n! E" J3 c$ F9 L
  7.             echo 'dog life!';, M2 [) y1 ?) r8 R+ v% c
  8.         }
    ! t3 ^7 I) w% i6 Y) o8 G! j& t
  9. }2 n( Y8 C* M6 q2 T' x

  10. - G; s  O' X. m6 i: V+ B
  11. namespace animal\cat;, L1 w3 i8 N6 I( R9 W. ~/ e1 c( s& U

  12. 2 m0 |* |- ^! O% p8 O- {' Q$ _
  13. class Life{
    " F. D+ r1 {4 p$ d& |5 L
  14.     function __construct(){' [; E' A# V5 ^# d0 n
  15.             echo 'cat life!';
      K$ @6 M9 W$ M* V9 K. h
  16.         }% v$ d, i) q  s6 ]1 t( k
  17. }. P) E* e) j; _
  18. - a$ n' [& n, R/ H! m
  19. use animal\dog\Life as dog;  
    4 V3 }, J( y9 H- u
  20. new dog();
复制代码

1 q* `/ a- }) m" [) x
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

3 Z% _0 t" t0 E% v8 K9 c  n
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php- s* \8 _5 `" M+ j

  2. - U5 M9 o" H' x. i! W) X) |' O
  3. namespace animal\dog;
    + `. f' t7 x* c# I+ B) ~

  4. ! ^* P( }6 N5 m' J
  5. class Life{7 O. b$ Y" A- V! q" _8 r
  6.     function __construct(){0 {/ h' [% V- |. i: v* T& _
  7.             echo 'dog life!';
    , g* }/ u* Y0 f5 t5 l- n* a
  8.         }
    9 V3 C+ \7 E) D1 N# c
  9. }
    8 b# k# S- R& l- o% P3 F. v
  10. class Dog{. z2 u1 r6 M% y7 m0 Y2 W, `
  11.     function __construct(){
    9 S4 A" `( F0 F+ t% y
  12.             echo 'dog in dog!';
    0 Q) `/ j+ k+ x) J2 r+ }1 g
  13.         }
    ( k3 y9 v+ }6 M5 R! A- z
  14. }" p6 u' E. H( N5 n' m! J
  15. $ s: X  h) q; f! U$ e' A: i4 e
  16. namespace animal\cat;6 p+ F" M) G1 R0 M
  17. % _9 y& H* P8 `  m0 x
  18. // class Dog{2 m; H$ w( K3 ?" [0 d3 Q# p7 c7 ~
  19. //     function __construct(){1 P5 M5 p/ {2 P, g$ G  t! ]
  20. //             echo 'dog in cat!';
    5 j$ B2 k2 F0 F$ q9 J$ Q, `
  21. //         }
    ) L' t) r6 W& j+ T
  22. // }
    : ^8 o. I9 S% ]; d# S6 G- D
  23. class Life{
    + S4 N. P# R6 f! K* M- X/ P
  24.     function __construct(){
    4 E7 Z6 f4 ^) Q! g' n4 O; X( Y
  25.             echo 'cat life!';
    & E9 a9 U, L; I9 l# B; P
  26.         }
    . k' `/ D$ z3 N; `, x
  27. }
    / c6 t% F0 h: z* v/ x% l" j

  28. % D3 k/ C# x6 q4 c$ n
  29. use animal\dog;  
    8 P# c0 v* c* B
  30. new dog\Dog();
复制代码

5 J3 {9 I3 o- U2 M) R( C
如上,使用了
  1. use animal\dog;
复制代码
' \9 G' ^2 v# f* ^. n$ o
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

* A1 ?" v( J, z2 z
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

% M, _! f+ j# o5 h* K
2 z: p7 `5 ]% I) w$ s. q: d. h9 ]2 B
1 w9 ]8 f! w  [" R9 Y

0 G& n7 s4 ^# X* a" ^: }4 ?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-21 23:42 , Processed in 0.117785 second(s), 19 queries .

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