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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
6 G- B# k) @3 a* ]# w' S, Y
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

& Q0 h7 `  U6 M" }' J: H5 J
: V% j  P2 d0 C2 k使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

+ q* g  s1 K$ @4 Q0 a
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
3 Y5 {& G: J2 S7 G2 H
结合使用方法来进一步理解它的使用目的吧。
+ s% n! Y6 n2 Y% R" m

& t/ h! p4 @; a; C5 i5 z1 k: rnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;* Q6 t% y& u- e; J
  2. namespace One;2 b" J5 l( j! N, u) K/ W
  3. namespace ONE;
复制代码
1 v( d$ ]- {6 k/ ^( r$ E0 w, Z; }0 W1 z6 s
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
+ x" _. y/ J* M
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   - [$ Q! P" L* w5 e0 I- X
  2. class Person{
    1 t+ @: q- ]* l, C4 U3 u
  3.     function __construct(){5 A. [# j7 L" E. m0 T
  4.             echo 'I am one!';
    ' R# G0 w1 T* b) E. H
  5.         }
    3 O4 v! d1 d4 C/ J- l- k
  6. }
复制代码
  1. //name.php3 {" R% O' t, ]
  2. require_once './1.php';
    1 s+ X, x! K9 [

  3.   o+ ]7 @, b: W7 h$ Q! l
  4. new Person();     //输出 I am one!;- u8 j( x7 v) l/ k
  5. new \Person(); //输出 I am one!;
复制代码

2 a+ L  X8 @+ C9 p% O0 z3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php4 Y& M: G# ~9 X
  2. require_once './1.php';- h: e2 X% U8 a! y
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

8 T2 D% |8 p/ H: q% f& B) R0 ?4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    * u8 @1 |6 I, t* w
  2. namespace one;
    7 ^  c( ~, B9 M4 P6 a* w. p6 G
  3. class Person{! }. `! S5 F4 L$ `' X. ?* g) H
  4.     function __construct(){
    0 g; l9 |) i& K. G/ W( D
  5.             echo 'I am one!';
    7 |: b6 e, {% |$ v
  6.         }
    + ^7 ^9 Z' E" ]4 @
  7. }
复制代码
  1. //name.php5 G. p& t% g- b3 {9 _% Q8 V( q" q
  2. require_once './1.php';
    $ w# ?3 j& }& y: P# p4 P( y  y7 X
  3. new \one\Person(); //输出 I am one!;
    " \; I" R, ~2 \: W! a0 M$ }
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

1 N  t1 U" Z0 V/ ]% W* w
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

) [. s, r. h" \4 \/ ]5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。. ^- `0 C. Z8 d1 k% U! o
  1. //1.php   ' e. I3 o, [4 `6 P
  2. namespace one;! Q8 v& x& b' m8 @. m4 W
  3. class Person{# P! _# e' _  y/ y: v* Q& b
  4.     function __construct(){
    / l1 W5 ^7 U( y, T0 t+ ?3 A; t9 K
  5.             echo 'I am one!';: w6 @' U( i% E; |6 ~1 h. f
  6.         }3 z. j$ D- M! t$ I
  7. }
复制代码
  1. //name.php' t4 {$ s1 ?! k  s; m( W
  2. namespace test;
    8 W2 P' _) c3 @& @) w
  3. require './1.php'; 0 A: b& N) C  O% {4 m- P* k' N* O
  4. new \one\Person(); //输出 I am one!;
    - f+ n- q) g) v2 F: \/ u
  5. new Person();      //这里结果会是什么呢,猜猜看5 b# S9 l- G  ~7 g' p3 u" s
  6. 最后一行结果报错:1 F6 m4 E0 ?5 ^  e* p6 N3 V
  7. Fatal error:  Class 'test\Person' not found
