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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
: v4 g8 [' X9 R5 K/ r/ n2 {' z
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
# d: m( Y; g: I; B, V: z
) I# m+ \; \3 E  I5 `
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

2 E" P) u# ?; _" ?8 a结合使用方法来进一步理解它的使用目的吧。
$ N3 m0 {, S1 ]. `

# n3 V2 M9 m8 N6 knamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;, N! N. w# x0 d4 p+ W2 J
  2. namespace One;
    0 H' f# S' F  y  t# p" F. c
  3. namespace ONE;
复制代码

" c. r# y, R2 g- O4 y5 Z4 G
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
; b2 F9 g, p3 E3 {" X1 a" A7 r
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    7 X: D$ g4 i5 D: d) C- l
  2. class Person{
    7 e  e2 {2 _: [* x) l
  3.     function __construct(){
    ; w4 l3 ]" w' |' H6 _
  4.             echo 'I am one!';* B$ o: H8 n) ]
  5.         }! z0 G1 t9 y3 m; a, K4 h% P7 _
  6. }
复制代码
  1. //name.php
    # @' C0 N- e1 I. |1 O
  2. require_once './1.php';  R! Z& k2 D8 a
  3. ) r# a2 E% t4 z% Q4 s
  4. new Person();     //输出 I am one!;
    ( q1 Y7 y$ e2 l7 J; N6 }
  5. new \Person(); //输出 I am one!;
复制代码

% D6 D4 e8 k! |( K6 u! G6 s3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php  U* Q4 f- u" W9 Y0 [0 L0 B7 S6 T  s
  2. require_once './1.php';
    " b) [/ d6 F% M7 K$ |
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
5 o3 J1 C. q3 c  \" M' T
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   7 n) ~" s( _; w1 f' L7 Y$ Z& s: X
  2. namespace one;
    ) W( E: V* l/ d# Y: s% E
  3. class Person{+ W) b9 |" i) v* g- ^2 n% p7 ]
  4.     function __construct(){6 k0 F/ d- h% r8 K- ?% E. b" w( u5 R
  5.             echo 'I am one!';' e0 g# T0 D& h- `9 z
  6.         }) h0 |+ P7 J8 O1 Y) y8 }, C
  7. }
复制代码
  1. //name.php+ k, ]; Y6 ?( h, Q
  2. require_once './1.php';- j1 p! N2 {) f/ ]
  3. new \one\Person(); //输出 I am one!;
    " Z5 B* D! D* u( }
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
5 X  ], q" C% A8 L; e& D* m
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

$ s* m/ O, G. ?$ W% v# f5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
: s: r+ L6 W6 U! `' }' Y0 ?
  1. //1.php   4 p3 b' j6 M2 o* y/ K( n( l7 H
  2. namespace one;
    : U2 J8 ?$ g) }' s
  3. class Person{
    - H4 ~2 K5 q$ [
  4.     function __construct(){
    3 Y! Y) I3 B0 C  u$ S
  5.             echo 'I am one!';
    " }2 O2 |/ ^, H4 z2 |7 `4 T
  6.         }+ b: v  K. H9 P; E  t! S8 K) ~. g
  7. }
