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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
/ h# b* |% A, {3 Y
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

9 j3 m. v" u: I, O" P4 b
$ ]- w6 a: Q, r% L1 P使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
2 @, f5 s7 e4 j, {1 i+ S* l) g0 x. k& e
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

% G0 T& o% }8 y结合使用方法来进一步理解它的使用目的吧。

3 Q6 c* W2 m* N0 A- q" {; k, R
  |; y: G1 O& R' [0 [  l: znamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    6 O, C9 z4 B) ]. v! M; M
  2. namespace One;
    3 }* ~8 B1 o& U+ f! o% K) G
  3. namespace ONE;
复制代码

) x0 H5 `& Z  \
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

5 O! O7 H' Y/ U! h% R2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    * U1 g6 o- P; Q
  2. class Person{
    2 `% T# n0 L: ]3 Y  t! E& ?
  3.     function __construct(){
    8 N9 M3 X2 `2 o$ j3 v
  4.             echo 'I am one!';
    ' e! ^3 ~, {( J! J1 q
  5.         }
    8 a) Q# s$ c- F  y3 m
  6. }
复制代码
  1. //name.php
    $ a0 S, C7 K- [
  2. require_once './1.php';" G9 M7 B# K, g
  3. # K6 ~( a5 @6 a/ q6 ~
  4. new Person();     //输出 I am one!;+ Z& i  W3 C+ }' n( ^1 s. t$ m* c
  5. new \Person(); //输出 I am one!;
复制代码

* l* U! e" G: s9 W3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php. k; R" U" T8 U  t8 I& W  A
  2. require_once './1.php';' }) u( c" D  Y! `
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
. `3 X5 a$ \6 C1 l9 K+ V2 P
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    % N+ E1 K1 W3 `2 |, E; l
  2. namespace one;
    . V7 m9 V+ D& f* Y  m( z
  3. class Person{6 u* q; [* D; m/ f. S- ?) }
  4.     function __construct(){7 j' j6 ~0 y) i, y" Q3 u
  5.             echo 'I am one!';* J$ \, }! E7 `* u) M6 }$ X+ _, r
  6.         }
    ) x2 g. Y: l8 E" r
  7. }
复制代码
  1. //name.php
    $ x4 H8 \; N6 P3 A( N! q0 |+ r
  2. require_once './1.php';3 }# M& ~5 @$ X  W- ]# y7 y: ~/ ^" c
  3. new \one\Person(); //输出 I am one!;* t  H+ b) \- h* `5 i: E" Q) D
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

, S  o( q9 U' w
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

$ a- s6 X/ l% p! A/ z" k& S5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
6 V4 l+ a$ H% T( ?1 x
  1. //1.php   
    - [; y3 Y/ s6 l& g* W7 d$ x* e8 w
  2. namespace one;* K. @) Y( I2 d" a! e  ^0 d  p
  3. class Person{' y" j/ Y8 i! \) a7 P" X- N6 l7 w
  4.     function __construct(){
    : ?( Z* Z+ h% l7 [$ n& w
  5.             echo 'I am one!';) Q* ?- A4 n# ~4 q/ m- s
  6.         }* R3 @% b" z+ B( k* h' T' g
  7. }
复制代码
  1. //name.php7 L6 b& X; G2 W- ~( N' B
  2. namespace test;& x  X  v+ O9 m! ]1 p, e  Y- H
  3. require './1.php';
    : B; X6 L! g- G4 k* F7 b. ^' Y
  4. new \one\Person(); //输出 I am one!;) `( m- P, q' P
  5. new Person();      //这里结果会是什么呢,猜猜看* q/ s! D+ P$ R  Y' U3 u
  6. 最后一行结果报错:
    ) m/ N  @4 S% c8 E7 o
  7. Fatal error:  Class 'test\Person' not found
复制代码
0 u0 q8 v2 k& S0 b
' B. }7 Y, c" c; P
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

! F5 Q( H% }. |" O/ Q( d: ~
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

9 \- r% m5 L; A: y* O2 W- t. |
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    9 X9 v3 \* ~. C6 K$ h% B. }/ n
  2. namespace test;
    % a& k- [; g9 P2 K7 h. }3 ]
  3. require './1.php'; + |+ b/ `9 r* |% T9 S+ u

  4. 9 b6 Z& V- v. p# |  W7 C* t( E1 z
  5. class Person{+ b$ J8 y5 d) E7 f/ D! i- U
  6.     function __construct(){. \7 S$ x: N* V* m/ C: F7 g
  7.             echo 'I am test!';
    4 ]$ }$ u! R# ~+ H
  8.         }( S) j  M3 d- \/ Y% G
  9. }
    / k7 n( M; c, l- P% A4 I

  10. - l" b" y/ T; [& M/ S
  11. new \one\Person(); //输出 I am one!;& w* c/ M3 O7 z. F  v# j6 _" X  o
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

* @' K2 t( K' q
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php( P' @2 H0 n4 A+ `3 x  d5 T8 b
  2. namespace test;
    1 W! @$ i# c0 e" c$ F# O. c
  3. namespace one;- c+ i- A$ |  e% L# T6 E2 N# J
  4. class Person{8 l# k! k/ Z( H9 D
  5.     function __construct(){5 a# d4 Z6 _) ~3 P# R% w( G5 }
  6.             echo 'I am one!';
    , H2 V7 y/ g- D. H( I' W
  7.         }
    7 Z, T5 Y8 l  E. o) r/ x: a
  8. }
    - l$ D" a% h/ E* Q

  9. ' Q' {# a, b" Z: d) f4 x
  10. class Person{
    ) f" z% z8 K9 s) _! y
  11.     function __construct(){
    # ?  S4 T. A- G3 o
  12.             echo 'I am test!';* z( R4 K0 @# V+ G
  13.         }
    1 r" p3 t* M$ Y% \7 ^% c# `+ }
  14. }
复制代码

$ C# M$ V/ _, V
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

5 p. z$ ]) ~0 g3 Q) C
看来简单的把require理解为替换,在这里行不通。
- D- d. r  U% U5 |& @
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" |% ^% S% d$ |4 i; c2 S/ W2 {
  1. //name.php
    / u/ G) k+ f3 u" k7 t% u8 S0 p% I4 D
  2. . Y6 m) p  v/ x6 @0 d
  3. namespace test\person;( ]0 F! Z  t0 ]' p% K

  4.   d  Y7 }7 ]" Q) D# H' ]
  5. class Person{
    " _. i+ `* {$ R. Q2 C- R: p8 s
  6.     function __construct(){
    0 M1 @0 ?: d# u( {6 X) `
  7.             echo 'I am test!';
    8 b& r) E& |7 L% b- A* w  [
  8.         }- _# ^% N1 q: p; }$ w* x9 C
  9. }
    + @" F  a& ^2 s5 T; Z) s2 d
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
' h) z7 C( n% b
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

