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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

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

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

以下皆为本人自我理解内容,如有失误之处,请多多包涵。
$ N1 |( x, z8 G& z# c; C* A& O
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

$ o1 Z7 K3 _+ F$ R7 z$ j- G+ d, |7 @6 J  F+ T  _( m+ C
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
$ d" k* T3 L) g4 S$ _0 `# Y  C
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

0 ~% Y) W2 U  H6 E) S结合使用方法来进一步理解它的使用目的吧。

4 q6 J1 E! E# G8 B
% F8 _% k% k9 Q2 v" gnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;% r. T3 S  C- W# f8 Z9 A5 |
  2. namespace One;
    ) x" g( v, [, T5 q8 C+ y: `% E/ u! z
  3. namespace ONE;
复制代码
( d$ X  @1 R# o" C1 Y% v* L  w7 k7 H! x
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

* Y& N$ \( G, X  t$ P( i2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   9 T3 e1 [9 M2 @; ^
  2. class Person{
    5 \3 Y8 [' f1 @/ F* G
  3.     function __construct(){
    & a( T0 c3 ?: V# w7 |
  4.             echo 'I am one!';2 \5 n9 a# {* f) a. }4 U
  5.         }- j: J( \- G* c
  6. }
复制代码
  1. //name.php7 `% V' ]# E9 {
  2. require_once './1.php';! R/ [$ o1 K4 A' b

  3. * s9 r6 i% L' u; [/ `: \' g
  4. new Person();     //输出 I am one!;
    & Q1 \4 J  T& J, S9 u
  5. new \Person(); //输出 I am one!;
复制代码
! G5 f  n7 i7 w4 H+ C, p
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    6 B5 z3 Y1 h; J# }
  2. require_once './1.php';
    ( i' _. f: Q- a6 J0 Y! l
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
2 v) Z0 @) N. X" C
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   - h+ b$ ]9 k/ f$ @& x
  2. namespace one;9 N! U/ y! M& o/ l
  3. class Person{
    2 o4 B3 O* k0 P, d
  4.     function __construct(){
    ! Q& S" }  |  z" d
  5.             echo 'I am one!';& y8 w- V; ~. t' x: Q
  6.         }1 p1 n9 V' f: K
  7. }
复制代码
  1. //name.php+ G* Y) m9 T3 x, _
  2. require_once './1.php';
    : X) P: ~' H5 r! d
  3. new \one\Person(); //输出 I am one!;  R( S6 T5 n5 ~4 ^# O) N1 A' x" A# e
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
- \7 P$ ^& ?6 F; A
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

8 m* G5 B+ U+ ~. _2 p& A5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。4 p; W6 l+ [  U! y: H7 B8 n8 F1 j
  1. //1.php   
    5 ~5 O2 P3 ?5 C" L  J
  2. namespace one;
    9 ]; |: G. o: }  T" W! S- j
  3. class Person{' F. p1 ~$ E* a/ P" K
  4.     function __construct(){5 A$ `1 c/ k5 t: p1 q( v  y2 R% ]
  5.             echo 'I am one!';
    & f8 \* e' S$ U& T
  6.         }8 k0 A* r8 D! J, z
  7. }
复制代码
  1. //name.php. U9 }4 F+ S4 |' Y  o
  2. namespace test;& F) i# @  E% x8 w
  3. require './1.php'; 5 \' `# e3 f8 k2 K- S
  4. new \one\Person(); //输出 I am one!;
    % I/ ~" U) X% M5 u
  5. new Person();      //这里结果会是什么呢,猜猜看
    9 a  U& I% S+ x
  6. 最后一行结果报错:5 ^, M) ^* @+ w6 i- t- x- g
  7. Fatal error:  Class 'test\Person' not found
复制代码
8 a$ h; e/ R$ f6 `2 ?9 x
- a" G  D' y; u
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

# G9 `; J2 v0 h( z+ T* F# p" Q: u/ [
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

( `0 G( m5 |8 e9 F
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php5 P5 A' d3 X0 b4 }% h4 S! ~
  2. namespace test;6 f$ X8 p1 D# A
  3. require './1.php';
    ) m; z* Y) h% ]) v; ~2 v3 w, R

  4. % v7 d' c& g6 j. _1 O
  5. class Person{, i* q4 e5 l9 ]" `* w
  6.     function __construct(){
    " ]" Q0 D6 X4 {8 [# E
  7.             echo 'I am test!';
    + D$ F9 o" F. X. T/ F3 d3 A5 E/ Y
  8.         }  @+ K9 |0 t: \! ~8 v* C* b6 q
  9. }# t5 p" a7 L/ \/ k" C* b+ x9 r8 H

  10. 6 K2 Q# m2 B6 p0 I1 G+ s4 J/ b
  11. new \one\Person(); //输出 I am one!;
      x5 k% X! l- n3 K5 g
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
- Y0 e8 z" i7 W; i/ n8 b: B0 `/ P
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php6 F7 M$ p8 b- v6 h* g( B
  2. namespace test;
    2 H2 |8 w  h, i
  3. namespace one;) @: |1 J% n% d6 M$ v3 }
  4. class Person{- Z% n! K8 K6 @
  5.     function __construct(){
    : P% ]; ^8 S& S: `8 k) x7 H
  6.             echo 'I am one!';
    ( j' D4 W" b8 N2 J2 i
  7.         }9 J% [; w$ W/ W4 K5 u
  8. }
    ) ?$ z4 p4 D/ F  m3 X' {

  9. 1 a, `6 {. A) G% a4 v
  10. class Person{; u4 ^" ]9 j! l$ Z
  11.     function __construct(){2 p. C( \$ ]7 o- U! N
  12.             echo 'I am test!';
    ; V& x  N; n7 T3 ^
  13.         }
    5 W5 y8 R9 A) A6 u
  14. }
复制代码
! R2 B. ~* J/ E2 \
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
) S  O( y  O: F3 e  Y( b
看来简单的把require理解为替换,在这里行不通。
5 I$ U) O! t% P' u) ~+ i
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
4 X& c) Y/ `9 z# ~
  1. //name.php6 |) E# r0 L# }' c# J0 p. Z
  2. - {1 G0 r$ \3 K1 q; _- e) p* _
  3. namespace test\person;
    ' J& Q& U5 v* V8 t4 l; H' A
  4. 3 ?4 o! D! K2 F1 {5 C6 [6 g
  5. class Person{6 m: t: s- ~  C. _( T$ V
  6.     function __construct(){
    5 E! u) F. b9 U% b4 E4 N
  7.             echo 'I am test!';
    , q) a2 S/ u: ]( H# n" X$ e8 z
  8.         }
    2 s$ c0 `0 C0 F2 m5 v1 ^- i
  9. }# i0 }5 H& n1 x$ S  K
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
% M% z" {1 M3 v: n# _5 Y% H
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
- k; u5 i. Q$ k, ~
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php* l7 y- w% ?2 m  l/ i  [
  2. 5 Y7 S/ V* A7 e1 y7 e7 [
  3. namespace test;& D; V. z1 ~; @
  4. echo 'zhai14';; p7 j# H/ \* \; m' i. }
  5. namespace zhai;
    7 K% ]+ r, E  ?" [) ]3 L; r! Y
  6. require './1.php';
复制代码

  i3 \" f+ X5 D2 j3 M2 ~/ F- ~
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
& L! }1 O- C: e( ]( o; B; A( ]
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。- u& k/ I/ q' ]6 u; h
  1. //name.php
    % B- e8 D! b5 T  x) W1 b2 k3 l

  2. " r2 Z0 G( T" ^5 D* a6 h
  3. namespace animal\dog;
    7 [9 Y+ j- v6 S$ Q# g
  4. % P+ z6 b, L6 N$ l9 C6 l6 b3 M  t2 [2 E. S
  5. class Life{) R0 q+ j! G- ?& M+ p
  6.     function __construct(){
    & a: K; J4 r. g6 |
  7.             echo 'dog life!';
    ( z& \' k" m* K" d2 B
  8.         }# N% q( m, P; Z. H* d
  9. }
    7 |2 B$ O) Z! i6 I/ w, f

  10. ) h( H! P- A" |8 t( `7 d+ \
  11. namespace animal\cat;8 H' V+ c: I& F9 w
  12. 8 R6 j: _- |$ S
  13. class Life{" Y2 ~+ _. J1 y/ k& i
  14.     function __construct(){
    7 f8 @6 f1 x! K' d3 E' @
  15.             echo 'cat life!';! w+ A5 a( ~( {- [: s0 f, A
  16.         }: J( M: z" e8 |! I
  17. }
    6 @/ _: ^( Y6 w* `6 P6 }. J5 D  Q
  18. ( K7 Z7 c; W, N8 n% L$ N% K
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间! |3 y: e6 q* k+ c0 y1 o1 d
  20. new \animal\dog\Life();  //A) N: T# B3 k0 }8 Q0 r
  21. * z, Z: j! i# g9 G7 A2 B
  22. use animal\dog;  //a
    4 B4 x+ `2 x7 M, F  f2 w7 {2 Q
  23. new dog\Life();  //B
    7 m- W3 z  @2 J+ l5 M

  24. ( H; Z9 s6 ?6 C) g' G: G; M9 Z
  25. use animal\dog as d;  //b. j& N- t; y: |  ?) Q+ o, S
  26. new d\Life();
复制代码

( y1 w' X' u) \
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

0 v! t( |+ U4 [
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
1 }! t% A( K$ r- k
相当于
  1. use animal\dog as dog;
复制代码
, b7 H0 ]5 o1 ]3 m) h
2.namespace后面不建议加类名,但use后可以。
  H$ p% |9 P+ n9 k1 t3 P
  1. //name.php& t9 n6 B" o$ Z6 I' O4 r% e0 ^/ }
  2. 8 `9 `) K$ c. c4 X
  3. namespace animal\dog;
    ! |7 I+ ?6 v5 m2 s% L

  4. " Z% Y& ?% k3 L+ q
  5. class Life{
    # w  b5 J' ?5 }( l. s( J* ?# A
  6.     function __construct(){
    ( g9 f8 c6 Y8 e# A9 `7 A% `
  7.             echo 'dog life!';. ^5 B9 C' |( C0 x
  8.         }& V$ g, R& q& @  X! ?  f0 l
  9. }, r5 O2 E' k- f/ E+ M& g( c

  10. 5 B% K8 C- V! `) r
  11. namespace animal\cat;" U- E' k+ R) Y7 ]9 J" P4 C

  12. 7 o. I7 M# Y$ Y. a, {& x: C
  13. class Life{
    3 @+ r* \( h& ~4 ^5 _, P
  14.     function __construct(){' g0 {# P3 c& t7 r) B
  15.             echo 'cat life!';2 S3 |$ E5 z" |! \% n
  16.         }
    + H( r3 S5 d- M! b
  17. }
    ( z1 k8 O( [, W/ z

  18. 9 z$ m: W4 |' C4 \; a
  19. use animal\dog\Life as dog;  # V8 r" M2 T* [/ e  C+ t
  20. new dog();
复制代码

+ I0 Y; u4 Y: r# H6 }
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

1 p& o5 u# [5 f9 l. S/ B& A8 {
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php: ^; @1 e8 j* f' @$ O5 f

  2. 3 x2 G" m5 j' k/ a, `
  3. namespace animal\dog;
    0 b) z; D: L  [) b$ n# V+ u! ~4 p! E
  4. " k( f0 C) ?0 j5 I
  5. class Life{4 g1 e" o8 O0 Z- x6 r
  6.     function __construct(){. e$ C  v/ J. }. L; C: H" T
  7.             echo 'dog life!';2 i4 l5 M$ M: J* n7 p" ~
  8.         }
    5 w5 g7 V% E0 Q! f3 o
  9. }
    9 k. c" [4 c, s0 U5 n
  10. class Dog{
    4 Y* c3 X! S" M0 z
  11.     function __construct(){3 |2 M7 _8 W& B" \
  12.             echo 'dog in dog!';
    7 Z7 y1 g. o& Y: ^$ ^, ~
  13.         }& z  w9 J; i6 d9 z8 {9 O
  14. }/ I: N: {9 K* n8 C
  15. + h* \( _) P, f, R# a0 h
  16. namespace animal\cat;
    # r$ r* ?# Z( z! \/ Y& f+ J
  17. 3 Q7 Z# S0 C. F* V
  18. // class Dog{
    # C) n0 r: T! D- w
  19. //     function __construct(){2 b9 @9 e" ]5 _% _
  20. //             echo 'dog in cat!';$ C1 @- K' a' x+ a5 d
  21. //         }
      ^2 I3 W, U% ^+ ?$ K; x
  22. // }
    1 j' l  [$ T) Q7 ^
  23. class Life{0 y0 g- }( J+ ]1 ~3 I
  24.     function __construct(){
    4 C+ g' V" Q* H) A  Y
  25.             echo 'cat life!';
    & }9 L8 K  ~( V4 s$ e
  26.         }7 x2 {3 @% w* @" w2 ^& v7 W" G* d
  27. }8 @9 }; l# ?* [2 u

  28. # ?/ f! ^4 j( f9 ~# P4 J' ?- N
  29. use animal\dog;  , t) g- ]; ~+ X2 x% R# W3 y2 H8 Y
  30. new dog\Dog();
复制代码

1 Y  ~3 v; O! _- d
如上,使用了
  1. use animal\dog;
复制代码

  l( k8 G& z8 W) ?/ J9 ?) G
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
* k/ t+ k% t3 K
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

% n( ]: }3 `  v4 q' o9 z! z' E1 e8 A8 f0 ?: S
+ }$ A; E" U$ k7 E( I

+ n) V% W- n( {8 c
7 k+ u$ o2 {: i7 j- i( g1 G2 F

最新评论

GMT+8, 2021-8-1 12:51 , Processed in 0.193739 second(s), 22 queries .

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