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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 9077|回复: 0
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。

6 U' C% x/ T" ]: c' I
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

7 H; X% ?- m+ P; X& L3 r0 @/ I; t, G, q0 e: \3 S
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
; q- W" Q1 Q: Z' O. C; S
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
8 m  U) w" U* w8 W0 o7 }- H4 e
结合使用方法来进一步理解它的使用目的吧。

+ V$ G  y- A4 h8 X  p) L2 }! H5 X2 B) R' m9 z
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    , l4 r) M1 J" S2 J
  2. namespace One;
    4 P) g! t9 u9 m3 K! l- E4 A' g
  3. namespace ONE;
复制代码
1 z8 P% R( H4 y& \2 J! A, G% |
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

; O2 z" y/ }' w" a2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   5 S& ]+ G+ _& `. m! P1 b
  2. class Person{. V# C5 M5 A0 o
  3.     function __construct(){( s- V( l: p3 A6 B! t
  4.             echo 'I am one!';
    ! c/ J' P' V" [( N6 E% J# Y9 B
  5.         }+ b! X! N2 ^1 {/ I. h/ _2 n
  6. }
复制代码
  1. //name.php2 q0 K" q8 n2 o- p- a
  2. require_once './1.php';
    1 i" O3 Z, J% b$ l$ j( [4 G. T
  3. ' V3 e6 \+ G: N& w; a
  4. new Person();     //输出 I am one!;7 |: s+ }0 }7 a8 E/ \. |- H/ x
  5. new \Person(); //输出 I am one!;
复制代码

) m2 @0 y8 e" g4 w3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    $ n9 r: D/ u' ]2 {
  2. require_once './1.php';
    2 G2 V) m+ s* W9 Q2 ~; N
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

5 A, V0 ~+ N& C4 h/ t5 n4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    # C) Q. a4 G0 h
  2. namespace one;
    5 P; U) L7 ]  u! e6 W
  3. class Person{/ P6 J$ K/ U: O" Y/ |
  4.     function __construct(){8 L5 n9 T  u  t4 K/ |$ i. E- b6 G% F
  5.             echo 'I am one!';0 o) h# p* v+ v8 d( Q+ p2 T4 x
  6.         }
    7 X2 u, |5 S7 ^& c
  7. }
复制代码
  1. //name.php- y$ `6 k4 g3 b/ b3 b7 V
  2. require_once './1.php';
    " E2 |8 K: B# _, `
  3. new \one\Person(); //输出 I am one!;
    9 N; @% h4 m  R+ Q' e2 {4 Y* [7 }  D
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
; s# _8 S6 M4 {9 e. z0 A5 Z1 Y
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
3 j( W) |. Q; G8 a" }0 y
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。+ t9 i5 b1 a" F
  1. //1.php   
    8 q! V1 K: {/ c
  2. namespace one;5 X  S! L0 T+ j# o
  3. class Person{
    . f4 S. Z- g% B0 ]
  4.     function __construct(){
    7 J6 F4 r* E. S" P8 y& |1 \0 n" o( c
  5.             echo 'I am one!';
    6 D& B! k/ ]& b5 p
  6.         }
    ) u+ o+ g/ ~; r6 p. D( O
  7. }
复制代码
  1. //name.php6 G! q  M) a1 _5 W5 Z
  2. namespace test;
    ; Y& M, W( u7 N, S$ [
  3. require './1.php';
    # P6 h4 V7 G0 F. x) {7 w. R
  4. new \one\Person(); //输出 I am one!;: N% C; Q2 u  x8 _3 Q2 T, S  ^( v0 v
  5. new Person();      //这里结果会是什么呢,猜猜看& V$ `( _% [0 R: R' e8 U
  6. 最后一行结果报错:! l3 a" H. x' l
  7. Fatal error:  Class 'test\Person' not found
复制代码

8 m; p( I& s( Y8 f+ D+ W
5 `1 t; \6 ]; N5 w- L/ o
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
+ S- X9 _* }" [( E/ L4 q7 d
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

( u" M4 Q- K; L! E
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    4 c, S6 ]$ h4 O7 d
  2. namespace test;* L" h( \. S8 O0 O2 v7 Z& o# r
  3. require './1.php'; . N$ P; `* k: T3 A# F9 G
  4. % A6 _& x0 P7 ?0 E
  5. class Person{3 I0 i' G- c' M
  6.     function __construct(){
    8 x! M% ~: O1 h, u0 ]7 w5 B
  7.             echo 'I am test!';# T6 Y- o' w. M; q
  8.         }# n! l* L& [% R1 r3 @! N# I9 T
  9. }
    6 J, b- v; J) H5 }" _( N

  10. 9 C/ I" M0 {7 g1 U% K$ C# F) S- [
  11. new \one\Person(); //输出 I am one!;
    * i, o' L$ ^- r% L* S9 h9 G. J
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
7 B. d* n- l# o0 F4 g
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php/ v& S) i% {% E
  2. namespace test;
    ) \' s; ^1 E7 D7 f; a0 X9 A9 J
  3. namespace one;
    , L6 ~* a4 y2 T0 |* q# ?
  4. class Person{
    # i, M7 _2 m7 A% p6 Q- B" Z
  5.     function __construct(){
    $ ^% |2 A# `4 c% K: u
  6.             echo 'I am one!';
    - G0 ?7 c0 D/ ]7 l& L
  7.         }
    6 h0 L& @5 f% X& c2 g
  8. }
    / B- o0 Q* p, X; }

  9. 2 d) o) r' p2 @* l/ Y1 N: |. x
  10. class Person{# w9 x2 l6 E7 h
  11.     function __construct(){
    ; Y- `9 B* P5 h- l, G3 o
  12.             echo 'I am test!';. S  ?6 m% y. `! ]& ]
  13.         }
    ' R  ?/ C% E5 ~6 y, L
  14. }
