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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

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

6 {0 }: B& `. ^; m$ J
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
' z$ p' o! N2 A- R( i

! G+ O% w( E" e( A使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
6 D3 p8 x! Y7 X8 Q4 `& @. ~
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

; s. Y5 v$ r' s( ]9 I" d, {结合使用方法来进一步理解它的使用目的吧。
1 a: N; a% |& K

6 ]: V5 w+ F! S% Dnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    3 R& k0 d( u- c% j$ I7 o4 i6 n6 |8 i+ e
  2. namespace One;" g8 d$ F9 ~! A3 p4 y* T; |
  3. namespace ONE;
复制代码

# r1 C" n1 z  j8 q% K8 C
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
( u2 z2 B$ y2 N
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    4 K- X6 p9 q: z, {+ _; f, g1 j  C
  2. class Person{2 W4 b. M5 g8 U& {( j
  3.     function __construct(){
    % i2 m4 h9 q8 n) {
  4.             echo 'I am one!';" @  p; ]) {+ B  c9 {! H
  5.         }
    7 l& Z' L8 W1 J  X
  6. }
复制代码
  1. //name.php: E' `, G1 Z2 w( }
  2. require_once './1.php';9 I- _; C0 E, S0 I
  3. ) x7 q8 X/ J7 j; q' y; U
  4. new Person();     //输出 I am one!;& v  G( U* c3 J. x  E. K( N
  5. new \Person(); //输出 I am one!;
复制代码
) K$ P3 R- o6 C$ o* z7 U- ]0 W8 S- n
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    + S& @$ t( t7 R* }4 D( m
  2. require_once './1.php';
    " a! N+ v  g+ B% [' J2 T( y
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
% G+ N' ]6 h. V" Q: {. X) ?
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   ; V/ a& Z( ^/ ^8 x( A5 y
  2. namespace one;
    " F7 ?) e% s6 V9 i/ O$ O
  3. class Person{
    7 k' C: V7 r" t4 v* o. c1 o7 Y
  4.     function __construct(){- }' V9 c2 k2 o: a
  5.             echo 'I am one!';  C2 m) V5 r  _9 O) O
  6.         }
      U1 ^0 \7 j+ p6 c' g. X" T/ V
  7. }
复制代码
  1. //name.php/ t5 Z0 z  A: h7 |& o
  2. require_once './1.php';
    & u& E+ e& F- K  z
  3. new \one\Person(); //输出 I am one!;  I4 x) h3 F, ~3 w4 K5 |
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

! B/ q  @# Z) y+ v& v* [
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
% x$ @' b% I5 r: E( D
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。  {: P, u2 G# I* ]* {  d& v4 x' g
  1. //1.php   8 q& T( f& f7 D  m$ |
  2. namespace one;6 a" m3 O% x! b; X4 W
  3. class Person{
    : w# |  o" \. A  V  Q9 u8 q
  4.     function __construct(){5 `# I7 p! I4 O' g0 Z$ L
  5.             echo 'I am one!';/ V7 }0 s3 ?( f+ B
  6.         }
    ' G+ T# s  u3 F0 {$ M) x! G
  7. }
复制代码
  1. //name.php5 e3 ]; T# J; V) \! b& D6 K% [
  2. namespace test;
    8 Y5 R" ~) ~3 v2 g4 H
  3. require './1.php'; 4 ^  F1 _" V6 x- E. |2 `; o7 G
  4. new \one\Person(); //输出 I am one!;
    / v  j3 t2 M+ g1 g# _# T
  5. new Person();      //这里结果会是什么呢,猜猜看
    , ^* s( o8 o$ }9 F; m2 Q
  6. 最后一行结果报错:
    2 t0 {* ]6 k8 b, Z* @0 m; T. N
  7. Fatal error:  Class 'test\Person' not found
复制代码
0 i& L& |# G4 ?
3 Z( }; b1 k) X6 s/ l, ?" G
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
1 Z) I! b  v0 E1 @1 k0 W
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
% @- Y$ K: Z" k8 o3 J" S
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    ! U8 e1 \' O+ H/ i7 F" L
  2. namespace test;' {% T8 y/ ^" b9 l; b$ a7 w& A
  3. require './1.php';
    " \# G, N4 [# |, i, F# s  I
  4. 0 G' \% k; K: B4 t: s
  5. class Person{% Z1 D1 l8 ?) l6 z
  6.     function __construct(){. ~% T0 [8 y. q* Z6 A
  7.             echo 'I am test!';
    " `  ]3 f' z, r: _+ h
  8.         }$ S9 n" `1 R$ p4 S* Q$ R6 Y
  9. }  v: s8 X9 k; ]5 ^4 L  E) z

  10. 8 [! E- g: Q% Q% H  d7 U% a
  11. new \one\Person(); //输出 I am one!;
    ! B7 e0 }4 O; Q+ j8 N0 v3 e0 e
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

. J9 i. R7 L2 P/ V* {" n% f
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    * i' |+ h8 j  \# H( c  ?
  2. namespace test;' A. B6 q- t5 n5 H# l
  3. namespace one;9 e" q" j1 U0 t$ j
  4. class Person{
    6 J) g+ i+ Z# G- `0 U1 d
  5.     function __construct(){+ G3 D* e. Z2 ?5 @/ Z
  6.             echo 'I am one!';
    # N2 Y& L$ R. I9 e7 j5 Q
  7.         }
    + G9 {8 E6 I' _9 A
  8. }
    1 E& X+ M1 Y% r* R. |! ]4 u

  9. . S. }: Z  u: {1 \6 `
  10. class Person{  p; J; M' }5 x# a4 \0 F
  11.     function __construct(){" i  n$ S/ C. Z8 L: G' d% D
  12.             echo 'I am test!';# }# `2 }( r* J) [8 o7 c; G
  13.         }
    # O/ f8 F6 K) k/ b4 n# {5 u
  14. }
