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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

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

5 {) H: A' t* ]  N! ~0 d
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
% [; ^" U0 ~9 U7 C

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

) T% Q( l! h; W  q结合使用方法来进一步理解它的使用目的吧。
2 m: p9 F2 i6 U* U

& J+ k8 W" |+ @* e% X% Znamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    % U) X. y" i, V% ]& ~/ A" O
  2. namespace One;
    ; t  @' ~7 P, a6 e  F$ O
  3. namespace ONE;
复制代码
* \4 l+ q6 v  M6 t
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
6 y5 [$ a* k: Z; Z& S% q9 T
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ' g9 s' B5 ^$ j- G
  2. class Person{9 Y" _( R' ?( K
  3.     function __construct(){8 k8 q2 q, j% J6 w
  4.             echo 'I am one!';1 t# x$ G2 f$ {% n& S: H) e7 t( n
  5.         }3 l. l4 {5 E3 B2 e
  6. }
复制代码
  1. //name.php
    0 w! j2 `+ |% o7 Q6 a( k: e
  2. require_once './1.php';
    8 c& p! m$ b0 X. J. Q8 T
  3. * v' \0 D2 L1 f. c
  4. new Person();     //输出 I am one!;
    $ d. g3 o& B  T8 W, U; n( ~# x$ C
  5. new \Person(); //输出 I am one!;
复制代码
; P4 Y+ h% B+ S$ p: }/ E
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    1 i5 x- T& @$ K% h, V6 |8 G; Z
  2. require_once './1.php';
    # f5 ?7 P2 h# @( `- ?
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

, ~/ E- d$ J" c9 [9 M+ F& _4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   4 n% D% h9 v% S; P% @+ ]4 ~( z9 p' q
  2. namespace one;7 E/ b7 D4 r4 i& g5 [8 D
  3. class Person{
    . G3 Q' p/ ]  J1 z/ s0 x' g
  4.     function __construct(){
    6 ]' `/ u# Y# ~2 h! u
  5.             echo 'I am one!';, ^1 R2 l3 u' V9 _; k3 s
  6.         }5 h. h. I+ O! `8 M
  7. }
复制代码
  1. //name.php
    9 V9 B5 a* t$ Y/ D0 r' A
  2. require_once './1.php';
    ( U0 q3 F& c, ]) V' H0 s- z# }
  3. new \one\Person(); //输出 I am one!;) f, N, h3 Y4 c
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

/ i+ [7 @: M+ D3 G0 A. k
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
% M8 A4 G+ b$ U' L" n
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。, m) x4 S  J6 R1 b) |
  1. //1.php   
    0 t+ L+ ]( x# |7 C5 L
  2. namespace one;; ^5 j1 K+ l- Y' ?5 F* J
  3. class Person{9 o3 j! Z6 I" y/ g( ?* H
  4.     function __construct(){
    % U& K1 k% I& [  G+ T+ x1 q! Y
  5.             echo 'I am one!';
    $ k% ]* \6 [0 m: j
  6.         }
    . x' M  M* O6 {. w5 W1 k. A9 G# P
  7. }
复制代码
  1. //name.php  M' P; u& |* M2 Q0 l, W" F
  2. namespace test;) R+ {8 \# _# J5 C) ]1 S
  3. require './1.php';
    : m* v, K" }) b
  4. new \one\Person(); //输出 I am one!;
    % w' ~9 |" u7 [8 q1 F& t. S
  5. new Person();      //这里结果会是什么呢,猜猜看6 Z0 x% [# }; {2 j( k9 E6 L0 m
  6. 最后一行结果报错:
    6 K7 u0 K( H7 I
  7. Fatal error:  Class 'test\Person' not found
复制代码
8 I3 \! ~2 s3 U5 z
; _$ i) M9 I, Q$ O* M
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

: r% ^  q1 p* s# L" q: \
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

% A2 U1 E5 m: W% k* ?6 P
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    4 f* R1 K7 v7 o! l: ?* ~
  2. namespace test;
    9 G, H( k( i. _# J; E
  3. require './1.php'; * B7 _, w. N! ?; ~+ H6 q( C

  4. 2 F! k$ a/ u8 I) [& G! x
  5. class Person{2 I' ]9 g* q( U- J; F* E
  6.     function __construct(){, u; Y' d% _; ?3 v
  7.             echo 'I am test!';
    ! I8 M* g) i9 `% F5 N6 A+ a8 \9 r, m
  8.         }% F, n( d& D3 X* T" L
  9. }
    * L! Z5 N3 k' g5 ^2 d

  10. 1 w0 ~: l  N! C0 U) P0 @  G' L9 e
  11. new \one\Person(); //输出 I am one!;4 Y4 V$ S! h, `: b! v
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

- G7 x% G3 j) ?2 P1 S
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php% e* l, \; ^; U- Z1 @$ c% |
  2. namespace test;( u8 Z2 {+ k; ^/ G/ g; P5 t
  3. namespace one;: m) Q( P# M, m2 B- ]6 V& d9 o$ W
  4. class Person{
    9 m, z+ ]1 r, }  M
  5.     function __construct(){. i1 p9 d/ l4 f0 Y/ r) G4 o' f
  6.             echo 'I am one!';
    ! P/ _, f6 U9 r
  7.         }
    0 v2 c5 R6 Y, K& W9 X0 w
  8. }) k4 Z, B7 ~2 E% L3 L# V: C
  9. ( h/ R# Y, _( w" ?. E, d
  10. class Person{$ i" ~+ [2 W+ z; [' M/ J3 h( [$ Q
  11.     function __construct(){$ o, `% r- p+ I: Q
  12.             echo 'I am test!';
    6 j8 _6 b9 a0 }9 w' E
  13.         }
    3 f; w' t) g9 U3 O9 f3 u" g* [% t) M' N
  14. }
复制代码
0 \  l4 Y" b7 Z. ]% N: g
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
2 f, D; F' V4 N  I, R% q; [
看来简单的把require理解为替换,在这里行不通。

6 A- ~, u  g9 O* i: o6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
4 E, m& [/ d+ @! B, {7 o
  1. //name.php
    . W+ J: R& ^& u5 r) b' U
  2. ) z" D- l3 K+ P3 U6 p
  3. namespace test\person;8 D/ D9 B; F) I% t

  4. & ^+ [8 i7 W; n3 F
  5. class Person{) f- \% y+ d: P% @) W' S3 S8 M
  6.     function __construct(){* i$ V5 t) h7 H+ y/ A2 L" P
  7.             echo 'I am test!';
    9 T' A9 G( Z$ Q6 f( |
  8.         }, Z' q. a" _" i) o9 n' ^) F: y
  9. }
    4 \8 [; ]( W% f# B7 O4 i1 ?
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

3 L. L6 E: [* U( a5 B0 x
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

. o, q% N2 }* f4 `. ^3 W* H  L  V7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    3 _! p8 g3 T, M. L

  2. 1 n- y# p+ T* |2 x! l
  3. namespace test;# V! x+ z8 A- I" d7 q2 y
  4. echo 'zhai14';% B, I$ G8 }) a3 v* l
  5. namespace zhai;
    ; W6 M- J; k% Y+ b/ b0 G9 t5 h& w
  6. require './1.php';
复制代码

2 y0 Z. u% Z4 ?
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

) U2 ~2 `9 U  fuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。5 q' U; y$ s; m: g4 o
  1. //name.php
    ! e6 U: }2 ^4 }; L' n2 w

  2. . M) E# o0 t  F
  3. namespace animal\dog;
    6 }* L+ h7 d2 l! P' n) E3 ^  q: F
  4. % H5 F9 M; N& n4 E
  5. class Life{) i' M+ q. F/ z
  6.     function __construct(){
    0 O9 `* E9 d, o# [8 G* ~& ?1 }- C
  7.             echo 'dog life!';! S' O, Y/ X$ n$ G* [
  8.         }
    ! [5 G+ x3 D5 c$ h2 D/ U
  9. }/ H7 o: o- r, \( F2 k0 ^
  10. ) a0 e, r- M- L& n
  11. namespace animal\cat;
    " J5 S5 W6 D/ y, t! S3 c
  12. & W2 o" k1 I- A! N1 `' i
  13. class Life{3 H0 Q. q' ^. ]! X
  14.     function __construct(){* y: D' g  f4 {  X% ]" c* E
  15.             echo 'cat life!';
    ( V  M& V' }' p( C
  16.         }4 ]* E$ p# w# e5 t* P- T+ E* C
  17. }. @* I# `' X/ N  X
  18. ; j. M' E  N5 k4 f& b
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间% M, l; q# ~, R9 e- V- p
  20. new \animal\dog\Life();  //A5 x% M) o9 O" Y. O' o4 J( e
  21. 3 [& b+ c; y+ X4 t1 M; h
  22. use animal\dog;  //a/ L4 j2 c6 A  Q3 I
  23. new dog\Life();  //B
    , ~' o, J0 q" o
  24. 5 A$ c' J: E. @3 Z6 j
  25. use animal\dog as d;  //b
    ' G% X/ t& B0 J  k4 h8 [
  26. new d\Life();
复制代码
$ C9 D2 N+ |5 n' P! M2 W
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
9 c. t" V. M, R; I$ r
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
3 p( N9 p4 Q& B% L, |. \3 W
相当于
  1. use animal\dog as dog;
复制代码

4 n2 M& z; p4 Z6 Q& p* G# M5 U" |2.namespace后面不建议加类名,但use后可以。+ S4 x# @& s  [: d; F9 K" u
  1. //name.php8 G. x6 d6 \' T0 ~2 v. i

  2. 9 }# a" I+ T9 }, X( z( y
  3. namespace animal\dog;5 A. v6 {! W) Z9 `, p( g9 ^1 I1 E7 R

  4.   L  O' A4 M! v5 G1 D- A: ^
  5. class Life{
    : z9 l" n$ `$ h6 n6 X" R
  6.     function __construct(){7 ~; \; S% k; i
  7.             echo 'dog life!';5 v1 {) Q1 |- ^" o4 W+ l  N
  8.         }7 J* ]: k3 C* K5 }
  9. }
    1 W/ e) u/ A' p( w  n2 n2 w
  10. ( c. y* O. B4 @9 F2 x2 A3 C
  11. namespace animal\cat;/ l) P3 Z3 C( f4 S; a

  12. # b) ^# c$ p0 q  u( ?8 P" q: h1 j
  13. class Life{
    ( S6 O- _- z# S7 E. `! |# M
  14.     function __construct(){& {# j3 U/ u& o* I
  15.             echo 'cat life!';' H. q% O! U6 Y' z7 c
  16.         }/ v% z4 r: b- N' W$ y: B' V
  17. }* h" ?( ~" ~7 L# N: m% T
  18. 4 A& V7 d! U% L: S( F* C
  19. use animal\dog\Life as dog;  & O3 t- f" D& g' p& J& z) {" U
  20. new dog();
复制代码

1 H  J+ i* T/ w2 k. q2 e$ ?
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
4 d/ b3 m% U4 i% S9 E0 a/ \0 w
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    ' m" n9 Y  D+ Y% Q; b/ o5 `
  2. 5 m* f" [1 |! ~/ C% d$ W$ E8 M
  3. namespace animal\dog;" A8 G2 y" U, R- T$ `; I( C

  4. 7 Y8 ^4 M0 W! e( ]6 G4 w
  5. class Life{
    - \( }' F9 @5 v3 f4 u' \2 a& v5 Q
  6.     function __construct(){
    $ A& A+ Q. L* g; `" W
  7.             echo 'dog life!';
    + N" f: v8 Q# Q$ Q% B
  8.         }8 I" Z; J/ w0 G8 g" ?6 s
  9. }+ W% `. f6 g/ d' @3 E8 h& [
  10. class Dog{
    5 M5 g! O' m- Z' R$ s
  11.     function __construct(){
    , G8 [* i  Y; t7 ]+ H; }& b
  12.             echo 'dog in dog!';
    8 g( o7 r, ]( {' A
  13.         }
    ) F1 X- |. K7 h2 z6 o. H/ h/ d
  14. }( X  l: z" ?; d9 x$ w7 A$ a

  15. ' f9 j$ c0 e6 @, M% v* ^
  16. namespace animal\cat;9 ?! o2 L* _" a
  17. : ^/ m8 J( t; q6 \
  18. // class Dog{7 r0 a6 U3 R2 c2 U8 u
  19. //     function __construct(){( g! T. B% d+ g5 [& ], ]* D
  20. //             echo 'dog in cat!';
      \" `( O4 p7 i( U/ T6 f  J) S1 u4 x
  21. //         }
    2 B; b8 i& d8 }" X
  22. // }
    " U3 }7 `2 u/ S) I/ o
  23. class Life{3 T# ], t# H  ~- A) S3 A& ?
  24.     function __construct(){! k1 O' \) C* t. D2 N$ z
  25.             echo 'cat life!';
    ( f4 M! S8 u  l$ W+ W0 C5 G
  26.         }4 g9 l0 g$ Z3 N; ^5 D
  27. }$ d! C2 ?( r1 P8 @, w1 [; `
  28. : l! l2 Y' M$ ?: y0 R
  29. use animal\dog;  5 V/ s4 Y3 _& w
  30. new dog\Dog();
复制代码
7 z9 L$ i; ]" @
如上,使用了
  1. use animal\dog;
复制代码
- p3 Z# w1 v' N+ i( ~
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

( Y& M6 n, n; q: W
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
3 \5 D- C/ Z; D- }( ?# s
+ t3 w( d2 t: a+ i! C
' r; P/ i0 s; x( C
$ I+ Q8 b+ I: x  H% p: o2 k

3 T9 {/ x3 T+ X( Z2 n1 ?) K9 T

最新评论

GMT+8, 2023-11-29 20:27 , Processed in 0.113765 second(s), 20 queries .

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