复制代码

2 k! |1 [2 y! Y. p0 K
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

* Z9 y* K  |  b  x/ w9 S: F
看来简单的把require理解为替换,在这里行不通。

5 \5 i. n7 A$ w6 w. S9 ]1 e# T6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
7 c& D4 z  t: G% Z: r
  1. //name.php
    & M) O2 o2 _4 h
  2. ) A( b" u- q* B* t( d8 D
  3. namespace test\person;
    : H5 a  J  D) g. F

  4. : z; h1 U! Z: D  H2 }1 ^) ^
  5. class Person{
    ) j  s% O7 ~, Y! ]
  6.     function __construct(){, s0 f* R" N& l" Q+ h# Y, Q" {
  7.             echo 'I am test!';. ~9 `8 l) w' u; N7 M; z) P
  8.         }" |9 y, g0 x+ k, I6 _. I  v
  9. }
    1 K5 M8 ^" J3 `& t, G
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

, K* B; a# }9 ^2 R
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

' r+ y" Q2 k) W2 S+ h7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php9 @- Y% a4 r* _( n, _

  2. ) E' w' F: V- v' M2 N- ~3 k
  3. namespace test;9 J8 \5 M% F  g( G' y' z- g9 x' l5 J
  4. echo 'zhai14';
    , z  z- t+ {2 L9 E
  5. namespace zhai;
    9 z! F0 K3 S3 g" D/ W: E& z& p
  6. require './1.php';
复制代码
  l0 b) D9 s: r& O& v
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
0 Q3 O! G# F. a- b" p
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。* n8 F# `; ?4 v1 A& [2 x
  1. //name.php
    * S. x3 j8 v0 N8 @1 c# M# Z$ `

  2. " V8 k8 g- ?8 C
  3. namespace animal\dog;
    " N( u  j/ i; g- }; ?  H4 ]

  4. ; Q8 F5 H& D5 x& g
  5. class Life{) ^' D0 ?! ^# t8 p
  6.     function __construct(){: b, w* _2 i6 R7 q5 N' q
  7.             echo 'dog life!';
    ! U. `( Y0 c3 ?
  8.         }5 U" B" k2 y) }/ X
  9. }
    3 k; U) B* A  R1 G. o% z0 ?

  10. 2 s8 i% z2 K$ Q! C2 E+ n
  11. namespace animal\cat;2 m. y5 z  ?! G9 `7 V

  12. + S) U9 N9 P% f( E' Y8 Q; G
  13. class Life{
      d$ j, O3 S# i9 E) d2 S
  14.     function __construct(){' X, V- i$ n  U5 j
  15.             echo 'cat life!';, }/ w" @) U, H0 Y9 R# m7 z
  16.         }
    % x. }  |, N& p: W  X" j1 @! H
  17. }
    5 \4 T8 S0 n9 B6 _' q

  18. - X- s7 C9 R  f! e, a" O( ?& ^/ i. |
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间* R; P* T/ Q3 c% q) e+ J
  20. new \animal\dog\Life();  //A7 M  N, W# r1 S! o1 o/ X) t" l
  21. - y# L3 F2 N% y, U
  22. use animal\dog;  //a5 s$ D: n. N) H  y" o' p* x4 J
  23. new dog\Life();  //B
    , S, [$ D; C2 K

  24. 4 X$ {# r" T& d! \$ @8 g- @
  25. use animal\dog as d;  //b
    - E; O3 w% ^/ o- u$ F# f
  26. new d\Life();
复制代码
  |% J4 y% g3 c* F. T. C
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
1 d$ u3 h3 \2 a
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

' u9 f; Z% o  g
相当于
  1. use animal\dog as dog;
复制代码

2 j3 O$ B/ ~. u0 `. S0 y% B. V2.namespace后面不建议加类名,但use后可以。1 J( R0 l$ ~0 _" ]+ n5 y
  1. //name.php4 ]/ i! k7 |$ n2 q; o4 T

  2. : u! o1 W- m* _1 m# S* |! m
  3. namespace animal\dog;: ]8 t0 \0 c5 i
  4. 0 Q" V3 x3 r& {% `7 H& O
  5. class Life{
    ) S' K' a# x9 P) M
  6.     function __construct(){+ |, T. s- t3 n; G1 S# b
  7.             echo 'dog life!';' K, Q2 K8 c: [1 |, t' C
  8.         }
    $ T' T3 ?  D" X. q8 s. _) {: S
  9. }
    3 p- _, Q5 o, J. g9 H- e7 u8 h

  10.   L+ j6 a$ ~& s8 i& v4 b4 t) A
  11. namespace animal\cat;- Y3 `) y) Q: b- z4 O

  12. + Q/ ~8 G0 h- _' y) D" _$ [
  13. class Life{. M+ t* ]/ V: H0 T( m
  14.     function __construct(){
    * V5 G+ c( L: W3 p4 @
  15.             echo 'cat life!';: [/ g3 @# r* E. W! s( b
  16.         }
    ; r* G- o5 }* K  h7 V
  17. }
    9 P) f' x% s4 b

  18. $ `! ^6 s; {+ H2 T# n
  19. use animal\dog\Life as dog;  
    : Y$ X6 G3 |) T: ]& W! p
  20. new dog();
