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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

1 z( l) k& I- R! G/ t$ l+ ~
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

1 v3 j" r9 C! T
! ]+ Z" h1 \+ ]) Z& Q使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

! t4 D- c) u  u/ V0 K
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
8 H+ O! g- ]6 J1 r* ?' m
结合使用方法来进一步理解它的使用目的吧。

9 V. N- Y; ?& b1 }& O: o0 a$ U& T, \& y. A9 n2 n
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    # `6 s' t9 j! ?; t# A" s# M
  2. namespace One;
    ) c3 F0 \% r. {! p9 R8 @# ^
  3. namespace ONE;
复制代码
, m- E. _: u+ {, a4 r
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

+ v8 s7 g1 p9 s; G2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    & X1 I( k! H) W$ |# K  I4 {
  2. class Person{, q( j$ x* p% H. E8 q9 O
  3.     function __construct(){
    % F; b" J6 d6 ]# Y" d* M7 i
  4.             echo 'I am one!';
    # V3 U8 R+ s0 q  L9 ?
  5.         }- R+ {1 L9 F7 q9 E2 B
  6. }
复制代码
  1. //name.php
    0 z9 S- D8 L7 j& F! v4 a# _
  2. require_once './1.php';6 h% |( u- C, y
  3. $ I: J6 q9 F, R1 M( b8 W
  4. new Person();     //输出 I am one!;
    6 H0 w5 W" ?# B% a+ R
  5. new \Person(); //输出 I am one!;
复制代码
" m, {0 P/ Q$ Q& \: {
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    5 d. j2 e6 e- I! U0 v9 y9 U% P
  2. require_once './1.php';$ W5 [, G0 H2 T$ Z6 v
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
0 j1 }3 U2 C$ A$ J, O/ `" y
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   ! [# p+ C2 D. U2 F
  2. namespace one;
    7 b& Y5 P9 G! q2 A2 n/ v7 x
  3. class Person{
    + B5 b1 y* f$ H' S1 \- U+ ?# N' t0 l* _
  4.     function __construct(){' c0 j7 v! B- n' \7 K
  5.             echo 'I am one!';. E1 B& I4 \7 f# h
  6.         }
    6 @* @% `2 A1 j# g/ O9 |% |5 @0 X
  7. }
复制代码
  1. //name.php
    ! O+ l0 y' R' Z8 }) |# e, K: Z
  2. require_once './1.php';
    # T  X3 E% f( s. @; j3 R
  3. new \one\Person(); //输出 I am one!;
    ; w3 |3 s% ^4 T) ?
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
/ R5 j/ s! x+ |6 r& B
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

! b) d3 T- j; W3 {* a# M4 Y5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。$ t3 b& g  M) S% z8 o5 i+ N) o
  1. //1.php   
    ; d" I6 L& j0 I9 Z4 ~6 S
  2. namespace one;, y% {9 u) i( z3 Z
  3. class Person{6 ?+ ~$ y: z" k- ?& C2 r/ ?: C! y% O+ _. a
  4.     function __construct(){7 ]9 w+ x) r- d6 k  C' {
  5.             echo 'I am one!';
    + h/ I# q) N4 m* ~* }& S
  6.         }3 w' Y8 p; W1 B, p1 W
  7. }
复制代码
  1. //name.php% f7 F) P! y2 X. x
  2. namespace test;
    ; T2 i" U; [- u- ]0 M0 L2 L
  3. require './1.php'; 9 y4 S" c* c$ k4 v9 r3 ?9 f; e' S
  4. new \one\Person(); //输出 I am one!;
    6 H2 Q0 T& K- G5 l8 Y/ H
  5. new Person();      //这里结果会是什么呢,猜猜看
    ; ~& K4 p: f  f% Y# w8 U
  6. 最后一行结果报错:' O3 E3 [! f6 ], y: V* R
  7. Fatal error:  Class 'test\Person' not found
复制代码
2 Y# Z, G2 j  g3 L

) D; Y) j. [4 q$ f% |. \7 s) ]首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

