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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
% m3 W# d: a" U
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

+ Z0 N6 W& {# A5 w1 {1 C- x; p( Z4 y' \; Z2 A
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

; D- t; H: [/ V/ U- t: K: T7 y
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

+ h+ T5 D- ^+ k- Q2 e结合使用方法来进一步理解它的使用目的吧。

1 L/ q5 m0 ?1 [) r5 g) i5 \5 ^  P- a
2 I/ V9 B$ _- ?& f+ Bnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;- ~. w' h# Z0 P1 Q' S  s0 u0 `1 ^
  2. namespace One;% J) ?2 ]3 h% W/ U! z$ |/ f. l
  3. namespace ONE;
复制代码

6 f* V9 }$ @* V3 l& e7 f/ V7 o
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
- Y* j( W0 I) r! u
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   7 E; e7 \' T$ c* T
  2. class Person{
    7 b* M/ Z7 b+ R
  3.     function __construct(){
    1 J7 g  ]* R1 v* G: w7 A1 g
  4.             echo 'I am one!';
      w) s# c  ^# [% C- m! y' T
  5.         }
    * I% J3 \& R9 F- A3 a
  6. }
复制代码
  1. //name.php- I% [3 H# Y+ C4 `5 L- E
  2. require_once './1.php';
    $ ~. D: D) m8 `6 ?# d
  3. & B8 @. e- d/ Z9 p7 p
  4. new Person();     //输出 I am one!;3 ?" F) T7 C7 j: S+ e
  5. new \Person(); //输出 I am one!;
复制代码

& p+ b! w/ V7 Q; ?; C# ^9 N% W3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php  T' I6 T' ]3 M
  2. require_once './1.php';+ V8 \+ G: ]+ O9 t+ k) P" T
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
% ]) N) F7 \# Y, M: Z
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   3 l5 {& H. o8 M: |9 Q" l
  2. namespace one;
    ! X( U6 Y. y  n) h8 x, g- }7 W
  3. class Person{5 ]8 o4 t; e3 @
  4.     function __construct(){
    - H" D6 T0 ^, M- W( K
  5.             echo 'I am one!';
    ; c# z/ y% Q- f7 y
  6.         }
    6 y' H5 U# P1 _# j) f
  7. }
复制代码
  1. //name.php
    & Z5 w% u1 T/ F0 Z1 z. B
  2. require_once './1.php';% j3 ~, ~; r7 X, T  ~
  3. new \one\Person(); //输出 I am one!;
    1 k6 [2 R, [! o1 E6 K- C5 |4 U$ O) P
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

+ a( D* l7 Q( }7 f4 u# Z; t
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

  t3 Q3 p9 N: O5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
! P2 p0 k2 a9 k
  1. //1.php   
    : p) q% P" H- }/ _5 b
  2. namespace one;2 e% I0 i" j$ n/ ^3 b# `
  3. class Person{: Q& {' m6 g' I# ?
  4.     function __construct(){( h" U+ C! D- j, w, L
  5.             echo 'I am one!';9 {/ V3 i3 ^' a7 G7 f" P* _  F" h  a
  6.         }
    * D6 X3 K8 d! |) i
  7. }
复制代码
  1. //name.php' r# [. Q6 }3 ]4 @, W. R* U$ e
  2. namespace test;
    $ \! D2 K4 r4 E) H( J4 v* S
  3. require './1.php';
    6 ^" S/ H) A* p# g" c% W/ D
  4. new \one\Person(); //输出 I am one!;
    & T1 z# \3 \% P
  5. new Person();      //这里结果会是什么呢,猜猜看5 g9 [3 [1 B( ^$ m# h% h3 v$ G0 z
  6. 最后一行结果报错:6 B1 |; O2 Q  A& s% \$ B
  7. Fatal error:  Class 'test\Person' not found
复制代码

+ `( _: a( w  u3 X! ?

7 I# q" A7 Z9 j( A+ r首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
3 p: n7 I/ G! d- u# n
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
0 W0 W" Z2 z. f- b% s
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    . v4 l. {3 o- e8 a' L
  2. namespace test;
    * b4 N) p) P/ `$ K' f
  3. require './1.php';
    ' K% G- d$ R: \/ b' q
  4. . I/ c; U- X  ]3 {
  5. class Person{& f8 A' J$ G2 C/ ?# f1 W# R1 W9 V
  6.     function __construct(){
    8 `: X% V  i2 a$ o7 s4 h) ?5 m5 o
  7.             echo 'I am test!';( n8 R5 V* f* G& t0 J
  8.         }
    # l: {$ S- i9 H6 y4 z# v$ D
  9. }  H( r) H4 ]/ j  Z3 }

  10. / X; w/ ]( j5 F5 e, b
  11. new \one\Person(); //输出 I am one!;3 {" D* o8 `% R, s; Z
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
+ R% H& D" L3 y# p* \1 N0 d1 w
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    ; A$ G* f# m$ U8 [
  2. namespace test;
    ) g+ Z/ L8 P$ Y2 R& P
  3. namespace one;
    . ~: y2 E  O$ |! g' [
  4. class Person{" u! i# f# g3 F! {& ^
  5.     function __construct(){
    9 w  w5 y: {7 _( ?3 c$ K
  6.             echo 'I am one!';
    * R. I) g' D- Q  _; `. ]& Y4 r
  7.         }) y0 ?- a% m9 _5 g% Z
  8. }
    3 L! H$ ^2 ^5 t; W& S& A% d6 [9 g
  9. ) E4 G) [1 `! |3 O( F) p
  10. class Person{; {  k  A4 u7 i7 B
  11.     function __construct(){
    : n) f; I* h$ Q" ~8 C; [
  12.             echo 'I am test!';
    8 r9 D  k/ j6 A% t' F
  13.         }
    ; b8 s  x3 J3 _8 O+ ^3 V: Y1 D
  14. }
复制代码
& d5 f3 D1 H( e( o4 o# q: l3 ^. Y
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

+ Y& L4 N* h0 H6 V  z; D
看来简单的把require理解为替换,在这里行不通。

$ g0 h; N. W& C7 N6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。  T9 B+ E' m" T. v: _
  1. //name.php* e4 m' A; q, J5 n" R- r- N

  2. 5 G' g4 {+ C' t& ~) [8 e+ k
  3. namespace test\person;
    ' I/ ~5 A8 k% Y, ^1 g' m: b0 S$ m
  4. / m; g) c; u" S* `, b0 g* ]
  5. class Person{
    1 t# l0 p+ B+ G; U& u
  6.     function __construct(){% G7 V8 |: K7 U9 j4 Y* {
  7.             echo 'I am test!';
    9 G0 W5 {, j* T, j! z
  8.         }; e1 \) m/ j- t8 v: i6 U
  9. }1 F6 v+ j2 m: i& p. T+ Z
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

) g9 w# B. @. F: ]  b2 l4 {. h
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

7 N1 Q3 Q9 s9 H# N( `9 O7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    % X) ~' O1 u9 Z# P
  2. ! x; Z* j2 D# y) ?' J! N: I7 y! _
  3. namespace test;
    7 }7 c" b. ~  z9 @9 s: F  y
  4. echo 'zhai14';* a- `* |7 h3 [- o7 t
  5. namespace zhai;" e8 _; @. X  p- i, z9 F9 _
  6. require './1.php';
复制代码
) S5 |  ]8 E( a2 e( v$ }
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
  k% S; a0 L0 l
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
2 c: |7 n9 e8 S3 z
  1. //name.php! t# N" P# G( Y2 z

  2. ' H) P6 I) r! |1 Y
  3. namespace animal\dog;
    6 c6 P0 W3 k- d* ?: E& y' T3 n

  4. 8 L5 ?5 F: P, Q0 F
  5. class Life{# D0 u! ^6 S& k0 [
  6.     function __construct(){
    / L: _6 Q" A& d3 D$ H( B. s
  7.             echo 'dog life!';  y1 J5 ?& V4 X& X' n
  8.         }/ v. R  V' H( M3 O; g5 w
  9. }& l0 \" e& z8 g" x

  10. 9 z; q. o# Z3 N( n5 V. ^. _; e% _
  11. namespace animal\cat;
    7 F1 u& S$ q9 W  S( |( W, f$ ^& _) F
  12.   O# b5 U( j# j& B3 X4 m
  13. class Life{
    5 c' n2 r3 R5 |. C% C! C+ @% S
  14.     function __construct(){
    8 J. H$ Z) Z5 b$ x
  15.             echo 'cat life!';
    $ {2 m9 e' X% U
  16.         }
    4 A9 T* U, r9 _* d, x
  17. }
    " E$ D; ]- B* {( D: Y: A8 o

  18. 6 o$ a. c, @7 p$ b- a3 a
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间4 \: i8 }4 d5 @$ A# v
  20. new \animal\dog\Life();  //A
    " {6 C5 A: d+ Y; Q( z- w1 x
  21. # r% g5 _# I2 l2 V
  22. use animal\dog;  //a
    ; u1 S" ~; _. A3 J
  23. new dog\Life();  //B# }+ S/ S- f  }7 _1 K
  24. + e: G; m/ b8 M" W$ [6 @, g
  25. use animal\dog as d;  //b5 A/ {- K7 u& f4 Y9 g6 I# V- C
  26. new d\Life();
复制代码
4 ?( \. j8 F# U
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

9 D8 h2 i) t2 ~; W4 D3 H& L
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
# i- B  a1 A1 _
相当于
  1. use animal\dog as dog;
复制代码
( I6 x( [& T, @2 U' W
2.namespace后面不建议加类名,但use后可以。* j5 Y/ i, g1 X6 V7 X
  1. //name.php( A* f5 p5 y4 x. m" m: h

  2. / S$ E, \" _  w% A! x: P
  3. namespace animal\dog;
    8 P  E2 V; n$ q1 G, ]
  4. 3 }7 {8 L& S9 ~! q' a
  5. class Life{. c! e1 k. L7 @* }4 U! C% n/ a3 q7 f
  6.     function __construct(){
    - n; V% x/ K2 r
  7.             echo 'dog life!';
    ' D; `. w( g* ^  D( k# |
  8.         }8 L' e6 t! w8 u0 D/ K
  9. }
    " g9 F( }/ u. T5 s% a

  10. - c5 Y1 l- r5 N1 E1 ]! M- L3 q
  11. namespace animal\cat;2 d+ y9 s( h1 Y' M. X5 g  I7 y
  12. 8 C: ~! h6 \  K
  13. class Life{3 {! L- l3 A9 m
  14.     function __construct(){& r9 G1 f8 m5 U" R
  15.             echo 'cat life!';( q( ~# ?8 Z1 o* R4 `3 n
  16.         }( \8 q7 C- H8 o* `0 p
  17. }
    / y1 N+ C; \+ j) \+ M' a7 R9 T
  18. * `' Y& K: c" \/ ]& c
  19. use animal\dog\Life as dog;  - I8 {+ H7 G3 @8 l! G0 j
  20. new dog();
复制代码

: s; l, v6 D" d: B3 X
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
2 M# B( T3 o  c; I
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php5 k6 o" H8 b7 }8 x4 x

  2. ( |7 t- t5 A8 P. d* X) v
  3. namespace animal\dog;( d% f+ Q+ i; S6 e

  4. ' D9 H. J% z# z9 u
  5. class Life{& L% `! n; a8 K3 Z" t. f
  6.     function __construct(){
    / t) Y2 p: S4 R/ M! k" X& Z& F
  7.             echo 'dog life!';0 q0 H4 J. ?0 p$ N4 `$ V; y- ^
  8.         }# \* D2 M% D1 |, Z9 q2 b- D) d
  9. }. [3 Y& a; ]* W0 I6 t: B
  10. class Dog{
    9 C8 U5 a& m4 p) [
  11.     function __construct(){' f- `& k- j* q" L
  12.             echo 'dog in dog!';/ Z, }+ G' J+ g( `( M( g
  13.         }
    8 j( ^7 @+ y9 s% D8 |/ Z
  14. }* ]/ B$ f) q6 @! n+ @7 ^& }+ j
  15.   D: o1 l; V5 q! }6 Z, D
  16. namespace animal\cat;1 f/ Q0 x# [. P7 }+ G# w. J9 e
  17. 4 H+ V$ ^0 S" r
  18. // class Dog{$ i1 \5 L* c8 b4 |0 v2 g: N
  19. //     function __construct(){: d: m/ W# _. K4 g
  20. //             echo 'dog in cat!';
    ; C( C: }* e$ b
  21. //         }  H* y) D0 R9 F
  22. // }
    % B' Q6 O, b8 ]: V) C
  23. class Life{
    , y( \7 N& [* T0 o) ~! O" D# {
  24.     function __construct(){+ M' ?" D3 S* q3 D+ B
  25.             echo 'cat life!';: n$ s& w# Z4 n! K3 f
  26.         }4 P( v- i& _: l3 C, w, J5 h) L8 A
  27. }
    7 f+ Q* l' ^7 ~* h: T* X
  28. $ `/ U2 |4 q. L1 g: A
  29. use animal\dog;  
    ! L3 a- B# J  l3 |, W0 i, C
  30. new dog\Dog();
复制代码
& ^/ S! y, k4 m1 B: b3 Q
如上,使用了
  1. use animal\dog;
复制代码
/ q+ E: t9 }$ q
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
# G* [  F  L" z$ {2 `# h
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

) V# Q5 r. M/ z
2 H  V6 o4 D4 K1 [$ \: _1 h: q' Z- q) t, n/ a$ g: S6 M
/ }& S# x5 u8 z
+ `) h+ S5 t' x: u+ h
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-4-30 19:57 , Processed in 0.057531 second(s), 22 queries .

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