复制代码
  1. //name.php
    ( C3 E  r0 X6 Z7 J# g2 e; R) ]
  2. namespace test;2 @, o, N. [  f; Q( e3 n
  3. require './1.php'; - K' ]* |4 K8 B# \: h* C8 f
  4. new \one\Person(); //输出 I am one!;
    + r1 ]+ s7 `0 I6 m: e/ s- K0 H" ?
  5. new Person();      //这里结果会是什么呢,猜猜看2 z: [1 o5 A/ v; w  ?
  6. 最后一行结果报错:! ~) c  J& {% m6 H& E1 H" y
  7. Fatal error:  Class 'test\Person' not found
复制代码

- i0 K" V  Q  @$ X# y
2 N) h1 S% F8 f
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
2 }7 `- E1 W) M6 v
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
# b. h: }. h$ y
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php' O1 }& }% J+ u! H% d3 S3 H
  2. namespace test;& r! U- W! y% @. _6 m
  3. require './1.php';
    ( W6 p( ^0 a$ A7 J# x% p

  4. * i* E1 }' s: Z3 M6 q/ p2 D
  5. class Person{/ o2 _) x8 h3 o  G
  6.     function __construct(){; J/ e; l) v+ u+ C+ o5 D6 x
  7.             echo 'I am test!';
    & V+ t4 O% E7 @* C& X  G4 Z' ~0 W. k
  8.         }
    , K( Y- l" J* X/ S! x  K/ d
  9. }
    % J5 N7 H6 f9 v( Y8 ^

  10. - P+ f: @6 z$ a
  11. new \one\Person(); //输出 I am one!;
    ) p# g* Q# Y+ G2 T, V* _
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
- y" y! S3 G/ M. K1 f! G$ P
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    0 o( ?) o. @& A' e( V
  2. namespace test;
    6 e3 v9 R# r% x* ^0 |! }: }2 Y
  3. namespace one;
    , i! w' U, E6 m3 R& [# ~2 D
  4. class Person{  F+ i8 ?! m0 E  |
  5.     function __construct(){) |! T( ]5 d" Y5 C% Y2 f: j
  6.             echo 'I am one!';
    : v' ^" s$ E& S8 r
  7.         }
    ( C% W2 e1 \! e
  8. }8 p% V$ [. R& n* L% |4 l
  9. # r( @0 G* C, Y: s
  10. class Person{
    + ]4 A2 T+ I5 B6 }  Q  f8 V% p
  11.     function __construct(){
    4 G  `9 n$ O0 E- ?) z" R" Z
  12.             echo 'I am test!';
    # ^- p) c0 y6 ?' _
  13.         }
    & _( y) G3 t: ^+ d
  14. }
复制代码

. ^- l' K: a5 I5 t" X
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
+ B( B% T, _# y/ q3 `
看来简单的把require理解为替换,在这里行不通。

, \" I5 V6 U  t6 I  I! q( v2 {6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
/ n8 u/ F, ~, N6 d& t# ~
  1. //name.php
    ! b$ D" |" m5 k7 F) L& i$ r
  2. . n1 z8 o  N0 {! i2 I5 O. G8 |6 b
  3. namespace test\person;
    ; O' s5 B, b) c; J. x5 _; {3 E
  4. 0 @$ X2 z7 H5 t  N( i
  5. class Person{% {  K8 F, P  E
  6.     function __construct(){9 e. w6 ?2 h8 n& O; D
  7.             echo 'I am test!';
    $ X$ p# R  q: o, \, z5 b
  8.         }
    ; |5 H# T8 E+ L, x  m4 E
  9. }3 p8 z" X2 Z) |5 U, T# b
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
0 J9 {/ v4 R8 [" Q& C$ u' {
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

- C( A- A; f& ]/ G: A: |7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php: f. N; [9 h8 d1 `1 J
  2. ' l% U' E# Y3 c5 [
  3. namespace test;
    , p, m( i! Y0 I0 L+ M. R
  4. echo 'zhai14';; O3 C" ^; A, F
  5. namespace zhai;  z% F/ j9 t6 Y! B( e; I$ |
  6. require './1.php';
复制代码

& y$ w+ C3 _8 B& E
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
3 U4 m: T& b9 e1 c* T! o' \( n
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。/ a4 g7 ]( x& a
  1. //name.php2 X/ Z" w! f) U" X) B
  2. + U* d0 c! O& x: q% t" J- N2 q
  3. namespace animal\dog;
    " t- J# T1 y3 _
  4. ! h& M- E% i! P4 I% ?
  5. class Life{* r5 T1 ]/ c. V) r
  6.     function __construct(){
    ; m# _7 W( `) a  k% \9 R; `
  7.             echo 'dog life!';
    ) }) x- d4 ]" `7 U$ f
  8.         }
    * i: V- N9 T5 O% ~, W: s, x
  9. }+ ?& C. K/ k6 i+ p( j# j0 p* A) h

  10. " N% ]6 _% W+ U. ]- \; P. x2 L3 ]  i) W
  11. namespace animal\cat;
    9 {, N1 X7 u( k/ ?

  12. & N& J% ^; V  a$ e6 W" T) V# f
  13. class Life{
    * T. p4 `1 I8 s) R. {) ~5 G- v
  14.     function __construct(){9 g) \1 q5 _  p/ H+ P' }" @1 t
  15.             echo 'cat life!';" ]; z! o+ E7 f) _. p, l& l$ o
  16.         }4 Z  [( q% s  M0 ~$ g
  17. }# {) V  P* S( l
  18. 8 W# \" ]8 C8 y& f/ G4 ^
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间+ T/ S; r$ X9 H- w1 `1 ^$ l9 B
  20. new \animal\dog\Life();  //A
    $ F0 M; P7 t" _' c  S# h
  21. ! V% G* n1 F8 c) h- F$ M( p5 |2 |
  22. use animal\dog;  //a0 ?' ]( N( C1 c% }' f
  23. new dog\Life();  //B' C3 b  H/ T( U" V

  24. - S- w9 V0 \, R- T
  25. use animal\dog as d;  //b' A7 [4 X6 O$ E9 n  ]: K
  26. new d\Life();
复制代码
- C5 W, Q& n3 U7 a
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

( I/ Q+ b: F4 G
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
+ w  d  b# N" y/ m/ [2 F$ m
相当于
  1. use animal\dog as dog;
复制代码

- l6 B; H, ?& }2.namespace后面不建议加类名,但use后可以。) |$ D9 t- M% y2 L7 P% u# F
  1. //name.php# c, ?1 t0 h5 d" n, j$ \0 x0 \$ Z  o3 G

  2. 9 X9 P* J; n5 a4 K4 k
  3. namespace animal\dog;
    : Z  \2 D* F; Z% W; r' F

  4. * B" |+ x! ]8 Z8 n
  5. class Life{, z& ?6 c& N0 k  k; ~9 j
  6.     function __construct(){9 j& J1 ?+ T4 e: Y8 O
  7.             echo 'dog life!';3 B+ s; B( N8 e5 K3 m2 Q
  8.         }& C' Z: B: j, I
  9. }
    : K! Z0 a1 R- G5 M6 P
  10. 3 v' X3 C& j0 v
  11. namespace animal\cat;$ K: O7 Z: a9 m) ?
  12. 1 d: r, G: P- _4 g8 U
  13. class Life{) d) j# p; R/ |+ n
  14.     function __construct(){
    ( a3 c& G* s- s9 |, p/ W
  15.             echo 'cat life!';
    % [& R8 g8 F- h" v* q  {/ l
  16.         }- H. i( h1 j: {9 ~
  17. }0 _' {& n: B1 B( `& b- _8 O

  18. ) T5 d1 }0 u  @9 ?. d- C2 U
  19. use animal\dog\Life as dog;  7 `+ O: ?8 n% _. X
  20. new dog();
复制代码

2 E+ x# O; F* p) a2 [
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
8 h' ?8 i6 L% M& j
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php3 m- P; l4 ]7 s0 W# @. Y/ W9 d. I

  2. ' y2 X! y  ]: s7 V% o4 U
  3. namespace animal\dog;
    7 p" A0 x% w: t% Q" i
  4. % L4 h1 B7 q! g" {
  5. class Life{
    3 Y7 p( }# [; d* t' c
  6.     function __construct(){5 a  R3 m- A* E. e! C" s
  7.             echo 'dog life!';
    , e8 A' G$ H8 s% i0 L
  8.         }' L+ S5 _) u; h! f0 M3 G: [
  9. }
    & T4 u: Y3 ?" ^8 H% x$ V
  10. class Dog{
    6 }) W3 ~- w2 }& H7 u
  11.     function __construct(){
    7 [! Y  K8 e6 `$ q9 u% N( W
  12.             echo 'dog in dog!';2 j/ K& \. T6 L: R# a( q0 c9 p- w
  13.         }; X; b4 W- g% E9 d; E% B. R
  14. }, q% _3 H7 H4 v+ [; s& e
  15. # C5 h) N  Z; O0 y5 ^
  16. namespace animal\cat;+ ~' u. B3 ]3 j+ {) l4 c

  17. . q) v7 W# z$ N. p# H6 B( a* h; S
  18. // class Dog{
    $ T, L7 c& R, J) D6 q' h6 {
  19. //     function __construct(){
      ^, H$ c! n7 [. {3 J) ~1 V& n
  20. //             echo 'dog in cat!';
    9 ]! |5 G" }, j5 U
  21. //         }; S# p; ~& ~' q/ J' x
  22. // }- @1 U6 U1 V. y6 Y! R" j
  23. class Life{* e6 u1 a' D$ C, A3 G
  24.     function __construct(){8 G6 K4 v/ `/ g$ `- |
  25.             echo 'cat life!';3 C& O: ~; _$ a% K% `
  26.         }9 k+ A- \' q' T
  27. }5 N+ q9 a$ n2 i% P0 _  V

  28. 4 C& |) }" B$ W/ _5 @
  29. use animal\dog;  
    8 @# @- ~- U( d  [; @
  30. new dog\Dog();
复制代码
! E  b6 A0 @# Y' Q0 y+ ~7 h1 l- r
如上,使用了
  1. use animal\dog;
复制代码
$ _# S9 ~, r, q) s
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

( \- F7 o( u2 C( d  H5 t
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
3 P" i; R' R, V, N8 M  [
' `' u: W- c# L  p) V

! e$ M7 k+ C( [
$ d5 n7 A. j! p5 S9 \$ H6 [& Q
9 E2 q0 J6 y- B1 M
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 13:01 , Processed in 0.053111 second(s), 19 queries .

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