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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
& F! |) s$ J4 v6 l+ D% ]: r
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
+ ?* X1 K& M! L
% _0 W$ R0 v  a; f& z
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

9 R& c! M- t; \  j: E* b# V
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
: k: J9 X9 M, e. j
结合使用方法来进一步理解它的使用目的吧。
4 P" v& U( [" A0 D) W4 W
+ X7 [7 |5 E8 P( q/ a1 [
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    6 M2 |# d- I0 B% l. ^! I
  2. namespace One;' @' u( n6 J3 ^! P
  3. namespace ONE;
复制代码
1 a0 o" i5 A& e1 q0 ~) `4 ]6 ^
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
8 L% A* q, o- A% K9 U' u
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
      [+ O+ w- m2 R* i/ g
  2. class Person{3 @, I  ^; J0 E5 U
  3.     function __construct(){  j, h! @! b) f7 x4 B  z2 B
  4.             echo 'I am one!';/ C7 ^% Y9 {& G/ q) [0 v9 z. a: V
  5.         }
    ! P/ l% V9 O  A0 f3 g4 Y
  6. }
复制代码
  1. //name.php/ Y: w* B$ H  I  b# o' g# J) g
  2. require_once './1.php';  h/ S% }2 f( g2 Y/ `4 P" b$ e
  3. $ @, A( Q/ m" H  S% `. q
  4. new Person();     //输出 I am one!;9 @- I3 D- i9 y* L5 L5 y, Y# g; ^
  5. new \Person(); //输出 I am one!;
复制代码

, _2 c+ \% @+ s  k& ]4 G/ S3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php( g+ t/ ~5 K+ t& D' g# i  W
  2. require_once './1.php';8 d; h* e4 P, l" b
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
1 L9 C$ Q! g. {+ R. L; F) ~$ l
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   , l2 l' F6 e5 L/ D
  2. namespace one;6 N7 f9 A( K: N3 H
  3. class Person{
    / Z  o# _+ ^: t' G4 x
  4.     function __construct(){% ^+ k: P. Z8 D3 |9 q) R
  5.             echo 'I am one!';
    ) c; m4 r- t) I( O
  6.         }+ i, k/ K; U9 |* `/ j9 t+ ]; o
  7. }
复制代码
  1. //name.php
    6 r0 h4 `% g+ W) f) r$ f
  2. require_once './1.php';
    6 l5 G) n1 z, x& b0 f1 J1 g+ d
  3. new \one\Person(); //输出 I am one!;# d0 J( w/ d* T
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

* N: r$ T3 }. i. d3 ?5 r# [
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

" r( I$ |( P8 C( z+ R2 a$ D5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
" Y( O) R/ F& g/ i- ]
  1. //1.php   
    7 @6 }9 X+ l3 @0 n
  2. namespace one;8 E$ U4 T' H* }
  3. class Person{& M6 C; u: e* U. e4 {) d7 t
  4.     function __construct(){( @% J) L5 i! |4 I! O
  5.             echo 'I am one!';
    # b, G1 ^% a; N) I" X6 Q4 R! Q
  6.         }
    2 E% f2 l) n/ m+ a/ e
  7. }
复制代码
  1. //name.php
    , a7 I7 B% v' P
  2. namespace test;
      ^0 B; p2 ^0 }2 q, Q" O
  3. require './1.php';
    3 b# L" u# J8 _. J
  4. new \one\Person(); //输出 I am one!;, k( t+ l& i# I/ s+ o+ a
  5. new Person();      //这里结果会是什么呢,猜猜看
    : w! y4 B- e: z$ @
  6. 最后一行结果报错:
      c( F4 F. r  c+ ?# ]( v; |: L( ^
  7. Fatal error:  Class 'test\Person' not found
复制代码

7 z& D: Q, S  c# W* i# p! z& k
( k  x$ L' U& M- M
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

/ l& D  a. j) ]6 Y1 |9 I
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

: r; }& c4 b$ U0 v  f: u* u
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    2 k: A! E% v4 q+ F  m- b
  2. namespace test;
    2 L0 M& @/ h' k- P$ M
  3. require './1.php';
    / J/ O( O0 J! ~  e
  4. 0 h5 ?# T* Z/ h9 ~  x9 b! [9 e
  5. class Person{
    7 ^# M2 b3 E6 S) w  G
  6.     function __construct(){' ]0 P" x( e( v) |
  7.             echo 'I am test!';
    8 c- \  y5 W  m2 {/ B
  8.         }
      v( g) X: T) v; w
  9. }4 c/ n, |2 Q' U1 I% H# Z
  10. - p. T4 t- ~* }: ~/ ^4 v
  11. new \one\Person(); //输出 I am one!;0 ?% u+ N2 H  D5 P/ N
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

