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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

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

4 s7 X+ X7 J; @1 R" Y8 T
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
- v  k# ~( @$ ^& c9 K
7 P0 M; w) m+ K& K. _
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

6 g6 F4 L5 K* S9 `1 M* X
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
0 m* W& Y2 c: E/ r3 L, e
结合使用方法来进一步理解它的使用目的吧。
7 K4 W  ~* _7 H) z, |' Q$ z5 U% ?# a- {
$ s  E4 E* [' i' ?
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;2 {5 p, w% S0 X
  2. namespace One;- u, V/ U( L, q6 l% u* P. _6 O
  3. namespace ONE;
复制代码
* T2 b+ B" y2 F$ p" l
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

; V: L" m7 G, ?2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   " }( a# @, G1 ]; `) ^: L
  2. class Person{
    ' a4 T8 {8 n; s* u( u+ U
  3.     function __construct(){
    ( S$ v- K( G+ v& Y+ [  _6 S& J
  4.             echo 'I am one!';
    , R! V% C6 o" y( v% E/ K. g
  5.         }  K, B6 v9 {7 Z7 R! y+ P
  6. }
复制代码
  1. //name.php
    4 S/ g$ a$ F: w  z( M+ i
  2. require_once './1.php';  v% F+ V7 {$ [1 _

  3. & M6 g6 W: ~- Q1 f
  4. new Person();     //输出 I am one!;
    / O& Z0 k& u" C; ^  P* f' t% j$ w
  5. new \Person(); //输出 I am one!;
复制代码

( X, w0 \* w7 P" Z. @% ]" H( k3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    & [- I# @* s! L! ^5 \
  2. require_once './1.php';
    8 n9 d- k/ l5 l8 o" t6 Y; i
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
6 a. e" o: ~4 _. J
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   % d# {/ r& o5 i( x. m+ A3 d
  2. namespace one;
    ! i1 |- m0 x, O  L3 [
  3. class Person{' h- n% E& _7 H
  4.     function __construct(){
    / ^. R$ w4 N6 i9 H6 j$ L
  5.             echo 'I am one!';
    1 O2 K# l/ Y. F7 j+ `" K
  6.         }
    4 J6 f7 x' K  u
  7. }
复制代码
  1. //name.php
    * G; F) O* C# I5 v- {$ r. {( ]
  2. require_once './1.php';7 G* w, z1 o" h
  3. new \one\Person(); //输出 I am one!;6 k2 q; D0 D2 v; y; k
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
% U8 o1 R$ V; U' w3 i
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
# F) O% r3 a" _& D! s7 `
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。4 K$ `, T0 d( k2 F5 q$ p
  1. //1.php   
    * _: g2 C' X9 P8 b& n: c
  2. namespace one;) i' b$ p4 L! h: e* M6 @7 `
  3. class Person{- |4 s6 ^4 r* U5 T8 e
  4.     function __construct(){
    6 S9 [7 \3 R# t7 a
  5.             echo 'I am one!';
    $ S3 F# p6 \$ d
  6.         }
    & @  _  b+ N  U+ K9 Q
  7. }
复制代码
  1. //name.php
    # e. B% L% X0 w+ w2 d
  2. namespace test;
    + E- v& |. j- R7 @
  3. require './1.php';
    ) c' s" M$ k6 |2 f# _7 r& z. o
  4. new \one\Person(); //输出 I am one!;  U1 S4 T; N4 _2 d) |) q0 S3 H
  5. new Person();      //这里结果会是什么呢,猜猜看5 O+ i4 U# L/ \2 B
  6. 最后一行结果报错:4 W6 w% P: r$ C. P6 [
  7. Fatal error:  Class 'test\Person' not found
复制代码

' m/ C( L9 c6 e3 X6 T

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

6 T9 \/ ^5 D- T% `7 q7 `3 S
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

7 k" T; y  A1 E
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php% G; E- b) ^9 F7 c8 f# ]
  2. namespace test;
    * o; ^. O# ?. F% _2 ~3 n
  3. require './1.php';
    " f5 c' A9 j2 D4 P- i
  4. ; \+ G0 k, i. U! M
  5. class Person{. j. t* E* j7 N8 l- Y2 X$ [8 P
  6.     function __construct(){
    7 I- c# w: u+ m& k7 P% L8 E6 K
  7.             echo 'I am test!';) U$ R) A' R8 |; _' U: A
  8.         }
    0 T4 ?7 T3 E3 ?
  9. }
    0 ^6 h: O6 a& i% L- v, \+ q4 P8 S
  10. 9 P6 |9 I+ j% k/ R
  11. new \one\Person(); //输出 I am one!;: I; }% P$ a6 i9 s' h2 i3 z
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
4 H5 ?) ?6 q/ Y% a5 E% C# x% Q2 H% J
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    6 v' P# L5 J( L1 C
  2. namespace test;
    ; ?# o- n, R/ _
  3. namespace one;
    * [- e$ z" V( K7 H- P0 T
  4. class Person{" T; \8 ?, w- [2 H+ J
  5.     function __construct(){" L6 [% P( z$ X+ K; D+ ^% X
  6.             echo 'I am one!';: r# v: U% Q  E$ V% K
  7.         }( Z+ l5 z' m) E7 Y0 u3 }6 c
  8. }
    , \7 b: C. c% }: J- y$ ?3 y
  9. $ m/ C4 I& M% J# Y
  10. class Person{/ y2 m' S& S" f7 e. j7 ]
  11.     function __construct(){" h7 _7 A; p+ b+ i% I6 Q2 z, ?3 Z
  12.             echo 'I am test!';$ @7 c0 A; @6 o! A$ I
  13.         }
    / H: N- A5 y/ g* H9 h
  14. }
复制代码
" ?0 d1 t  Y6 i7 W! m
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
- \2 w: H! o8 v$ ^
看来简单的把require理解为替换,在这里行不通。

+ K& E. i/ ^( F1 ]( J1 ~4 f0 k; P6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
# |3 y4 K5 V7 C5 r# j% v2 d& |
  1. //name.php) A: L  i3 b! J( L3 {# b, `! U

  2. - ^' a+ p/ H6 l0 O: O4 |7 j% G
  3. namespace test\person;
    , j1 M  w( \# G0 x) }: ~

  4. ' Y/ [6 V( w) }
  5. class Person{
    : W" ^$ M* h% ~0 P4 @& `0 c0 L
  6.     function __construct(){
    4 F4 @8 \" k, _- L
  7.             echo 'I am test!';
    6 [- f1 M* w' ?" Q* J
  8.         }3 o. x& U8 P4 w$ L8 a; A
  9. }
      J# p. \+ k3 F8 F; _# ~
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
% G; |) z3 k0 d6 i' K( n
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
; w. }/ R. o# J5 \$ o% u* D: h% z, N& t
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php  V# z6 X+ b0 S3 A4 c

  2. 1 I' Z& A2 {8 h+ o# e; K
  3. namespace test;/ d# L7 |. s. V4 @7 Y" m% q
  4. echo 'zhai14';) `2 ~) z8 D5 x8 T9 K! T2 V5 ~" _
  5. namespace zhai;
    ( J; a4 z; d. L) @% ~( y- F
  6. require './1.php';
复制代码

1 j! z# f; f0 V/ m: V) a% D
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

# H# e' ^9 U  M2 ?: ]* w8 v1 s" ~use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。4 T5 X) \! Q8 j' L( E, n
  1. //name.php* W5 f" D! C7 i4 A# R
  2. ; F, V) f& V, ?  K$ J9 ?
  3. namespace animal\dog;
    - M6 |0 o( ^( I2 U
  4. 3 h$ D/ @. E1 I+ R- u
  5. class Life{
    * v& D" y$ x" h; H1 O
  6.     function __construct(){( k6 N* ~4 y( b4 k' ^7 V( ]$ j2 J
  7.             echo 'dog life!';+ x$ U9 b* C% i: L! x  {
  8.         }4 V# }8 L# Z' J2 r$ H4 m
  9. }$ n+ S+ m- q$ e- d9 P. z

  10. * [, z  K! o9 h, s( w( ]
  11. namespace animal\cat;, |3 K& k( y$ s& Y5 n$ K+ y0 O! U

  12. $ u5 R2 t4 }, f$ |' E
  13. class Life{" A- R3 z& B' @; |2 ^: r' y* p+ ]
  14.     function __construct(){
    " ^: {: I2 c8 `6 I
  15.             echo 'cat life!';
    % Y9 s" b( U2 V
  16.         }$ `9 p4 B% d8 s1 O9 N/ ~
  17. }7 ]/ ]$ j6 t% Y" s7 I( G

  18. ( r2 s% X' X7 F: u
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间' l2 v( K4 S) _, \0 z
  20. new \animal\dog\Life();  //A8 s2 B' X: s! x: o- }/ ?
  21. ! b; D- G* U7 y
  22. use animal\dog;  //a7 c) V6 h, @& V/ p3 l
  23. new dog\Life();  //B, j' X5 W2 W& B  A: F! _

  24. , r/ E) l( Q0 d# R3 s& p
  25. use animal\dog as d;  //b
    0 g! M* Q# U& s) F
  26. new d\Life();
复制代码

- [  u2 {+ l5 S' G
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

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

; j9 z9 o) H; S5 J2 `9 Y
相当于
  1. use animal\dog as dog;
复制代码

7 y! z0 u" k. l. M$ V/ L) e! r2.namespace后面不建议加类名,但use后可以。
1 f8 e. i  Z1 s$ Y/ M& O
  1. //name.php* ]1 C  o8 d( b
  2. $ g( [7 _& j; S
  3. namespace animal\dog;
    ' E" `3 v! C8 I" V6 n

  4. * i4 o8 J* Y+ J1 t  v% K) N2 w- E
  5. class Life{
    ) Q2 C6 G# X# k! g9 B% B
  6.     function __construct(){8 R& v) e. i+ p+ j4 u
  7.             echo 'dog life!';
    - N& d1 [; ~+ K  }
  8.         }; S& X9 Y5 N" s- J
  9. }" U! \% x% u3 Q: p

  10. / s0 v, |, r4 v2 g$ s) V& Y
  11. namespace animal\cat;
    ' X$ q% b; D2 {$ _

  12.   o' _/ `1 f% d
  13. class Life{) r! ~3 V/ g5 h4 M8 ?9 j
  14.     function __construct(){
    , p  d1 }7 d4 R+ }4 F+ Q
  15.             echo 'cat life!';
    / n% a. ~$ k; D
  16.         }3 t- e& p4 R2 V( ?) R4 n
  17. }& C3 n1 E; V" p& f3 D2 ?

  18. & r" b4 e, f# ^' ]2 P  V0 J" t; j7 c
  19. use animal\dog\Life as dog;  , P8 L* t- i# {) v5 m& I
  20. new dog();
复制代码
# k# A- }% p$ }* \7 l6 l2 }
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

) }/ f7 a: H% a# r* |8 c
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php' U+ Z* Y( q" ?; l2 O

  2. 4 E, b% U: u' J" Q, z& Z6 [
  3. namespace animal\dog;
    ; S* e+ D9 J7 g( Z6 c9 n# u

  4. & y6 w1 ^$ b1 v+ f0 ~# o+ D
  5. class Life{
    % b2 [) w$ x5 i7 B" E
  6.     function __construct(){: N' G. y+ I% W# ^) m0 d9 C
  7.             echo 'dog life!';- y3 b4 u" U6 n, ^4 i2 l
  8.         }
    5 z3 s$ U4 {9 `- Z+ Q! {
  9. }
    ; N- V* E3 k% @
  10. class Dog{4 V. _( q4 ~( S0 }. [. c4 ~& l% W
  11.     function __construct(){
    + u1 r! t2 V  V5 i' O. ^! {% a. N* b
  12.             echo 'dog in dog!';
    % Y% M  ?6 b7 ^7 X6 T& Y
  13.         }' u: n8 x' d, n8 n9 ]
  14. }
    $ H$ k. o( U" Y# l
  15. * z# n2 g/ r* ^" F' M; m6 D
  16. namespace animal\cat;
    , U* t! }* x* B% {: z" T8 x

  17. 1 ~4 A# f# R! S9 X
  18. // class Dog{9 y  |& L, z+ Q2 `9 l
  19. //     function __construct(){$ ]; }, A6 O( I4 y
  20. //             echo 'dog in cat!';
    1 T, j8 [8 s1 f- K, S8 g
  21. //         }4 W5 Z4 G$ Q- D8 C8 A7 w% o
  22. // }
    2 L' M3 Q4 r# r/ l' w! S
  23. class Life{3 z% p7 ?- x% V* _) o
  24.     function __construct(){
    " J$ ]  a2 I9 p2 |: t
  25.             echo 'cat life!';
    ! ?/ t( M& K# a# Z
  26.         }
    9 @2 n- S6 M$ R5 @: i: \
  27. }" k1 J4 k% K9 A% k; N5 k. X8 `, w
  28. 6 ^9 ^5 K4 C9 w% U  V/ s
  29. use animal\dog;  9 i! ?# G7 B# _! H
  30. new dog\Dog();
复制代码
% j2 X3 p0 l6 \" C# G" O" H0 S1 i
如上,使用了
  1. use animal\dog;
复制代码
! O# C7 Q: c& \/ [
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

9 x% o7 ^+ n) E& s4 K- {
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
7 b/ `9 F) ?: ?4 m3 M* F* o
1 P. d+ ]1 v, w* H7 Y/ L0 {" g

: \* R2 w2 E# C7 E# g, i  r% D( F/ f1 g* [% Q2 h
4 @* |  F2 i( [: W- P

最新评论

GMT+8, 2023-2-1 16:44 , Processed in 0.109756 second(s), 20 queries .

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