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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

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

; @% K, r% O. b! D7 t$ L
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
/ e% y+ w" ^+ W" }7 y

4 X% Q- l( n- M  A+ x  T使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
0 W+ A8 B: A4 R8 K
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
9 c, o8 C0 F5 T& A8 p  O5 f
结合使用方法来进一步理解它的使用目的吧。

+ j  ^8 C( v. `( a/ E+ Z7 j" H0 w1 X* c- r
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;* g1 T/ r% M' o3 ^& Q# G. F! ^
  2. namespace One;
    3 x9 r+ A  Z* o% k, p. A
  3. namespace ONE;
复制代码
: \8 H! G% k! q/ k- T' u; l9 }
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

  n/ `; l; @8 J: j2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    & i* a2 e% F8 ?- C: a7 s
  2. class Person{
    9 {2 k; ]. Y* s3 {
  3.     function __construct(){+ @3 B0 f$ ]* u; h
  4.             echo 'I am one!';
    & L$ `7 `6 {! N  S2 C3 A2 r& }
  5.         }
    ( P# t* k- F& ?: [) ^
  6. }
复制代码
  1. //name.php
    0 l, k# J  _* h4 A: U/ w
  2. require_once './1.php';, k# U) N1 l& e) m4 L) ]% Q6 A% j

  3. & D: g- _7 I& z" g: a4 g
  4. new Person();     //输出 I am one!;1 x% M9 M* |5 R" J8 D8 n
  5. new \Person(); //输出 I am one!;
复制代码
. @8 A! W; q9 ?7 c
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    4 E8 J( S0 @. l+ v! B; C. T# ^
  2. require_once './1.php';0 m# n, }  X  K# r
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

) v" H8 Q0 F' ?# R3 q& E1 x+ B, @3 t4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    ' P( c, J8 Y8 v+ S( z3 y
  2. namespace one;
    + a" k, ?0 Y0 d* G5 D
  3. class Person{
    , F+ A# t; H/ S! s9 K  i
  4.     function __construct(){
    ' O9 G1 b. {# b+ K" u
  5.             echo 'I am one!';8 ?2 l* S8 j+ \: c
  6.         }
      v6 }2 b& c# f! B  Y
  7. }
复制代码
  1. //name.php
    * s, g, t$ z% E0 g& q
  2. require_once './1.php';0 K8 t& `# b; Z; ^
  3. new \one\Person(); //输出 I am one!;5 M  k( C) c6 `' j- x
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
9 ^5 w. n2 g5 T7 T- F( P
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
- E; k. s0 j+ Z' K2 `& ^
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
5 e, y) V4 I  T5 ?8 q$ M6 w1 |
  1. //1.php   5 i2 L: {) O6 t9 Q+ U" v
  2. namespace one;2 `" O: Z- N3 m7 J5 z
  3. class Person{
    ) J* t: H5 D+ {8 Y) r+ ]
  4.     function __construct(){
    4 A( C: \; v6 A& G% T8 V3 g
  5.             echo 'I am one!';/ P1 w1 Q7 P8 ?9 q
  6.         }
      k$ {3 m  _' f3 F5 X2 n
  7. }
复制代码
  1. //name.php
    4 g$ M- n- B8 ?: ^! |! a
  2. namespace test;
    & \, i8 X* p; d8 y8 i
  3. require './1.php'; ' P5 G: M/ ], U0 s
  4. new \one\Person(); //输出 I am one!;
    3 Z" V1 V  r! ^) u; B, q* v
  5. new Person();      //这里结果会是什么呢,猜猜看
    7 p9 N5 w$ {6 g+ x) t+ c2 T
  6. 最后一行结果报错:9 A" s; ^, Y' i% b: F8 a
  7. Fatal error:  Class 'test\Person' not found
复制代码
3 Z: w( P) X& L6 p5 Z

7 _2 S4 S0 l" O4 G; U% l( J首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
/ |$ ?0 L9 T! B
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

% U, R' O. {; u5 `+ j7 l5 d
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    1 k, [: K6 F$ x: O- s
  2. namespace test;5 l, _# l# g0 h7 o
  3. require './1.php';
    ( ~5 t: X6 {+ o) w: e/ z0 F

  4. + x$ `2 J7 f5 ?# j4 X
  5. class Person{3 k- B3 e, ?3 |7 i
  6.     function __construct(){
    , u+ s, l$ w2 A4 O4 K; }
  7.             echo 'I am test!';% \/ X; _! h# y) ]
  8.         }7 \$ h# O0 Q/ M9 B3 {: J* k- E, |
  9. }  a3 ?" q8 D! B: H9 H

  10. & Y3 F$ ^, `  n8 _
  11. new \one\Person(); //输出 I am one!;$ u# M/ R  [# }- L
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

$ n+ \- M6 I" `  @9 p* U' p
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php! ]4 ~$ m1 Y$ N) W) H$ _
  2. namespace test;2 q. T# d# g, |9 {3 g4 c
  3. namespace one;
    0 t% Z4 r# ^( E. ?
  4. class Person{& o& i7 {) x( ^* O8 a* m
  5.     function __construct(){4 N2 h: D! D2 ?7 J* i# x1 ~
  6.             echo 'I am one!';! U# F( ~+ T! `# s
  7.         }
    + h, R  P: L  M! o# Z% k8 Y# K% w
  8. }
    4 u5 _& f  \- ]7 S# M) w) q' l
  9. - W. _1 ]  g" j+ X8 H
  10. class Person{
    0 V5 }$ E! A& f7 W# }* [0 F4 h
  11.     function __construct(){
    7 ?2 J- A4 ?) h+ I$ ]+ J
  12.             echo 'I am test!';' @( A. B* C2 W
  13.         }. `. ^) D5 F4 r
  14. }
复制代码

: t1 d4 c' x& s4 Y8 b# M
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
4 ~3 B' b6 r& q! Z5 o) T
看来简单的把require理解为替换,在这里行不通。

2 |3 E2 I2 I8 T6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。; K2 L# A" R2 Z0 O
  1. //name.php
    # K  r+ ^/ Y' \" L

  2. / a1 E( ^+ l! D! v$ k
  3. namespace test\person;
    0 @* i2 q8 I! {( I, q% P; Q8 f
  4. 8 E; a( k% a; k7 K* y1 U
  5. class Person{1 M3 j! V) w- C& w0 k
  6.     function __construct(){6 ?! _7 ?" _. g1 D# t4 z
  7.             echo 'I am test!';/ ]0 V5 `8 D  b* ?1 W& J9 j; [7 R/ `
  8.         }
    2 l7 b- D/ s& c2 B% B( B
  9. }
    3 Y1 [  G) Z3 Q9 B5 R. K4 C" q+ A" c7 ^! y
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
/ Y) I+ o8 j9 f
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

( m# j' ~# o  [7 V: [7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php) I: p( G8 b, O5 ?8 R: [

  2. 0 \, M' E0 p/ b5 l  p
  3. namespace test;
    $ k+ c+ L# {# ^3 F8 r5 v* z
  4. echo 'zhai14';6 R/ Q$ q0 f2 s9 ?7 u" T2 q% X! e
  5. namespace zhai;
    0 a- E2 R5 t1 Y/ Y! s
  6. require './1.php';
复制代码

# Z; }( a( t5 a8 B5 X/ t9 p
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

& `3 [5 U+ E0 j/ ?( R8 M. Duse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
% {% P* ~9 o. L8 M# C
  1. //name.php
    " O. a% p- c  L2 a7 ?, P/ @

  2. / z( a+ z" W3 G' U: s
  3. namespace animal\dog;
    ) Y5 V5 I8 Y. \, ^* y

  4. / \0 m: `% w, b( ^* n" a2 x( u& O
  5. class Life{
    7 K5 W# M) ~0 k; g! u1 M# j
  6.     function __construct(){
    ( A- ?; \% K3 S' w5 m
  7.             echo 'dog life!';
    $ k  g3 J) j1 g
  8.         }
    ( I5 c& J: a; T& e6 [
  9. }* ]4 ~  O+ ~: ^, i/ \* K! H5 _

  10. - o( p% r; C$ o  y: W
  11. namespace animal\cat;
    5 M. l9 d; K/ \" u4 B
  12. 1 z. k- W/ ?) S' v$ w- R
  13. class Life{
    $ v- q  j2 x/ x" ^, e0 a$ X/ c
  14.     function __construct(){) R& s5 {. `. W
  15.             echo 'cat life!';: p9 Y' H1 ?2 v6 R- P2 N+ i" H/ N) }
  16.         }' E) _1 N" s# V
  17. }# O: e7 E( N/ P3 ~- p. |0 z* F  e5 @' V* D
  18. 0 @' ~$ I# o0 q
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间+ d  R5 N/ U9 c/ M" I
  20. new \animal\dog\Life();  //A
    ' o# T- O' C- g' u! q0 ]0 \
  21. , i: F5 T5 v3 T! P1 y; o* M3 c
  22. use animal\dog;  //a; N6 B# S1 _4 d3 Y) x1 C0 b3 x
  23. new dog\Life();  //B8 U" Y+ f* s- n* w) T8 H' N$ V5 U

  24.   H4 d* k5 \5 ]. M9 i
  25. use animal\dog as d;  //b) _9 P* k3 _, I' J
  26. new d\Life();
复制代码

! V( I) @& g" L. {( r, C' K  l
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

9 t" s9 Y& H6 C( t: S
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
5 ]; S: R% o- l4 q6 l9 W0 I2 O
相当于
  1. use animal\dog as dog;