* s* T; J/ ~) C. _7 \. X  H
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
1 k7 l5 d( L" x3 |/ D! l4 `. T0 g
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    5 \+ H7 b; D$ M! [+ e9 ~; {% x
  2. namespace test;, r! j) B+ H( l, o6 ]
  3. require './1.php'; / C* g+ s  U& ^% U+ u

  4. / l: o* h  U5 i5 @+ o6 W
  5. class Person{
    0 E0 g# t) e- y( m5 F! c" Y# V# j
  6.     function __construct(){
    " N! C4 [: b6 j9 |6 x6 k7 h% l
  7.             echo 'I am test!';
    # W6 y  @; ^# f9 q1 C
  8.         }) @7 Q. Z9 j% s# H) ~" F
  9. }
    : |$ D+ c3 g. r9 r

  10. - b4 R" D/ j# `
  11. new \one\Person(); //输出 I am one!;8 W8 L2 m+ P2 k. Y8 P8 E3 H8 [
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
0 {$ v$ N7 J( a  \
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    0 x$ O1 `0 c3 c, G$ r5 [
  2. namespace test;8 K( @/ u/ |# ?, I, V# {4 t5 R  l
  3. namespace one;
    7 S& m/ _! r3 ~0 o( R- h4 @
  4. class Person{( [+ j8 S. p( R7 X9 l
  5.     function __construct(){% _  f' o* y8 o( }- r9 U. ~
  6.             echo 'I am one!';$ M* P$ j! [) P' d# I- V# G
  7.         }
    ; \* x# g5 t. R9 ~6 Y3 J
  8. }1 y$ E% k: E4 e, I0 ^" r: a; X; j9 s4 F
  9. # x% m1 l. C, g; \( f
  10. class Person{" T; p; k5 @! t" E
  11.     function __construct(){  c' v; J3 \+ k: }6 f
  12.             echo 'I am test!';: Q4 d; E! l  X/ r
  13.         }3 j$ b7 e8 ?, n8 ]; q
  14. }
复制代码
5 |4 s; v4 V: [( W* a, V6 {" X
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
9 B& G+ \1 J: m. K: L% X% H8 S
看来简单的把require理解为替换,在这里行不通。
- `6 b. S) f) w0 ~- R8 i: _9 ^7 u  b
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
2 q5 m1 g' _( m
  1. //name.php% n1 a/ C, B0 z' \3 n

  2.   l. C+ K' ?2 [! X% i3 J
  3. namespace test\person;5 E' `9 s: C& v0 _' k

  4. , M* Y( O/ b3 X) ^; A% ~/ p
  5. class Person{( ?2 i9 j- h# b; n6 R
  6.     function __construct(){
    3 ^# s% n. i' h
  7.             echo 'I am test!';4 t/ c9 A: I/ L6 Z, a8 {1 Q# P
  8.         }
    , V' f/ q1 |* N/ @( `% q: c
  9. }  n) K, \) j* p" w  `
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

) Y- O+ F6 y# `3 I! p0 u
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
" x4 E! T& i: H8 \
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php( I8 ]) N7 d6 f5 @, c
  2. 9 I+ |4 c$ |! l+ }, R, Y! I
  3. namespace test;; Y7 J% K/ g) P2 B2 Y2 _' v- J
  4. echo 'zhai14';$ d) i. B& `, X) E! O# |0 }0 Q
  5. namespace zhai;
    $ D1 x5 J6 O5 J- n' x* `8 n
  6. require './1.php';
复制代码
) Y8 n% B: n3 w
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

