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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

0 q" Y, ~( z# K* [
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
) A# o( Y. m: B8 ?. G( F2 H

8 T( P- o) G2 A- D  O使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
1 L: m) u, s) Q; s& f
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
) ?# \  L+ C8 N) c
结合使用方法来进一步理解它的使用目的吧。
" s+ o# u: U2 ^+ n  f7 A+ g3 `- a- V

  c6 @  B- o& I3 Inamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;7 B# m8 i, l& v* X) |* e& ?; H
  2. namespace One;
    ' x: e1 J6 |4 X* M5 J4 K; w, c
  3. namespace ONE;
复制代码

1 ]% Z$ q# b# t7 T" N
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
7 \' B  K6 P, E" d4 q9 k  ?
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    8 j+ X% `/ u- x4 y
  2. class Person{( Q, B# `* j1 w/ N
  3.     function __construct(){
      ]0 x( n$ `! v! ?8 V' H
  4.             echo 'I am one!';
    5 O6 t& Z7 x1 f& E2 {
  5.         }) l+ Q4 T! a# O! y4 ]$ Z
  6. }
复制代码
  1. //name.php8 Q6 F  H4 Y5 N
  2. require_once './1.php';/ X4 _( X0 i: s4 ^

  3. 1 w6 G& O1 e  R2 O4 F8 M$ B
  4. new Person();     //输出 I am one!;
      K4 m$ g" M. O2 s+ D3 ~1 V" \
  5. new \Person(); //输出 I am one!;
复制代码
  U* Q. D& D4 D( Y% Y9 b0 Y. }
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    ; |8 R& D! W  [
  2. require_once './1.php';4 I7 P6 }+ P8 ^. J# J! Y4 d" l. q
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

. O" a7 K: B3 s8 B/ m2 u, \) |4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    ) s* w6 [2 s; L- {4 n9 r
  2. namespace one;
    1 ^( g1 P$ s% ~, `2 v/ p
  3. class Person{
    " x% E# I0 g/ {" N4 d- N3 x4 r. A
  4.     function __construct(){1 j3 c8 @. o5 _7 v
  5.             echo 'I am one!';  U8 z! |& a1 v  O8 ^. ]( \
  6.         }
    6 h: E3 D8 B. I9 y( Y, @
  7. }
复制代码
  1. //name.php" h0 a; U! W& e& {1 D# {* }
  2. require_once './1.php';
    * ]8 X: Z( `' H
  3. new \one\Person(); //输出 I am one!;. b: {, I) `) Y" b$ H/ @
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

& F) f' P" B$ H6 t
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
% L/ ?( ^) Z5 q3 W, R9 e
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。! Q+ n) G: J0 c
  1. //1.php   
    ; K% t. U" q/ U3 _/ \
  2. namespace one;
    4 N4 d2 M  E7 P4 A1 F& F
  3. class Person{
    # Y9 R5 V! G3 o' g  x0 w! H
  4.     function __construct(){: ~2 a. S' ?0 o8 L5 ^8 W7 W
  5.             echo 'I am one!';; O/ F- ]9 \( J9 G- ~) T
  6.         }
    7 C/ ]% t+ a; D; T  j9 x$ |
  7. }
