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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

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

5 M& e) I1 ^  ^1 d5 p
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
) K" M& m. r8 _

4 ]5 N; k" c7 D6 R使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

5 ^5 r- ^% P. L) Z/ l结合使用方法来进一步理解它的使用目的吧。

4 i: x$ g2 k; i
5 u% f9 ~5 e  E- D6 N- b- ^  gnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    - M8 x6 L* c# x, _/ V
  2. namespace One;
    8 T/ K* p* {4 ~3 s2 A
  3. namespace ONE;
复制代码

% D. v- a: v. d: F! Z
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
& g3 C/ l! M2 l1 G, B  w% h
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ' N3 ^8 l: q* m( l. T# A; w$ m
  2. class Person{$ n0 w! `. w- X4 j  D8 X
  3.     function __construct(){
    6 M9 y- [* V+ O2 x* p  f
  4.             echo 'I am one!';
    4 P( e& S: m7 R  d% D
  5.         }6 Y8 {2 X3 ~# u" y" X6 R! O
  6. }
复制代码
  1. //name.php
    8 O( i( A3 E9 `6 V' v" z
  2. require_once './1.php';8 D' J6 n4 c$ t9 x- h5 G

  3.   `4 C6 p; a2 g4 `5 x8 P6 V
  4. new Person();     //输出 I am one!;
    " Y# B6 o: T0 R7 i- F, G- j
  5. new \Person(); //输出 I am one!;
复制代码
6 H% {, d. N8 Y- g! k9 M$ H8 I
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php% l- \; r: j0 D0 J
  2. require_once './1.php';
    2 b( q. R$ F. z- l
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
4 l, @3 D' j1 K1 F, B& G' u- d
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   3 K8 {% a' n' v3 D8 i7 X
  2. namespace one;) t1 G7 E. j3 w9 d: G
  3. class Person{- K( q8 L! Q. K: f  `& v
  4.     function __construct(){% J" \% a7 g, J& H+ L3 T& `
  5.             echo 'I am one!';$ e# }  Q; d7 H7 v. _7 z# `) J
  6.         }
    3 n* D( Y' L9 }+ d
  7. }
复制代码
  1. //name.php
      B9 d' j# T' p/ L4 d& Z. |
  2. require_once './1.php';0 Y+ Z- D5 F- W9 Q
  3. new \one\Person(); //输出 I am one!;7 }; J; h; Y# C
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

7 z1 ?, x/ n0 _0 A. A
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

- e9 \  g' {( O3 M5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
0 p6 u5 q8 b. E6 K, K' s
  1. //1.php   + N/ L5 ?1 a9 q3 K: a4 I7 e
  2. namespace one;" N6 ]) h$ L! V5 a2 P& A3 N
  3. class Person{
    / M1 j( C1 q) m; j1 n% Q1 ?  v
  4.     function __construct(){
    , a& i4 _* H; t: ?
  5.             echo 'I am one!';
    : B1 F, m+ z& h: d# X" Y
  6.         }
    * o4 \/ F: ~- T: J: U$ l
  7. }
复制代码
  1. //name.php5 L/ D* n, d) z) }* o) `* @( B
  2. namespace test;
    / A6 C4 @- R" |# A7 g' n
  3. require './1.php'; 3 ~$ |% i  f8 n8 z9 W# x7 S5 L
  4. new \one\Person(); //输出 I am one!;# v& F  w, {/ v6 }- Q2 E  m  r
  5. new Person();      //这里结果会是什么呢,猜猜看
    5 i/ |5 E4 _! n& s- J" x  I/ o* i
  6. 最后一行结果报错:
    6 Z) k& I7 P; ^9 V, `& N/ w1 w
  7. Fatal error:  Class 'test\Person' not found
复制代码

5 C( v' D8 C7 n* y9 l  {( p

3 J/ z& Y  @. n5 K首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

! }* f  ~$ e" k
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

6 V8 ~' I( e/ `+ w5 K" e' i; s" S
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php- |" g& p+ M- c9 Y# D2 @
  2. namespace test;- G4 l* p2 w$ Z* D! `
  3. require './1.php';
    6 G# A4 z( E( ?# {
  4. 7 x* p2 J, f% t0 o  E: I" e
  5. class Person{
    , O4 ], Y9 I7 r9 t" b! }& n* N
  6.     function __construct(){
    6 \9 i2 j$ J3 s6 n6 e7 Q5 G
  7.             echo 'I am test!';; w, i, W! r; Z
  8.         }& z5 F" r5 i$ X( ~0 H+ L
  9. }3 Z* w: y+ b& M
  10. 3 t6 h/ N+ j6 J1 S. y2 C5 d3 U
  11. new \one\Person(); //输出 I am one!;
    8 S3 l. E8 |1 o- H7 }! v. S8 f! O4 R
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

, i2 {4 k( K8 d
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    8 y; m% {$ b3 }6 p
  2. namespace test;
    - c, g: M2 O$ g
  3. namespace one;
    4 c2 b3 c7 O5 b8 q
  4. class Person{6 H- I. _  {) x* x
  5.     function __construct(){
    ! C4 f' _1 @3 I9 _
  6.             echo 'I am one!';8 _3 d# W5 m7 ?5 W& ]
  7.         }+ D6 ^2 g7 C  o( r3 k  N
  8. }
    3 B6 `$ [! |3 I5 C5 w3 Z
  9. # j4 d3 m  y% D2 g/ [/ D, d
  10. class Person{
    * B- O8 B7 L8 C8 o3 s
  11.     function __construct(){6 w1 H* F4 c8 d4 k: V4 G4 q  `
  12.             echo 'I am test!';% c( O7 y( t. o9 \7 V
  13.         }
    $ ?, \/ V+ N7 b
  14. }
复制代码
0 r" A- D1 S& K$ R
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

: A& ^+ V. m- w: [5 i9 T
看来简单的把require理解为替换,在这里行不通。

  A4 ~' k+ J! g6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。% B' I% |* _& \, r5 f  ]
  1. //name.php
    # _& _' W5 b* h; N% I) ^

  2. 3 v8 M7 V) c- T3 ]! ?# ~6 @7 L
  3. namespace test\person;
    0 W8 r2 a# v& Q% Y3 ~8 X

  4. 7 U5 T7 |* ^* n
  5. class Person{$ X9 F3 o( h1 ^0 F  R5 Y* l2 @/ A5 j
  6.     function __construct(){
    5 |$ o& h" ]4 z) Q' w
  7.             echo 'I am test!';
    + T" C( L( _) ?( c
  8.         }% M2 |) k. p' D; ~3 B9 ]' e# f. [
  9. }: j8 P* y" O4 h: a
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
- |2 L) @3 b5 U1 P8 u5 e
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

6 C' _  f; `( h. s! [& b; @7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    ) p' d0 e: l5 D: U( O
  2. ' Z: u. Q( B8 [8 I
  3. namespace test;( Y3 r, x% Z3 l( C) }7 I
  4. echo 'zhai14';
    ! P. ~) h" b4 K. h+ |9 e
  5. namespace zhai;
    5 v5 W" r2 }- v/ H5 k
  6. require './1.php';
复制代码

2 V" A1 s; f8 Y  a8 _0 T
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

) e- p! s, i# z4 I' N, quse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
! e' b3 @7 n  {9 o/ S% @3 r$ u
  1. //name.php
      ]" P$ `+ E" Q8 S( d
  2. % j' ?$ z1 L% s
  3. namespace animal\dog;
    ! n8 {5 z8 ^6 U* j5 Z0 H# L* h' }

  4. 6 A, C$ h! |+ }! B
  5. class Life{
    # P* l% s- P5 S) D
  6.     function __construct(){4 f* F4 R6 C3 l  s- S% l, d2 a
  7.             echo 'dog life!';
    / q# H9 U8 F7 m* {0 H0 m) ^
  8.         }) |2 }( N8 o, \! n7 A: b
  9. }# r" K  Q& T( T+ Y4 h

  10. $ g" J* \6 `* C* C/ y1 n1 h
  11. namespace animal\cat;+ p" g" s' w2 j
  12. : l: U" h& w( G  l
  13. class Life{
    & A4 O2 L  d" H. J
  14.     function __construct(){
    & g' \% D, n! N, Z
  15.             echo 'cat life!';2 q; x1 \, P; p% `7 u7 F: `
  16.         }
    & G/ @6 m; b: M& p) h
  17. }
    . f. w5 z* g) ?! b! Q# {$ X6 Z! {2 Q: w
  18. , Y( o) _+ q7 T6 U$ B# Y
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间; s- @$ [9 C/ v2 P0 b. U3 e  R
  20. new \animal\dog\Life();  //A3 x' E( L* p5 W( J) @- r/ q

  21. 0 ~1 B4 K: R( y- f+ o
  22. use animal\dog;  //a
    8 d' s1 C; c0 Z0 Z
  23. new dog\Life();  //B& }4 Z" g9 e  j" V

  24. , T) t  `7 G9 L. Y8 U1 [6 h
  25. use animal\dog as d;  //b9 o% F9 t# b6 @' C! q
  26. new d\Life();
复制代码
8 X! I) `. Z1 {& r
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
3 P* }+ C+ D4 [: l, s, _
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
' ]$ F+ {" j. k& U  s/ r; h: ?8 W
相当于
  1. use animal\dog as dog;
复制代码

( H- V/ b' o5 w2.namespace后面不建议加类名,但use后可以。
# Q, R( U; ~" V: Z# m
  1. //name.php% f0 ~' U2 l4 t2 ^) M  l( [' m6 X, _
  2. 7 ^+ [- n6 w, U' d% T0 L# O
  3. namespace animal\dog;
    ' w& ~% i- P- D! n/ Z8 }
  4. 7 R6 c0 ]; p0 b$ X0 J
  5. class Life{+ z( k: M  |6 o9 Z4 @2 `
  6.     function __construct(){
    ) Y  B  P+ X  E; k& A* E. v
  7.             echo 'dog life!';
    1 B% X% v) q% ]4 d
  8.         }
    1 j( ]$ h( A9 F6 b) j. l
  9. }7 g5 z( N' ~) Z$ c

  10. # V6 m6 p9 z3 R% N! X
  11. namespace animal\cat;# G2 M! V8 ~; e0 m; k
  12. ( Z0 C/ k) T5 i* c/ P9 ^6 a
  13. class Life{4 l2 t+ u3 v/ n; R! W$ O
  14.     function __construct(){
    . Z% M& Y) `0 p- {( f
  15.             echo 'cat life!';" E( a9 a2 N! r3 t: q) K/ A2 |  H
  16.         }7 p% C$ \/ D- m( s2 t# M- c
  17. }
    % V! z- E3 ?! \6 A/ J; b. p1 x

  18. ( S& ]5 G& ]# c3 I+ Y! J; g
  19. use animal\dog\Life as dog;  
    / y5 A. G8 f1 d; U) [. Q0 Y
  20. new dog();
复制代码
- V' |/ \) ~* Y* t# b
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

9 i- O1 ?! Y" U  D
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    1 V( _1 D/ ?: Y; ^9 K# Z2 D

  2. 8 F3 {. @% b/ f, h3 T
  3. namespace animal\dog;
    7 e1 Z/ O/ f* c; T( I3 ]8 S

  4. $ y! c2 d  z4 g9 t0 J
  5. class Life{
    9 G& L" a- ]# o! I* j
  6.     function __construct(){# z6 e$ W2 ~8 n% x$ L0 F
  7.             echo 'dog life!';
      w! y- J6 v( Z0 N
  8.         }. e* [, M2 l8 V$ s  o
  9. }
    * R. n# g! |/ n9 X/ \
  10. class Dog{; U2 H5 J! O& ]9 u
  11.     function __construct(){$ Z1 M0 t' P2 g
  12.             echo 'dog in dog!';: a. }# \, p1 C2 [. P+ c8 w
  13.         }3 k6 W8 g* I% e) z$ a; G
  14. }& Z& l" f9 j8 _/ b" l8 k7 `& ^

  15. ' e0 K% f, e) `" U
  16. namespace animal\cat;6 L, u. H/ X2 X0 K  k0 Y6 j  t
  17. $ I2 w3 z# ?& i9 B& \: \& |) C$ E
  18. // class Dog{' g3 _, E# R- w6 o' v
  19. //     function __construct(){/ |3 D" r$ |$ T
  20. //             echo 'dog in cat!';
    0 U% o6 K1 F9 n( q; p
  21. //         }1 b6 N2 m3 x" c  w
  22. // }0 [# C2 c% M. R' ?2 A1 M( ~! d7 x8 I+ a
  23. class Life{6 L. _- O! i& g# J* k* c" H0 E
  24.     function __construct(){$ ~& H: k3 N7 B1 v, d! k$ N
  25.             echo 'cat life!';
    ; l" J6 ?, S$ j: P0 r) _
  26.         }: \/ b$ e; k1 v* g  G
  27. }
    0 g+ C. V: S' k- S8 Y

  28. 1 W2 X, b8 Y3 d0 a, O0 I: s
  29. use animal\dog;  
    2 `' p) N5 T; Z
  30. new dog\Dog();
复制代码
, \- W! J- r2 i( o3 T
如上,使用了
  1. use animal\dog;
复制代码
: C. E+ w7 L/ E9 Y" Z
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

. v' n6 p% }# t* X
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
- Q# t7 F* |& w% W8 S
1 m1 v! R& q5 H: C/ i4 |
  N. |7 H& }' A. k+ I0 Y; |
3 o: e2 V. i( {* f0 W. v* n. L

. ~1 T: ^+ S; g: s# K

最新评论

GMT+8, 2026-7-15 15:38 , Processed in 0.082046 second(s), 22 queries .

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