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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

- H1 l- m! j- C; [: @* P- E6 z
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
* X* t4 g( r) Z, ^) o5 D) u1 S
3 M" R5 w# U6 ^. u; k# l
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
- C5 ~5 y' L* O# u2 ~+ L
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
* t, a/ C4 ?7 _6 T5 z5 b
结合使用方法来进一步理解它的使用目的吧。
$ g2 [# F5 q$ m, I

8 S% j2 Q5 Z& j0 n' cnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;# d8 `0 r; ~6 w
  2. namespace One;
      `7 d' t" P$ s, {- L& p
  3. namespace ONE;
复制代码

0 a/ |7 l8 t6 f$ ~6 b2 k2 h
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
7 r1 D2 c% Q. Q! h, ]/ q: V
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    / t' U$ L+ U# h0 r# [
  2. class Person{! x+ E+ s- p) H3 b3 t; b+ M& y- ^
  3.     function __construct(){
    : i0 H* u' |" R! j  q0 U
  4.             echo 'I am one!';7 }7 z3 {+ R$ |+ [
  5.         }
    & h6 a' L7 v7 G6 u7 }: G* c8 ?
  6. }
复制代码
  1. //name.php
    ( I; D! @6 n6 v/ V& n$ \! K: R
  2. require_once './1.php';
    9 T) |2 O( g. j; C9 \5 e
  3. . }) g. m8 Q4 @% g
  4. new Person();     //输出 I am one!;( t  I' c9 D- d2 ?9 Q" n- S5 j
  5. new \Person(); //输出 I am one!;
复制代码

: q* Z7 N4 p8 L- _3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    , {* y9 f, i! T( v3 @
  2. require_once './1.php';
    ) K" z9 s9 J; L  ~$ R7 m3 f
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
% [! _, u5 y- G; x! `# d
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    ; x% x) e' U1 ?$ x2 {' Y8 _
  2. namespace one;1 c; r! w( h5 d& i" i* K
  3. class Person{7 z0 A& C5 F4 B9 P; U" U- H
  4.     function __construct(){/ r" U) T. A. g8 r9 u8 R" h* R$ a
  5.             echo 'I am one!';& J5 l$ K, ^# [+ J' ^' j; o
  6.         }7 w  q1 K# P; e, c: E* t* L
  7. }
复制代码
  1. //name.php
    7 e; Z% `/ ]  w
  2. require_once './1.php';& C! g$ m6 E. o4 U  [7 j* {2 U  r
  3. new \one\Person(); //输出 I am one!;
    8 ^: }# b$ h4 G8 p& ~
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
- O* E. z+ I  F; ?% Y9 S' a3 @
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
* w2 G1 q* ~2 j9 {" I9 I: U. l
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。' S( e7 C+ V$ Y; E, z" W5 l
  1. //1.php   
    : c# f8 J+ _: H) O# L1 J
  2. namespace one;
    8 x4 R; m  _! E) T5 C- F- q
  3. class Person{5 I8 p6 R- d. s0 R
  4.     function __construct(){3 I) O+ j+ T9 c* c
  5.             echo 'I am one!';
    $ A# X. I1 |- n' s1 _5 l$ O% m( K
  6.         }
    1 p8 _: `; N  T7 j* M4 l' Q6 o
  7. }
复制代码
  1. //name.php! u# R$ ~0 R$ m5 I9 d- A
  2. namespace test;
    ) Z7 U& \: L4 K/ D
  3. require './1.php'; 6 n* J/ ?0 e* F3 h
  4. new \one\Person(); //输出 I am one!;& C9 |; f# m/ ?
  5. new Person();      //这里结果会是什么呢,猜猜看: D' d4 D) o: _8 f* F0 h9 i
  6. 最后一行结果报错:" W: I7 X, E/ ]3 _) f8 B$ ]$ W
  7. Fatal error:  Class 'test\Person' not found
复制代码