3 a# F+ S2 ^5 y2 b$ I7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    ! s2 F+ W& m: F5 S' n
  2. ! g' a# r/ Z3 B/ j1 r
  3. namespace test;- D) w0 M/ p. R* x0 R, W
  4. echo 'zhai14';
    ! H* m7 z8 V- |. R; u- n4 `
  5. namespace zhai;" B. g! G+ C) o3 v( M
  6. require './1.php';
复制代码

$ Q5 D/ U/ x# o$ X* e: w' I: q( D
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
/ H" t( `' n$ {4 \' b8 H1 C
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
9 z! l/ R0 k! j2 Q0 h
  1. //name.php* Q# k* V0 \6 m, t2 {
  2. $ z5 C- ?2 {6 j7 j1 T
  3. namespace animal\dog;- i. q+ K9 z7 S3 m- r* t8 k: s6 P2 t* u
  4. 1 ^/ |. A' N! A: N0 z( i5 P* M
  5. class Life{
    : q& v: J5 G; u& v4 @: j% v
  6.     function __construct(){5 n4 h  |# ~: G8 @( g& i+ v
  7.             echo 'dog life!';# m( ^9 i8 X& d3 T- |& X
  8.         }  \+ F1 G- V* O
  9. }
    5 ^. W" {3 p+ v$ k

  10. 2 E$ ]. r4 B# Y# ~9 Y6 U, R
  11. namespace animal\cat;' y5 B9 N# G* w! Y4 S
  12. 0 `+ {4 j8 ^4 R: W' g$ Z$ Z% O5 F
  13. class Life{
    1 y" U& G+ S5 k* I* b( a+ X! d- v- G2 `
  14.     function __construct(){
    4 l) d/ B+ W) C" I
  15.             echo 'cat life!';
    8 U- W# U; i. W8 O* K9 S. Y$ g
  16.         }6 h. ]* _+ Q$ |1 O5 `
  17. }2 p; j0 J7 d# \- }4 y' q
  18. & N, N& I- x, b4 S0 f
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间  W* w4 z( a2 h6 x3 H
  20. new \animal\dog\Life();  //A" K$ k; a2 L) j! I1 n  }2 F( \

  21. / t7 n  p; `5 }3 p. v
  22. use animal\dog;  //a) q! T5 k  S, D5 L% _3 @
  23. new dog\Life();  //B
    ! |1 M+ P% v1 ]! M4 w& Q# r
  24. 0 H: v- m8 f- ]. p3 X/ o
  25. use animal\dog as d;  //b
    0 C& B' S& ~6 p* b) Z" H
  26. new d\Life();
