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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 8485|回复: 0

[php学习资料] PHP命令空间namespace及use的用法实践总结

[复制链接]
发表于 2020-7-1 23:37:46 | 显示全部楼层 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。

5 m; D& {  B' Y9 b
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

, ~: b6 G6 z. s: z( s# N$ }) T
+ O. D  o9 N; g( U* I( m1 N# P  s使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
3 Q" c2 N- [; ?, x+ o2 g8 o
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

6 \5 }$ c% Q3 k4 ]7 o# K结合使用方法来进一步理解它的使用目的吧。
1 X3 C# p9 ]2 s0 O

' m$ z4 q  b; |, n+ Mnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;% {3 g" O. h7 M2 o) p1 Y
  2. namespace One;
    " G6 L" n' [* w* H. Y, D  [
  3. namespace ONE;
复制代码
9 P" V+ t5 a' i
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
8 c" y  k0 [" n
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   " t0 }. \- x) \, i
  2. class Person{8 Y4 d! B3 o% j$ Z$ f4 N1 w
  3.     function __construct(){
    2 {9 W1 C/ q( G1 P# o2 M. W
  4.             echo 'I am one!';5 n. u! D/ J; g' U3 P6 b
  5.         }' @' a  y* L4 i* s3 v
  6. }
复制代码
  1. //name.php" i* R- v% m9 [/ h; E( Y
  2. require_once './1.php';" z' I3 ^' X; C- V2 n$ i' p, S6 i
  3. " b: ^  ]5 I! G6 O. P" w" L9 V
  4. new Person();     //输出 I am one!;# ^( X2 A' t' k7 l2 |) \' r8 D
  5. new \Person(); //输出 I am one!;
复制代码

/ A  b7 M  |) B3 k! M3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    % ]* `' x, G( K. d. \4 S
  2. require_once './1.php';
    # H+ W; B7 B7 p# G9 b" J
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

& G  N& p) m1 Z4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    ( ^* b1 y  o: V1 c! [4 Z
  2. namespace one;
    9 K3 f5 X! u8 m* Y% ~
  3. class Person{0 }/ G) V+ Q" N% s; O6 }! h  y7 y
  4.     function __construct(){
    7 x8 K8 y9 i" q+ m& D! V
  5.             echo 'I am one!';) l7 ~# s0 H6 h8 J; Y5 ]+ j) b
  6.         }8 R/ _- J3 @9 L& B0 b' ~
  7. }
复制代码
  1. //name.php
    7 g9 x* m, o1 h* P3 H
  2. require_once './1.php';* B3 `3 D3 w# L
  3. new \one\Person(); //输出 I am one!;9 D  p6 D7 g& J( }3 L0 U+ ^  q
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

9 W! H3 C: e3 T- U4 e+ `5 }
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
- a# P* M+ D+ _; w% V! v
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。) z' a) _9 t1 ^" o) z, r3 p5 u- B
  1. //1.php   
    $ [) ?/ t+ o$ l4 N( y7 k. Z
  2. namespace one;; X9 P6 @% e1 ^* f9 C5 J. e
  3. class Person{
    9 Y+ A4 g. ?% @# |4 t" {
  4.     function __construct(){
    , Y1 S8 i8 G% c
  5.             echo 'I am one!';4 ]$ c3 w* T( [
  6.         }8 f; O: W3 R/ ~7 O1 i
  7. }
复制代码
  1. //name.php6 t, a8 _( @5 @1 ^% ?1 D
  2. namespace test;
    ) c9 g4 F" E3 b4 O: A
  3. require './1.php'; ( f3 g( p! F, H" z3 ^  w1 g2 U/ A
  4. new \one\Person(); //输出 I am one!;1 t, k5 {" |% ?. s
  5. new Person();      //这里结果会是什么呢,猜猜看5 i4 D0 E; ~; z0 b; e% n
  6. 最后一行结果报错:
    8 G$ P, A: d/ x; p: \  h' Z4 _
  7. Fatal error:  Class 'test\Person' not found
复制代码

/ ^: |7 H& D, h1 T
6 L* [# i7 }& ?/ F% }
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

5 M4 M: Z( w, Y  i) P- n' u( Y
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
0 {0 f3 ?7 {5 A
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php. x9 D; P0 N" M! i' ]& ^, a
  2. namespace test;
    9 n. M0 G8 y+ @4 z. e6 C4 a
  3. require './1.php'; : c  ~1 |; U+ R7 B1 H1 P. H
  4. 9 O1 K& X/ ]8 v  Y! ]; Q
  5. class Person{
    % d+ K* C! w9 b1 ~6 j* j6 h
  6.     function __construct(){, x. Z( D3 r6 G: z! j
  7.             echo 'I am test!';
    1 I# h( g; I/ X  k
  8.         }+ U: l1 K! [& ^9 K5 v" M
  9. }7 F0 t* U6 Q8 x" {8 i% _
  10.   [8 e: j% G* U4 f& H" R+ m+ Z9 g
  11. new \one\Person(); //输出 I am one!;* G$ G* c) }9 ]# {0 o
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
  [7 Z/ E3 c' X% _1 ?: Y9 p8 P( F
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    ) f& B4 H. P+ t% a
  2. namespace test;! ]- X3 A0 ^7 O
  3. namespace one;$ z0 |; c8 S3 ^* J
  4. class Person{9 C) [; P; G8 M% {
  5.     function __construct(){9 i. y% k: X, Y: f% I9 I! t& y
  6.             echo 'I am one!';, L- O/ y9 p, ]7 [' m
  7.         }- W) t5 n/ |7 N; h
  8. }! t7 o8 ]- \6 Q
  9.   h$ o" }+ c  _6 w# P
  10. class Person{1 W$ D  A. M+ t  |; W
  11.     function __construct(){
    , m* S+ D2 ~) i) T' Q4 `0 q
  12.             echo 'I am test!';
    : S( F. `3 m2 x  }+ W! j
  13.         }
    8 }3 i2 g. h2 P- J
  14. }
复制代码

! W: T' j, ~4 A% w
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
7 N+ N" t' t3 V& e
看来简单的把require理解为替换,在这里行不通。
, c: R, m9 O1 Q1 g- h
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。8 C5 I, B$ p6 |. t
  1. //name.php
    $ A2 X- [5 ~- n9 ?' K- k' c
  2. / ~: D) e6 P; [
  3. namespace test\person;
    & _0 H. d. p2 ^8 [! q

  4. $ U1 \- ?8 b$ E
  5. class Person{
    6 z: W& c* c! b( b# ~  p" o
  6.     function __construct(){
    $ {$ s+ c& ]- y3 {/ _7 I
  7.             echo 'I am test!';
    9 C* I# J- \- |! L6 U" ^
  8.         }
    6 ?. A7 M0 O9 w4 M
  9. }
    4 P4 f0 P7 a( y8 L* l6 O  o
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
( h0 T. B; U1 M
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

- ^  l7 Q- i6 I7 {6 u5 X7 @7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    & W( S8 K# Q/ ^$ C0 Z
  2. 5 q/ p1 M2 |' B1 E6 Q# X
  3. namespace test;
    . X3 C* R4 ~+ ], U3 t
  4. echo 'zhai14';- x% w: f- _7 V* J4 r( i( Y4 l% _
  5. namespace zhai;
    ) k& y& A( B/ \  F( j2 I
  6. require './1.php';
复制代码
! L8 Z' o% V8 D+ j2 G
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

6 c  V& u8 {# M4 t# y2 @( _4 wuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
7 C- Q, q" \; e8 n1 D3 @
  1. //name.php
    $ l" |% z# I* W: p" m* U. d: D

  2. , n2 w1 p7 u/ P
  3. namespace animal\dog;& @3 S5 L( o7 B& [  c+ C
  4. & `; f: j% L" J
  5. class Life{
    ' L/ K9 P& D! b: B: m$ d4 J
  6.     function __construct(){5 f( G+ _  h8 U( ~/ L( P
  7.             echo 'dog life!';
    + r) H- ~* f, p  m. s
  8.         }8 G, x. e- j, D! @# y# g
  9. }8 i# L/ Q" a) W& P( t& M! k$ q

  10. ; e- I8 C# E- Q3 t! |1 ]% L4 G  @$ l
  11. namespace animal\cat;
    4 `6 o/ t" ~0 R+ }7 }+ P' N0 U' `$ o& N

  12. 3 P: }8 s) e7 s" Y+ M
  13. class Life{. f9 f- m, F$ y
  14.     function __construct(){% i, F2 ~: M# g! R. `* B1 T
  15.             echo 'cat life!';: M' A9 U. `5 P4 l8 x+ _
  16.         }6 s  D. r6 Z- Y: S/ h) i2 x
  17. }
    . K7 c2 j0 L  N* \/ x9 }. f% q9 L

  18. 9 r$ r0 @6 G$ x, G+ M
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间3 V; O, p  F3 K9 j+ Y% N. ?" ~8 K3 E, C
  20. new \animal\dog\Life();  //A3 N: e6 n5 Y7 H* y- T6 j9 e0 }5 g7 W

  21. 4 Q! l6 G* ~4 Q# N0 r8 k1 m  N
  22. use animal\dog;  //a
    + Q* p) R2 E# m* N; u* T$ t
  23. new dog\Life();  //B2 u  y( A/ d2 l

  24. + ~! ~3 @) B% A# `6 B: R+ f$ o  K3 \
  25. use animal\dog as d;  //b
    ' T8 D! {3 O/ p/ p3 ~
  26. new d\Life();
