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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
- W- ?. Q! s. H6 x) L; S/ W
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
0 w) ]  m4 d, L+ e6 g7 G# P* I' z
2 c' }) }5 n4 k6 Y- p3 B, t8 ~
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

) l: S- @2 z0 h' l1 \结合使用方法来进一步理解它的使用目的吧。

* B! X% o. s+ `- N6 K) `3 l: @: m+ Q6 p) u7 i
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;( B- \7 K  ^: ?# y
  2. namespace One;
    2 {( X/ u9 W8 x: ], L% T
  3. namespace ONE;
复制代码

% L& ]/ m+ a1 Q# V
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
$ s4 I2 _& t! @1 F, O
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   : n7 T- A% V. w; J  @
  2. class Person{' D: H& b& N1 S
  3.     function __construct(){+ T6 g/ z/ B6 R3 e; r4 _+ A5 n
  4.             echo 'I am one!';
    5 Y9 C( R* ]* B7 R) N
  5.         }
    3 X" ^* M8 w; ]4 _" ?
  6. }
复制代码
  1. //name.php8 |3 ?& O  j+ @. h, J+ h
  2. require_once './1.php';
    3 G% T! }, \2 u0 r+ h
  3. $ k1 X) P  E' U2 z0 [
  4. new Person();     //输出 I am one!;; Q. D3 }' ?$ j& B: C% x& @
  5. new \Person(); //输出 I am one!;
复制代码

* ^, U: X6 C% X# V9 q6 _( }3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    / `( r$ r3 N( S3 S
  2. require_once './1.php';) V9 k7 t- u+ ~8 ~
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
8 ^: D+ M% a0 v2 t  E
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    5 T! a$ m5 o% l6 a% C6 T
  2. namespace one;" w' |9 }6 Q/ \6 w* T' d
  3. class Person{, t% z& Z  o* ~( S, v
  4.     function __construct(){
    ' `' Q, [8 t8 n% u  y' i7 K  P* ^
  5.             echo 'I am one!';- B4 U1 T& \9 C% P. \
  6.         }
    / Y% h7 m. B: `5 {/ A" Z
  7. }
复制代码
  1. //name.php+ F2 w. A9 v2 r, y! W" _
  2. require_once './1.php';
      k, f0 Q; J) K2 R5 @) V
  3. new \one\Person(); //输出 I am one!;5 [- }' v3 y$ i: t5 m
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
! u) O+ d5 G  z8 Y# _. l5 G
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

' ^8 X* S- a. ~& _% Q$ O" v+ W5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
8 D  D  K  b3 T( g% ~) U+ j
  1. //1.php   
    ! g6 j; p* B1 D0 f, T0 J! @
  2. namespace one;
    . H3 U; j: X. A$ X: W. a/ |
  3. class Person{
    9 U: P& S* C0 j9 ^6 \
  4.     function __construct(){5 a% }& O0 E+ M$ e8 {
  5.             echo 'I am one!';
    - P" Z* ~& A3 v1 N  ?6 y- s6 a8 r
  6.         }) V% X. }+ @) b. }) N+ i/ I3 y
  7. }
复制代码
  1. //name.php
    5 |& g3 p8 W" B& ^% `: ~* @
  2. namespace test;
    4 ~6 ~2 L2 G# [3 i( X0 R( v
  3. require './1.php';
    3 P+ l! }1 ]: ^! ]& W
  4. new \one\Person(); //输出 I am one!;; M) _& x/ r: c* j% a
  5. new Person();      //这里结果会是什么呢,猜猜看
    5 }- F+ k! b7 ]; V" U$ [4 {
  6. 最后一行结果报错:
    + Y+ X& v7 h/ [/ j. B& Q' q2 b
  7. Fatal error:  Class 'test\Person' not found
复制代码

3 x( P# v) z: |( H  b' G

6 {3 A$ B7 I. M首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
) v  p9 M0 R/ }
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

7 ]3 N. X7 c' F6 |/ R
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    1 ?7 w4 ^  J& B# s& _
  2. namespace test;9 X$ C% B" ]( K2 V, D
  3. require './1.php';
    7 d/ u7 F, f* E8 x' D

  4. ' z6 F' }- i$ A9 [/ E% m) P
  5. class Person{# Y  i% r. ~; e
  6.     function __construct(){. y2 Z. I5 M+ I  b$ B1 [9 y
  7.             echo 'I am test!';
    $ \% }- c/ C8 E; G
  8.         }- Y$ \7 E1 H# k$ }6 s
  9. }& U1 g/ D3 _; J6 F

  10. 7 f; T/ Q, h" D3 I7 a$ u
  11. new \one\Person(); //输出 I am one!;* f, l1 L# ?( E0 C& }3 E' M" ^
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