复制代码

, _+ @" E$ @! X9 ^- s2 c9 `3 \2.namespace后面不建议加类名,但use后可以。
# J# k2 w" [5 p( i7 l3 Q
  1. //name.php
      [/ K9 j6 D6 C3 s0 u9 x& _, a' u
  2. 3 A1 N5 w! M' v# M
  3. namespace animal\dog;
    ; P* B2 ~' B4 `
  4. 4 ?) w  r6 u1 d/ y* P# J
  5. class Life{
    : P4 W# k: i& F5 }* N' y/ K9 W% D
  6.     function __construct(){
    3 T9 m5 ]& i: A4 L: k1 |
  7.             echo 'dog life!';$ n4 I  Z3 ?6 E& B/ Z. a. h* N& k
  8.         }
    * A* R) g1 @0 [) v5 z
  9. }# `  g9 f% O0 V; c7 q# ~
  10. & J( U4 i7 H' j5 V- e2 m% [
  11. namespace animal\cat;: Z8 l% \7 s" Y$ j' X9 k2 R

  12. % Y' _* C' |* c( }8 p, X# N
  13. class Life{& g0 E7 `; T' T! D' q5 n
  14.     function __construct(){
    " u/ N4 g3 n* S$ D- ]
  15.             echo 'cat life!';8 R/ M0 g7 S4 A, ?) D) d- p
  16.         }$ {9 P! y( |* H2 T3 ^/ Q
  17. }' S: a% k5 Y) N5 @; w
  18. 0 Q. `' o/ i& M  D# v
  19. use animal\dog\Life as dog;  1 c* S1 _, O7 @9 d, {( `
  20. new dog();
复制代码
; L$ R$ h% ?$ d7 J) s6 @
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

3 |  G7 _5 K1 Q
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    8 g+ K* Q% X9 k9 r! r) Q
  2. 2 T) f' l( K5 B$ ]9 \1 E" s7 {
  3. namespace animal\dog;
    / J5 Q! \4 O5 C- B
  4. & T; H8 M  ~& J5 e
  5. class Life{
    ; l( k8 r% k# m' n
  6.     function __construct(){# [. Y" @7 U. B& [
  7.             echo 'dog life!';
    2 G2 V9 e  r( T" Z) ~/ P# x( s4 ?
  8.         }2 w5 K% h4 F1 @8 A# v
  9. }
    % w3 |  G! w7 U+ ?
  10. class Dog{
    ' h; |, K8 j9 W" Z
  11.     function __construct(){4 _9 T+ u: `$ M* o  R! H
  12.             echo 'dog in dog!';! }) W- d1 I. E. u2 Q3 e$ m2 z' c
  13.         }
    6 q9 m0 H, o' F
  14. }) W, E4 _- K% m3 f3 k; R# K) O2 y

  15. $ }2 r0 A  b6 X8 w$ q6 v% ?4 I  z  F
  16. namespace animal\cat;( P% ?. B5 y" w) |  r0 z: w  {; M* f

  17. % l- L4 l: D" ^7 I, M% i
  18. // class Dog{
    . w6 g8 \: X$ l4 S1 q1 |: K, Z
  19. //     function __construct(){
    - k3 o4 T3 ]/ p! z
  20. //             echo 'dog in cat!';
      _: Z. T, {. A& o
  21. //         }: n: ]% g. c; ^
  22. // }
    1 n2 G1 G1 Q, R& c
  23. class Life{/ R* j/ [- P3 g& z5 L0 H$ C
  24.     function __construct(){' e! }  o; Y' C( I( r0 m- ^% R
  25.             echo 'cat life!';/ D" {- N( l+ c' v4 ^
  26.         }
    ) J  z1 W2 U/ ?$ T& ]  a: m
  27. }+ k$ |' U: A* d- C8 w" t
  28. ' ^! h  b/ r$ M* ?- r
  29. use animal\dog;  
    & b0 o1 I' ^: T, i& b- y, d
  30. new dog\Dog();
复制代码
! u- S# d. }. R1 P4 l' I- U
如上,使用了
  1. use animal\dog;
复制代码
' v. z- [) w: l! q3 s  T# L) v
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
! h* c: G8 W2 b7 c
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

; s4 y* r- ^4 \- G8 G! C; O. X9 t% I2 h# q. j( C5 K8 ^: E& b
% c/ b1 h8 g' D9 X# \

: _8 |% ^: Y& M) a, U) a" v# E, \" d' v" T, J* R4 W

最新评论

GMT+8, 2024-12-22 02:34 , Processed in 0.144313 second(s), 21 queries .

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