复制代码
* \# a2 P6 y/ ~+ s6 }1 {: x
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

! H6 N$ g3 o* H) ~" c8 t
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
" s& X/ k8 J6 e
相当于
  1. use animal\dog as dog;
复制代码
; e, Q, l$ X6 i3 g$ j+ H
2.namespace后面不建议加类名,但use后可以。. ?& }1 V5 x. \4 ^' J
  1. //name.php$ E5 S7 b% D3 \, l. r$ W

  2. % ]  F) l) Z( V* {
  3. namespace animal\dog;! g' c) O. X* Y" I' z  K6 V
  4. / B3 ]) P1 c  u/ d# i
  5. class Life{
      k& H5 p* ]) @9 }. K8 K3 L% ~
  6.     function __construct(){
    ! d# }% C9 A4 Q& F7 G2 u: H
  7.             echo 'dog life!';
    7 C" `  Z: ?9 D; \3 I
  8.         }
    ' p  H' q/ S; r$ ^. k
  9. }
    5 v& x9 `9 ]; K) g, U5 Y
  10. ; [" e9 h; }" V2 a4 N
  11. namespace animal\cat;
    & t9 P3 O4 y0 t

  12. + V  w. H! U. w  w; ?) X
  13. class Life{
    ; @/ N, ?9 q% H0 V7 Q# {
  14.     function __construct(){& m9 W8 t0 F% u/ ~( q' V  Y
  15.             echo 'cat life!';
    0 v  B3 W" k; i# n2 Q3 ]# V. r
  16.         }
    5 L6 B" x& z. y- W% f% a  V' c* b
  17. }
    3 X$ B) T5 I* E
  18. . i: k4 k: _% g! g4 M" ^' J$ M, Z
  19. use animal\dog\Life as dog;  
    5 ~* T) t; E, n/ z& T- b9 h; r
  20. new dog();
复制代码

+ K7 N  P. w$ _, O
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

: k. d' G+ M! d3 o4 M+ z) ]9 O
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    # m: y/ R; G8 z7 j

  2. " y: |3 I7 X" ?3 _
  3. namespace animal\dog;
    ' }7 O$ ^( u0 O) [& |) |1 u
  4. / e: }# p1 |3 P5 x4 j
  5. class Life{
    0 j- r- x& D5 k9 O; Q5 J
  6.     function __construct(){9 \$ ~& S; _/ z7 i. j# V( n  H* _
  7.             echo 'dog life!';
    & r* k$ J7 F2 Y" t1 u
  8.         }
    # m5 v5 S8 s( q( G; P% K  v9 z
  9. }
    5 ?- J% P# z9 n& G1 Q6 t
  10. class Dog{
    * d& T& M0 X+ q6 G* c
  11.     function __construct(){
    % J/ Y3 t5 I, ]( g/ ]- U2 n$ V
  12.             echo 'dog in dog!';1 Z% {; e+ C$ F' R& K. g
  13.         }
    * {+ U' [3 e% ~# ]
  14. }
    7 ?  r2 r9 g% r0 w5 A

  15. 4 o* W' m3 U. e( e6 d
  16. namespace animal\cat;
    / E3 Q' Z" ]$ |

  17. + T4 H. @6 s2 q3 C* J
  18. // class Dog{0 x. x" r0 Y2 Q+ d
  19. //     function __construct(){0 N3 g" ~; _% q' O4 z8 a4 \
  20. //             echo 'dog in cat!';) {3 v) A' G: S1 L- [
  21. //         }
    , z) H8 f" `2 N) U
  22. // }
    3 a) Q1 @2 W0 e& D
  23. class Life{
    0 F* V# L6 Y% r) X! k; ?8 f! t" ]
  24.     function __construct(){
    8 P; j7 M$ R) Z: T& c
  25.             echo 'cat life!';
    ; a  e$ U7 G2 K7 |' t
  26.         }
    1 w5 p4 O/ u  B4 K2 p( u
  27. }
    9 i. R5 a6 B1 i' ]1 |( J8 x
  28. ' p9 T0 Y! U  Z) ]5 m
  29. use animal\dog;  ! m5 b; b3 {7 j; K7 q
  30. new dog\Dog();
复制代码
7 M& z# I1 a: i8 D0 u
如上,使用了
  1. use animal\dog;
复制代码
, h/ G" z: ]- ~' o/ z* n/ D
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
# v5 t; _! E- ?4 P
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
6 Y1 R- }5 J0 R% c! g1 c, g
6 t; H9 [7 {3 W4 @* w8 T
( a* e) |: l# r

- q( Y" H5 H, J  C3 v  A
* t& P8 v( X* z! a* A
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-3-28 16:54 , Processed in 0.152189 second(s), 22 queries .

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