& `/ d( J2 u  K# q/ w4 _2 H
9 o9 ^# }" Z& u/ |. t* e
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
  n3 I+ F" f6 J
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

. x& I! R. Y# ?6 y0 h
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
      T5 l' i! {6 P# _
  2. namespace test;5 z% `5 n" T. j" P1 Y  ?% |$ U
  3. require './1.php'; + Q0 H1 Z" E  \  `; z1 y

  4. 7 D/ @/ @4 t$ r% u# M
  5. class Person{
    2 _3 Z5 @4 i" o" ^% C. ^
  6.     function __construct(){2 R$ l1 d( T7 z+ C  H8 t
  7.             echo 'I am test!';
    7 S0 }  s/ t/ B: o
  8.         }
    - D9 v, N$ j+ `& ^1 l
  9. }
    / e" e6 O7 @7 H1 N) E% b1 V
  10. ' M+ ^5 q7 I2 o) f
  11. new \one\Person(); //输出 I am one!;
    $ F1 ~* R3 G, J" L. Y9 r: s4 r
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
  F4 @( l& O( y) i7 H5 X/ C( p
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php2 v$ m4 q) s( m" G7 e
  2. namespace test;. S/ |/ d5 n- k% Y" f1 i  R) E' }
  3. namespace one;5 I7 c7 S5 g7 `5 N& g  L* @- P; m1 G
  4. class Person{! a; X9 a2 b% e8 k7 s
  5.     function __construct(){
    % Z* c' F, S3 h. b- `# H2 k, \! X
  6.             echo 'I am one!';
    : t4 w# f# D& `
  7.         }
    ( v- z1 n' k6 m$ ^' J
  8. }1 s6 M2 i& p7 Z; S1 x9 u4 Z

  9. 2 P' S$ m' C3 J9 L
  10. class Person{
    * \: L$ n( O7 h- W/ v
  11.     function __construct(){# b1 G( N9 R6 f  }) a( Z
  12.             echo 'I am test!';
    7 v. P5 y! N/ b3 o& ]# Y/ V
  13.         }
    2 p% e) K9 h5 S4 p3 A
  14. }
复制代码

" s- J3 J. @% n1 p
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
# w9 \. I" `+ e) N9 O2 e5 g9 Z
看来简单的把require理解为替换,在这里行不通。
' H& z' _' c2 X* q7 h
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
0 H( h! c1 O' M- m# P( j) N
  1. //name.php" V3 M8 I, R" }& u! U

  2. ; T+ f4 y( a! P8 L* l1 w! N
  3. namespace test\person;
    0 U0 C7 L& ]7 v% R7 K

  4. ; A- F( h: X! A" r" ^
  5. class Person{
    6 A! F" k; k/ i! M# C7 H" @
  6.     function __construct(){
    & x7 b. R/ G/ N/ `  m6 N- c
  7.             echo 'I am test!';/ R' l# w$ s; E& Z- U* e. P
  8.         }
    & q5 i! m" P/ ?4 g
  9. }: m4 ?( U/ a) G" Z
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
5 y/ c# [: I. O% X
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

0 K' m8 q$ z" J( p- U  A2 M- l7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    8 l7 d3 C' q$ I
  2. # T0 E2 N, M% r5 w, J7 ]2 J) v
  3. namespace test;8 r+ u& P) v+ Y9 Y3 n$ a
  4. echo 'zhai14';; c. X! L. _2 k7 q
  5. namespace zhai;
    " i1 w2 @$ B0 d: i' W: j
  6. require './1.php';
复制代码

9 X: C) z1 K) R. @' @& ]4 J. ?0 }
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
# j$ E2 V1 c1 R4 M% T1 k
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
% g) G9 M. M% W; W. H! B# w
  1. //name.php. F) ~) z  j1 z% _! I* T: \. s
  2. : ~# Z: l( L3 g! q1 s! P
  3. namespace animal\dog;
    & |5 Q6 z4 J$ d% \3 y0 S

  4. ) l3 w# M; `- [' b0 u  j
  5. class Life{: F; A# d2 h6 M' L( G6 ~! l' z
  6.     function __construct(){
    ' {4 Q1 N2 W5 Y; }3 Y8 s
  7.             echo 'dog life!';
    9 _9 y8 `. m! K9 h2 N: B
  8.         }, G/ p# M/ j1 p
  9. }' ~5 X, g: Z- P6 U+ {

  10. 1 Y2 v  K. ]' J9 o! |! a/ c$ _2 P
  11. namespace animal\cat;
    ( o6 h1 l3 Y) _/ ~

  12. 3 S/ L$ c" F4 F2 S; G/ h9 `
  13. class Life{
    : a/ Y# Z( \- o0 A2 ^
  14.     function __construct(){- i2 n7 M( y$ _5 P$ }5 o: D
  15.             echo 'cat life!';
    : h# r- X" D* M! x- q& f! g+ T
  16.         }  ]' A# L. }# U- I8 m7 _
  17. }; j  H7 `2 m% x2 M1 {% O
  18. * x/ U" s' \/ }, G, m4 O
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间% C) c2 u' I" Q6 c7 w
  20. new \animal\dog\Life();  //A" j% J4 G- B3 N7 x2 |

  21. ! q. x3 I$ c" C. Y, M5 R) f% w
  22. use animal\dog;  //a2 c+ A5 ]# g7 @5 a! P# Z3 n
  23. new dog\Life();  //B! c' V7 a7 N+ K6 w0 k% s

  24. + N! F$ _" M' i0 b) P- T* d$ @; f
  25. use animal\dog as d;  //b$ B) u- d3 ^( B" E* Z4 n! o/ o* K
  26. new d\Life();
复制代码

+ o3 f+ {3 ^' i" |: Y$ N
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

1 x4 N# W/ a) m( C4 H7 M! R
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
) o+ @' P: r' C7 Q% n5 U
相当于
  1. use animal\dog as dog;
复制代码
' t+ k5 ~/ y" A% y4 ]2 ]9 S
2.namespace后面不建议加类名,但use后可以。
( N$ a. c8 c7 k. w" f
  1. //name.php
    ( G, q2 f# o5 J  t8 S9 o
  2. + h1 k2 |' _& w
  3. namespace animal\dog;
    " r4 A4 K2 s4 m$ d

  4. : z( [  \1 o% l
  5. class Life{7 _( O2 D( i5 P
  6.     function __construct(){
    " }0 R1 M, v$ S: f$ w
  7.             echo 'dog life!';/ H7 n4 V4 G+ l8 w/ z
  8.         }
    , e6 O! `: G  p; ?/ p0 ]
  9. }; I  B- k% N( p( K$ \1 B
  10. ! G2 p! C, K: m- i' T" M
  11. namespace animal\cat;
    1 H* Q! k1 y6 `$ t

  12. ) \* H$ ]/ |! O7 z$ u/ E! H
  13. class Life{
    ! E4 e2 b2 P/ G$ R, l; B
  14.     function __construct(){
    # [. @% J' m: K' c
  15.             echo 'cat life!';/ |  b8 q0 H% H7 L5 X
  16.         }- W5 ?. X+ D9 e8 e
  17. }6 O3 U: }$ z* O- _* A: f

  18. : f( F7 b1 M% p! u( ^1 |
  19. use animal\dog\Life as dog;  + i1 z$ _9 @' }5 P7 j$ Y
  20. new dog();
复制代码
9 @% f0 d' p; M+ D/ \# X( p( d+ ]1 P
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

/ l7 _! O: m6 |. _& X7 e
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    ; W* s5 S! E. @# c* k0 c' m

  2. % r) A) [3 X3 W( Y
  3. namespace animal\dog;6 m3 C+ g7 e- t
  4. ! r7 X$ S4 }, F) g+ E$ \
  5. class Life{
    & N8 V0 z+ q* a
  6.     function __construct(){- e4 U4 l# T* H" m
  7.             echo 'dog life!';
    , Y$ `- Q6 n8 i% f( q# ^
  8.         }/ b% Z2 Y9 [' U; c
  9. }4 S% ^6 J5 l' m, f2 d( C
  10. class Dog{
    : F# Z; }0 m; T) l
  11.     function __construct(){% }2 l* c. C2 X3 }9 U! [# ?  `" d
  12.             echo 'dog in dog!';5 w" A/ X: i9 T
  13.         }7 @1 e/ X5 I+ w" X+ {# r& H
  14. }
    + K# T# }" y4 |2 C
  15. . _1 Z, p; U& U
  16. namespace animal\cat;5 J7 E2 G/ v! {0 p$ \8 q. w. l

  17. ; Y9 `  Y  {, _4 r% G. A
  18. // class Dog{
    " [. |4 T' m/ V$ }& N
  19. //     function __construct(){
    & n" q8 e+ {% t* }
  20. //             echo 'dog in cat!';) ^% Z$ N( k% g, |, w+ u! G. U
  21. //         }6 x3 p- g: A3 M
  22. // }
    4 p, L8 ]( s% A3 t7 L/ v2 c
  23. class Life{" ^( e  d, Q& @/ |1 ^7 H
  24.     function __construct(){
    5 Q! P' i' w( R
  25.             echo 'cat life!';
    ' w2 i. l* C3 ?5 `2 V  Y
  26.         }
    9 X, x) B: X5 m+ R
  27. }
    , `% {' W1 D6 \0 ^, E

  28. ( y( T' O! l1 L# R) ]6 L8 Q4 d
  29. use animal\dog;  ' [! g% k$ H' X4 u3 [- q& W4 l- Z0 |
  30. new dog\Dog();
复制代码

9 ~5 _8 G! w+ X
如上,使用了
  1. use animal\dog;
复制代码

" }$ R. m) s( |1 n( G
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

2 z; ]/ T3 L6 S- e: C7 ?3 |- f7 D
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
4 G+ `) o* [1 R7 l2 ]/ Q
' d4 k1 K% {* U- H) J1 H1 r% j
' @! M5 _. \+ Z+ K7 N1 d
" l; H3 y* G/ n2 C# P, ?/ \

1 v" c  A! `1 @7 _; e1 b3 M
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-4-28 06:14 , Processed in 0.122391 second(s), 21 queries .

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