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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

7 q$ N! m0 [8 R- B+ P7 N
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

: Z: n. r; B6 x& x  G
; e6 r6 |& `& e  J使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
, d. Z# @' u  M( h4 B
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

# C5 d6 b+ i" f4 Z5 j/ `结合使用方法来进一步理解它的使用目的吧。
/ ~3 d( x: u& F4 b; g/ P6 t* Q* S

8 j; t" A$ |& p* K# o! _namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;" H8 c& P  G! I& w! q
  2. namespace One;
    0 I( I% d, U# w' j" J+ G2 F1 m
  3. namespace ONE;
复制代码
1 l, Q9 n+ d/ v( F5 b' _. K
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
! B3 U% c+ J  W% f8 q2 ?6 I
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   . f* V7 O! k  Z) l2 ?3 j3 ~
  2. class Person{3 b" f. `+ N& X3 N. K! ]& O
  3.     function __construct(){$ G7 |; g# A  C8 x
  4.             echo 'I am one!';5 T$ c' r3 n6 z* j5 i6 \
  5.         }6 K, s' f8 ~& E  x, ]- H
  6. }
复制代码
  1. //name.php
    6 x. A" n- d# C, G
  2. require_once './1.php';" Z) f3 T0 s9 K+ y+ P

  3. 6 I* g. z1 d+ K0 A1 h
  4. new Person();     //输出 I am one!;
    $ E2 S, X2 I, P% p
  5. new \Person(); //输出 I am one!;
复制代码
9 S) p" g8 K4 B) b) q1 `
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php2 V. A% q, y+ Y$ t6 f+ q
  2. require_once './1.php';
    % K) C; w( e& u* f: w& I8 G- }
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

2 |8 f* A: M- z" H' s# H- P4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    9 W/ n7 d( i# {7 W) o; P' D- v2 p5 A
  2. namespace one;
    & D4 e% ]! i, \
  3. class Person{2 m% u; r5 E( M0 x1 J  J0 `% @4 ^
  4.     function __construct(){
    5 P! h* Q8 r" j! Q
  5.             echo 'I am one!';
    7 F8 G: |! E: O( U  F% E4 `; ^
  6.         }4 v9 D; ~' I; a7 }9 B; f7 }) H0 s
  7. }
复制代码
  1. //name.php1 ?3 N# f! }* _
  2. require_once './1.php';
    9 g9 U8 U+ k# ~0 T/ T8 s
  3. new \one\Person(); //输出 I am one!;+ `' n+ \! K' d: w* W, C! I) m
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
5 ?7 w! K" e1 W" S
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

6 T! F5 k0 ~% Y+ o( M' z5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
) z% }' W$ t, p0 E6 ]
  1. //1.php   : E8 k/ R# z1 A1 S/ n: k$ I/ N  l6 U
  2. namespace one;
    * k4 p$ U1 d' z$ S  W2 P
  3. class Person{
    % D+ d* u) q0 ^$ S, s
  4.     function __construct(){% f7 F  S3 [2 V6 Q' A) @! g
  5.             echo 'I am one!';% v( L0 [4 ^2 s) u2 b4 w  u
  6.         }* ]) k4 V  ?& V1 A9 J* M( L
  7. }
复制代码
  1. //name.php1 F7 [, O1 t" d; q& B, g
  2. namespace test;
    % {- i5 v7 K3 W- P7 i6 u
  3. require './1.php'; " J; s" L# b1 w0 C/ ]
  4. new \one\Person(); //输出 I am one!;
    . X8 N8 u- z# |& V2 X6 T0 `# U
  5. new Person();      //这里结果会是什么呢,猜猜看5 ]9 H8 l: Y3 m, P
  6. 最后一行结果报错:
    0 t/ x# h1 [! q; R$ O
  7. Fatal error:  Class 'test\Person' not found
复制代码

+ ?* F0 }: c) f6 D# s, c8 m5 V. P9 e
1 i% I+ p+ A8 J, Y$ ~; p" X
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

