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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

PHP命令空间namespace及use的用法实践总结

发布者: admin | 发布时间: 2020-7-1 23:37| 查看数: 15348| 评论数: 0|帖子模式

以下皆为本人自我理解内容,如有失误之处,请多多包涵。

4 B, U( c/ x* V+ |, ^5 h8 [$ Y
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

7 S2 E, E4 h* Y( b
. V. v9 W  C7 I( G' p使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

- t' i. @& d5 S结合使用方法来进一步理解它的使用目的吧。
5 q. P1 D! ?& \0 `: U" c

" Q$ u% e# x, V$ U3 n" U( anamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    & `/ Y: {+ v5 I( x' A3 N- |
  2. namespace One;
    8 O! K" w, T, V! c" q" P1 K+ c: \4 E
  3. namespace ONE;
复制代码

, o- ^2 V6 ~) J
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
- u; |' M7 Y, S" x5 J3 K8 o* s$ V- T
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    # e7 y* q( v- {
  2. class Person{1 s1 c- |- {; \0 u1 a. }
  3.     function __construct(){; c  \) I4 z  i6 a: N& o
  4.             echo 'I am one!';
    0 ]9 J/ J' Z( }# }
  5.         }
      N! e; y; E7 {- ~# P* v
  6. }
复制代码
  1. //name.php- @8 F! g7 o* M+ ~' `. x! y* p9 h
  2. require_once './1.php';
      \& P% J/ |; ^+ B- ?0 G
  3. 3 K8 W& G6 P2 O' N) s8 q( e! [' T
  4. new Person();     //输出 I am one!;
    1 I3 v& E1 P" r' c( M
  5. new \Person(); //输出 I am one!;
复制代码

" o5 Z) D  v3 Q! p7 e' @3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php& U: _  z0 t$ ^8 A: p
  2. require_once './1.php';
    6 d0 O3 r( @& j
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
( U0 f! E' U, B4 V% @
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    & A! p0 }1 _  {  e; L0 h6 h- W# t
  2. namespace one;/ s& n1 S) \7 N' g) f* c3 I
  3. class Person{
    6 S5 A+ ?) M# Z; f
  4.     function __construct(){% O  O+ [( V! ]4 r
  5.             echo 'I am one!';
    ) P6 F' X1 @6 r3 J+ C, Y
  6.         }
    ; g! [; W. E# Q3 W
  7. }
复制代码
  1. //name.php- e! ~" s5 \0 h. M: Y5 g
  2. require_once './1.php';
    1 c  Q7 P; o* |% t+ d9 \
  3. new \one\Person(); //输出 I am one!;! M+ a' ]  F* [$ o
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

4 F6 b1 z6 O7 q& p
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
- K* z$ R' x- u# }$ }* F, F; I& _
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
' }+ f  N2 d. h$ z# |: {/ s
  1. //1.php   
    . `4 i5 x* b" P; K0 r4 `
  2. namespace one;( U' K0 F4 W! G
  3. class Person{% F3 x+ _) t, K3 A
  4.     function __construct(){
    3 t9 P( O8 z! T- q0 V' b
  5.             echo 'I am one!';
    * ^! v$ y1 e8 Y9 M* }
  6.         }2 \7 L& A7 D# t1 h1 W/ R
  7. }
复制代码
  1. //name.php* w1 J. m- X1 m' L( n# D
  2. namespace test;# ?2 W& Q+ S0 U0 p- e
  3. require './1.php'; / g+ v, m# X& s& i4 k! J3 @: l
  4. new \one\Person(); //输出 I am one!;
    ; B6 w# `: |) [9 z# L9 A4 e5 c
  5. new Person();      //这里结果会是什么呢,猜猜看4 }8 R1 X. B9 d( J
  6. 最后一行结果报错:
    6 Y3 t0 t) i- \* w* Z& ~
  7. Fatal error:  Class 'test\Person' not found
复制代码

$ i% H" T8 j% p8 @9 a& S8 d7 z
0 M. |  v9 N+ h# G" V' q: e* E
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

: r) o4 t! e+ Z. H# \2 u
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
% w* G4 K' G# y- G3 ^7 ]/ s
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php5 r& a; T9 l; L% m1 D- b
  2. namespace test;
    , o* h( D$ K7 }- a
  3. require './1.php';
    , _' R% J3 I) j

  4. - V2 ^5 L8 W+ ^6 d
  5. class Person{
    ! {) h  K7 e/ p( v% R4 R* i
  6.     function __construct(){
    : ?: X7 N+ l0 D4 B* @( S( G
  7.             echo 'I am test!';9 p# S$ X9 a+ m! _. ~
  8.         }
    8 y9 w5 \3 L) z9 u! }' P4 v/ F! E
  9. }& j2 Y, O( g9 d' Y" H+ N. z
  10. 8 d1 z& d% |% Z3 W. x( Y0 Z1 G# {
  11. new \one\Person(); //输出 I am one!;1 }$ E2 Z5 f- E
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

- A2 j+ C- m7 J: \5 a8 |
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    & c4 K* {) G3 w
  2. namespace test;% _9 K  x2 z4 _8 T
  3. namespace one;
    ' G; ^& u1 z% g) |
  4. class Person{+ P* M* _) ^7 y' ^% x* X4 n
  5.     function __construct(){$ A5 }: y+ |( V$ o) D( G& w1 ^
  6.             echo 'I am one!';
    : z! t0 E" q2 Z3 M
  7.         }
    / C% \3 p) b, S# w0 `, Y
  8. }
    - D9 ~" R: K- x4 D! I, r/ b

  9. , Y1 g" K$ I" a+ p
  10. class Person{
    0 J' Y* A! O% i$ f& H
  11.     function __construct(){
      |  X* p0 S9 X" K9 I$ m. {
  12.             echo 'I am test!';0 \. b( q2 [. P" E8 T9 r  T
  13.         }% M7 t) o* w2 ~8 X
  14. }
复制代码
. [( m4 K4 h& i% S# \
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

& a2 _6 \* ^, P8 [# N
看来简单的把require理解为替换,在这里行不通。
& D7 B' ]6 s5 `7 M2 A% K
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
0 w5 P2 q- ~) V# S
  1. //name.php7 _+ o9 {% [7 B+ i& o' H
  2. $ }0 J, n$ ^1 ?' e$ U2 ?
  3. namespace test\person;6 G: g9 y, p, a5 p

  4. 8 `) A8 B9 y; {; T  V% H$ {
  5. class Person{- c5 w( \, F; c
  6.     function __construct(){
    1 c* a, T# z! [6 G9 A8 e- x
  7.             echo 'I am test!';3 b; a6 o- x& n- L- C2 {  [, H4 ~
  8.         }" P# V9 ?0 T2 _" o$ e( X
  9. }0 a% l& v' m1 g: o2 x# A' r
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

0 T9 s0 u0 d! x- z. i2 A- p# ~
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
0 u- F, q7 z& C( C1 Q2 r
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php8 B0 k4 P+ L' O# c' i4 O, ]7 q

  2. , u  p5 P# s! }1 T
  3. namespace test;. |+ d* S" a- [7 A& S
  4. echo 'zhai14';0 M" l+ k5 l# J3 v2 P' h, `7 O
  5. namespace zhai;. Q% L5 w7 N0 h* J7 i
  6. require './1.php';
复制代码
+ v9 Y4 Z6 C* ^* t
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
# t0 V+ ?5 h9 |! h+ j8 g
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。1 P, t3 x! n) m; l% z: j! U
  1. //name.php
    ! h: `  H8 o) ~/ ?

  2. 7 k$ n: e& h7 p
  3. namespace animal\dog;! o& `" q. O! m5 @3 n

  4. 1 S5 Z. L+ u' ]
  5. class Life{
    7 o- D9 W/ l6 \
  6.     function __construct(){
    9 {) D6 E( n3 [% n# _4 @% ^: [
  7.             echo 'dog life!';
      r, f4 X2 e  q" _
  8.         }
    4 K; d1 S3 m0 h) ?% E: p+ u
  9. }& S8 f# {1 v( e, s
  10. - D; i+ y8 M: f2 r- U) X
  11. namespace animal\cat;
    % K' v- [, J4 ~" P1 L

  12. 1 ]) C) }. L' Y
  13. class Life{9 h  a- N. A6 J$ h
  14.     function __construct(){
    ! `7 v1 `( @1 u
  15.             echo 'cat life!';
    # C; L. s( g% h: j9 o% W
  16.         }
    7 u& V, w7 r) }. z& a
  17. }$ p+ f2 ~* |2 |& H* Q& L# [5 ^) X
  18. & E( K7 Z3 x1 H" s# ?
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间. @# y9 C! U% n- _
  20. new \animal\dog\Life();  //A* Q) z2 s! @$ P3 w

  21. : ?! S, r7 x* @
  22. use animal\dog;  //a# K; p5 |# e8 ^, Z% M7 `2 {$ V
  23. new dog\Life();  //B
    0 t* U/ J2 o+ r. c, Q( r2 D# R
  24. - G) C1 y) G/ r) F0 e
  25. use animal\dog as d;  //b, B( V) N4 i0 b
  26. new d\Life();
