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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

4 h& @, f3 {" ~2 V: o: @3 z. `% h/ e7 L+ {+ ?3 ?2 y' c7 x& d8 R% n
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

+ _% |6 ]! u$ D* s) D3 B9 |+ Z. a结合使用方法来进一步理解它的使用目的吧。
. r* d" R. D, d) a) x

4 Q* u( }: E3 V/ D6 Cnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    & g# [+ w! L' ~
  2. namespace One;; {6 Z( J) n' B0 H7 z
  3. namespace ONE;
复制代码

$ u8 R) \$ h# }- N
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

, l, @; N* D* Q; k! d9 X2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
      G$ z3 k9 l; `$ Y& h1 W/ f  f
  2. class Person{) M' E% T  {2 b& z* [
  3.     function __construct(){
    % ~  Y- k- T0 Z0 E/ ^  D
  4.             echo 'I am one!';) n& J% F2 A% n( ~" L$ p$ U! K
  5.         }' ~/ d! _1 Q/ I5 W" A) w
  6. }
复制代码
  1. //name.php  [- b5 Y  H' v& H9 v8 M: t3 A
  2. require_once './1.php';. s# Y' s- w3 N" `
  3. 3 [7 k2 @6 U  A: r2 ~
  4. new Person();     //输出 I am one!;" m9 z9 i8 o, F/ @0 F4 e
  5. new \Person(); //输出 I am one!;
复制代码

. |& e2 p' I2 g8 d3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
      Z$ _. x8 `4 \3 w- I
  2. require_once './1.php';
    ! G% ?( S* \+ n1 e! C& N
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
/ a0 E0 S. b2 ^, X# ?
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    , e  G* N6 X% }1 G
  2. namespace one;+ V3 i9 t; Y, f* j5 I8 B  S
  3. class Person{. s$ g8 x( ^  {3 H5 ~9 d# K: q
  4.     function __construct(){" R  I! u" E5 J& O, ?5 \( {
  5.             echo 'I am one!';3 _& M5 [$ Y. i% H% w8 Y2 r- {
  6.         }5 P: _. z2 I+ P5 I" e' P5 E, n
  7. }
复制代码
  1. //name.php
    5 R2 m% R# e  ~
  2. require_once './1.php';
    ) r9 _( C- M( s- Q8 o
  3. new \one\Person(); //输出 I am one!;
    % c2 O% Q! v/ P& B  x; D  \
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
# T9 X5 J- c. J8 N# F
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
1 S3 X8 [2 X& p1 k3 r: t
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。# Z. X7 E4 q$ U; a. M: \
  1. //1.php   8 ?9 t& b7 J  n, |$ W9 D. l
  2. namespace one;
    6 S2 N7 _$ X1 n0 G
  3. class Person{4 D7 w9 [: J7 u0 v
  4.     function __construct(){" m- c: h% G* c. P! [" b5 J
  5.             echo 'I am one!';, Q7 S' D- D* B  O. l: K8 I
  6.         }
    / m% Q6 j6 v) d4 K
  7. }
复制代码
  1. //name.php
    : [) m1 v) z* q& F  `
  2. namespace test;
    0 Y" ~+ z$ v6 J& o6 T
  3. require './1.php';
      C% n- b9 O7 N) \& w& Z! P# u
  4. new \one\Person(); //输出 I am one!;
    1 U: e: \& {( w/ p, m# W- I1 k
  5. new Person();      //这里结果会是什么呢,猜猜看$ n# u9 r: }8 w
  6. 最后一行结果报错:
    & N) i( M" q$ O. i, N$ Q+ F9 Q
  7. Fatal error:  Class 'test\Person' not found
复制代码

# ?& `; B7 C3 x5 c1 Z
% }% y. L$ O- u6 A4 O* Z
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
9 u3 k+ X5 @/ Z0 e) u# |1 U
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
9 J6 i! h+ N0 Q" o8 \
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php) v3 x, ~. ^9 @" ?* y) I/ q
  2. namespace test;
    & z- ~4 H: r2 r; U4 u
  3. require './1.php';
    " u3 I5 x9 b5 `: s0 X

  4. - l; S2 `+ c8 z: V2 h
  5. class Person{
    4 W" m, V3 ^  x5 H( B
  6.     function __construct(){/ x$ B3 O6 V  p) r
  7.             echo 'I am test!';
    2 J: _, h- i: Y
  8.         }
    7 x$ O  f+ P5 J8 w" t# y
  9. }! T3 R& a! ^* [5 }2 D# X
  10. 3 h, N9 M6 e& H8 G- _- A! X* q
  11. new \one\Person(); //输出 I am one!;
    2 Q# r) B4 U" C' x3 }8 \
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

& O" y. ?6 K+ N+ S# I% A
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php, ]! j' ^; D' {5 j8 C  |
  2. namespace test;
      `* T! N% v' y, E  y
  3. namespace one;2 b3 t: t9 b9 |, d
  4. class Person{
    - d8 X' @$ |4 m3 C- S2 h
  5.     function __construct(){
    8 D; Y3 }3 u% u7 n" K
  6.             echo 'I am one!';5 @1 s# {/ u- L. Y3 Q
  7.         }
    , T* ?7 o1 M- \
  8. }6 K8 }" x2 i/ b3 t
  9. 0 s. L- ]) F4 O+ b
  10. class Person{
    + @" C; {  a$ w: P) v
  11.     function __construct(){
    / E7 b: v( g) P* @
  12.             echo 'I am test!';
    3 o1 E: g0 i$ k+ [# ~
  13.         }" S6 F$ }. z; n  d) Y8 q1 @  O9 I
  14. }
复制代码
& Z( |0 c( v' N) w
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
( p- a. u) T$ e4 k: l
看来简单的把require理解为替换,在这里行不通。
4 b  z3 h7 Z  h, z( A
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
% [3 z3 W# ~% G" V- _! _/ u
  1. //name.php
      |* G7 K$ Q) N  g/ h$ e

  2. . @: z7 o# \, `/ z1 A# }. @, t' _
  3. namespace test\person;7 |, \  }& U( |& L' g
  4. / Q7 v9 |0 O* k8 R
  5. class Person{
    # m- a) K# ]3 n. B. {, [; x# @# Y8 i
  6.     function __construct(){9 c5 K/ D' ^4 w9 b) v: @$ q4 }9 K
  7.             echo 'I am test!';( m' ]1 `& i( z* b
  8.         }5 _) F) o: y& b3 L
  9. }+ H& h( j. `, {6 [( s" r
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
. y# r* A' h8 K- F
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

1 E# f+ i3 Y7 g5 a! e' U5 k" M. D4 G7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php2 m3 F- }# O: n' X
  2. 4 \+ n& j" _; ]* p3 @
  3. namespace test;  W: O" g# h& o/ v( J' P6 N
  4. echo 'zhai14';0 y0 B( J9 C: J
  5. namespace zhai;, C/ ~4 X/ Q6 ^" ?
  6. require './1.php';
复制代码
1 R/ m# ]9 N# X( O
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
/ J: b  t: d1 L0 ^/ c. L$ S4 X& Q
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
# a9 @7 X) E) d
  1. //name.php
    ! ?) s. ~# Y. R' v1 }) w5 R& u8 k

  2. ) M& F, K( L+ s4 J" l0 h7 H* Z% R
  3. namespace animal\dog;) ^7 W: `% L  q2 V: I1 v
  4. 9 S( O% v- m- E$ w% e
  5. class Life{
    0 ]# d2 i' k& @+ C
  6.     function __construct(){- w% w/ _; l9 Z
  7.             echo 'dog life!';* k+ E# J& q, D6 C. l! E
  8.         }
    0 I" }, t) f* c- y9 ?4 \
  9. }% Q8 S; U5 p7 s5 U
  10. 5 f! u- C' f3 n7 S6 V' h$ _
  11. namespace animal\cat;) }# x: z( g* S

  12. 3 |. ^+ @# o& w* e# U3 J' f/ G0 j
  13. class Life{
    " S* ]0 P0 e6 F0 D% H' x: p
  14.     function __construct(){" \( @% a  l0 x8 I
  15.             echo 'cat life!';
    7 |* |. R- U. R8 ?; s
  16.         }2 I0 Y: V! ]7 B. u6 J
  17. }
    1 y2 T4 E+ B6 R7 p2 q; c* }

  18. 7 L; v. V; C$ R% w
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间& c* O4 g8 Y2 B( g+ O. q6 K8 l
  20. new \animal\dog\Life();  //A
    # x/ E2 K5 h# i! |5 A! `$ G9 J% h

  21. 7 p; M* m' l$ [9 b- a
  22. use animal\dog;  //a
    $ y' y, Q; S) L& j6 u$ u
  23. new dog\Life();  //B# M+ F6 u: y# [
  24. 1 e1 c# R& E' L6 R9 p
  25. use animal\dog as d;  //b1 k& X& q, `0 a5 H* V& L# h
  26. new d\Life();
复制代码

7 e  v* A$ G! n* W; B/ A6 n
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

0 u* U# h7 t  |% f/ [5 O$ n
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
# l, u) c, ^7 Y" m, z
相当于
  1. use animal\dog as dog;
复制代码
  |8 ]# ^0 w! w: L  a" I5 [
2.namespace后面不建议加类名,但use后可以。3 y2 O; H$ G: K/ Y
  1. //name.php# X" M$ K  a' i( E! @! F" S

  2. * o( p) }5 U: W5 n5 b; m* ^
  3. namespace animal\dog;
    * w3 {0 _# P- U# H, i6 R& o3 a
  4. 6 Q) ]; l. k2 Z5 a' {' @" G5 U, H' F
  5. class Life{+ `# L! U. s# C0 S. \% s3 G
  6.     function __construct(){5 I$ ^1 P8 ^+ x! m& r9 U" e- c
  7.             echo 'dog life!';
    ( {9 O' P' b% r- z/ n
  8.         }9 s$ a# J4 o* S6 J3 s. y* `
  9. }  T1 C7 k4 v8 i' r7 k* s9 M
  10. $ p/ d* F: @0 s' c
  11. namespace animal\cat;: s1 h) A0 ]8 e0 L

  12. " }- D  c9 k* V2 K- k
  13. class Life{$ W* d6 }' m9 z( @
  14.     function __construct(){
    ' i" S7 z" `8 D( P, }; g
  15.             echo 'cat life!';
    / p/ ^! p; J, L4 u7 x' g0 x# m: g
  16.         }- f7 p+ K& W9 m3 m- C6 v; O% O
  17. }
    7 Y) e8 l; d6 Y" w' x
  18. 8 k% T, b/ h9 f. M- D; [
  19. use animal\dog\Life as dog;  ' P4 g8 n  S6 O# i3 F! y/ c
  20. new dog();
复制代码
/ {$ h( l2 D" T! v2 @  `; P8 z: Q  ?
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
. N! {* @  |% ^1 r% X
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php( u8 ~6 e1 N, N$ T& ~
  2. * @. P9 {. q; ]$ V
  3. namespace animal\dog;. W# g  q  `6 T& U/ f( H2 t# E
  4. & z4 [, I- R0 Y
  5. class Life{
    4 V# G5 Y/ I  X
  6.     function __construct(){' Y  V7 y: ?; d  B
  7.             echo 'dog life!';# a# Z* o. z# O4 c2 e" K5 }
  8.         }# a3 ~1 J! o8 Q& ^/ U* X/ `; Z' `
  9. }: p  p8 u' F  _4 _/ F
  10. class Dog{1 i% s4 U$ `- C1 ^4 S9 Z" h
  11.     function __construct(){
    7 o3 B2 m8 u* S8 ?
  12.             echo 'dog in dog!';
    3 I/ \0 m; U1 e) k/ d5 A! D9 g
  13.         }, U5 A# L8 m. d- [
  14. }
    0 t) V* S# f$ e8 P6 l# P

  15. ) c9 \+ O$ J+ b+ D; ^' ~
  16. namespace animal\cat;
    * O$ ^, s+ ^7 e. t

  17. ) l1 Y# |5 C6 N6 a
  18. // class Dog{
    ! ~9 d" n- Q0 ?5 O+ g" @  r" _
  19. //     function __construct(){! S0 j5 a5 S2 l5 m3 O
  20. //             echo 'dog in cat!';7 ~2 W: m, G' L& U; j
  21. //         }0 X. X5 L* A) i: a
  22. // }- t- H) j  l* ~
  23. class Life{6 w2 t& f6 W! |9 N6 G
  24.     function __construct(){
    1 h7 x; n* S& h- y: w0 e! K
  25.             echo 'cat life!';
    2 d6 f' V. ]& h! {
  26.         }  ]7 @9 l- I$ U1 h' q! ~1 g7 r
  27. }
    8 y" B% Z. T" P% f. K4 \! l+ P1 u
  28. % N  [$ g: t6 I! j7 Y( s% ^
  29. use animal\dog;  
    " {3 o- e' N! r% @: Y) b
  30. new dog\Dog();
复制代码
; ~1 k5 G2 H0 k
如上,使用了
  1. use animal\dog;
复制代码
) p; k* X6 O) A8 k8 N5 a2 x( Q& O
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
/ q. H0 j; X0 b
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

/ B6 n; p7 c. j& p5 v8 `1 `. |7 i% Z1 N  x& g1 [: r

) D3 l: r7 H+ Y9 \* [
. C& H& O+ c) i' G  z" [2 A# k, Z5 q1 t5 ~+ p9 f0 `
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 00:15 , Processed in 0.067791 second(s), 20 queries .

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