复制代码

) F) H% h! Q) ^, {/ \4 v

* h4 m# P* m$ m& b首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
! V' P3 ]! x  |8 G  w1 z
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
0 R& U$ S3 N& s5 a( P3 A  ]1 q
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php8 r! @4 a0 z# a. [; |
  2. namespace test;+ c: V9 P; B3 t' N$ N/ @
  3. require './1.php'; 8 h7 H! A: S$ D4 m

  4. # l8 s$ |, [3 A! N  n2 q
  5. class Person{
    0 B1 I+ f, Z  ~$ @* c. p
  6.     function __construct(){
    $ g# W$ x" ^- _5 D- B) |# c
  7.             echo 'I am test!';
    " N1 v+ v0 `1 y# j
  8.         }* u( k1 V6 s$ w. O
  9. }
    ' y/ p0 @% y) Z2 g5 X' ]3 k. M+ \2 t( ?

  10. . F7 r  Z9 ]3 C
  11. new \one\Person(); //输出 I am one!;. j. v# f4 b+ y$ a
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

# A" D8 l7 C2 u
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php2 Y* \: B- E3 @$ \
  2. namespace test;
    ) n8 o/ y# z5 `; w, [
  3. namespace one;
    1 Z+ @& j) p) y, v
  4. class Person{' T% z& e2 f: M1 f4 y7 V* s
  5.     function __construct(){
    3 W5 f! V; {. R# G
  6.             echo 'I am one!';
    % f0 P- E0 E- \- O* o' F) D, s
  7.         }
    % g6 h* ]7 F% x$ b  v3 P' a
  8. }
    ' I* j. G* j7 G5 {; `. @% e
  9. % O4 D! \+ m% V/ O
  10. class Person{3 `3 Q# }" A$ \  }2 u; D
  11.     function __construct(){  u6 A$ J) N6 `3 c, E. W2 \
  12.             echo 'I am test!';& p6 P6 A' I9 ^( g6 x- u
  13.         }
    . B# \( a- z# B2 l* g
  14. }
复制代码
8 x' Q2 X0 h7 }% N* |
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
# O' p4 W) p4 b2 `: Y' h
看来简单的把require理解为替换,在这里行不通。
) q1 C' U' f9 j2 Y- B, g
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
2 {, L& k# {- `$ A
  1. //name.php
    ; @3 u4 p! |% j( U* m, s
  2. + {. g, N, F" f6 U' ]8 K  ?2 [
  3. namespace test\person;
    & w0 M7 M( g* [9 U8 n
  4. 0 v/ H1 U* S3 W0 B
  5. class Person{
    , }4 q7 s: d* k
  6.     function __construct(){6 q. }$ N) x0 M9 Y4 s6 C# _/ K/ S
  7.             echo 'I am test!';
    6 \, R3 l, C2 d* S+ F6 X- d+ {! s4 R2 Z
  8.         }5 [3 X; \& F. [" b7 a3 ^9 R# S
  9. }' X/ n6 S: U* `1 _, d! R2 i" i
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
! F: T+ I' p0 J1 |& ?
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
6 a$ j) T  d" }) p/ d
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    * k" y/ s+ b6 R- p# R4 O# M, O  m- d/ t3 _
  2. ' q% A0 M" S/ a: D! I7 l+ K+ }3 n! j
  3. namespace test;
      i# f# z+ Q! L
  4. echo 'zhai14';2 w; |3 z/ S. N5 I9 O2 R& Y: G
  5. namespace zhai;( f. V* [" y- C) ^$ V  o
  6. require './1.php';
复制代码
, P5 y$ c2 X- S6 d2 a( f& I1 N
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

9 C$ g" U' r& q6 F8 n' k1 @& W% V$ cuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。+ y' {% h0 l4 X
  1. //name.php
    + _" ~# w0 Y+ U: b5 [* u' l$ _

  2. 0 c3 K3 G  _$ W' ?
  3. namespace animal\dog;+ B3 y4 e% u% q1 @

  4. + ?/ F. a) }# `  V6 I
  5. class Life{
    4 D- I# [5 V# T# L$ y5 n
  6.     function __construct(){
    ' f" R3 B( u* ^. Q
  7.             echo 'dog life!';) C% }5 {) B: c& g- t% A
  8.         }/ V5 v) X) W  n# w9 I2 D) S2 y
  9. }
    # v2 v0 \( }2 ]8 C3 q0 ?

  10. " ]2 N! {* [* l& n' w6 w
  11. namespace animal\cat;
    " J3 P% w- k. T! B/ ^

  12. ) ^4 F0 ?6 R- A8 ]6 o6 O* @& H; u
  13. class Life{# x' p+ ?( T$ m  h$ U$ ]6 B$ R
  14.     function __construct(){; \; ~8 D! K& \$ K) o
  15.             echo 'cat life!';' R- E, X2 N, w. J9 u
  16.         }
    * G2 d, c& X: J. q. N  x
  17. }
    . V: R1 g( w, w) E; s8 V

  18. % u5 N+ v: h5 V; f, C
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间/ N3 d9 H0 U, y! t* h. z. H. \
  20. new \animal\dog\Life();  //A8 F; @, p, _' Z# q! s
  21. . c- C* A( P' b  n
  22. use animal\dog;  //a
    8 f) a" @2 k4 M  j. q
  23. new dog\Life();  //B
    + f, o/ F% o& }$ V8 G) W& O
  24. ! Y* [! a* H- N( X) v! n
  25. use animal\dog as d;  //b7 w( H2 ^8 v1 m3 k* Y. R# Y
  26. new d\Life();
复制代码

) b; k3 R8 j7 x( }
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