3 Q9 s( H& K( {! V
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
. p6 D: @4 |! z) w  f# @
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    4 m  v3 z  E. I* f
  2. namespace test;
    : q9 ^$ ^4 V  q$ s, E
  3. require './1.php';
    ; f( _6 |, I1 ^# \, c
  4. ) W$ j3 z* `4 ~. Y- x, B. c
  5. class Person{4 H1 z& s; n# l* f6 `8 p! e, Q
  6.     function __construct(){
    ; o  O  q1 C4 a- S8 H, h
  7.             echo 'I am test!';5 j8 _, A  N+ G" L( n: ]6 |. d  Y
  8.         }4 v4 Z# p7 S) K7 V
  9. }0 y2 r6 G7 R. i- K. h
  10. # l' E& K9 H$ V
  11. new \one\Person(); //输出 I am one!;$ L' m9 X; M9 i3 f7 S
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

* K0 H! A) D( \8 ]4 s1 x* @4 K
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    $ Z( M3 I7 H9 X7 @; U6 F
  2. namespace test;
    8 E) a! z( A5 G" i8 w& s
  3. namespace one;
    * @1 G1 }& C$ m6 U9 @/ z
  4. class Person{
    , U3 ~: Q4 h- T0 V7 c% V: Y; B
  5.     function __construct(){" W% w; n4 k( K
  6.             echo 'I am one!';5 T- t: z) ]# ~$ V$ Q% x3 W; v: C" K
  7.         }$ J5 N# L# @  ?7 c  }) v8 l, U8 D
  8. }
      s) N; N" `5 l! o
  9. * e/ Y3 m, l" G
  10. class Person{
    7 h; s, g, E) M  r3 A3 A# K
  11.     function __construct(){
    : x* i( C; G& h" n
  12.             echo 'I am test!';( Q5 s) O2 f0 P' i0 s
  13.         }: i. Q8 s8 s5 j# i% T# r
  14. }
复制代码

