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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

' w; I4 M& I: l  \
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
0 R6 U  E0 Y5 O" g3 O# \# T
& [1 V! [: h# S4 M8 |) N
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

+ m, I. H' V2 ?- r结合使用方法来进一步理解它的使用目的吧。

& G& {9 |9 U' Z8 w# s
8 n' M  r( e1 `namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    # e$ m+ [* h  q0 p- n% t
  2. namespace One;
    6 F" {# O6 M* x1 e, B
  3. namespace ONE;
复制代码

8 e& t3 g# j. U6 S" I7 \  a
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
: V# b, f+ Q  C/ O& X
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    3 v0 A# ?9 t5 _$ C# f5 Y
  2. class Person{
    , k: ^. v+ u/ D6 q
  3.     function __construct(){! y' J& v+ N9 l2 ?  _: j
  4.             echo 'I am one!';/ p; Y5 w/ k+ R4 D; ?# Y. k
  5.         }
    3 H+ ^5 y: V# F, [; v. o
  6. }
复制代码
  1. //name.php
    5 Q6 Z2 I$ Q0 h
  2. require_once './1.php';' c' g  f4 i5 W* I
  3. / o4 S( `1 t9 k
  4. new Person();     //输出 I am one!;
    # ]8 B. G) @) g# a+ |& X" Y
  5. new \Person(); //输出 I am one!;
复制代码

" F3 d% `' w( ?; }# q( \% A. O3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php0 Q4 E+ X" r2 E* {
  2. require_once './1.php';
    . f8 J: N% z" j( `2 x
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

; J! _% n1 W) I" f8 S" b! s4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    " M3 U$ y! Q' I; N
  2. namespace one;
    6 @( J" y/ W) M
  3. class Person{5 }7 v' D! c8 g1 X
  4.     function __construct(){3 z! }& F5 l9 g6 M5 D8 Q6 z
  5.             echo 'I am one!';
    4 ^( _$ b1 t( Z: c' Y, M0 K
  6.         }
    ; O6 j% D3 x$ H9 f) b
  7. }
复制代码
  1. //name.php- U- i3 b: p3 Z5 m5 X% r
  2. require_once './1.php';: Q; m$ w# P5 @( r2 D4 @9 J
  3. new \one\Person(); //输出 I am one!;% e. D( f4 t  G
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
& ~  G0 {: V0 x* M
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

! @3 U* {! E" G5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。3 E$ }8 W9 F# M' z" w
  1. //1.php   
    7 `# O, {1 E7 h' J
  2. namespace one;
    5 ^1 c; a! Z, H) Q; P. x
  3. class Person{
    2 ^; W8 k4 p6 ^% ?7 S
  4.     function __construct(){, u/ x; j$ r% l) a% |
  5.             echo 'I am one!';
    & I$ ^* f! d4 o! `& h8 Q
  6.         }! y* t4 Z% O4 ?# N' f% S, V
  7. }
复制代码
  1. //name.php
    5 @; L! S3 e- P6 D  o8 I5 l
  2. namespace test;0 p- w  `% h, L0 m
  3. require './1.php';
    $ K2 V0 j3 o, m  i
  4. new \one\Person(); //输出 I am one!;2 I9 y( n0 r3 d
  5. new Person();      //这里结果会是什么呢,猜猜看7 {4 r- t: v, F) k
  6. 最后一行结果报错:
    5 Y6 |  F9 H6 K5 e
  7. Fatal error:  Class 'test\Person' not found
复制代码

" e8 H& L# q7 s3 T/ A% n
% g) _$ J4 J2 Y- \; p( F% d
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
* X8 o2 ~! H* H, v6 D' h
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
- P9 }5 |7 r- S% o
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    & |5 ^2 n2 _- L0 x; s
  2. namespace test;
    # a* N5 k- p! X
  3. require './1.php'; ( [& `1 _  @: s
  4. % E7 d$ Q! ]) s1 Z1 E" [
  5. class Person{9 Y' U/ ?6 R" @0 K
  6.     function __construct(){$ f% H* `4 S# ]9 x) o" q$ }
  7.             echo 'I am test!';4 j. `0 ]0 v5 f' y
  8.         }
    . J! `) \# @' ]' j
  9. }+ |1 S' t' t! d' W- g
  10. * \7 d& t; ]; o7 \* W
  11. new \one\Person(); //输出 I am one!;
    7 b! ~% z( |# X
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

$ _) k/ h! g# Q, r
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    3 y  d9 G' K0 L& ]) O5 R; l5 n; d% W
  2. namespace test;
    2 N7 B) ?6 R7 N4 q: _
  3. namespace one;
    ) X) w2 g2 M. Q/ F. L
  4. class Person{
    - ~+ m8 z& f0 ~; n0 H1 S$ U
  5.     function __construct(){  J2 a5 L" \5 f5 j, n4 X
  6.             echo 'I am one!';
      i1 z3 P) V! q$ `; s1 B( f9 T( f
  7.         }3 t  M+ A/ ^: ]6 u1 C$ F
  8. }2 m. _6 y! R$ c2 m) }" V- L

  9. ! a) A& j" N8 l/ [0 ^4 {- m" R9 D
  10. class Person{* h6 V& |, p" B) H2 {
  11.     function __construct(){
      E# d4 k; G6 K0 H1 ?  }( }* e
  12.             echo 'I am test!';% j' ]# X1 p- Y5 C' A& t1 u! y
  13.         }
    3 m8 q: P( c3 x- ], g8 Y
  14. }