复制代码
  1. //name.php
    5 Q) S' H; s" l' x* `& M
  2. namespace test;6 Y$ X. W+ S8 C+ V& x2 B
  3. require './1.php'; . ?/ B. E  `, G
  4. new \one\Person(); //输出 I am one!;
    ' A0 T3 i2 E2 {! x4 y
  5. new Person();      //这里结果会是什么呢,猜猜看0 w  f9 F# s1 x/ d! N
  6. 最后一行结果报错:( g* a( y: m: r* y4 K; i
  7. Fatal error:  Class 'test\Person' not found
复制代码

  r( \& |% C2 ?  P: j

5 k4 u' }: l) {' p2 ^% M4 n首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
1 r% Z5 I% {! e5 k& k
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

, t' e  ^! v% T
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php8 j! a2 H0 p1 `  }9 n/ U7 p( `( x
  2. namespace test;1 A3 }* |( G% B/ ~% m: C7 v
  3. require './1.php';
    $ c+ J1 y  ^$ x1 q/ B" v
  4.   k( Q" L  f9 U$ F% z5 R
  5. class Person{% q! A5 M4 t& B$ D7 j) Q4 u
  6.     function __construct(){! r0 p' B0 _7 Q  A# I( v) Q
  7.             echo 'I am test!';  }1 H* d3 x' H) `9 V
  8.         }
    : y; Y, I: i/ C7 i2 q2 {% w6 O
  9. }' P% Q9 i( d9 W  i
  10. * v$ U" T: z4 |6 W- H
  11. new \one\Person(); //输出 I am one!;
    7 ]" x" O" Q$ H  [3 V% ^
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

$ V$ l# _3 q* G" m& q; C, l( E
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    - r" `. f6 ]6 K1 d
  2. namespace test;1 v) @) `4 `: S; [7 P8 P. F1 J/ _" Q# t
  3. namespace one;
    3 k$ j3 ~; v6 r; |/ y
  4. class Person{" {. {# X6 @1 _: l, w. i! N7 j
  5.     function __construct(){
    - i8 l- V7 J$ W
  6.             echo 'I am one!';
    9 G9 l( _: p6 O& K( o3 M
  7.         }, I. Z3 F4 p4 Z" `8 V
  8. }% ~  f- G( g8 W  a0 g5 S
  9. 3 [0 Q. q$ e" z+ ]3 b/ d+ M6 d
  10. class Person{
    : c: |8 B5 I( V- m
  11.     function __construct(){8 ?+ _! f9 {1 P5 L
  12.             echo 'I am test!';
    . l2 r7 J. M) C
  13.         }
    $ L4 Q( q' _5 i6 u/ n3 I
  14. }
复制代码
5 H% f; r' a! @" N3 l' O2 r
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

2 [9 g3 s4 |! c5 }, j9 }7 o
看来简单的把require理解为替换,在这里行不通。

0 Y, R0 @4 h2 F$ d* h6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
8 X+ V/ N. Z1 [: [! E
  1. //name.php. e8 P1 D1 @! |% {* M+ o
  2. 7 d1 f: E' ?* n' |% L: V; h
  3. namespace test\person;8 T- U/ h2 L1 b$ S* U6 K

  4. 0 j" Q& L& t0 B* H3 P8 L( E' W
  5. class Person{$ X& s; j  U; D5 y( h# O
  6.     function __construct(){$ {/ P( i5 G# V$ r8 o9 u$ `! x
  7.             echo 'I am test!';5 Z/ F% s" S- i, r+ i7 h6 d
  8.         }
    ( @2 {/ n9 t0 N4 k& |% W! M
  9. }% p/ L) [: S7 J7 E/ O* n8 _
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

$ s) Z) d  u  v# ?$ S% F+ g
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
1 N, ]$ `5 a' e; ?2 g4 z
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    1 |# P. F) W8 w
  2. 9 F+ U/ |( y& G
  3. namespace test;! q1 g# g% h. i* Q( i* w$ Y/ k4 y9 h
  4. echo 'zhai14';
    4 H( d) W. }6 R; n* D4 }
  5. namespace zhai;1 ^8 t& A3 X, G7 L8 s& ^9 M3 K3 ^
  6. require './1.php';
复制代码

" K  l: X' P) y( a
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

0 f7 l3 `3 {/ @: o) l: luse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。8 q( L/ l6 M2 Z6 l3 F
  1. //name.php: k9 U+ L% l  Y

  2. 6 {0 K8 G5 t' ]5 Q; G; D) J
  3. namespace animal\dog;
    + Q% N5 d6 {7 ]8 L" J) ]
  4. : Z/ I( d3 d7 G' f* e
  5. class Life{
    3 g( E& D7 D0 W" u& \; O! m) N
  6.     function __construct(){7 ^5 q% H2 k* C% Z# `3 C
  7.             echo 'dog life!';& ~) }# d( a5 ^0 X% C: h8 h! {
  8.         }
    ; z0 j" I$ S$ X. L% R0 h" N! A0 y! ^, _
  9. }
    5 U. i; l# N4 H9 [' a
  10. 4 H2 U. T0 k% L/ O+ P
  11. namespace animal\cat;, U! A3 g) r' i4 a0 C: `( c3 L

  12. & e% o! O- u  b5 S' l
  13. class Life{
    & Z5 ?; L  Y8 x+ P
  14.     function __construct(){
    1 ^" {5 N6 J2 L# O3 c
  15.             echo 'cat life!';
    + V- M" G! G. H7 f
  16.         }
    ( F7 {  U. a2 I" H4 H) n: ?
  17. }
    6 G! Y+ x/ f+ x6 r

  18. ) \2 U% r$ E, s1 U3 D- T
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    . ^  C! d( }6 i# N  c* Q
  20. new \animal\dog\Life();  //A
    - z* n5 ?4 B! E# q; t

  21. 5 k8 U8 \  ~) v' R2 S$ t
  22. use animal\dog;  //a" o9 K9 ~5 B. g3 R! a2 ]  `
  23. new dog\Life();  //B
    1 D' Q) i1 K: u1 X# f5 P

  24. 7 ], V6 J  |% Z5 B, Y1 N' b2 }. C# T
  25. use animal\dog as d;  //b# q8 L, B5 p; |  [6 T
  26. new d\Life();
复制代码

  S$ w" T* N" g4 k7 B
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
( V( q2 }( r. @0 u( m
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

  ~, Q$ a+ a4 b* P9 V' Q
相当于
  1. use animal\dog as dog;
复制代码

* [  t: [5 N- S) m/ D1 O: u; @1 b2.namespace后面不建议加类名,但use后可以。
; e$ @) W8 o* R. o" n: t
  1. //name.php# _/ s! D* `, h- I
  2. 2 ?$ ^* ~" @$ r( c* Y* w( R+ L
  3. namespace animal\dog;
    8 S8 ~6 i$ ~" s

  4. 3 p7 y& U, s. w& H
  5. class Life{
    7 T0 n% U0 l2 }- `" i" _% f
  6.     function __construct(){9 B! f! P' z/ K
  7.             echo 'dog life!';
    6 d! ~& Z9 B7 ~8 h6 s! S
  8.         }% z$ \9 p  ~6 G3 g% Q
  9. }3 o) T3 K+ G8 s0 `/ t; M% f

  10. 3 {0 T& U/ f( \
  11. namespace animal\cat;$ h6 b, l9 \) d! }
  12. . u) G# S9 Y4 D0 X! M! n. Y
  13. class Life{
    . g9 D( T& n0 w( Y* e
  14.     function __construct(){
    ; \( z& A4 q8 n2 Q
  15.             echo 'cat life!';' u1 g- r3 D$ m0 Z  w
  16.         }
    5 `! T7 ~6 F1 |
  17. }# W. O3 B/ a  @8 u4 H
  18. 1 Y: G9 G8 J' D, B8 `# B
  19. use animal\dog\Life as dog;  
    # {# Z$ c! B( Y. G  \2 ?3 X0 O
  20. new dog();
复制代码

6 H& C# m5 [: v* b" D7 g" \4 a; Y0 W
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
0 o6 x( m4 M1 z0 U' E$ C- {
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php) ~2 J& m9 i0 |1 L

  2. 9 K( h& k9 G3 T' K
  3. namespace animal\dog;
    : c4 i. J( ]2 p+ ]$ V4 ?4 }) r5 [
  4. ' ^- w* W9 @- L' a* ~# y
  5. class Life{
    , {; C( t$ n8 O. p
  6.     function __construct(){
    " y! \, H7 ~9 D- `
  7.             echo 'dog life!';
    ! L- _+ I& C) X8 j+ c' T) N
  8.         }5 X( F. o, q0 e: P: ^5 Y
  9. }% L# M2 z, S0 @
  10. class Dog{) o2 W9 M' H7 D9 _
  11.     function __construct(){
    0 T6 x: L# X+ @2 W+ o) k# K
  12.             echo 'dog in dog!';' U1 Y" z3 w6 K6 m7 f" b8 ^1 k8 R
  13.         }
    3 H- c% J$ y# C& S2 m; v
  14. }+ }/ K% L9 x! W6 J( v  ^
  15. 2 y4 m4 y: w7 b: f  a( h. H+ m
  16. namespace animal\cat;% c* Z. J( U9 `

  17. 9 K- u& ~8 J- c" y
  18. // class Dog{# M% ], P/ k  ?
  19. //     function __construct(){
    7 Y$ I6 @# G8 C# s
  20. //             echo 'dog in cat!';
    , M: x! a2 x1 o; S* b
  21. //         }
    . }' p! h5 O5 o; ~5 r) d6 f
  22. // }3 I2 ?( y. [+ o5 D  V
  23. class Life{* b$ p9 D8 m# A0 c0 V$ Z
  24.     function __construct(){
    * V: h( e5 v' ^: k) x$ z9 o
  25.             echo 'cat life!';, s1 b0 j' l6 \8 F8 @
  26.         }
    ) f8 R, `; `2 _/ n! A: N. q3 z
  27. }0 z+ O5 C0 I% }; D6 J& Q
  28. $ B7 k- k8 I" J. O7 B* g
  29. use animal\dog;  
    8 Z# i+ K; r) H  s5 x
  30. new dog\Dog();
复制代码

( C( M' Z- j" k, G  J3 t( F, ~! i
如上,使用了
  1. use animal\dog;
复制代码
$ R5 \/ ~8 w5 g! v
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
8 _% ]$ P0 f1 {2 A$ Y' f
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

9 h3 Z+ d: W5 ^% k: i$ \6 ^
/ }7 d+ @6 _7 Y8 {/ T( I0 ~( ?; v2 B# b% r- E- _4 f

7 v2 b; d6 {# v% A  M& W9 K$ y* B+ M
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 10:05 , Processed in 0.052645 second(s), 19 queries .

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