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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

- A, j% y" O/ n+ Z; A
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
' L* A9 o0 n2 w% m* H: }7 a

6 k' ^, k3 F! S% u2 u使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

4 _3 m2 }. z* G* w, E2 u+ ^- q
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

6 k& b' @% X6 ?1 ?% o) u/ J结合使用方法来进一步理解它的使用目的吧。

9 |9 u6 m$ I+ z# \: g
7 f) ]  ?( ]5 k( L5 @namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    0 q- P% B  a+ o; ^
  2. namespace One;
    ! p6 u8 \  a8 ]& Q/ Y! B( g4 Q/ I
  3. namespace ONE;
复制代码

3 d, E2 O6 H5 d7 j2 M* v
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

. K, a' M( |. N$ |7 N4 d* y& s2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   % |9 X2 B" V: J9 R) N" T4 E+ m
  2. class Person{
      t$ y. k* R6 D+ _
  3.     function __construct(){# M, @) n+ {: s& y& z" W- Q
  4.             echo 'I am one!';, }# K( v9 V; G8 u: u
  5.         }7 @) ~2 H6 u: p4 u+ q
  6. }
复制代码
  1. //name.php
    # }+ z1 ^! m5 T9 W; h% f) Y! `
  2. require_once './1.php';& m6 ?# F& K- X- v0 g4 Z  [/ i
  3. % I) a/ Z- w; ?3 J9 J$ o. k
  4. new Person();     //输出 I am one!;
    , y0 j5 ]0 G6 J2 {
  5. new \Person(); //输出 I am one!;
复制代码

+ y" ?% z( ^5 U8 ^% y$ w3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    5 f  y' ~- O- X! y
  2. require_once './1.php';5 b1 B: H7 |' H8 u% e
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

5 g7 Z: `; i) w0 h4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   ' r/ O! M3 e7 i2 \4 c3 f7 I
  2. namespace one;' j2 a% N" b. v: c
  3. class Person{2 K' C( b; H% P+ A; J0 R+ ?% {
  4.     function __construct(){
    : e4 Y. _& P9 m: ]' c1 q1 k4 P* X4 d/ J
  5.             echo 'I am one!';/ d- _, u. s+ J- g3 S: J
  6.         }1 D0 d+ M# L) p( I9 a- k
  7. }
复制代码
  1. //name.php( q- O4 u; X# V# c# @
  2. require_once './1.php';
    2 g2 E* k: r0 M0 e# \) O3 z; l
  3. new \one\Person(); //输出 I am one!;
    9 X% a+ m% a/ h; j7 f& S
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

  c: f+ V) e* e7 N( J7 `) D# t
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
7 O; N( I4 J8 R1 V& A6 p8 {
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
" L0 z5 s( A$ f. B9 s
  1. //1.php   
    1 ~+ G, |  I" q1 I
  2. namespace one;
    - J  U  ~( w8 ~" f2 n0 Q! C
  3. class Person{
    : s: Y8 U# e; @
  4.     function __construct(){
    9 q/ n; l8 m' B8 Q0 d1 g+ O
  5.             echo 'I am one!';
    - m6 A3 S4 T' U) Y; K4 W
  6.         }
    $ g; W& }6 z+ K1 s5 y- }% a
  7. }
复制代码
  1. //name.php* \, L$ E! U- d; M& Y5 F
  2. namespace test;
    $ |: a& P# w9 E! ?
  3. require './1.php';
    / y2 K, Y5 ^6 {7 ]3 ^6 }2 t
  4. new \one\Person(); //输出 I am one!;
      n, d# P! \8 _" D/ C
  5. new Person();      //这里结果会是什么呢,猜猜看
    / c  F- B9 `) Q" ?8 \1 |  h0 E1 Z
  6. 最后一行结果报错:
    # K- o9 C+ T0 l- B  \0 M& c2 J
  7. Fatal error:  Class 'test\Person' not found
复制代码
' M. _. P, `, m( t8 i

) Z! V' a5 M) R' H. W6 W首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
  v+ l1 t4 t/ a8 A6 F2 R& R2 Z" p6 j
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
1 Q/ {: _) u( x2 `8 K
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php% K3 [" X2 p/ [# D
  2. namespace test;
    " Q& ?& C" y% r' L' B% X
  3. require './1.php'; & L' E8 ^& V  m' `, S" t1 b
  4. 2 I% t6 m5 Y) Q* u
  5. class Person{% n2 D( M+ \: t8 m: T: m7 @8 ]6 B
  6.     function __construct(){# x+ h+ M0 o& V2 Z& e) S
  7.             echo 'I am test!';
    * @  J! S2 _; X8 \& p- N7 T& H4 C
  8.         }
    8 s+ [. H9 P* d4 o, C! o7 U5 D
  9. }# P! A& a9 z( C

  10. - e; M0 p! B! k
  11. new \one\Person(); //输出 I am one!;
    3 q: A0 N6 `2 k$ M0 ~
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

: V2 e$ E1 C6 V$ D
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    , q5 A% e* C1 b& A
  2. namespace test;
    , t7 T/ G! D4 k! D  S& L
  3. namespace one;
    / S; t8 b6 ?; z! s0 i' c4 d. I
  4. class Person{
    ; b9 ~6 w! I- s: t! T
  5.     function __construct(){
    ) e3 }  ^* s+ m  F9 j
  6.             echo 'I am one!';2 U* W9 r6 B  S6 ]. t8 x% S
  7.         }
    7 J! @1 S* {1 u# N- k4 V
  8. }5 y0 D# Q, ]9 e5 i- y3 E: Y% n: p
  9. 9 J% w7 g, {( l& H, g
  10. class Person{6 A6 A, q  l- D5 s/ |; f: b3 X1 s
  11.     function __construct(){
    ( ]. Q, `% Z' |: a" }8 g  i
  12.             echo 'I am test!';
    $ O  I% ^$ m  z) g8 ^0 A. S+ q
  13.         }
    7 t$ |# e+ n8 }$ `' {: F
  14. }