复制代码

) F9 b( \$ z8 \; T
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
2 v9 |8 }* Q# c
看来简单的把require理解为替换,在这里行不通。
, U1 X6 a- y" K9 E
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。8 S, b: c# A7 X6 I% v% f8 V
  1. //name.php
    ( O* C' m' C8 U- F" b0 P) B
  2. 1 n4 t; m% c  ?' z# `7 B
  3. namespace test\person;
    2 x9 O4 p0 M" o4 y$ r& k- M
  4. * e& ]1 l7 s' G+ @
  5. class Person{
    * T/ W  {( s5 f7 g4 J- a0 V
  6.     function __construct(){
    ( y3 ~- ?+ z8 T9 l: B
  7.             echo 'I am test!';4 V1 |+ f5 j1 u
  8.         }- E0 @$ r9 o5 O. ~" c2 O
  9. }
    ) A+ m/ |  f; h, G
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
! _% l" H/ q$ J1 u$ t4 T' Z
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
6 h6 q1 S: V  D# v0 Q& W2 R
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    ( t; Y0 R+ f9 j# J8 P  [4 d/ r- g& U
  2. 9 s; H' T5 {, R  x/ Y$ O$ M3 A
  3. namespace test;- `4 [9 D- b3 }4 L- A! I& I1 t3 U, S
  4. echo 'zhai14';* r5 W/ T* Q; C3 Y+ m( m$ i* {8 T
  5. namespace zhai;# y4 G9 Y6 O3 v% k
  6. require './1.php';
复制代码
/ u3 C4 l7 n: J" R9 ^2 M
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

: U' N$ ~4 T7 n9 b! d  suse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& f! w1 n! ]( X& Z- Y
  1. //name.php
    2 ]* ^  o/ e& {) O0 u
  2. % Q( v. K5 j9 A
  3. namespace animal\dog;
    . K7 f7 ]2 ^4 a/ S$ P
  4.   b& D8 v1 N7 v1 V; |/ G
  5. class Life{
    8 G9 C( D$ ^) u# W% I$ i. r
  6.     function __construct(){
    % j) d& T) ^. s  T; ?
  7.             echo 'dog life!';
    . o5 r' o- Y9 F
  8.         }% F" |# @3 f) e) `3 h
  9. }0 @; _6 H9 ^& }' ?% ^5 M/ M
  10. 2 ^, u1 R: Z2 m' P9 ^6 I: `/ J
  11. namespace animal\cat;
    $ a3 p! x5 p1 T9 g7 J
  12. % V# C; N/ t* ?0 T" k6 G. C
  13. class Life{
    , q% K3 ~6 l8 F4 G+ q
  14.     function __construct(){$ f( b/ F' b- g! h/ T4 O% c
  15.             echo 'cat life!';
    - r& P7 O' r% F% E3 {2 G' P( X
  16.         }
    ( @8 R9 r# ^+ r1 Y+ c
  17. }/ q8 P2 |( M0 e% J7 [0 \0 v% f/ R8 V

  18. / K1 B3 M: |! }7 u! W
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间* ~7 _' h/ g2 d7 F
  20. new \animal\dog\Life();  //A- |) P# ]4 ^' m: |) l+ L3 _2 T- H

  21. 6 u$ m, [3 X# t# n- E" P
  22. use animal\dog;  //a
    3 V+ f0 ]! m0 h( E9 H
  23. new dog\Life();  //B
    4 U) e! h+ o7 F+ k8 c3 t9 x

  24. ; d! M$ R' t$ T# i& x9 }1 t
  25. use animal\dog as d;  //b' |/ Q- Q( L9 L& {- C# J1 A
  26. new d\Life();
复制代码

, \% r- l0 k4 q, ~, x0 |" Z( Q4 q
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
9 O8 ?. S' s( V! I# j
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

7 k6 V4 t( h! l: P' Y; \
相当于
  1. use animal\dog as dog;
复制代码
: E' `! B& H, [! t5 p
2.namespace后面不建议加类名,但use后可以。
0 ~  o' r- s" W1 Q0 B. M: K7 Z
  1. //name.php
    % e* s/ s- w- G% k
  2. 8 U. N8 R5 K' B" v" h
  3. namespace animal\dog;
    2 @2 h& h# l5 `/ E4 h2 e2 H; W
  4. * V6 W# j  y6 U- f# k  q2 h
  5. class Life{3 z2 O- \( T5 f5 y
  6.     function __construct(){$ C( E; }. b/ R1 o. ~
  7.             echo 'dog life!';
    7 d' C6 d5 H1 e" y& C! A- C
  8.         }
    ' M0 \% m. L( o  i& e1 z3 d& i0 M
  9. }
    + u9 G, ?- ?& e+ Q

  10. , l# N( F. c2 {
  11. namespace animal\cat;# q! G/ g3 A' ?: {7 f5 g
  12. 8 j9 ]& c9 |9 S
  13. class Life{
    8 P3 m0 u, R9 E3 @+ [( Y
  14.     function __construct(){0 A2 n! A$ F5 Q2 M( b( D
  15.             echo 'cat life!';
    5 z0 A; c9 [& M. i$ m# ^5 x& n/ N, v: e
  16.         }. s0 k; m' o5 G* I: m% O
  17. }- {- D# d7 y% f0 r8 v

  18.   R& K  c! y! a' N
  19. use animal\dog\Life as dog;  # `0 X$ R. ?; I" e& _
  20. new dog();
复制代码
( b$ h+ g! g- v3 F
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
6 u* V0 V: I; r. I% M  h+ j
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php) J; ~: \: t, g. G

  2. - T& j; ~/ h. \% {. q5 ~9 m" w
  3. namespace animal\dog;( S. J) E2 ]; [* A

  4. ( B7 W! K+ g- k5 q
  5. class Life{
    * g- [& b1 J4 J; N# M9 r1 `! I' R
  6.     function __construct(){! c5 g( Z/ P& y: t3 l. @1 ~
  7.             echo 'dog life!';9 G! V' R. C0 l& L& m5 a3 |
  8.         }/ R9 a  W/ a: s+ x! H6 k: h
  9. }
    3 z0 ?) a; V4 L+ Q& z8 K1 [
  10. class Dog{
    8 {  Q6 y7 C/ J' u/ R
  11.     function __construct(){, p6 e6 ~% w. R
  12.             echo 'dog in dog!';
    1 f3 {* y+ C& Q* m* B6 e6 i
  13.         }
    # x! g1 l7 I  `7 ~# M' t
  14. }
    6 n9 w3 _2 O" i3 i: y. \
  15. ! W9 }, ?, d& z" Z' j
  16. namespace animal\cat;
    1 F/ b, \8 |8 b6 T% h- E% g& J3 B
  17. - Y! W0 X7 W* E4 l# b
  18. // class Dog{5 q( D2 d5 e! U. y5 i4 K
  19. //     function __construct(){
    / p8 @" ?, @; F0 T
  20. //             echo 'dog in cat!';( A: ]1 N" ~) O' d: x
  21. //         }
    9 o( _. c/ R1 v. c0 P/ l% ?. h
  22. // }8 Z/ y( p  H7 X
  23. class Life{
    0 _' `# {7 G( j; t( J; M  d
  24.     function __construct(){' Y( g  O. v' u# }$ @
  25.             echo 'cat life!';0 [  f% ?; W- L, G- V1 Z; C
  26.         }
    7 R+ E0 p/ O" C: k* D
  27. }
    / h* V2 ]" e7 @" {4 x$ w$ k

  28. 2 @( F% [% [  w- u8 ^* [, }0 B& ^4 B7 j
  29. use animal\dog;  ! N' i; z. |, y. l
  30. new dog\Dog();
复制代码

9 ?- I0 i* S+ p) c1 W+ Y
如上,使用了
  1. use animal\dog;
复制代码

6 t+ A: f, ]1 d
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
7 _# k7 q% f+ a- k; i
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

# ?+ T8 y* Y4 J+ M& g, V( J  y* ^3 Y9 F& ?+ U" p/ c( L
3 ]& g) i3 o- }( s& M9 ?

: ]8 O. s( T$ ~/ |) h- X* c" k& D2 t
# H5 Q1 H" X0 C. h" L

最新评论

GMT+8, 2024-9-8 10:35 , Processed in 0.110670 second(s), 21 queries .

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