复制代码
0 j% x* z: d6 I& P- j3 @6 T1 Y
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
0 |. q% F4 M& w. y  f  ?
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

6 k5 h% |& H$ Q2 c1 o/ u, P- @! g
相当于
  1. use animal\dog as dog;
复制代码
5 w/ j% \0 {! [2 |
2.namespace后面不建议加类名,但use后可以。
$ R% |+ v1 ~) y2 ?( ~/ m' D
  1. //name.php9 L7 i% h& ~8 U! t5 M

  2. 3 k7 I# x& D2 N: B) z5 V: h. W2 S9 O
  3. namespace animal\dog;
    # |+ X! R% M5 I9 b; r/ X- L  ^
  4. : D! i. N% |- O
  5. class Life{0 G, a: w% @6 Q2 u
  6.     function __construct(){# o5 d$ R( K# l2 }$ `4 r, I
  7.             echo 'dog life!';
    . Y2 u# B. B9 r4 A) p: E
  8.         }
    $ d9 v. i4 i$ s! U. z, X# N
  9. }
    1 q4 b. V# v; P

  10. 3 [# l/ w: M1 x$ ]$ |
  11. namespace animal\cat;
    0 w2 P$ k$ V' N7 Y. i' A
  12. 9 F5 a/ y' D, Q! V/ s
  13. class Life{
    2 e' P4 c  K5 C0 C- P! `
  14.     function __construct(){
    . l4 Z: m- k3 }' S$ I& u% @- M
  15.             echo 'cat life!';- E$ B- L/ C+ e' y6 [. U
  16.         }, R6 p- m! T. T* q  z
  17. }
    / ?6 k) _  z/ k3 a3 Y
  18. 8 z2 w, E/ F4 i( y+ W
  19. use animal\dog\Life as dog;  # r+ A4 y  V7 f% G/ M
  20. new dog();
复制代码

- k# E  f  m" s/ `) x1 H0 r
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

# z# w/ u6 E/ p: c+ F* C  E' z2 k/ w
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    # ]4 E8 {' V: y- D
  2. " I3 ]# d' W+ [7 O3 B/ r) L
  3. namespace animal\dog;
    # l: A; a. h) u, p/ _8 T# }# a; g

  4. 3 {: e2 T. P; N  |- w4 j1 M% ]
  5. class Life{9 Y6 I( d6 p* z! P2 Q% v
  6.     function __construct(){
    8 X) e' G( p* J$ h
  7.             echo 'dog life!';# t# K( n; Q! l* E9 s7 N
  8.         }
    5 ?3 c4 W# o8 a( s* p2 r8 h9 j7 \
  9. }
    7 H' l4 x; W' h" K# a
  10. class Dog{
    % q( x$ ~& ~2 M: d
  11.     function __construct(){
    5 `9 W- X3 b8 B$ w, J; B
  12.             echo 'dog in dog!';1 b# [: q) ^# s/ h% x& b3 p
  13.         }1 q# p, H: i% Y% \
  14. }: D  X$ z& e! t. Y8 n% F

  15. 4 F' y8 q! a6 F- n
  16. namespace animal\cat;
    $ T* v1 @# }3 s' j( \( K

  17. 3 ^: D! m* }' l3 A4 `0 a) g/ C
  18. // class Dog{
    * J4 Q; M, X' ~" S
  19. //     function __construct(){. ^0 }& o+ ]0 k& \% K1 g2 D
  20. //             echo 'dog in cat!';
    / r$ g/ N- W; P3 k
  21. //         }
    " r* U( n' u8 H: O" D; _7 j# c
  22. // }
    : M! O9 `6 _, k4 r7 X6 S
  23. class Life{
    , M% _' C: \9 k8 o7 {: [, e0 Q5 R
  24.     function __construct(){
    & V: f; _  n5 f" E7 Y# k
  25.             echo 'cat life!';
    + g# C1 \- ^( T+ O# s0 ?* Y
  26.         }
    ' q8 V% z- d% o2 P+ h
  27. }
    4 `8 f  P( A  }- |

  28. & h5 u+ u4 h( w" g" n' g8 ?) m
  29. use animal\dog;  
    . K: |9 c* s& Q  |3 r
  30. new dog\Dog();
复制代码
) \0 i5 I9 i6 ^! e
如上,使用了
  1. use animal\dog;
复制代码

4 W& F- D- t) Z! ?' B2 e" `5 n
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

) P  ~3 F) y& ?
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
4 `" X* H6 ~: M$ b9 q

6 r$ V( e2 o5 f
% b  g6 C8 e& A
' U0 L/ _4 W" A' ]' e: W8 A! x
! F' J0 X% |( a, M. y( N& n

最新评论

GMT+8, 2026-3-17 14:04 , Processed in 0.054539 second(s), 19 queries .

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