复制代码

+ J+ R5 H. D* `& _1 ~- \0 {
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

& y7 b1 S- f8 X+ d
看来简单的把require理解为替换,在这里行不通。

0 ^# m1 f2 s1 b# |2 ~6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。  T/ _6 Z1 I1 [
  1. //name.php; f4 o5 c: O+ F2 c- p! V* i
  2. & P4 s! J: z' S
  3. namespace test\person;
    ) j6 C! i% f1 h- R- z& M3 [

  4. 8 R, ]5 s: A! X) i4 {
  5. class Person{
    : }6 D9 a( n4 h8 n! z& Q. w$ P
  6.     function __construct(){- R9 l0 S4 G3 t/ z; N4 [
  7.             echo 'I am test!';
    9 H. A* q. |: ^7 K) O
  8.         }5 n8 ~  y$ G2 \' b4 b* @
  9. }
    6 q% P/ L! O, p+ ~
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
3 e( R  ]2 f( @; z& l/ n+ R4 B; r
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

. ?( C5 {# q2 U) z7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    2 {# q, Q3 E4 V! }& D& l

  2. 5 _$ V% D- |; r+ G$ Q2 p, C  o
  3. namespace test;
    5 u% Y1 g" d6 H/ X5 I* \: [
  4. echo 'zhai14';
    4 T; M6 @- I% }! F( a: d
  5. namespace zhai;
      B  @! m( ~, V  y3 P# l* o# ^
  6. require './1.php';
复制代码

# A8 C' G( e, C* {
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
" p3 K# o& d. l+ a
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。, P3 `' b  X+ t, ]* R3 f
  1. //name.php0 o1 u! G! P; J5 L. H- u
  2. : x9 E# j3 H9 y0 Y! j9 J$ Q
  3. namespace animal\dog;. T- @4 E2 R, w3 m+ @
  4. * R. M+ j4 r% u1 {9 B
  5. class Life{
    . ~2 C! r. _: G
  6.     function __construct(){
    : K' L( \6 L  o+ `
  7.             echo 'dog life!';, E  S/ o2 ^$ H( v6 d7 d: f& A
  8.         }% ~5 q) h1 F5 r7 z5 V, u
  9. }  c; q! i. d" z( U

  10. & Q+ }- t; {- h0 @/ w+ k- G* X. q5 a
  11. namespace animal\cat;
    - H" f5 v6 S. q  _% L% Q

  12. 5 v/ p  z, O0 g
  13. class Life{
    6 N/ D1 N, J3 u' x
  14.     function __construct(){; b1 r8 g4 u% I# T# ^& f
  15.             echo 'cat life!';4 S! J# O& S, b7 R
  16.         }
    7 W0 W  l( @* S* [
  17. }) o1 L2 D# `0 Y. ?# [2 w  F3 i9 E
  18. ' q" e  ^/ Q0 ^8 U+ z
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    - m1 f+ N& ^$ g1 b; F/ J
  20. new \animal\dog\Life();  //A4 o: r9 a. ~3 Q7 e/ {+ @" y

  21. ( O8 n7 z8 T/ R) p5 F; l
  22. use animal\dog;  //a
    $ i: Y1 L4 c. ~- o; d) V3 Y
  23. new dog\Life();  //B: \  A% S8 C. R: }) c7 N

  24. 8 v9 P4 B( r- z0 h% @3 Q
  25. use animal\dog as d;  //b8 R8 I4 g) p2 t0 n3 i4 C9 D
  26. new d\Life();
复制代码
4 B; V' B5 n) E
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
3 ]( M9 x* z; `
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
- e% T) L# e& y* O( y
相当于
  1. use animal\dog as dog;
复制代码

+ a) r4 b' h8 |/ V' Y9 r6 i) j0 r2.namespace后面不建议加类名,但use后可以。- K  W- @, ^& n, m$ v
  1. //name.php
    4 ?4 v- U4 ~% P$ j# o6 ~1 Y4 s
  2. ) [6 C1 C; @% x$ g3 k. E& o2 i
  3. namespace animal\dog;. m( J7 \/ H+ }2 ?: ]: B# C
  4. + B4 B- U7 i, w' E+ _) `8 e4 y
  5. class Life{$ a' `( B2 y) L% V
  6.     function __construct(){6 f& _6 ]9 d/ F9 U; j" {& h% v
  7.             echo 'dog life!';' y6 \% S2 b2 L* H
  8.         }
    ; k& I; W5 m) M1 Y  Z& i5 i) w
  9. }0 ]/ b9 J; x/ Z$ u' T

  10. . i: ^6 u2 G+ i6 v" b, c# n
  11. namespace animal\cat;
    * b: H1 j' W/ W( f) d+ @% s* O
  12. " A. [# b% I; v- e+ e& u9 P6 O
  13. class Life{  D# @6 H& _" l, x
  14.     function __construct(){
    % \7 o8 U0 K! S% c7 o  f
  15.             echo 'cat life!';
    8 q4 {+ x! ]6 a
  16.         }
    5 Q* X% p3 c0 Z  m$ S) f: |
  17. }$ p" H' L- L# R6 j5 R# n
  18. 6 ]4 S6 Z2 Q0 T" i
  19. use animal\dog\Life as dog;  
    - p' q6 I- I4 P4 @5 ]
  20. new dog();
