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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

$ h! c$ F6 a0 k, o
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
3 z: o1 S9 C! M9 y
+ k) e6 @7 y# n) `  Z
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
5 d# i& c' k$ n% f
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
  I# C9 u. J6 m( e: l6 a- E# t
结合使用方法来进一步理解它的使用目的吧。

2 Y& o% ?0 W7 h9 \( S& V/ I
2 \% s  k. c1 X4 \/ N" f% @namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;6 A: G0 M) J8 |7 Q
  2. namespace One;
    & H# }, y* m$ {2 j/ N! _
  3. namespace ONE;
复制代码
5 K! }6 c# \; a
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
) e2 m, [5 C7 ?
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    9 {7 b- |& S( g2 ~% D
  2. class Person{$ R! C  x1 B) y4 K* k2 p# J
  3.     function __construct(){
    " C$ Y) K) O9 }5 b  t2 Y
  4.             echo 'I am one!';. \' E% A- r; [# v; V. |' Q
  5.         }
    % [; B9 g" v* ~. @
  6. }
复制代码
  1. //name.php
    " N# R5 M" J4 z) z
  2. require_once './1.php';" u( p/ u9 |8 }6 S& E4 a+ y' z9 t

  3. . [' s' G( ?7 R2 g7 b4 D1 L
  4. new Person();     //输出 I am one!;
    9 h- Y1 V; u1 z$ l! A0 C
  5. new \Person(); //输出 I am one!;
复制代码
) j  g# x5 Y% O/ B0 l
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    1 J* r( _0 {1 c3 x, d* M
  2. require_once './1.php';
    ( p2 M: B. q$ v* [8 Q) |6 C% n
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

5 w! {& U9 j* L# ~6 P* r2 `7 ~4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   & ]. H9 {# _" E, O$ [, h
  2. namespace one;6 f& s1 l0 ]" \* D" C1 w; z9 f7 ^
  3. class Person{& i0 m2 q  V, A, g5 y
  4.     function __construct(){
    ' f7 D( i' |, W0 b1 L8 j
  5.             echo 'I am one!';
    5 q* x9 P2 J4 d( u/ O" d
  6.         }
    & O. z3 m' d9 L2 }& }3 ^
  7. }
复制代码
  1. //name.php
    1 V1 H' n+ G7 g6 V1 J
  2. require_once './1.php';1 s0 k# `# o" u
  3. new \one\Person(); //输出 I am one!;5 |3 }. o1 O' y
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

3 g7 I: M& I6 K% L- o8 N
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
/ m& m2 ~6 U* Y
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
1 D) y% f- W  r
  1. //1.php   
    5 J" M% W: i" e) L2 B  \* i# T& k
  2. namespace one;
    . g, u$ E7 _4 f- ]5 c" p: ?
  3. class Person{9 z( w- f* l! [) w. a, _
  4.     function __construct(){! V  L" z$ _' M1 G8 K7 `
  5.             echo 'I am one!';
    ! i( Q4 |; @+ }+ [; o( |/ L
  6.         }6 n& b) [) c0 o6 ?7 |
  7. }
复制代码
  1. //name.php
    9 v' p4 B  w9 m# c" N
  2. namespace test;
    $ Z0 H! R" C8 l4 e% h/ e5 P
  3. require './1.php';
    7 A- Z8 `' W8 S: G
  4. new \one\Person(); //输出 I am one!;. _4 Z. e5 z3 @- h4 d
  5. new Person();      //这里结果会是什么呢,猜猜看
    " {8 ^8 J9 i/ P- C" H
  6. 最后一行结果报错:2 x+ Y% I' ^1 ~+ K. \- J2 q
  7. Fatal error:  Class 'test\Person' not found
复制代码
! {$ o6 P  f5 ?1 v) a% e8 E

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

* D) n( k% G  s" `: J( J# p* C) f
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
& _9 D) \* F2 f# {2 r% ?
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    2 p& a4 i; Q3 J( w0 W& U6 o
  2. namespace test;8 s6 D) ?2 S5 g0 Q4 H* t6 u2 `
  3. require './1.php'; 1 j$ G9 i* A3 r! `; X! B! N  [- [
  4. 2 s  N/ E, n) j
  5. class Person{2 p) k: `* m, M! C! A
  6.     function __construct(){  h4 g5 [7 u' v: j
  7.             echo 'I am test!';
    : V  Q2 K* f$ j$ V1 p
  8.         }; p+ P* m1 K; ?' n& a9 @, ?7 H
  9. }
    2 ?. ~1 v6 N8 Z0 S; S& H

  10. & }! x" R) x1 d5 \4 Q8 E, X5 d
  11. new \one\Person(); //输出 I am one!;
    2 K( K4 o- V5 ]+ `# H0 b8 J
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
/ l7 M  K6 V& A% n; ^6 V
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php) _# P' F& j; \( Z# F* [
  2. namespace test;! _) r- b- \1 x5 J3 G  v" P' y
  3. namespace one;
    " R! b  U9 t! `, c' G
  4. class Person{
      O# F' l% S; i9 A( P% N
  5.     function __construct(){* \4 _5 ^" P7 Z# ]$ v
  6.             echo 'I am one!';
    # v& z' q) z" L1 C
  7.         }
    & i5 ~' e- d, n* L/ n
  8. }9 D6 N. E; [) W" [( V# u
  9. ( n% F* F1 R( u6 Y
  10. class Person{1 I' U* A& Z  \8 E1 E7 {
  11.     function __construct(){
    * B) y& q) b: J7 r' L) Z8 D: F
  12.             echo 'I am test!';
    ) \% K* b0 l, Q2 p6 w/ m$ O; I$ K3 `
  13.         }; t2 c% R+ w0 R8 \
  14. }
复制代码

/ m6 e/ r) m- @  O  j5 ~2 k
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

# |3 H9 i. o( u, D0 b( B
看来简单的把require理解为替换,在这里行不通。

" N4 @% S( d2 C0 u, L: d6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。. S; ~1 j* h0 H  e3 W) u3 |1 e
  1. //name.php( Z+ G2 U6 E3 h3 H4 D$ r

  2. 6 m4 N( C1 M7 R: o+ D
  3. namespace test\person;, R2 N. k* G- h- A
  4. # @5 `- p$ t% \# n" P7 |' s0 j
  5. class Person{; w. ]+ I5 R4 I! A- J, Z6 X
  6.     function __construct(){) [( @* i/ Q' ?: ~0 r7 p3 A8 ]. _
  7.             echo 'I am test!';0 s, ?6 a$ f9 d  e
  8.         }
    " y, {  |# I5 b5 e6 \
  9. }; Q6 p* v1 C6 ?4 t7 ^3 [4 _
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

1 `$ Z+ j3 c4 T0 }# P
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

! z; v$ @& H# {0 c* E7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    " q# d3 G) U3 A5 `& L; y
  2. 4 x# {1 x4 q; |; @' B0 C2 V
  3. namespace test;  q5 X! W7 J" Q* k5 g8 J
  4. echo 'zhai14';9 ]& ?6 ^0 K+ I: j) W7 O6 C, M
  5. namespace zhai;
    , i( K6 o! i. E* k9 ~
  6. require './1.php';
复制代码
/ p' n/ h% {! B' U/ {, v4 ?# T2 L( r
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
/ a, V! [; R( ^7 b" @5 p" u
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。7 I  D2 H. ]* g& X! \: U. N0 v" w
  1. //name.php' H9 G# {3 p9 `& {& Y) j0 R& {: X8 ?

  2. 5 N2 ^8 r2 L9 E! A. ]
  3. namespace animal\dog;9 Z# o1 N4 S1 }% ^; k3 \

  4. 9 h; e1 Z* i& |  [' @2 R; v$ X. j
  5. class Life{: g3 Q# p0 c( E. J/ _2 A3 h
  6.     function __construct(){
    . }' d4 |, F% d3 M+ L2 X, g7 v& a7 e
  7.             echo 'dog life!';
    . [" S" ]9 A% m" a. w* \% ~" Z
  8.         }: }4 S$ m7 M9 B0 Y1 v' [
  9. }0 [3 v# u1 h6 w! z( |

  10. % d( S# a6 i; z& s9 s
  11. namespace animal\cat;
    , @. D/ g& C, w7 [5 m

  12. 2 |$ [4 E- M0 Y; L# c1 k3 l1 v
  13. class Life{6 a. q' {3 j# ~0 ]7 z* M
  14.     function __construct(){
    3 c$ k% z( k$ w& m) R* }. }
  15.             echo 'cat life!';
    8 v- S* W- r, p6 u
  16.         }
    0 y" m7 z+ t1 O# i, s
  17. }) R# i( c) D$ X1 l; L

  18. 1 y, P7 `: i, ~7 a9 ?
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间8 q/ M* K) N1 x- Q% L+ d# n
  20. new \animal\dog\Life();  //A$ y7 u) F4 K9 Y- q. w! }6 ?3 v, Q

  21. $ a5 S3 P9 ]5 q5 _5 W) N; G
  22. use animal\dog;  //a
    - n' P4 K& ~9 S0 `
  23. new dog\Life();  //B+ G6 `0 m5 p5 S3 M

  24. * j3 q* m3 M' o( d
  25. use animal\dog as d;  //b+ Y  P$ u: g2 y! d8 y4 h1 j
  26. new d\Life();
复制代码
, q' B$ I! q5 _- M7 p
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

. [( ^/ _3 R/ {- b! V
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
7 o6 Q9 G" E3 H$ n2 L
相当于
  1. use animal\dog as dog;
复制代码

5 n+ T* ^5 C2 i* w1 u2.namespace后面不建议加类名,但use后可以。6 n# x+ B' [$ q+ H
  1. //name.php, R2 _) J' b1 `) `
  2. 6 F5 J, B. A! h. S
  3. namespace animal\dog;
    . P- r8 m: @8 T3 p: f

  4. 4 @# ]! z, m5 j% u# V; D/ j" H, Q
  5. class Life{$ h" u( J1 g* t: V' v0 O& Y1 D2 x
  6.     function __construct(){
    ; l9 R3 {; J% A! S. b1 r
  7.             echo 'dog life!';& m/ l7 r8 I( ~' p3 a
  8.         }$ O4 U: l& T7 _
  9. }
    $ O& @3 e( U; [3 t# L* Q
  10. & {1 f5 O, _' s
  11. namespace animal\cat;
      T; H7 D# A: ?' T

  12. - N5 v4 G( ]% E
  13. class Life{
    / J, w7 n$ M' b! w
  14.     function __construct(){6 R- E* Q5 ~( `* ]: A0 \
  15.             echo 'cat life!';  x% T( w' S  i# E7 X2 W
  16.         }: I  M8 m; D0 [' N- S' \
  17. }
    $ e3 n( b' B; @- o8 [* ~( z
  18. 6 G4 H9 f. ?; @
  19. use animal\dog\Life as dog;  ! v7 k- {/ c( g& e% d
  20. new dog();
复制代码

6 Z+ j3 y$ a8 S- H
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

7 @$ ?4 J, `) J) S* c
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php5 G' b: C( N' V! G6 b
  2. 5 U* H8 Z- T  \6 |
  3. namespace animal\dog;
    2 D4 v6 m  b' u3 G$ O

  4. , H, O0 A1 B  s: @# l2 B+ p+ [
  5. class Life{4 l1 q* g$ q4 x8 ~) T# F2 o4 @# R
  6.     function __construct(){
    / w( E- \3 l) n" J& h1 K
  7.             echo 'dog life!';
    # q1 o0 l2 \$ o3 H
  8.         }, ]3 N& {; F# p+ @
  9. }
    7 q/ v2 @% C) a% _
  10. class Dog{/ D( N9 u  O( O- j- `; g
  11.     function __construct(){
    ) x5 d# F# J5 b; G8 u% v
  12.             echo 'dog in dog!';3 G9 l. ^4 ^2 ]3 x# S
  13.         }
    / B! p& o% |; z) X1 U7 m
  14. }0 `% R/ n  R4 T; I

  15. " U% C  x3 f& `$ E0 ~
  16. namespace animal\cat;7 D& J  r  @& b3 D
  17. 1 Q2 @5 u3 F0 l
  18. // class Dog{  f: h4 i7 }' \* g
  19. //     function __construct(){
    3 m+ C7 z3 S' o. W5 n
  20. //             echo 'dog in cat!';1 K; d2 x' P0 v) M
  21. //         }
    7 B; l, J# n( c, R" J$ q) k" Z
  22. // }! O# W* y3 a+ b
  23. class Life{( x& z5 o+ q: b, P9 w& ^" M6 r
  24.     function __construct(){5 ]. f: _$ v6 O0 z4 f# h% Y3 g
  25.             echo 'cat life!';% R/ k" n3 e' ?  @5 \" p
  26.         }% X. U6 n) S0 o
  27. }
    . O. N* m# v- j  P, B7 ]
  28. 6 R( I+ H! L) I' B
  29. use animal\dog;  4 r0 q! U4 J4 C9 d$ F
  30. new dog\Dog();
复制代码
, s5 M& h: c. D# U: r7 _: M
如上,使用了
  1. use animal\dog;
复制代码

: S/ y* Y- u# h. s
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

! L1 L0 ]3 ~  p. @3 @9 e
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

+ O( U: L( J# N: K8 U9 K" P* R- _6 K4 u4 D6 ?+ ?# ~, m
1 r0 ?# L2 i+ f% x- D: a
- k% D8 F, b! i1 p4 W) d  q9 {

, Z5 m2 g2 H  ^+ a& c
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 12:11 , Processed in 0.126304 second(s), 22 queries .

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