. m7 @7 K/ g1 R1 {# \' v  _
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

. R, D$ M0 {1 F
看来简单的把require理解为替换,在这里行不通。

5 X9 }# H) S  `) j; d. M6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。4 F) m! L6 ^6 e# O, l" d5 d
  1. //name.php9 [3 ]9 Z0 d3 d  o/ `
  2. + U) g3 l4 i9 `4 p3 D5 t% C/ r
  3. namespace test\person;; n: {4 p1 m$ t8 U& @. W

  4. ! c) {% Z4 R/ f* _& e
  5. class Person{% p" b* V& V. N& q6 c
  6.     function __construct(){
    9 E$ u' E! }: \  w
  7.             echo 'I am test!';# @3 |9 h7 Z9 T& Y. s8 T; m3 K
  8.         }
    ) _4 q  ]  }6 [3 H) q
  9. }
    6 w. R6 c0 W2 g7 M* n
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
+ {5 p4 n2 ?: F' K; j
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

7 y1 W- q* E- v! K7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php3 k& C# t: k' w* ]4 s3 |* \
  2. # f& f, q: X( r
  3. namespace test;& v; p' j3 k" r) m5 d# {/ Z
  4. echo 'zhai14';
    ( d3 O$ E$ N7 Q  [
  5. namespace zhai;
    2 ?- k6 ~2 A# }8 s3 [2 k
  6. require './1.php';
复制代码
; ]% v: O% p5 K6 M" F2 i
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

# E* M) Z- e4 P  j, m4 U7 K4 H3 Guse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。; h* Y; r$ I3 R, H- U& k
  1. //name.php
    ) |1 A- k$ F. }' n7 N  ?
  2. ' v# K/ D6 n, F" A# N4 D
  3. namespace animal\dog;& p: M1 D: A" U9 g8 D, N* h" }
  4. * N% p0 s' {7 _4 X2 x
  5. class Life{
    6 r6 {3 m) z1 U% M$ _! A$ j
  6.     function __construct(){
    ( H* b1 a1 T" Y/ F0 o
  7.             echo 'dog life!';
    7 P& H- u9 `7 F8 r8 z
  8.         }
    : Y7 U  ~  x9 E: `
  9. }) F- m* k; ~9 d

  10. ' T. v/ Y  @) \, I8 p
  11. namespace animal\cat;
    0 r! M- i2 [: `9 M4 v" d
  12. % G5 W" L: W( ^
  13. class Life{
    $ d* n" g6 \3 B! T- v- i
  14.     function __construct(){
    1 w! @* {5 A8 [, n/ ~+ D1 I3 d3 Z
  15.             echo 'cat life!';
    2 `6 d# N* ~7 [. e* S
  16.         }
    # @8 G/ G! x) d# W8 y
  17. }
    . X; ~# `1 }4 o

  18. " M: n: e$ q7 c1 o1 ]+ H2 t
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间! e; O+ J* Z* {  {3 o/ e
  20. new \animal\dog\Life();  //A
    0 ~9 A' L& [, I/ O" P

  21. # o( Q8 r4 e4 |1 w
  22. use animal\dog;  //a! H- a5 y( E' o( K+ ~  B( q
  23. new dog\Life();  //B: `4 ~5 d$ j! q' e  o

  24. 8 L+ ~6 r7 S) A5 A* l  T  t
  25. use animal\dog as d;  //b
    " d4 x! L9 v) A
  26. new d\Life();
复制代码

0 N% N! v, n5 x
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

% z! P3 W$ ~" i/ W6 J! Q. X
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
, c1 @0 @; q( a7 N. x. d2 _' p0 k
相当于
  1. use animal\dog as dog;
复制代码

, G! W: S. p2 \+ H( ^' I7 S2.namespace后面不建议加类名,但use后可以。
" Z: D/ S  Z3 ~" n4 ]8 N% p
  1. //name.php
    ! r+ l" z0 ~! I0 z5 R
  2. , U4 e" ^3 ?+ N1 U- c6 X' h
  3. namespace animal\dog;5 n, \6 h$ f# m) k; s7 P
  4. 7 B( @% E2 p- Z/ _. B6 x4 G5 h% v
  5. class Life{) B2 q. \- ^$ R, p
  6.     function __construct(){: e& d6 G- i5 Z4 Z" x" {/ K
  7.             echo 'dog life!';: e5 V" |: u8 a# v' {$ m
  8.         }
    7 Y/ U9 F( V% S/ p1 @8 \9 P1 J
  9. }+ a: K5 }* @+ |4 {# s) T- y$ C8 q

  10. 5 I$ e6 ?* U  h7 Z0 j6 L5 A" ^
  11. namespace animal\cat;9 q$ J8 x2 Z" _3 p& S3 D- o" t
  12. # h6 U$ c. Q& ~. Q. @/ R/ W
  13. class Life{/ r# x& N) C; f& q
  14.     function __construct(){
    % N! {# @& R9 h' g$ q" c# V* W
  15.             echo 'cat life!';
    " Z1 k% ]5 R; i) p- O7 {
  16.         }
    ! W1 i9 o9 y* O" C+ D6 Q
  17. }& }8 X; O0 M2 P  F

  18. 9 z0 G6 P; q/ z
  19. use animal\dog\Life as dog;  8 F$ }! r) u0 a7 M$ f: U* R+ f, ]
  20. new dog();
复制代码

; C, [; e$ P* R/ ~+ q
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

6 t+ H( Z/ G" B# n7 Z7 z! m
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php% F  y, W/ y5 A+ n. J+ E  H- I

  2. # h( d3 A# w) _8 P: s, ~
  3. namespace animal\dog;2 C# L$ X1 G& s4 K, A/ U& J/ E

  4. 7 K$ I4 l8 K9 o
  5. class Life{
    ! E- j# Z9 |: @) @
  6.     function __construct(){
    + a. Y" J4 s' n* Q
  7.             echo 'dog life!';
    4 I. z/ |/ p& Y4 e' i0 _
  8.         }
    % x* @, z; K8 `' j8 Q
  9. }
    7 {, V1 w1 Q* f: q# l
  10. class Dog{
    ) z3 R6 O5 b# x
  11.     function __construct(){; q, j  q5 ?8 c
  12.             echo 'dog in dog!';
    4 u6 ^( |2 A2 G
  13.         }
    " e( h8 N8 H1 Q3 U8 c
  14. }7 o! T9 ?) ~* Y: k

  15. , p. ]& r* l- S4 J& q
  16. namespace animal\cat;
    6 W$ A8 \4 C& P  A/ M
  17. 6 [8 q. _3 g; t( ?  R8 \
  18. // class Dog{' j% |' o) q# f7 o5 }1 }0 t
  19. //     function __construct(){
    & n8 U7 H2 Z7 ^# Y  L, t
  20. //             echo 'dog in cat!';: F, l. K* j. r+ _& T& W* x
  21. //         }
    ( ?$ V: _1 _4 x
  22. // }% X( ]0 ]/ G; y1 N  l# y0 I2 `
  23. class Life{( _5 s3 }- m; D6 u! e
  24.     function __construct(){: w1 {+ d5 }0 X) q+ h
  25.             echo 'cat life!';! {( O: [: j4 G  Q8 z
  26.         }6 i4 b$ ~+ r8 |0 F  ~
  27. }
    / ~  x4 o, L7 f6 q# b6 \; s% w  j
  28. ; d' u" ?4 }  n% Y; K
  29. use animal\dog;  
    ' X& q! W8 \* v% g% P2 h+ i
  30. new dog\Dog();
复制代码
1 l; b/ r) `0 ^+ b
如上,使用了
  1. use animal\dog;
复制代码

+ H" n6 p  Q  N/ `
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
: N6 X" ^1 {( ~. |" y
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
- }9 }' q3 t- @( ]

  E. L0 }6 C7 C2 K  h0 g* a8 \* A. `& m

& O) K* n; K$ l% Z; g9 |8 e8 Z' G5 [2 `! P. {
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 03:10 , Processed in 0.054706 second(s), 23 queries .

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