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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
* C& l8 @& U2 @2 S
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
; W% a+ @, q$ A
9 R( E- {. c* a
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
3 W9 ^+ U( g9 x* ?# S3 E
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

' l, P: e2 P7 U# a6 K结合使用方法来进一步理解它的使用目的吧。
) j- ~9 J. ?* Y% A6 P. [
; J) g0 K2 Y1 [/ A+ J  _" y* Q
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;* |; e" s7 p$ s* x
  2. namespace One;
    ! ?+ x5 E+ d# ?' M5 t# b! q
  3. namespace ONE;
复制代码

. C* B9 {/ y2 s) t2 a2 e4 Q
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

0 F! v4 E7 U1 `* T, }2 i2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    ( k0 {! `1 B* A! ~6 A
  2. class Person{' h2 s2 _5 V' \( x: d
  3.     function __construct(){
    2 n* [1 v) w9 g6 G; Z+ P% ~2 f6 X  P
  4.             echo 'I am one!';
    . k5 B0 ~8 m; U& m9 u- C7 V$ F! Z
  5.         }
    4 D" e/ m+ ^/ `- [( v/ c
  6. }
复制代码
  1. //name.php3 y6 R( b0 D, ]( X5 ?
  2. require_once './1.php';
    - x5 u9 o* c- R# p

  3. " V; [) @% r6 i2 t4 p2 ?
  4. new Person();     //输出 I am one!;
    6 r3 G  z4 f& {% O( V8 |" Q0 F
  5. new \Person(); //输出 I am one!;
复制代码
8 `+ a* D/ V; O! `, o! {9 R, y
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php0 H* @" a$ u0 w* V' x7 H
  2. require_once './1.php';
    % K7 ^# M  A  j) S
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

/ T& p' x# A6 G5 s) v8 y4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    " H! W2 u& a- u% v
  2. namespace one;
    ' J3 S0 U: S4 S" I
  3. class Person{
    1 O8 `4 i" j( f
  4.     function __construct(){
    - Q! k2 \) X: L+ r( X# Q" g0 T
  5.             echo 'I am one!';
    ! R+ Y: \( P& ?3 ?$ p& V0 `8 o
  6.         }
    7 z5 `: Q0 o0 [3 F( }6 f
  7. }
复制代码
  1. //name.php
    3 r* _: G! a0 N" `
  2. require_once './1.php';) c2 e1 r% J! u1 i
  3. new \one\Person(); //输出 I am one!;, O# ?2 i0 n) c, ~8 ?
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

! j$ X% ?$ u2 H
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
0 d0 S% T; L3 q2 R% G5 j
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
* j8 K0 \" c5 d: r$ z
  1. //1.php   # G& I  Z* A% q+ Y$ J+ ?% ^% B
  2. namespace one;7 D7 I1 [0 A- Q: V6 r: U
  3. class Person{
    * W7 Z& t: N/ @4 U
  4.     function __construct(){7 e# T7 u: P7 {! R
  5.             echo 'I am one!';  f3 @' z3 h3 m* f: A$ j
  6.         }
    4 G7 y+ ]! F3 O6 v7 C, F
  7. }
复制代码
  1. //name.php
    0 ^, O0 T3 r" W1 g* H4 i9 V8 e
  2. namespace test;
    9 a1 n4 v- ?2 D, u9 J# m& B, ~$ }
  3. require './1.php'; ; ]* g/ B$ ?1 L' }! w
  4. new \one\Person(); //输出 I am one!;
    ; D% L; a) e) {+ y- `1 L" [
  5. new Person();      //这里结果会是什么呢,猜猜看
      z3 n6 n5 N( U) n
  6. 最后一行结果报错:
      I/ m* D! O0 U+ T! a0 M# ~3 X
  7. Fatal error:  Class 'test\Person' not found
复制代码
9 ~7 A4 C2 K0 H: }. m8 I! E1 O
* I: \8 z8 u8 t  R
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
5 d6 r( `* P7 a5 Q
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

' J7 ~* \0 h% F& q. V
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    # \  a9 g6 M& a( m. V$ u9 K
  2. namespace test;
    * ?. \5 F& h% W4 q- n0 A& _& ^
  3. require './1.php'; ' z$ b$ Q: Z3 ?) C3 a9 p) J7 ]0 V

  4. + u# V4 c" d4 [5 ~
  5. class Person{
    5 Q$ e. c0 A4 @( {2 }
  6.     function __construct(){1 R) G: M! [# x+ Q, i4 ~! R$ N
  7.             echo 'I am test!';: U3 R) K6 Z; V4 O  I& d+ l5 Y1 W
  8.         }5 x' o+ z/ t- f4 s1 {, [$ G
  9. }0 ~- E  t, h4 E  Z1 Q/ H4 z1 d
  10. % z# L- I, F4 }6 }
  11. new \one\Person(); //输出 I am one!;. [+ h" C2 l- w& m
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

* _5 b0 ?$ |3 h9 k* F
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php: i. E) P" S! J2 p2 d
  2. namespace test;; ?% L- y7 I) k. [. u, e$ b! q
  3. namespace one;6 w5 u7 f' P3 `0 \3 Q
  4. class Person{
    # y3 C' w# f! \7 l$ @. r
  5.     function __construct(){
    2 B8 N3 g" A8 I* O+ Q
  6.             echo 'I am one!';
    ! n' W' M; G( Y9 P4 [) p
  7.         }; _/ U+ b2 d* J- R4 `
  8. }+ v0 o! S: R  W( l. _% }+ Y

  9. + ?# v7 f/ L- t8 |
  10. class Person{
    ) j7 }0 `' z: P, y' ?3 M$ S' I
  11.     function __construct(){' o6 V. s4 P' p( A5 ]: p2 x
  12.             echo 'I am test!';
    6 ~6 s# |- p' u9 Q
  13.         }
    4 j: T0 Z6 Z( v4 s- E" H
  14. }
复制代码

; b$ F+ \. l5 O" m
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
8 m0 ?0 r, p7 _+ Y: y
看来简单的把require理解为替换,在这里行不通。
  ]; P% ?; I! E% a) p- t3 K# ?
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
  H' u( y5 g  D: N1 o8 ^4 d+ l. M
  1. //name.php4 D( D' @( t9 Q( S7 y1 b, A- p1 n2 D

  2. , Y) O( S9 Q3 {0 H
  3. namespace test\person;
    , s1 U0 a/ ?' S( o3 K( s
  4. 0 A5 s& X; Z: t
  5. class Person{4 F$ N/ d5 n# R" E% D* Y) o) U2 ?
  6.     function __construct(){
    & T5 q1 B7 D7 |
  7.             echo 'I am test!';' j- \/ S/ p5 Y; n: Z% g# F
  8.         }
    6 i' O, v( x/ Y" V2 {# d
  9. }7 v& r# ?* P$ o, ~9 E1 X0 m
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

& U  L2 p, G" L* m3 E" ^7 ]6 T5 M4 {
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

1 [4 I; u( U, ?+ z+ F# m/ x7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php) U8 l6 c. w; P* O% M) g
  2. 1 B( C4 S- P! m2 e6 |6 k
  3. namespace test;4 m4 h, R3 b5 g0 Y
  4. echo 'zhai14';
    2 c2 |) s9 }( d$ S
  5. namespace zhai;; h3 Y9 O: Q& t/ k+ P
  6. require './1.php';
复制代码

  X9 ]1 }$ X+ [  y
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
) U5 I+ X( u6 a( ]( @
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。$ u/ E0 v- s9 o2 L' Y1 @2 g
  1. //name.php  n8 i9 m( n0 O; w% z  m# W

  2. 9 l% W; W* D7 w, V
  3. namespace animal\dog;* M- W8 N" w  f! h& @) {
  4. $ p1 V! ~; X& B& b- u  N8 f5 K* `
  5. class Life{& Y) S1 @, S% [  w3 g- _
  6.     function __construct(){
    * D1 _1 B1 b, B1 `# @/ s) p* T3 A
  7.             echo 'dog life!';8 Q8 S2 B' q, s, t' E* ]3 D
  8.         }7 D/ V! }3 a8 e4 e5 I+ R
  9. }
    ! i3 K$ u6 h+ l( t. ^0 @9 t

  10. 6 q1 M2 K; a1 u7 ~; G  t
  11. namespace animal\cat;
    * L2 k# ^' ]9 e; F: H5 |' V+ ]8 Q: D
  12. 3 t  r: m/ s/ F% I& R) x7 \. \
  13. class Life{
    7 d9 R- l2 Z& Z
  14.     function __construct(){" [# @, o3 m- O. R( q
  15.             echo 'cat life!';
    ; H; Z3 `  ?9 E: ^( H
  16.         }
    8 |& I$ i6 l8 F* P+ y% i
  17. }
    + ^. o. R4 u$ f, x7 Z" Q

  18. $ B3 q% Q4 }. O5 R9 @! @+ O
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间* H* A; J2 L! j4 _& Z) l
  20. new \animal\dog\Life();  //A. v& z, T) R5 p. s

  21. , h( f. q9 g; D# y' p0 _* V
  22. use animal\dog;  //a
    7 A7 {" m* M# i  J6 B( }7 x2 a( S
  23. new dog\Life();  //B+ q4 G* G9 }9 x4 u9 z+ E
  24. % b! U9 R0 X) d/ n
  25. use animal\dog as d;  //b
    2 C$ S9 \. \5 ]/ ^/ y+ e
  26. new d\Life();
复制代码

+ ^9 @) g5 V, f5 X
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
8 T) h& d. ]: @) v& O# D8 E
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
1 Q/ K: Q8 v- M& K$ B
相当于
  1. use animal\dog as dog;
复制代码
, S# Y6 e' L8 d9 X# S' j
2.namespace后面不建议加类名,但use后可以。. Y! n: P% k: i, C4 i
  1. //name.php
    , L  l' z, e' h% }2 \  `

  2. 5 K: `1 a  j+ U1 u6 {/ t  M7 z
  3. namespace animal\dog;% Z& K7 L! [1 Y" j1 x$ I
  4. - C5 h- \) C2 \$ p# Q+ R
  5. class Life{
    9 `* U) M/ ~3 u5 O7 I+ \
  6.     function __construct(){7 Q$ D, o2 [2 }9 e' n
  7.             echo 'dog life!';+ |- Z- D, v6 b- |. z
  8.         }
    6 p! n& J9 v/ p  ^
  9. }
    ! O' n) m8 K- k5 ]  Y

  10. 0 T* Q! K, ?9 g' Z, _; I
  11. namespace animal\cat;! P( }# D( ^2 z4 @; H/ }
  12. + k! ?+ Q! x- ~% u
  13. class Life{
      W/ H# [3 x& u+ l0 U5 A; H
  14.     function __construct(){- ]: m3 f( r' o7 y0 {
  15.             echo 'cat life!';& V+ w7 V9 N" E; ^% ~
  16.         }
    7 x8 g3 r. @, h. j8 x3 \. Z
  17. }
    2 i, ~' b; o7 n
  18. 6 t' D3 H4 `& X
  19. use animal\dog\Life as dog;  
    2 ~  [- p" W7 p/ S- r
  20. new dog();
复制代码
/ I( J: @) C7 b4 ~; R8 y
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
3 ]: M: h3 ?& Q6 [, }# j6 x) b
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php- V& w& s; \! I

  2. ) H3 p  q4 h' t0 @- W
  3. namespace animal\dog;
    ' e! f# k* @3 Q9 J+ {0 d" r: W: h, f
  4. ; s2 o* i2 K& z4 x
  5. class Life{
    # M; G! m5 o% {; T) \& [( C
  6.     function __construct(){: H: o: S& K! N+ Q8 w3 {0 |
  7.             echo 'dog life!';
    3 h( d, ^6 L" C6 i' n
  8.         }  r3 ?9 |, R& e' ^- b
  9. }, W; Q. c/ e" ?, r* y" D
  10. class Dog{
      i5 b8 V  ^$ I2 L
  11.     function __construct(){
    3 _8 F! `2 r  [/ Q7 o! E8 }
  12.             echo 'dog in dog!';4 @6 \. m. U$ v2 W7 M- y  |7 F
  13.         }
    ' V0 R) `0 f- w: e1 s, d
  14. }9 g8 G  _" U0 c6 _

  15. 5 s7 n! m% r& V9 D) Z6 ~' j
  16. namespace animal\cat;
    & M5 K' L3 |/ {1 j
  17.   m: I! F2 |! Y, ~6 J# m, l8 w
  18. // class Dog{
    & J/ y7 U, d. h. \7 A2 ]4 T
  19. //     function __construct(){; C% e% l: N! N
  20. //             echo 'dog in cat!';
    . F# s/ H- p, N! l$ ]  I8 }8 }
  21. //         }$ J) m. d  v) ^
  22. // }, b" P2 A* r+ U1 O
  23. class Life{
    1 x+ I6 n$ h% o& y
  24.     function __construct(){
      e. k0 [: H( p! Z; h
  25.             echo 'cat life!';
    ) M8 W' {" e  e# N0 S0 ]3 _; F
  26.         }6 T3 v) Q8 H  E) |' G
  27. }0 a1 H$ y3 S  h* S8 ^* {0 A7 `
  28. 8 Y+ j, ?+ ]# [  l' E: k' V
  29. use animal\dog;  
    * _) a5 X- k; Y% J: H, Y
  30. new dog\Dog();
复制代码
" l0 W# J: R+ v" y7 y0 ^
如上,使用了
  1. use animal\dog;
复制代码

0 g. m% y, z6 R
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
7 j$ x0 _, L2 g% U. t3 x' V; z
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
2 g$ _: M" j$ ~7 z) t8 r

3 E/ V" j; C5 n" G1 p4 T# d7 c- i3 B1 |) ?  p4 n
0 @3 P- M% C7 u9 h* J2 |% u

/ N" M+ u& r# ~, K1 u+ p
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 16:43 , Processed in 0.118826 second(s), 19 queries .

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