复制代码
* a, s3 Y/ N4 ?* l
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
: Z  u. I9 }# D* T; b  |+ X- F
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

: H9 ?' q2 |4 K+ B) Z. c8 m
相当于
  1. use animal\dog as dog;
复制代码

) A, X* t$ N/ D+ r5 Q* }2.namespace后面不建议加类名,但use后可以。' o. q; K; V& _% h  w+ B% g! M
  1. //name.php* G8 _: j- x9 ^7 n! |

  2. * G$ j; E3 y4 M3 p- t" S
  3. namespace animal\dog;
    & s% x2 z, ~3 q* M& D& j$ H
  4. 2 b7 E* }* L% m  d1 Q
  5. class Life{
    % Z7 ^2 Z; e' I3 F* r% Y& d' c
  6.     function __construct(){3 D* B! A( ^& P$ w
  7.             echo 'dog life!';' C& z2 z9 h1 T5 @
  8.         }# K3 H2 h3 y& a% w- \
  9. }
    3 `% ]7 A% c( E) o

  10. 0 \9 h0 k7 ?0 k: {5 M7 [7 D
  11. namespace animal\cat;
      \  j3 Y) n7 Y& k4 r( {
  12. 5 K  p6 v5 I: Q  |' Y
  13. class Life{
    : U# z" N9 N) O) j
  14.     function __construct(){: _* Q0 P* m; J# I! V7 r2 s
  15.             echo 'cat life!';7 `, T# `% q4 _2 o) ?/ C  o
  16.         }7 d( [! i" h& D0 G5 t
  17. }
    ; }3 f$ @/ d) A0 g3 w4 n: X2 h- W

  18. # D3 b) N- v: s1 M
  19. use animal\dog\Life as dog;  
    # r* B7 f  W0 K2 q) q" ?8 Y2 J# O3 C
  20. new dog();
复制代码
$ e- e1 N# W9 V( T4 e
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

7 z2 ]* R0 |- O9 K6 P& T
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php/ r* l# f, z! Q( w3 v

  2. % |, o  [" B5 b# l/ {/ i
  3. namespace animal\dog;
    " g1 o$ M* D/ e  F
  4. 9 `! Z5 s9 B" S2 R  p0 _: U
  5. class Life{
    & Z1 \/ w5 e  }' z0 ]6 V
  6.     function __construct(){/ f: L# H" l) E  L& a9 s0 `  e7 r
  7.             echo 'dog life!';
    + a9 ^" f( Y0 W$ ]% @
  8.         }3 L7 H9 R1 {) i- J
  9. }
    & `. v! x( O" g
  10. class Dog{
    0 u% Y5 l; y9 H3 a& K7 a: ]" b
  11.     function __construct(){
    8 K3 H3 J: \4 [% t% ?& E
  12.             echo 'dog in dog!';
    3 Z2 S# G# t9 O: Y
  13.         }4 Q' ]+ `7 y' _4 |& R
  14. }
    - ]. L' l0 r/ y1 t; i/ Z; A, x
  15. 6 x0 K$ S0 ?0 k9 a- l9 b" w
  16. namespace animal\cat;
    8 U' b* ~* R' K

  17. 2 L- ?( E# b3 l5 Q5 a$ H
  18. // class Dog{( p9 D3 h" [. Y' _5 O
  19. //     function __construct(){
    6 o9 U8 r8 P/ I- L7 r
  20. //             echo 'dog in cat!';
    0 C- U% q3 w* f6 c" o7 W
  21. //         }
    ; b8 w, K9 I, d
  22. // }* p! D% \1 n+ l- n% c
  23. class Life{( ?* [  H. `% i3 o" N
  24.     function __construct(){  U* x8 p  L/ D" n
  25.             echo 'cat life!';
    7 {' s( A; m6 e1 i8 ^3 g  D
  26.         }- M3 F( k& U: j& _( D( T
  27. }) o* t1 a0 K  o8 J

  28. 0 G: z. E2 o# @, K  t" \
  29. use animal\dog;  $ V! Y& k1 d9 a  A5 u0 _
  30. new dog\Dog();
复制代码
( g4 s, m  |  n+ D+ [
如上,使用了
  1. use animal\dog;
复制代码
' F% @- T# e9 M' n+ `) ~% h
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

: @+ A; Y0 D/ ?) B) B2 N
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

# m2 K" T2 h" J- z1 M& f* q7 Y9 Z) }4 i& F
: o' W# b- Q' v, }" U5 A% o

6 H% W4 F' a; `4 P; T2 D
+ U7 w. |, k- U! O6 G: ]& U

最新评论

GMT+8, 2024-4-20 21:21 , Processed in 0.120902 second(s), 19 queries .

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