1 T$ |) x5 j6 p2 @+ [6 J
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

+ C( w$ o2 X. X" v* I
相当于
  1. use animal\dog as dog;
复制代码

: C1 r5 |5 g1 S* U2.namespace后面不建议加类名,但use后可以。
' C+ G/ D6 u/ W
  1. //name.php+ o- z3 ^' T3 ]# s# e

  2. 3 ~  p/ u# P. _0 j5 [
  3. namespace animal\dog;
    ) I2 x# D2 P8 w0 y

  4. 4 M* W% c4 S- f
  5. class Life{
    4 B2 L5 B1 V" V4 H
  6.     function __construct(){
    " f5 d# M1 |' |4 Y) x* @7 d
  7.             echo 'dog life!';( e! x; s4 n/ g' P' B6 [
  8.         }
    $ [: o. x3 R2 ^: F3 v7 e
  9. }0 p  l5 x* S- p! j

  10. # s  v" ^( a- [: N
  11. namespace animal\cat;+ u5 w* j' S* L4 v
  12. 9 R: ~6 K+ G; T' p7 b: B. U! f
  13. class Life{
    8 c( [( y7 ?+ T3 E) e( E! W
  14.     function __construct(){  ]+ `: K5 c) @1 D7 B/ [
  15.             echo 'cat life!';# J, l8 y: G$ d  B# ~+ c6 s
  16.         }0 T" I1 }: R! G9 x4 j' B% _) Y. T
  17. }
    2 K' `: k7 r% x3 {
  18. 0 h. g+ a" ^3 |% x& W1 c2 F; z& ]% R, X
  19. use animal\dog\Life as dog;  , }1 D& s/ \6 U* ]: A/ X1 N- I$ |
  20. new dog();
复制代码
% W. \+ m; U* f5 W, l1 @- m7 b' W
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
1 O0 |( N: o+ c9 i8 c
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    % H. i3 F0 K2 F% y' V/ b. N
  2. - j  D* _1 C2 Y
  3. namespace animal\dog;
    8 P5 y' [% |+ ?% k- g
  4. 7 P0 \9 F! n: V" p  z: E7 ?/ W
  5. class Life{+ E, O& K1 `2 U* G( T/ F9 D# b: l+ A
  6.     function __construct(){2 s& M' U- U7 u8 A/ Q$ f( n
  7.             echo 'dog life!';6 x, T0 N: W. k, d6 A! _2 G! n, K
  8.         }6 j. T! H& ?4 k  G- M( h& {# _7 ?
  9. }
    * ?3 s/ v) x& X9 b/ L# P  N+ S
  10. class Dog{
    5 z  k3 o8 i) f$ x8 ~3 I+ c
  11.     function __construct(){9 b% ]8 p5 t% R, ]: s: D
  12.             echo 'dog in dog!';, w  o) E( d4 r4 B
  13.         }
    7 c( u( c/ A; O$ m
  14. }! b) x7 r' x6 j2 h- l% Y
  15. ( v& e9 `6 T) k$ h; K( r
  16. namespace animal\cat;7 K9 m, u& ]4 ]1 D1 b

  17. 7 n" x3 ]  l' f, t, m
  18. // class Dog{3 w: i  S( ]* U6 x' m- V8 [
  19. //     function __construct(){. G; I: R; L* }1 c
  20. //             echo 'dog in cat!';
    0 x  H, X$ s: |
  21. //         }
    8 n0 Q$ f& q- c
  22. // }8 ^7 R( Y& N2 ?& M
  23. class Life{& e9 _( z2 F" @" b; J
  24.     function __construct(){
    9 l2 s: E' @& {5 Q5 _* \$ R& |" z3 s
  25.             echo 'cat life!';$ \% b( _6 }+ @' q: X; ~8 ]$ d4 a  E
  26.         }2 X+ o: l. c, N
  27. }3 G+ Z7 h) E8 z; h: \6 X' M" K
  28. / B$ l& ~7 r+ n  o2 @, _4 `
  29. use animal\dog;  
    1 r3 O0 f, W6 y  T- g+ Y" G9 R
  30. new dog\Dog();
复制代码

" M) T/ c7 s2 |8 X7 K" P
如上,使用了
  1. use animal\dog;
复制代码
& U+ l4 l4 J7 B- I2 c
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

) v9 ]& @! O& L1 l% t/ X
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

! A/ z4 x6 W# T& \) T. z4 X+ l
2 o4 R' p) {2 ]1 _8 W8 O* }7 [' H" u) M& S* ^

  |. u9 g/ B: ^8 }. b2 K7 v" V3 R7 s7 w. F: {! }8 @

最新评论

GMT+8, 2026-5-16 00:30 , Processed in 0.055772 second(s), 22 queries .

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