. C. h+ i( ?/ a/ E1 \2 Y
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php% ~5 s- S$ i1 d3 z7 k" R- U
  2. namespace test;
    + O# P# B* o0 d. |4 I! d8 K3 x
  3. namespace one;
    # o" \8 k6 {8 v0 _2 v
  4. class Person{
    # M- L) \  z' z- s+ G8 V+ w
  5.     function __construct(){
    5 d+ ~+ M( Y2 o+ u4 C0 c
  6.             echo 'I am one!';
    0 {9 ?4 ?$ D/ U) R. J; ^6 E7 l3 z1 I/ X
  7.         }8 x# Z2 J# ?2 |& f
  8. }* J- M8 z- ]4 @9 ~1 Q
  9. 6 S+ O& `# Y; a' z+ n
  10. class Person{8 S0 W# v7 d  u' K" ]
  11.     function __construct(){
    1 n& U* k3 I. @7 ~/ j
  12.             echo 'I am test!';
    9 c/ D0 u- `, y& v$ `% ~
  13.         }
    ; S6 z- u9 Z: T( {& g  b/ z9 D
  14. }
复制代码

" s: r" |8 m6 `/ w" {
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

. T! ~% M0 i4 q3 [# ^
看来简单的把require理解为替换,在这里行不通。

1 j" D' c: d1 s9 Z* ~) P% F6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
) s9 k0 s! s3 j9 q$ J6 i
  1. //name.php
    9 U. G  X% t- t1 o+ @( I. L
  2. $ H8 A0 Z' j. t# o5 ?( Y
  3. namespace test\person;
    ( \: Z) m  S( U/ p

  4. + y/ u9 J0 @  d' K; E* a
  5. class Person{; g4 l2 ?2 W, m; P4 z/ S
  6.     function __construct(){* [: L2 t  z0 _" M3 c* h; {
  7.             echo 'I am test!';
    , F9 C6 A6 q6 l' I& k
  8.         }5 V$ n1 S* Z/ C9 S% W
  9. }1 M  X4 q7 j( A5 G& Z0 R2 ^. p
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
- L9 p( F% z* K
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

( ^8 T' r3 B3 a8 A$ B7 r$ r7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php' j$ n1 z7 u9 P+ ^- ~9 n

  2.   F3 j- k( a9 S! `1 @& x
  3. namespace test;
    : m  c' d* S8 J3 g) D
  4. echo 'zhai14';
    ( W  y+ S0 b; U8 y. J
  5. namespace zhai;
      [  [4 s. p. y$ ?3 X( l1 y5 m
  6. require './1.php';
复制代码
* ~0 ?' `$ O+ A5 B
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

; F) K1 q9 Z2 `/ F: M; [use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。& w0 X& z5 j0 o0 M' k& N
  1. //name.php0 W% H0 Z! C. p/ R- W& r6 [
  2. ; Y! L3 a6 _5 g& h, R; f% ^: D
  3. namespace animal\dog;! \& `  b" X" T! V: {

  4.   d( \3 H. _1 f
  5. class Life{) C6 i0 l2 O5 |) M
  6.     function __construct(){
    8 y+ F8 J. @( _2 @4 q6 w
  7.             echo 'dog life!';
    + f" h8 V8 h: a. O& u
  8.         }' Y" N$ x) i* C
  9. }- w* J+ a1 g8 A
  10. ) a7 L: H9 J0 ^4 z- R
  11. namespace animal\cat;
    0 V. w- t, u- U/ E: S: _% {1 i" e+ ^7 G

  12.   I- g. J1 O8 y! f# j
  13. class Life{7 l' U: ~: u7 x% t
  14.     function __construct(){
    9 V( _# \  T; Z8 Q- g
  15.             echo 'cat life!';/ e! E" {; N' _9 p
  16.         }
    9 I3 ]4 X: O0 y0 n8 F0 n  Z
  17. }
    + g5 O6 G0 Z% D  w( s5 r
  18. 0 [' }; h  k, f: R2 c
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间3 \4 i6 y* o- h( N9 O+ \0 o( B
  20. new \animal\dog\Life();  //A
    ( m5 ?0 ?1 p, U# L6 Z/ C/ O

  21. ( P, \2 S# s! j5 q4 y5 @
  22. use animal\dog;  //a3 k; q" {2 |9 L3 ]# K. I: J( G
  23. new dog\Life();  //B
    5 t) N! P! C6 ~; b( _

  24. 8 M' b3 P; {' n" s; w8 W! r/ K
  25. use animal\dog as d;  //b
    . q6 F& \! j( U+ H9 A5 Y% j- `
  26. new d\Life();
复制代码
9 \5 H# X! ?, v
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
: n* V# v' }/ `) p3 D, B
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

5 @) N  M' x/ ]4 A+ V
相当于
  1. use animal\dog as dog;
复制代码

# y# v" Y9 v  U2.namespace后面不建议加类名,但use后可以。! ^# [$ F4 A8 L/ B4 a; J
  1. //name.php( B. U7 R) L9 v- }* t
  2. ' W' p7 s6 l, _# G
  3. namespace animal\dog;4 x7 h' N0 f' L1 _( Z- K8 G

  4. ) t: r" n. V! \( c
  5. class Life{( v( r  w6 a: x8 v/ O- C
  6.     function __construct(){
    # n* `; C& D2 E6 w/ R
  7.             echo 'dog life!';
    . [8 `7 T( }6 f$ H5 P) o
  8.         }# A; r* _: V& e- x: D
  9. }5 B! \) M6 L- S7 I: Y9 h

  10. 1 Q  D/ B* l- J* b) g" }. ~
  11. namespace animal\cat;5 X* t, y. W6 s! B8 T" \

  12. 8 ]* Y* @% r0 Z2 U5 M
  13. class Life{6 G$ k2 h  P3 x" v. d
  14.     function __construct(){
    $ J+ X) l) d3 N. A4 R
  15.             echo 'cat life!';4 ~* K7 C$ h9 X7 s4 w
  16.         }
    : R7 S  q) z- t  d7 V( ~0 E* p0 P
  17. }
    ! H3 h9 \' x- p4 Q0 k' A$ N+ i# ]) j8 a" j
  18. & D$ G2 a1 D8 {( \: s
  19. use animal\dog\Life as dog;  $ C& A$ G9 j3 ~3 q& D
  20. new dog();
复制代码
9 Z1 S$ S8 d, Q" Z
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

' z* A6 P7 ]. h/ p4 u. o) P
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    ; ?: @8 p8 x( L) ?
  2. & ^7 ]: I3 S" i+ A, i
  3. namespace animal\dog;: o$ p- y- N' @8 I+ m& |
  4. # U! W0 T$ E0 O4 B
  5. class Life{* J. V+ H' ~. T4 x7 ~; `, E, e, Q
  6.     function __construct(){" m1 G, _8 Q# y  `
  7.             echo 'dog life!';
    6 ]/ v3 [+ ^% N
  8.         }
    % d! ^7 k% ?: \# T; y( F, x
  9. }
    3 L2 K  T$ B3 e1 }: V. X
  10. class Dog{
    ; q# h2 q  L( q" E
  11.     function __construct(){' L  v0 m3 N* u& e% ?5 O9 i
  12.             echo 'dog in dog!';  Z% e1 C$ |: V
  13.         }8 M7 H; e3 j1 P
  14. }4 E# ~  A; i% Y& C

  15. * g0 O1 P7 O& M# X; n7 v
  16. namespace animal\cat;8 F6 ]* n, h' k

  17. $ J; u1 v9 s0 p, i& \, g9 B" j
  18. // class Dog{/ B: h! |: X( m' r. h
  19. //     function __construct(){% E% R3 {: h! J: A5 G4 M
  20. //             echo 'dog in cat!';
    6 e7 O  |, l5 t1 T" m1 O+ @
  21. //         }) k. S6 `! B" v
  22. // }$ N) `' ^2 L3 y
  23. class Life{
    ( c- E+ P. N- a. v: [, ?
  24.     function __construct(){
    1 F7 P9 w8 i5 A2 W8 M: k/ q; s3 W9 F
  25.             echo 'cat life!';
    ) u' T' f$ y; |' g) b7 m
  26.         }
    $ w8 [; h$ U* Z4 y  b2 O# U1 s# w
  27. }) y7 [3 E+ r  a1 S

  28. ' c$ A# {+ `; r" ~* ]
  29. use animal\dog;  
    . s" |: ~5 D- |, ^) g3 o
  30. new dog\Dog();
复制代码

5 ]+ G2 U" _0 M. W2 c# k
如上,使用了
  1. use animal\dog;
复制代码
, b9 W* R6 J# x
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
2 a3 h1 p! d& S- W
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

) [: i* `- c4 C7 F9 ^' [; `" C1 M$ K( |6 d
* f/ y4 E; f  E& z) e% q
4 C. ~5 I1 s7 l! b/ ?1 A
: v# m: c4 C, N& X3 }( q% p

最新评论

GMT+8, 2024-3-29 09:35 , Processed in 0.128234 second(s), 22 queries .

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