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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
5 ^1 L& e/ z; {" U
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
% v0 s, ?1 f  e) I; r# h

7 Y% f* M$ K: ^0 P9 h6 g使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
& W7 Y" f& l1 `( T5 X
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
9 S- y1 j/ ^1 ]" ~# e
结合使用方法来进一步理解它的使用目的吧。
% h+ t" M- G& l" ?" y* D

. g, z: ~0 P8 A, ?8 ^& S& bnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;/ c( {6 y5 R$ m* y! V! R. P
  2. namespace One;2 F/ I( h4 b. ~( H/ J4 h  n
  3. namespace ONE;
复制代码
$ P: Z0 Z, F9 a6 L: p2 R
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

' Y5 ~8 s3 v3 I, X2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   % M! Z# z: }: u# W' [: f
  2. class Person{5 b) a2 |8 j) P8 y
  3.     function __construct(){
    * j1 O! g7 r6 W& v: z
  4.             echo 'I am one!';
    , J2 d0 f5 Q* }4 ~' b- i
  5.         }
    ; T9 ]1 u3 o. j  y( Y3 Z
  6. }
复制代码
  1. //name.php
    9 P+ \& Q$ o1 E1 E% x* j8 |
  2. require_once './1.php';$ c4 M$ ^) j- `! y' W% p9 O. G

  3. + r" Z7 y7 R  |
  4. new Person();     //输出 I am one!;6 V& ^4 z9 I2 ~4 |9 F* }4 {5 O# b
  5. new \Person(); //输出 I am one!;
复制代码

: Q# [& {6 t. A0 v/ O4 }3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php2 }: W( E2 r! ?9 ~! |
  2. require_once './1.php';
    . u  C  _. k2 l9 u, r
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
. k" o2 [/ D. d; a
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   % `+ ^6 e3 {8 \8 C
  2. namespace one;
    ' r! n$ @% ^4 x) U2 ?
  3. class Person{0 M" s" o/ p+ O
  4.     function __construct(){
    9 S2 h3 S% [+ ~1 l8 i4 i
  5.             echo 'I am one!';1 D4 b  r* Q& G7 |* Y* [1 A
  6.         }5 e% P6 s( _$ \! V! C0 @
  7. }
复制代码
  1. //name.php6 T8 r, {* Y7 F' Z( {0 M& V
  2. require_once './1.php';
    % R1 _- B) F9 }* a; w# \0 M
  3. new \one\Person(); //输出 I am one!;1 H+ u1 X+ J4 n! |4 L3 i
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

" \; K# u9 x( A- c
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

- u7 M4 N' H8 R" {. s9 H0 u! W% {5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
1 ^& J( w9 R9 s4 \9 Q2 ~
  1. //1.php   
      A2 c5 y* b6 d% N0 q' G
  2. namespace one;8 Y; y" T. F+ P: E1 I
  3. class Person{( L  r" q9 p9 ~, C3 I% S
  4.     function __construct(){
    $ p5 p$ g& J. E! M* w
  5.             echo 'I am one!';
    * r0 y9 n- C1 Z  O
  6.         }
    8 P: z- o* {6 F2 x. {
  7. }
复制代码
  1. //name.php+ ]* [1 z( x1 Q; ^: D7 j5 c/ j
  2. namespace test;
    $ E2 n3 K7 ^# F# j1 L
  3. require './1.php';
    7 T( _' y6 ?# L1 Y2 O" _6 H! Y
  4. new \one\Person(); //输出 I am one!;: }( S! [, Q9 p" D5 P
  5. new Person();      //这里结果会是什么呢,猜猜看; z8 T9 s4 I$ {) _, K8 {0 X
  6. 最后一行结果报错:8 M9 ]* K8 C$ `% r3 e
  7. Fatal error:  Class 'test\Person' not found
复制代码
5 i( c0 K5 K9 h

& f9 e8 S) _: }7 Q, B9 M7 B首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
( b  j: I8 g, _
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
: F- y) _# c- _6 R( X" B* X$ D
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    ; y+ t0 \6 s! z$ E, `
  2. namespace test;, S1 f; t7 m1 m; n
  3. require './1.php'; . V$ E6 ~% Y7 l; W+ S4 X
  4. 2 w6 E7 b" i* m+ `* }
  5. class Person{
    ; L7 @7 d, |. D# ]9 [/ M
  6.     function __construct(){6 }- m$ A* i: _* P7 k. X/ r
  7.             echo 'I am test!';
    . z9 Z1 c  `# m
  8.         }) ]9 ]8 m6 e5 R! R4 F/ n$ D/ e5 n
  9. }
    0 x" ]  F) Y0 r5 l$ f: H
  10. 3 [+ F, }, i! k4 r# {) W! @
  11. new \one\Person(); //输出 I am one!;
    * G2 _' H4 G2 ^7 J& Y
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

/ }% k9 }8 M3 r; ?9 M. \' y
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    ' f+ C& ]3 B5 p, ]- a9 S/ k
  2. namespace test;
    ( |- |9 A! R# k
  3. namespace one;9 Z( Z& _7 ^. v! H9 N9 ?6 I. [
  4. class Person{
    ' |1 _* x; t) Z% a4 c' T/ @
  5.     function __construct(){% i; k2 L. ?+ n% i
  6.             echo 'I am one!';6 f: v+ W- p; \$ O& ~
  7.         }. k( i4 {  I. ~* P9 r
  8. }# l8 f' f6 E8 v  i" }$ b

  9. . e" F- m8 }! u6 s
  10. class Person{
    7 x; D+ e0 U( v% h6 n7 w& A
  11.     function __construct(){
    , p2 r: A1 G8 @$ u
  12.             echo 'I am test!';! \- E% s4 N+ `$ `0 L
  13.         }
    1 u& q! ]& E& ^; R4 o) {: I
  14. }
复制代码
' p. `, U8 y, G1 k
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
  `# F% r( s  }. o3 X% u
看来简单的把require理解为替换,在这里行不通。
$ ~7 n2 L; q' [. ~0 x* R6 E- M
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。7 i! A6 J5 m8 W( r: Y
  1. //name.php( n3 O& f2 x" ~: r1 h
  2. 8 j6 y' q# J; b- y8 i7 U* O
  3. namespace test\person;
    : T8 @7 ?& ?# C

  4. ( I, K1 _) V8 ?
  5. class Person{
    ) Y$ D- s+ E! b. ^
  6.     function __construct(){
    $ l2 Q8 D/ W9 N7 w1 m4 u" c
  7.             echo 'I am test!';
    : z4 |3 L$ z* ^& n
  8.         }
    & x  P9 U  Q: m, x
  9. }- R* l' h; R6 p$ `$ y
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
+ F( S+ \# l, u# i& R
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

+ J; s- l0 d; K( N7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php; m- F5 p8 `, u% i9 K( l3 M) c

  2. % u6 M9 [1 I8 C- M; }* q* {/ [
  3. namespace test;! n8 \4 ~6 v& S9 W
  4. echo 'zhai14';  Y* v% r# r- ^
  5. namespace zhai;
    ) G% o" @" _& u3 q+ d" a
  6. require './1.php';
复制代码
; M' K1 X0 ^" n) m' W1 f+ j
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

$ v: H  y( {7 m. q0 cuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
$ J  U6 i) g$ c( I( S2 M
  1. //name.php3 T/ }3 _9 @3 ?! r
  2. 1 E' c, R' d/ p' r+ z# Q7 g$ h
  3. namespace animal\dog;
    4 V" y  f5 Q8 j9 ?; d& i3 I8 o

  4. 2 E1 k, |/ J! y! Q
  5. class Life{
    $ V+ }% w$ U. _0 _- z. O& C* R  [
  6.     function __construct(){  z  n1 q6 T; d% e. D
  7.             echo 'dog life!';! u5 b! {( r, [0 B; L9 N
  8.         }. b( f) L" X7 J
  9. }
    : ?0 O0 r5 {3 `3 _* Q* X, S

  10. ) H3 ~+ a) d3 H% n: S: J  I8 |
  11. namespace animal\cat;
    ; H+ s1 \# q& x- I' W. s# w7 N

  12. 4 m6 ?& k2 ^/ p9 F
  13. class Life{! b5 b* g' H' n- m1 @& a% g
  14.     function __construct(){% }- X% _0 W) a! u* a
  15.             echo 'cat life!';, e/ j/ ~  e' c  N
  16.         }' _% `4 N9 ~4 N7 W
  17. }
    # I) M  [  o, f6 Z
  18. " S( @: @' h' A2 ~
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间* Q2 O; `# G) y2 [2 V" {$ F: U
  20. new \animal\dog\Life();  //A/ [( h& V( @9 g, f; J, V6 P4 B
  21. 8 [$ w8 N- s5 s4 l
  22. use animal\dog;  //a
    9 C: g! i. I! T* E. j4 z+ x0 D1 @
  23. new dog\Life();  //B
    2 B) p' j/ T5 ]  Q% z

  24. 8 I, ]( k: [5 U% Q; {6 j7 F0 V
  25. use animal\dog as d;  //b) r0 d! ~" v# w! }% r: O
  26. new d\Life();
复制代码

/ V' t0 f6 r* C0 L+ a
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
) K# J* L( p- C* m) N- W1 F
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

6 b. S$ C! S3 G$ k1 ]
相当于
  1. use animal\dog as dog;
复制代码
, S- z7 C9 W5 U& k3 I
2.namespace后面不建议加类名,但use后可以。8 A2 }/ D) Y& I) Z; J) Y
  1. //name.php
    $ O9 \/ E) g! {( T) o" r4 H1 q$ ~- x
  2. ; A# {/ g2 R/ |! i( j( G0 p
  3. namespace animal\dog;
    6 U* I3 _7 J6 d- y- l8 ?0 p4 s

  4. 2 N0 E- v( |' e' F' v% {
  5. class Life{
    ( e- M0 F, p) ~2 t6 L2 a! h4 d
  6.     function __construct(){" x( M& n4 s: J, i
  7.             echo 'dog life!';; t' [+ C6 L/ u$ L  B1 L' n! {/ Y
  8.         }
    + l9 @$ |  Y, E3 L5 R; H& D& t! `
  9. }; h6 Y  N: g7 r3 F
  10. ( [/ U/ t8 g. b6 V1 o* b% e. ?
  11. namespace animal\cat;" G( X0 \. D* l

  12. 3 w3 O. L2 O. p6 A: P; B
  13. class Life{
    5 M( a: ]: w% x# _, u
  14.     function __construct(){7 t. h- p- R  Q' m6 p) H
  15.             echo 'cat life!';
    5 q* y6 u6 X' E
  16.         }
    ; S! t( b; s8 {2 f/ _
  17. }: K* t9 ], M  g* {2 s
  18. . R: g+ X1 L% Q. y) a
  19. use animal\dog\Life as dog;  1 q) m. X- {; g% g
  20. new dog();
复制代码
6 o7 ?( d! d6 o7 i. R. X. z& T
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
7 K. T5 y0 x& C: {; ]" k; r( n
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    * [1 R( |7 R' l* t" e
  2. 7 R" s; S5 i( P" _* v) b, |
  3. namespace animal\dog;
    - |3 s+ V: y, u6 u

  4. - t- C2 K+ A, X
  5. class Life{
    ' x$ V5 y( v# Z/ A" r0 D
  6.     function __construct(){
    : ~/ V: B! [, K3 W! \' o! v
  7.             echo 'dog life!';5 S, t3 e& i+ Z' A! K& m
  8.         }. P/ N6 |6 ?: f8 V" Z
  9. }
    7 o9 Y4 ~! n/ k: y
  10. class Dog{( ~0 `" y) ^8 I! G  v
  11.     function __construct(){
    : V' h# T* b3 ~! S
  12.             echo 'dog in dog!';
    5 v, N- J3 b  v; |& g
  13.         }
    ) B( y" G3 O1 ?9 Y* T1 b& E$ ?
  14. }, h" h8 n$ D3 n

  15. . k; t! f; e& V2 k: w' |
  16. namespace animal\cat;
    " W1 F1 M2 ?' U3 m3 n

  17.   H1 K0 P2 w# K' e/ i) h7 q
  18. // class Dog{
    ! Z& R' l  B3 w# c
  19. //     function __construct(){8 O, q3 h/ J: |& a
  20. //             echo 'dog in cat!';. \7 q+ f% R' o6 D7 I
  21. //         }
    ! Y3 b, F, R% Y5 V& U
  22. // }8 F# k1 H: P- X0 u4 u' s5 N4 X. }
  23. class Life{
    $ P7 ?5 M# c' c! U; F; e) r
  24.     function __construct(){
    ; @: `) \/ ~8 R4 n( D, h8 ?
  25.             echo 'cat life!';
    ' E: u, o" G) g6 m5 m# K
  26.         }
    2 E$ O/ {* {/ Q, [
  27. }
    $ r; U8 C% B/ Q! F
  28. ( b4 i3 U1 k9 A5 r  ]4 ~% J8 o; ?1 V
  29. use animal\dog;  2 F. z- `4 I$ }1 J
  30. new dog\Dog();
复制代码
2 C  \: d5 w# k; _7 a9 R
如上,使用了
  1. use animal\dog;
复制代码

6 Y& }: H  i0 d$ `; W' w1 i
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
4 E% Q- W4 m. C7 k6 ^: W
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

! C1 _, y  x4 B4 W
' r6 S& W8 m4 R; g1 C0 I
1 g8 ]0 h3 |2 z( I% M; `1 G7 _. d% N( U$ W
( M3 t. n6 n: a8 W/ M; u
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 11:45 , Processed in 0.060345 second(s), 19 queries .

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