复制代码

4 ^; _+ Q) \+ C& u" F  F
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
, r3 A/ R* b8 A
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php1 N9 E- g! B) J; K

  2. 4 a( l5 w5 y* s% N, ~, k. ]
  3. namespace animal\dog;) |$ `4 ]( a$ u

  4. ; u3 n4 B0 q% w# A' L
  5. class Life{6 I# g# i+ h4 S  ^0 y
  6.     function __construct(){* ^" D" X; k. N/ c+ s6 p& ~
  7.             echo 'dog life!';
    & q' ^9 X- b( f0 s* R( r( m: }- l
  8.         }
    ( s& l# r0 ?; a
  9. }
    ! n, Y0 p! {6 |+ k6 \
  10. class Dog{% a8 K# v" Q% i1 o. u
  11.     function __construct(){
    2 q, b5 @! e$ k: q3 b
  12.             echo 'dog in dog!';+ V. Z) v; m# X! y6 a* c/ b* c2 v* t
  13.         }
    - `* w8 n) @1 }  N
  14. }
    % l% i3 E2 l$ B$ T% `

  15. 3 X8 o" P/ F( V: `7 j
  16. namespace animal\cat;7 W5 o$ Z  K8 P! m' e" H
  17. 2 M" V6 ~8 E+ ~0 g. E
  18. // class Dog{
    4 C$ o$ U/ p9 `
  19. //     function __construct(){
    3 H7 r, l2 W. j3 q% m
  20. //             echo 'dog in cat!';
    " F8 y, d6 y' p, ~9 N- |
  21. //         }
    4 J  A, O1 F6 y8 \
  22. // }
    $ k( {8 b0 M# A& A! x' }
  23. class Life{; @# i( s( j- j, _6 U6 q& a6 I
  24.     function __construct(){
    1 ~% \. _' ]( E. v0 ?$ y
  25.             echo 'cat life!';  ~' R. _! _$ I( b% u5 O! t0 R
  26.         }* V! J+ `* i8 c/ n: s% M' e5 _. @5 u
  27. }
    / a' E" [  ^0 ^8 H* n& J

  28. 6 |! C: L9 H+ r5 g) M" _% [
  29. use animal\dog;  
    , D) J. f) w! F/ D6 n' f
  30. new dog\Dog();
复制代码
6 P( h: ?7 c; q, n) L+ p
如上,使用了
  1. use animal\dog;
复制代码

( C: j7 Q4 p0 M$ G5 @* D0 F$ H
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
# c4 J9 d5 R9 E) I6 S
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

: ^# ]3 J+ \4 D, |% L* ^0 d6 f( v7 _& s) t; D  O# W# |

+ F& a' A! I- j8 a9 |3 H. x( Q1 Z- o; c

' i( O& i' r) @' y' }
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 03:15 , Processed in 0.058066 second(s), 19 queries .

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