/ v3 I. R: l: J  A2 a* W
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    5 [8 e9 |% l' @: [/ I, x% A
  2. namespace test;
    6 X7 S. M0 b. z; V1 G0 l4 l1 p: Q
  3. namespace one;7 x; L$ ]- o( \% R) d! {
  4. class Person{
    " J' P) r1 g9 u' U1 X/ _
  5.     function __construct(){& E- t' s2 H. s" z! L% W$ Z
  6.             echo 'I am one!';
    9 z1 b$ r- l+ ]# i6 u# @
  7.         }
    $ n. G% u0 D/ T% i, v1 f, t# b
  8. }
    ' A. n, v5 O$ N8 E2 f9 E1 X

  9. % w4 E: K5 P: D* A' n# H! c
  10. class Person{6 y2 l. C& {* `
  11.     function __construct(){
      K8 q- g: G4 \% X  f
  12.             echo 'I am test!';7 l# e7 [5 R% n. ?: b
  13.         }
    : `& l4 R# h4 I: E4 t( \; ?
  14. }
复制代码
' v! O0 A6 r( q' V$ N' T
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
+ [% E. G. r6 v6 H- y9 o
看来简单的把require理解为替换,在这里行不通。

& T) f3 Z8 F% u' @9 i6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
- W% u* F* x8 Y5 H
  1. //name.php
    ) {3 T: o3 I6 D

  2. # N5 j8 Y( A7 N* S
  3. namespace test\person;. G; P$ ]5 `% P+ s: O

  4. ! P7 f, y; N( Y. I- F8 y
  5. class Person{
    1 b; @& v" z/ q' ?; ^: B% K& f
  6.     function __construct(){
    4 X6 j9 i1 A$ ?" G1 L" U
  7.             echo 'I am test!';4 \$ R8 l$ `* Y/ `& P) V/ a* o
  8.         }5 p4 E+ c: N- {. o: y7 S$ ?) _6 f
  9. }
    9 Z* B4 f( q: c- C( s- }
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
6 d  T+ d1 ~0 U
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
9 P' A* w. o+ T" q- H- u  W# a! k; [% h
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    ( i. V, n7 m3 n$ T
  2. 1 H0 e1 ^/ X) I1 a4 ^, J+ t
  3. namespace test;! _) q- Y" `& k& L! |; y
  4. echo 'zhai14';( Q, {4 D: [5 i2 @! @
  5. namespace zhai;. t: B2 R9 x- s- s$ D
  6. require './1.php';
复制代码

9 ?7 ?3 Y' L: U* Q1 W* R
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
% b/ X) p+ q& }/ Q4 n
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
6 C3 n$ n7 \4 q1 Y$ Q4 O
  1. //name.php8 v3 X* e, z1 w' n) n* i
  2. ) p* n  b; D1 |/ [% w
  3. namespace animal\dog;+ A9 N. G9 R5 W5 M: i. R; y5 |

  4. 8 h* _& {1 M9 R0 U: Z3 q& k
  5. class Life{7 q& B5 A7 R6 ~9 `" a
  6.     function __construct(){8 W% a/ i4 h! w0 u) r! Z' K; c
  7.             echo 'dog life!';& m0 }, x* \& i- @- [- m0 c" O
  8.         }
    5 Y; Y* U8 ]1 `- Q% d
  9. }2 T4 g5 C& {5 K

  10. 4 C! O( x: _$ i3 _% g; R. c: L3 T8 m8 b
  11. namespace animal\cat;* K" U4 [6 M$ ^% |6 ?, ~0 `
  12. 9 R9 i8 M: J- T* H! q
  13. class Life{9 z' o# f. \9 ~2 [( l  D& I' f$ q
  14.     function __construct(){
    ! }- x2 M+ O$ @  v
  15.             echo 'cat life!';8 q: a' v3 {4 U3 f! B
  16.         }
    * P% e2 c9 `. a( M
  17. }
    & f6 h% k& N, o6 u

  18. + x/ h5 ~) ?) }& O+ W  d4 L
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间0 N! V+ e! s: l) o
  20. new \animal\dog\Life();  //A" w% Z, B+ ~1 P( n% G

  21.   ^+ _- w; [) U
  22. use animal\dog;  //a5 B/ q0 x7 X3 s+ }
  23. new dog\Life();  //B
    . f" R- S4 e% y, \. y3 ^9 s* N
  24. ) I1 r/ g: a" S: d
  25. use animal\dog as d;  //b  n  }& B1 J, F3 [
  26. new d\Life();
复制代码

+ r8 ^( ^7 o* W1 H# Z% X
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
% J/ Q$ z" b% _! {
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
6 c9 G' G. g/ G5 b2 i# c
相当于
  1. use animal\dog as dog;
复制代码
2 u, X0 m- ~* O7 [( h
2.namespace后面不建议加类名,但use后可以。
% j) B: H8 u9 G0 G$ I5 {
  1. //name.php; L$ O  F  `( t! U4 r! ~% d' V$ D
  2. 6 F3 o% }! i% X* O
  3. namespace animal\dog;
    - [) |. m; q9 x. R! A- `5 B
  4. 8 A3 }, c+ ^7 n% u. C
  5. class Life{7 o- a7 u6 a3 ?: T0 I* p
  6.     function __construct(){
    . R0 N& H4 P% Z
  7.             echo 'dog life!';
    ; u  X$ ~* N- X; W
  8.         }
    . [6 T8 p0 }6 M0 k
  9. }
    ( r  I" J$ i: T- Y  Y' d& U) h
  10. # I" d/ }0 C2 S6 ^9 k" m- l5 s) \
  11. namespace animal\cat;
    1 M$ X, q2 U  R" |7 W
  12. 6 A7 U# Y5 p$ A0 ]1 _
  13. class Life{
    " `6 A& o3 F# H7 _
  14.     function __construct(){3 _8 v% |$ y' b
  15.             echo 'cat life!';
    . X/ _! n4 M! Y: g; X# @/ T! r$ Z) v
  16.         }
    $ ~8 b: B: p" V0 b
  17. }) o+ k3 g& s& s+ K' F1 H

  18. ( C  A, {# ]7 s# ^* k9 @7 g& D
  19. use animal\dog\Life as dog;  
    4 P. c, {* f# s1 [- T) ?* k
  20. new dog();
复制代码
5 ^0 N: z) Z2 n; \$ c3 c, A
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

2 N. E, C) D  B8 N1 R* {
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    + M& h8 B3 a2 C1 ?
  2. # O! E" T: A3 _" d
  3. namespace animal\dog;6 O6 x/ [' B  Y( G/ x: U4 j/ B
  4. ' h$ a$ X2 T: ], ?: j6 q
  5. class Life{/ d0 F' U6 b/ V5 r, ?
  6.     function __construct(){  e! u+ H5 N% F# }
  7.             echo 'dog life!';
    % i: N) l" }# `% ~  d3 U
  8.         }
    % P4 i2 ~* _! T0 s+ h  S" Z+ P% h
  9. }; e- U( y' e3 j% }7 F) ^
  10. class Dog{' O- ]$ b3 S& }5 }) p
  11.     function __construct(){
    . R- I1 u$ }1 `: R2 J- t# ]
  12.             echo 'dog in dog!';
    3 m9 Q# c5 @) ]
  13.         }
    + Z# x' P1 T. g9 m8 X3 s
  14. }
    2 D1 D+ q6 S; I  W( ]' U

  15. + j; q9 ]9 J- g
  16. namespace animal\cat;  x6 }5 \' k8 `9 c7 G1 G
  17. % p# a: k6 h9 }! Z4 P# y5 E6 c' Y: ~9 |
  18. // class Dog{" ^2 b% i% m; d9 T# z! T
  19. //     function __construct(){
    7 |1 W) Q9 _( T) b/ R" c
  20. //             echo 'dog in cat!';
      k. r9 ]% B7 }( L8 p" T! \
  21. //         }" j  N+ d  r+ }+ L3 A) m6 U7 k
  22. // }
    " {! j- \  ?% c) R( M7 F" B3 D: L
  23. class Life{' ?  m# Q) @. j) [' c
  24.     function __construct(){
    6 k. X. B( X  Q1 X
  25.             echo 'cat life!';9 N6 _$ I5 k/ z2 x& s
  26.         }
    2 m3 }. v" ?# G1 ]) l  s
  27. }
    3 {! \1 E$ \; \( h

  28. ) S1 z, G8 z7 L# t, x+ x
  29. use animal\dog;  
    " Z+ }( h0 C! u  T" ~) V4 K
  30. new dog\Dog();
复制代码

. Q4 c7 j( t) E# [; S
如上,使用了
  1. use animal\dog;
复制代码

& E; k- N3 p/ t9 i4 d$ v" _( U2 X
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
8 k  J/ k$ z: K: J/ L) L  b. R
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

7 X. G8 e+ z5 l' y$ B2 x4 a& g
3 M# _$ r( K% j; c
8 h2 L+ X0 E+ h4 F
* b& R( w. A9 F8 V( J' B
: U) {" t: v3 \. \

最新评论

GMT+8, 2024-7-27 11:10 , Processed in 0.110764 second(s), 19 queries .

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