复制代码
: p/ e, s. y5 `" |! H6 l
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

3 n: B3 R& M+ y5 }% q" C
看来简单的把require理解为替换,在这里行不通。

1 ^1 V4 _; s+ @" J  H6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
+ b( D9 F4 i3 k4 |( _1 |
  1. //name.php
    # ]% Z( x# W8 _$ m5 \
  2. 5 a0 B( v) {1 r' C: o. W: \
  3. namespace test\person;
      x8 E% c* T5 g$ F' E5 y$ u  e# P

  4. 1 e7 h7 A* f  z3 d2 Z# J
  5. class Person{( ~8 f8 Z7 Q5 ^
  6.     function __construct(){
    % _4 l4 n6 P( y9 ?- s9 L5 o8 x  w% v
  7.             echo 'I am test!';' D1 W& g$ B0 Q* u2 R8 R& i
  8.         }
    : g9 O+ }! M5 k5 r1 i/ @7 v$ n  E9 t+ |' Y
  9. }
    ( J. ?+ X3 r# A' e
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
4 y% }! a. E6 M5 l$ {& |, W
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
5 N/ c/ Z0 e2 \6 _( {6 j
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php3 Z& R" L+ h- F4 v7 @0 P- s
  2. 3 j, K( v% j1 Q& F0 g3 r
  3. namespace test;
    , o' n6 o3 D& ?* l( x
  4. echo 'zhai14';) M% P' |" x+ U5 ~) o4 _2 Q
  5. namespace zhai;" \( a1 f: k" y* C8 L
  6. require './1.php';
复制代码
: M* e, U9 \( q* {
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

2 w$ Z: F* [- `- iuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
3 I, c; `4 ]! I0 A' |
  1. //name.php3 i& {, A: z! U* v/ l

  2. 4 U# }( l+ m5 h7 w
  3. namespace animal\dog;1 L# a; e- x# E1 G( g  [$ W/ [

  4. ) o7 W* L; v  h9 j) |; @
  5. class Life{: o  R* G4 ?- K
  6.     function __construct(){
    * b1 |! J% J+ k3 d7 Y3 H2 y
  7.             echo 'dog life!';
    - I7 O4 t- N. f7 g! U3 \/ L
  8.         }
    + b1 n3 G7 i" Y" ?( c
  9. }2 |! O9 X9 V* Z  D
  10. 9 H8 }9 t, Z2 c8 h# P9 k2 q
  11. namespace animal\cat;% T0 q: ]3 T  x% N: `9 j6 q

  12. 5 x- `% L7 b  Q5 A# h
  13. class Life{1 T/ H% P8 |& o/ C
  14.     function __construct(){
    ( d, ?) b0 ~) U5 R& x
  15.             echo 'cat life!';
    8 n9 {1 ^3 a! B2 Q( h0 o/ e+ |) g
  16.         }
    7 F8 I0 v, I1 s& i7 b+ x2 q- f
  17. }9 V  ~0 n/ I1 Q) T

  18. 3 O- I* N3 X; \" k% z! c; ?! G
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间; T  }6 t+ Y  a
  20. new \animal\dog\Life();  //A/ a8 e" o1 B; `% z# C2 }$ u/ `: F9 ~
  21. $ `$ N1 K# a& N$ Q
  22. use animal\dog;  //a8 f' L" e/ c. o4 w- u+ S: N
  23. new dog\Life();  //B( K0 l( q. o. l/ i$ N

  24. 1 i- u3 ^* k6 U: H3 Z+ h0 C: j* r* E, _$ R
  25. use animal\dog as d;  //b
    1 a# l: K- p8 e8 M
  26. new d\Life();
复制代码
# f2 h) o% H' z' p9 D
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
  h' T- g, U$ M9 }) L4 o
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

5 A0 z3 M) J6 F
相当于
  1. use animal\dog as dog;
复制代码
- Y3 t' L. t' n. J5 ^$ ~$ G" L/ }
2.namespace后面不建议加类名,但use后可以。
3 M" O& T6 X9 G: R
  1. //name.php
    0 j+ z* Y  S! f& A" ?  _

  2. ) O/ F( E1 [8 K9 S
  3. namespace animal\dog;
    3 H  A) |7 z! U7 f, J
  4. : ?2 `1 U  r; |- w4 [3 l
  5. class Life{
    5 y+ e3 G6 ^. P/ }+ b3 B  u4 F
  6.     function __construct(){
    ) B0 D4 O. ~. k* i& H& d
  7.             echo 'dog life!';
    * m7 r1 ]$ f; l6 v5 k6 o% @
  8.         }
    & a( {( e5 {0 m1 L1 r# u
  9. }
    , s5 x) ]4 ?3 t& V1 M6 s9 g
  10. 9 H4 z0 ~8 t6 f5 d; ^
  11. namespace animal\cat;$ a/ K( O4 O" t5 U2 U
  12. / g4 ]" @5 I, t3 o4 y& y3 j; ?
  13. class Life{
    ) c6 @( u  u3 h/ n0 N& Z. b$ P$ J8 L
  14.     function __construct(){
    4 W4 S0 G! W: S/ @. j! D4 a9 U
  15.             echo 'cat life!';! p# q8 B% \( C4 M, u6 t$ k
  16.         }$ |4 X. E) b4 d  k$ U! P# r) ^
  17. }* t) K8 V' M' B2 j  A0 k

  18. $ J/ ^/ L. q- G5 B2 s
  19. use animal\dog\Life as dog;  ( E- {3 G; {' M1 z
  20. new dog();
复制代码
6 w6 {9 C! _# X
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
& T0 F$ r0 o" @9 K: G
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    / D9 \0 ]8 ]3 B& S6 U9 {1 |

  2. 8 G( Q+ s5 N& I4 d) A# Q. j0 @
  3. namespace animal\dog;9 b8 m& k$ h  j8 H- T# O; n
  4. ! A- z. l$ K2 Q1 v( ~
  5. class Life{
    0 M$ k# E. K" S  D. C8 I+ [
  6.     function __construct(){$ d/ \& e1 c' m' D. f
  7.             echo 'dog life!';% H' z" N2 y- x& N
  8.         }
    3 S% x4 C6 \! G, {4 Q
  9. }
    3 ~0 S$ B( A2 v
  10. class Dog{5 ?8 R; T& l* H5 B% ^) }! ~
  11.     function __construct(){4 @' o) f  n4 k* j
  12.             echo 'dog in dog!';  z( g; D/ w; s) @- l3 O3 l
  13.         }
    : F( b2 P9 n  J, V1 u2 M
  14. }
    % J) y, W' s" s0 [: ~8 C- g

  15. ! Z  K$ M# q0 p1 \+ \7 T
  16. namespace animal\cat;3 D3 U$ W% L( J* p) ?3 `

  17. - r  I1 Q- h3 E" L0 q7 `8 ?8 T
  18. // class Dog{$ H2 o. w" K; G  T- w
  19. //     function __construct(){
    , l5 J' p0 K* ?8 S
  20. //             echo 'dog in cat!';
    " B0 r7 i) W1 G
  21. //         }
    " }% u! G7 S( i) l% v% D/ g
  22. // }
    : a0 `/ g# v0 a, U- [
  23. class Life{
    ' D6 Z4 A/ _5 {! O! G
  24.     function __construct(){
    + }% h3 I7 E& O: `0 j
  25.             echo 'cat life!';
      \! V+ B, ]0 A
  26.         }) `" T7 a- f, s
  27. }1 s1 G$ b2 m# b8 O- j* m4 _

  28. / ]  ]7 n; X+ {
  29. use animal\dog;  
    $ U: u+ h, l# ?# a$ f: y" ]
  30. new dog\Dog();
复制代码

; z: Z6 c( d. [7 O5 Q( ]' o  b
如上,使用了
  1. use animal\dog;
复制代码
, ~8 B8 t3 O  p8 J4 P+ C; K  D9 h2 Q
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

: w: f' ^' z8 @. X. _( t, V
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
4 v7 o/ y5 g6 m+ [+ m) c

- E. a/ U6 L# ]- |2 b' B4 _. q

+ U2 ]# k! r: t
  Y/ P8 d& K/ O: L
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-17 16:06 , Processed in 0.081919 second(s), 19 queries .

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