' Z/ @, R( v; k! d/ K& t, euse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。9 A; v3 v2 r7 `* U( W+ i' M
  1. //name.php6 }- c+ U; [8 ~2 A% d- }  v

  2. ' a2 Z. A) U+ x0 c' ]$ B
  3. namespace animal\dog;2 X/ t2 I8 W9 L1 n' T( V
  4. 3 S( J% {" A8 @/ c( }4 u
  5. class Life{
    * `8 G* G7 t5 |' v
  6.     function __construct(){
    3 |0 n& R! c( W7 O/ X
  7.             echo 'dog life!';$ s- [  w* T; n7 Z8 ~, @9 f3 x
  8.         }
    ! _- j8 t" I* U3 A. E' N- |/ S0 E, v
  9. }2 d2 H" b  x- |$ N2 L

  10. " ~+ c% G8 {  v: H
  11. namespace animal\cat;
    0 X- c- l$ Z5 q! A, z

  12. 3 }" m9 I" r! z% E
  13. class Life{3 s2 ~; Y: C/ h8 X7 s5 t0 G3 M9 n
  14.     function __construct(){
    % O# C6 ~: A+ p* o3 O
  15.             echo 'cat life!';. C) W8 q4 F+ Z. b4 Q
  16.         }
    ' ?* {( E) n& i* U
  17. }
    " M  r8 X& {5 Y+ \% A" p1 y/ [1 B
  18. ! \4 |8 S8 S! n. b
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    $ o; U  T9 g7 r; a6 N. i  X) c( R
  20. new \animal\dog\Life();  //A
    / Q! C! M' U: X
  21. 3 q8 \+ o5 l2 @5 {* s7 h8 ~
  22. use animal\dog;  //a" a! i: H% |1 W7 g5 N2 X! U
  23. new dog\Life();  //B
    0 L) ]4 y+ K" Z' j0 n& b5 O5 o

  24. ; E' i7 U& H0 L: e6 d. H  v; O
  25. use animal\dog as d;  //b- h. @$ q, [5 j6 E0 N
  26. new d\Life();
复制代码
$ a/ m* a9 s9 A
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
8 C9 v2 U# K( I
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
7 {6 q, p0 R6 A0 @- R* j9 o6 z
相当于
  1. use animal\dog as dog;
复制代码
0 @7 l5 ^4 K% ?3 e% r- i
2.namespace后面不建议加类名,但use后可以。
( V& [; I$ s7 J! `2 x4 l
  1. //name.php
    7 {# d3 ]2 C7 r/ T" n- i& M
  2. ' ~# i  M/ `1 G, V8 |. k% b
  3. namespace animal\dog;  v' v  J# J) |

  4. 7 {/ G8 L9 |6 G: N# \
  5. class Life{
    3 O7 ], m9 \; V0 y! l; n
  6.     function __construct(){
    ' E" X2 L; \7 @; n( K( u0 k
  7.             echo 'dog life!';, d, W$ {) `) @7 F0 f7 q( |7 n  j# |+ [* X
  8.         }
    % \2 u# }: P# Z8 g
  9. }
    : V& ~. Y- ^# y/ H' `+ T9 I9 T! E

  10. 2 A8 b# T( Y% j& g& M
  11. namespace animal\cat;9 U0 L1 ?. c1 F  p4 B+ H

  12. ; h  G3 a/ h! ?! u, M) f( u
  13. class Life{
    % e) @' B6 u" u# c# \2 t4 H
  14.     function __construct(){) Q# z% n/ ?3 ~
  15.             echo 'cat life!';
    # {* k. _: ]7 M4 v0 J# w
  16.         }
    # ]# P. n8 q8 D7 U  z
  17. }, R8 `( R! a4 M# y3 N" U" o
  18. - c/ n6 n+ P# ?+ T0 J, r% @
  19. use animal\dog\Life as dog;  
    ! E8 D1 c6 o4 j' ^4 d# ]1 C; |
  20. new dog();
复制代码

, u; }4 Q; X* b. K
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
! f6 H! ~3 f- z  I6 Z. h+ W/ R5 L
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php4 u2 l, e3 r1 a

  2. # S* i9 Z4 x0 {4 l; ~( L
  3. namespace animal\dog;) n/ T; f1 _0 b% h( _
  4. ' M, f: h: S0 t+ `
  5. class Life{& T, Y9 p$ H5 B6 W! n6 `; z! [& b
  6.     function __construct(){
    5 f" [8 x7 {. w$ C% c$ K, t
  7.             echo 'dog life!';0 L+ Q. J1 U- v  a
  8.         }% z3 q4 J" k, m$ ]( h
  9. }+ ^/ l& l, ?# D
  10. class Dog{2 Q. `7 X1 d' N# G
  11.     function __construct(){
      `5 |( I' K) s
  12.             echo 'dog in dog!';
    9 V3 ^' L% n$ y# S9 I7 I
  13.         }
    & L- i1 f5 h5 h4 q$ i4 g$ Q! c
  14. }
    2 X+ ?1 I" o0 z+ \( A. L; P

  15. ; w6 V5 g5 X4 n; `2 r
  16. namespace animal\cat;) E0 b- a+ G7 v6 L, V8 U3 H, ]. @

  17. $ S7 o/ V% s$ c
  18. // class Dog{/ x" Y1 r  L+ S: ]
  19. //     function __construct(){
    : A3 _3 U) Y2 j. }  ^3 D
  20. //             echo 'dog in cat!';5 Q3 Q2 M5 e5 ~" T. x
  21. //         }6 N" \  E. t/ P7 R) X2 m: o* B- S
  22. // }* `6 A  v* f3 o. c1 H
  23. class Life{
    ! T# U* F' {) F. f! O$ K' d
  24.     function __construct(){
    - D6 m' ^) a" {& V9 z& ~
  25.             echo 'cat life!';6 I  R- i# @% Y4 ?4 x
  26.         }
    # `: c4 T4 u" ?
  27. }& U/ ?8 I2 y; g
  28. 0 S( A; i3 \# w1 X. E
  29. use animal\dog;  5 w9 o9 [1 s% _0 |
  30. new dog\Dog();
复制代码
' @, c- |: T7 f, L- o; q  S
如上,使用了
  1. use animal\dog;
复制代码

) u7 ^! h4 B5 T
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

( L; `. v# L# q/ Z# j
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
5 B2 v! `1 H* Z
6 m% G: C5 o8 g! N  C: T

: L6 Q9 c, c) a& g& ~. ?. q" H- V
" x- l0 c2 x9 W9 W) i, E
" _( B* v3 w& c9 `7 e& ^
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 14:28 , Processed in 0.057711 second(s), 20 queries .

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