复制代码

  I& o; b8 J0 b, [! ?
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
& z* e% A5 r. R$ A  @
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    0 z2 ^6 H4 v, P4 v; O  _

  2. 7 J: h% ]+ w1 n$ G0 ?( R2 O# S: {
  3. namespace animal\dog;* }, U* |3 [: t3 d( ^: c
  4. * {8 F. y5 V9 i, ^4 u( c4 j$ c$ `
  5. class Life{! d" d! N7 d9 U$ n. g0 `; s7 ^
  6.     function __construct(){5 B% Q5 V, ?0 i" D) v. o9 Z, g
  7.             echo 'dog life!';0 E/ n1 t7 r) m* l- A) G
  8.         }
    ; d4 @. t3 n* Y& ^" }, g. w
  9. }
    7 @4 r8 s% r) ^0 O
  10. class Dog{
    + {* l/ l" f/ p% h4 Z
  11.     function __construct(){9 i6 F. ^: w7 d% u% _
  12.             echo 'dog in dog!';
    5 a( L2 S* b  s
  13.         }6 ^6 g* R" Z  S; M0 h  h1 V0 G. t. m
  14. }
    . h4 `/ @( t( o' B2 F) p3 W- j$ p

  15. 7 c. o  C1 w+ W
  16. namespace animal\cat;
    / W' G- e7 ~6 g( z

  17. / G$ d4 H- W/ D2 L! w6 M/ [
  18. // class Dog{% v0 z. L" t( J  M) l% ~: @& S
  19. //     function __construct(){1 e) w4 S( f" M
  20. //             echo 'dog in cat!';2 n/ K3 w# [# E9 y* W) N: N6 M
  21. //         }
    % D5 h3 e2 a* Y- h
  22. // }1 u+ `5 k# |0 c. p9 Y" u
  23. class Life{" t" w) V' m4 d  |
  24.     function __construct(){
    # L0 z! b- i5 ~
  25.             echo 'cat life!';
    - V. Y& J( x+ z1 I
  26.         }
    ; G6 X# C1 `" S7 o+ b
  27. }
    % b$ B5 T# ?5 L' h

  28. 7 F9 M( D+ E; M1 U4 Z6 W
  29. use animal\dog;  
    + w! J0 I) A' x$ _' A' e* L. c
  30. new dog\Dog();
复制代码

5 w, N1 F0 n& n, U, H
如上,使用了
  1. use animal\dog;
复制代码

# N; Q/ h; ?. l! k1 D/ \* N
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
$ i" v+ A% Z7 y3 ^" }/ f: h+ g
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

: p7 }: \  e9 }$ n7 d7 C7 l
4 g' x. L# Y7 H" I8 |
: w8 E; G& a& N6 V; t+ N9 F' j+ W& {- H4 @8 X

. d2 T1 F4 m/ F7 E# s
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-13 21:40 , Processed in 0.147456 second(s), 20 queries .

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