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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1538|回复: 0

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

[复制链接]
发表于 2020-7-1 23:37:46 | 显示全部楼层 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
( E$ c9 ]2 m6 A4 Z: H
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
2 `" g, k  K6 f2 ?, Q& L

2 k7 B& _) h' Z4 ?; u使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
2 J1 P2 D3 S$ E( g( s
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
- H0 `; J. o" ?3 v9 O, R6 m" n2 e
结合使用方法来进一步理解它的使用目的吧。
7 @) x" C) f) [
8 _- _& z( ]0 _/ `8 x$ l* }
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    ; t8 Y2 q4 O! T2 p3 P
  2. namespace One;& W7 d$ E7 |9 j
  3. namespace ONE;
复制代码
! v& n# e& m: }+ {% D- [* t9 i
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

- v2 \( K- I6 `. m0 t+ ^2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   / G6 h; l8 C- F5 J  H* N: U
  2. class Person{
    " K; \9 D% P4 _" R' K4 U4 P
  3.     function __construct(){6 P( |$ |: Y" _* G* R. ~: ]
  4.             echo 'I am one!';* h( Z- V6 y) C# Z) M8 v) ~
  5.         }+ L/ [! {2 B- o3 D( ?7 b
  6. }
复制代码
  1. //name.php
    4 p9 u5 {% ?) p2 f
  2. require_once './1.php';/ B! _3 e6 a+ }& }  z- G

  3. & {* e! o7 x" T& x' q7 o7 c
  4. new Person();     //输出 I am one!;4 w$ x1 O5 N9 ^/ G
  5. new \Person(); //输出 I am one!;
复制代码

& w' D* o- N+ p$ k3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php! N4 n, D, f9 t% z7 b
  2. require_once './1.php';0 E' L6 b* ]4 I& M& R
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

9 Q6 z1 W3 z2 t" c% J! _4 g4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    / _! k5 s3 Z1 F( I1 i5 G7 `
  2. namespace one;+ u( s5 V, {* ?% R  P1 t8 O
  3. class Person{3 C. F( H: Q+ M6 u- n) `( k$ L+ _
  4.     function __construct(){5 Y% o8 C: ?4 j
  5.             echo 'I am one!';
    & m2 G! C$ R8 I( |% _8 T  d
  6.         }
    ; u) i# U9 |- k( M3 m' v% d
  7. }
复制代码
  1. //name.php) @& I" [5 E4 C& S
  2. require_once './1.php';+ L0 f: L3 q: l) e
  3. new \one\Person(); //输出 I am one!;
    ) ~5 {* o: y3 B% S
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
6 K) Q, N" M! E3 v5 j( q" A
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
5 P0 _$ [  w5 F9 S7 B% \
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
0 P% ]: y5 _1 Y' z4 I
  1. //1.php   
    / t$ I$ C7 g! J; s% e* n
  2. namespace one;3 s) ~  y3 y: v$ C
  3. class Person{5 Z( O% {" m+ r9 E" w8 `
  4.     function __construct(){' a+ v: Q$ f2 o; \- ?
  5.             echo 'I am one!';
    1 [( \1 j* T  @" X" B$ h- h
  6.         }' k8 n; ]" b4 _# Z
  7. }
复制代码
  1. //name.php
    + |4 X. I7 G- y! X+ O) \
  2. namespace test;( W9 T3 ^  K1 D# n- U" U
  3. require './1.php'; 9 v- ?3 [& _  ?# }% P$ I) L
  4. new \one\Person(); //输出 I am one!;
    0 z1 v* Y5 ^0 k& k( ^% }# i% O8 a+ V$ B
  5. new Person();      //这里结果会是什么呢,猜猜看- w) b) u/ Q6 q4 z
  6. 最后一行结果报错:
    & K% G" H6 f; X/ S9 y( J; I
  7. Fatal error:  Class 'test\Person' not found
复制代码
8 Z! _! k! O% N" o$ Y8 ~
9 e. T) c  O2 c
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
6 X( z9 v. \7 N. F3 t
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

/ e# I' L2 K+ l3 t4 x$ O* W6 X
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php- i# [. P' w& t' i
  2. namespace test;6 N3 ]; N' S6 a2 x3 B/ N& c) w
  3. require './1.php'; 5 Q# \. D) x" P

  4. 6 q- t) r4 a5 [* U6 W7 H4 H$ ?
  5. class Person{0 S8 p2 y1 {) o. D$ `/ a, T
  6.     function __construct(){
    " K4 W8 J8 Z# n
  7.             echo 'I am test!';
    - e5 }) h0 a% Y4 n, a
  8.         }
    + N, ]& J) L8 H- H- k3 O. F
  9. }
      f- v: B" V. z. k2 r' }, _

  10. - a! D# Q- ?: X
  11. new \one\Person(); //输出 I am one!;
    % |. Y9 b* ^3 g9 h& ^) n% v; q, d
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
7 J7 S% U& `/ @% t7 C; b  J# ?
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    + U* K$ l# f, H& P
  2. namespace test;
    8 ~8 v, }$ ~# {) \! B
  3. namespace one;
    7 G# r: ]) a0 n+ u
  4. class Person{
    % Y( g) c$ I) G/ v4 _
  5.     function __construct(){' P  F& r1 {0 ]0 K( m- P- s  {
  6.             echo 'I am one!';
    " r) t: @; O  [! `1 V7 f
  7.         }* |9 p. i$ \7 c! R$ ~+ |
  8. }
    4 t6 U8 L2 Q) j4 K

  9. ; v: t# w* J  c3 R+ N" ?
  10. class Person{6 R( P; s; B9 f' k6 c
  11.     function __construct(){* _  F) u" t- L6 R: x, d  t; Q
  12.             echo 'I am test!';
    ) O! O' q: ?7 |
  13.         }
    . y1 l0 i0 l0 \
  14. }
复制代码

* H/ ^" r, {7 s, \! J" |
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
2 g  l) c4 c, z3 y9 M% y% X
看来简单的把require理解为替换,在这里行不通。

( l7 |2 i& z/ `6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
; ^$ K1 d9 q( K6 N1 q
  1. //name.php8 u1 }& o- k# k! }1 y4 I

  2. $ X& Y3 U" [2 Z7 a
  3. namespace test\person;$ t* M" }, k& i2 ^+ n- d& n  |
  4. & {' F: ~7 `8 E- @: n/ T  b- R, Y
  5. class Person{- Z) W) I3 Y3 c8 O0 n" s9 a
  6.     function __construct(){
    " E% n, B# ^5 a7 M4 I
  7.             echo 'I am test!';1 e1 b" m. Z# q
  8.         }
    $ a5 N- O$ _6 U+ f- ]
  9. }/ ~4 E, s1 D* j( |4 N' l$ J4 v
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
/ n9 p4 u$ E7 T: F
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
4 ?6 J+ O3 O! u- U1 x
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php: `: @  `% k% |( L( W) h' l; K

  2. * E- g; p) t6 L, L  o4 n' X2 b
  3. namespace test;4 v8 r! u* `; A0 R7 O- P
  4. echo 'zhai14';
    " N+ u, B3 ^4 E
  5. namespace zhai;" m- `( H1 i- b- \
  6. require './1.php';
复制代码

7 d2 ]4 I7 z9 d6 `. ^3 |
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
( x: k. f: y( i3 C+ M' O
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
' v  c" t+ {! a
  1. //name.php! T: H" v! n( P/ _
  2. ) J7 Y; g; j" H8 h* \2 y% {
  3. namespace animal\dog;
      K( o- B. K" Z% ^5 D3 X( j6 `
  4. 1 R6 C2 _' g. \6 z3 i0 v
  5. class Life{% Y( @- H5 _+ }1 u0 E; Q
  6.     function __construct(){2 E# y/ C! i! n6 ]# |- q, d' V
  7.             echo 'dog life!';+ \! f: o. q0 q! G$ ]% O- r* [7 [
  8.         }- _2 i$ B( ?5 S' F' t) l: U7 `/ u
  9. }
    : G0 q5 k  p( W7 z  }4 x
  10. 6 G) S/ Q! r+ r# p+ S/ l- r; x
  11. namespace animal\cat;8 N# y; k7 D4 `

  12. 2 a% b" |6 B$ j# F1 S3 u3 [- d
  13. class Life{, n9 W9 t1 F/ A
  14.     function __construct(){0 C8 j# O) W1 v
  15.             echo 'cat life!';
    : k6 }" u8 V0 }8 }7 s' P% w
  16.         }
    - N. p8 B2 z% i  L# _
  17. }
    5 ]2 I* T& j* L( r5 K7 P8 m- V

  18. ! N* P4 w& ]# |1 h7 M5 s: p( b
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间% H# k! A% Y* f
  20. new \animal\dog\Life();  //A: O1 I. C1 {7 F% z' ], k1 q
  21. 9 q2 C. ^6 q" r
  22. use animal\dog;  //a$ ^1 H. t: r* b8 v: C6 q
  23. new dog\Life();  //B4 T1 j- u5 R& ~: a  A
  24. # Z7 B4 p( [# T# N8 I& ]
  25. use animal\dog as d;  //b
    3 R- s3 U% `" B* G
  26. new d\Life();
复制代码

7 y' Z! R$ |* n" e4 F$ A3 z6 j
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
0 T- P% P" u* h; c7 V
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
! W  |( j4 v/ v8 b# _4 v
相当于
  1. use animal\dog as dog;
复制代码
+ n0 L4 e7 \4 o, z: G9 Y) y
2.namespace后面不建议加类名,但use后可以。- F* w6 d/ b# C+ v" J$ n0 c* L
  1. //name.php
    & E6 g4 \. |0 `) z8 V
  2. $ f) j6 Y( [3 |! {* d& k5 c6 u3 c* P
  3. namespace animal\dog;
    $ J  B+ S# D. I) S$ O/ F# P
  4. 0 p, D- |1 s8 q4 l% [3 X$ u4 Q8 ]) h
  5. class Life{  K2 }7 V6 p; w% p# j' g' E
  6.     function __construct(){
    0 j) d. G/ `& J  k4 ]% K2 R7 S5 ^: |
  7.             echo 'dog life!';
    8 W' w) i" h; E$ @% s3 `
  8.         }, k5 e( [( D& @
  9. }9 C7 x  |  z# v' r! m
  10. % N2 s( ?  t( L& V3 c: g
  11. namespace animal\cat;
    6 q% ?' J6 n7 z. N/ k' \

  12. / X: m  C# B6 o& M4 L
  13. class Life{* T7 I/ D4 B/ V( L! n3 W. ]3 q
  14.     function __construct(){& m! K, m9 j- G/ T! d) D
  15.             echo 'cat life!';
    - W9 q: p- e: G
  16.         }! }) F' _, y' a
  17. }5 ?% T  r& Z; `8 Z& Y2 V
  18. : W& t, l* D1 I0 j
  19. use animal\dog\Life as dog;  " @' z# ^* R+ f4 v1 r
  20. new dog();
复制代码
( r4 _) A& K. V- G# a. Y/ Q
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
5 n& i- N) G) H; c
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php- J- f' c& Y3 g6 t0 L$ q
  2. 1 `" H' u- {  |
  3. namespace animal\dog;" @! `9 \: y+ a' v6 U
  4. % P  |, m7 Y8 @8 I& Y* l, z
  5. class Life{
    . K  U2 A# b8 }
  6.     function __construct(){
    " P- D+ L9 d0 R# X# W$ r
  7.             echo 'dog life!';
      L: y1 K/ m) C0 e! I$ B5 q9 R$ [
  8.         }
    4 h! o4 p' H9 G+ D/ q" E- O, d. u
  9. }2 R: N: F+ b% p8 ?3 b
  10. class Dog{; Z3 c" t, {5 X& B7 f8 c
  11.     function __construct(){0 Q* w7 A2 H/ X! g2 E/ k
  12.             echo 'dog in dog!';4 C# |* ~# }+ B# M+ _8 h4 {
  13.         }2 E; v$ O! J4 p$ u/ u
  14. }" R. m6 O% f! d$ l( a% f: l# O
  15. , B8 P; c& P3 t0 Z. ^6 @  @$ s
  16. namespace animal\cat;3 ?9 ^. h# b7 M$ [$ x
  17. ; e. U4 R" V1 N6 b; J* J
  18. // class Dog{
    8 l/ K6 G" F$ j) N- V/ ]0 u% [: h8 g
  19. //     function __construct(){0 V' @5 @# M6 c- `
  20. //             echo 'dog in cat!';
    $ Z, w$ N  q3 u! G+ Q' w7 G
  21. //         }
    1 [& G) r: v6 R& n
  22. // }
    % E/ x1 H0 Q6 h. a6 _9 W, o
  23. class Life{
    $ [) r( k7 d+ e. V* N* D
  24.     function __construct(){  g3 l, S9 O& A" a1 C2 E' y
  25.             echo 'cat life!';5 v& Q* o- K  v  R# _
  26.         }
    ! S) s2 h- n1 B0 S* e( `
  27. }0 W6 F3 b2 c- w* v2 l
  28. ) s7 x4 e7 }# U# \4 i5 @
  29. use animal\dog;  * ~8 Y0 h  i8 i
  30. new dog\Dog();
复制代码

; Z& x0 w" @' W- X4 L
如上,使用了
  1. use animal\dog;
复制代码

$ M/ \% _% f. @# u
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
- i4 M* R$ e, f( O8 z( Z5 y+ _
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
5 a. _9 n1 \# J

$ W# a4 u2 K# _8 O0 s
. P7 ^; }: t8 _, a! A% C+ A- |8 n- @' ?6 F( m
3 M# \" x4 D' ^8 D+ ^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2021-9-17 15:29 , Processed in 0.131852 second(s), 22 queries .

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