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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
9 z" D7 }2 L% o# b4 _" ^
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
" X0 Q/ E2 K0 O# E& D/ k) s
1 a9 t' }" n# q2 T: R
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

$ [. r2 k+ m2 f) |# Y7 t结合使用方法来进一步理解它的使用目的吧。

) r) N0 {* ~. Z, ^: J6 ?, x0 L2 y" `$ ?: N( `
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    ' P, k' o8 i4 B
  2. namespace One;
    ! j1 \3 l( d/ C% X7 A1 z2 \
  3. namespace ONE;
复制代码

3 q/ U, M, ^3 `; C5 R9 n
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

, r/ k; K( O( y2 F* a  t4 Z# {2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   4 H! B3 G: {3 B2 [- p! e2 s1 f: k
  2. class Person{8 }% E. W0 a$ k+ V
  3.     function __construct(){+ X! M) R9 [! w( Y  Y/ V/ V% b; j1 I8 q. c
  4.             echo 'I am one!';
    3 X+ @0 P: ~# r; }
  5.         }; A; I% j* R1 C2 m2 X9 x
  6. }
复制代码
  1. //name.php7 j7 c/ m. m6 A7 ^2 g; I: U% x( o
  2. require_once './1.php';
    ! r$ k/ [9 n/ M* r

  3. 9 y1 y- _$ x! x" K
  4. new Person();     //输出 I am one!;
    2 p# n: L* _( u* L# W6 P, ]
  5. new \Person(); //输出 I am one!;
复制代码

; _9 _. p3 S6 j& x3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    / K( v) Q6 Z6 }, {9 e. S
  2. require_once './1.php';
    * A  @4 Y# P+ |9 s+ n
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

, r$ H' u  c- N% E4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    " n5 M) j: g" d" ^* _$ z$ _2 f- y
  2. namespace one;
    & w3 @; B! W, Z
  3. class Person{$ z1 A7 D. Y+ ?+ x
  4.     function __construct(){, `1 U' a0 X) ~; z
  5.             echo 'I am one!';6 _) t/ Y0 N" C
  6.         }2 l$ L' T, p% V: T) D. k
  7. }
复制代码
  1. //name.php
    # L& R* y$ F$ [, s
  2. require_once './1.php';9 s+ d7 s( G8 ~5 @& Z: U9 d
  3. new \one\Person(); //输出 I am one!;6 Z: R; I( b2 Z( L
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

, Z; ?: c% T, W$ B( O
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
# Z) k$ U) z2 c2 v$ M
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。* B0 V4 J( `  T
  1. //1.php   
    & P& G' C& d/ q+ D; }
  2. namespace one;* o2 t6 i" M& z
  3. class Person{
    " d$ n/ f. l  G% j. D5 L# X6 y% x
  4.     function __construct(){
    $ C/ X' Q0 V. ^" P
  5.             echo 'I am one!';2 T0 ]  m0 E6 m; M  x4 _; B
  6.         }* A7 K) q' A" a" G3 s2 C
  7. }
复制代码
  1. //name.php3 B+ O$ {# _: d" k0 w
  2. namespace test;5 I/ [5 n, Y1 n/ u# y) w: q% Q
  3. require './1.php';   ^3 d4 e( R. j" D$ H
  4. new \one\Person(); //输出 I am one!;* r, R& p9 v2 g( [" N
  5. new Person();      //这里结果会是什么呢,猜猜看
    9 r6 Z6 ]$ F6 _4 m4 B! r
  6. 最后一行结果报错:
    8 w+ R, |% B% P0 P
  7. Fatal error:  Class 'test\Person' not found
复制代码
0 [/ }6 W" h4 n4 e, J
, g( ^  l3 `3 _% m; G' Z) h1 ?
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

; h: J+ |1 e; d" a" J4 Y
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

# z0 O* n, D8 T# |7 N3 a- ]! `# t! y! X
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    6 N4 i) e# q" u9 {4 F; A2 ?
  2. namespace test;
    4 @2 {% L' R# l
  3. require './1.php';
    8 h3 Y) G! r( q& X/ G
  4. : {" N# O" T8 L
  5. class Person{
    " D% k1 P) v  H( L! R
  6.     function __construct(){" ?+ J& I  r7 N5 Z) n
  7.             echo 'I am test!';
    ( X$ J! U4 R6 Q+ D* C5 L# Y
  8.         }1 }: \4 ^8 @5 _! }- ]+ L" \  Y- ?
  9. }
    ( N5 A# }9 X7 {* K
  10. : \7 G: t9 D9 G3 M
  11. new \one\Person(); //输出 I am one!;
    $ x5 k4 Y( b. b/ [
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
$ s& j) |9 ]+ B- i/ r/ `
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php9 w' s* }% S5 P6 I8 q6 E) x
  2. namespace test;5 _8 x! ^- c( w$ B) F5 g5 s$ W
  3. namespace one;* S' B7 W" l6 D: V* G9 k
  4. class Person{3 Y( c6 T; L7 d2 V. @
  5.     function __construct(){
    $ N4 H' K* j, A3 ^% }* |; v. Y
  6.             echo 'I am one!';
    ; N  ?8 G/ _5 l9 l5 T6 y% Q
  7.         }
    - B0 M0 v: N$ s+ o" l
  8. }
    3 a7 h) J0 Q1 k0 h

  9. . X" u. J. N8 `# Y4 Z
  10. class Person{
    ; E3 N, g: q4 v
  11.     function __construct(){
    . J  b' V  i# i6 |2 x. Y( l# \
  12.             echo 'I am test!';8 J/ \8 X/ ^7 Q8 p
  13.         }
    * I3 c' i5 n" U! T
  14. }
复制代码
0 K5 m" s4 E- j+ I  p
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
4 \$ a( G* F3 n! c
看来简单的把require理解为替换,在这里行不通。

7 X4 ^2 s  k/ r& H' ]" `6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
( W/ w- Y* F, [9 Q0 k1 ^- i+ O8 [% u( o
  1. //name.php
    0 k+ a, y' q- q8 ]

  2. # O% f* R% p8 v
  3. namespace test\person;  b7 C( m; j; j" M0 G

  4. 3 C; d7 B# ^5 F* g( m, |" [
  5. class Person{
    ! q) T  i# c/ G5 ~  O2 b; C
  6.     function __construct(){+ b0 c/ l7 n9 K8 g* r  K& C- D6 Y
  7.             echo 'I am test!';
    * S, ]4 a) i* a' w' S' n& \, p) q
  8.         }& \; G$ p1 O1 s+ j. M. L0 A9 N
  9. }
    , F9 U9 Y+ h7 J8 o0 b8 {
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
! x) s7 `+ r+ |) ]9 i& a2 |
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
- ~5 o  s$ Z) _+ u4 w& o* H! w
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php) B6 Y) C2 _% p5 M* x4 w
  2. 2 u4 B( Q% T. A9 m2 K
  3. namespace test;
    ; m3 Y6 W+ u: w; b
  4. echo 'zhai14';9 E" K& I6 b& o- Q$ ~& m" m
  5. namespace zhai;
    ' ?, n6 D* T# x( u
  6. require './1.php';
复制代码

5 O1 A0 P4 |8 Z% Y/ A
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
  ~7 L/ q- G: H) }; L
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
  E2 i( w) |* P8 q' j
  1. //name.php7 K: O3 f4 M% U

  2. & e( B" o, g% r+ _
  3. namespace animal\dog;
    9 F! B, y% S8 u, d/ ?) ^

  4. % [, E2 ~  d( o8 _" }- p- ]! k
  5. class Life{
    ( y5 C/ {1 x9 r6 B! u3 E
  6.     function __construct(){7 @, V, [$ y8 |" u  u3 E1 }/ ?6 E
  7.             echo 'dog life!';) v: ]- Q+ K& c
  8.         }
    2 A" {- `& |5 }2 o
  9. }7 j! z/ B0 y+ ]: P# {/ Q
  10. ! o/ }. e; b! A: g8 v
  11. namespace animal\cat;8 _) v5 b8 K6 q0 G3 A) c4 \0 b
  12. - N. ^1 C' M  t, |
  13. class Life{0 ^% S9 J7 U9 S6 D1 K
  14.     function __construct(){4 y$ N; a4 P  r, ~& s" F( T- O. Y9 ~% U
  15.             echo 'cat life!';. v) x  A1 E5 p' i
  16.         }2 d  S& k: F9 d" Q
  17. }3 E& o1 [2 U, ?" ^/ i  a: C, Z
  18. 7 L: }, m/ _' t" k# }) l8 p% p
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间% L7 g  v1 n5 h2 |. |4 O7 _6 Q, Y5 c
  20. new \animal\dog\Life();  //A$ H0 y9 t# x0 ]6 U

  21. : K* \4 [# x. U. F) Q
  22. use animal\dog;  //a
    ; j4 F8 n- z; h) Q: u
  23. new dog\Life();  //B2 ]2 m- `9 z: X0 u
  24. ) A4 k5 J- W% L- q1 c0 A
  25. use animal\dog as d;  //b
    / c, l+ O* Y. `% R% A; I/ y
  26. new d\Life();
复制代码
9 h' g. M& a2 v5 s+ j
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

% T# ?  s6 |$ D
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

& S- }( c) Q$ ?5 b* U
相当于
  1. use animal\dog as dog;
复制代码
  o& h0 [9 {: g! ~( n7 |2 y. X- M
2.namespace后面不建议加类名,但use后可以。% y% c# S% b/ `2 Y
  1. //name.php
    . ~' C' A9 o9 l4 B

  2. 7 C/ D5 n5 A" _9 I8 i) f9 t
  3. namespace animal\dog;
    % u3 S: E: M; q8 R) h) Z
  4. 1 D( ^! g  `, \: f
  5. class Life{0 z% k( V) @+ l" H! x8 w8 `
  6.     function __construct(){% l: n: k# V4 G' j* [+ b
  7.             echo 'dog life!';
    * x- G) E/ T0 y* T
  8.         }
    ! k3 ]$ K# F6 s8 |
  9. }
    ! b# n* W+ e1 l4 A+ K2 H9 R$ W6 `  m; H

  10. / w; P4 ^- G# {$ q
  11. namespace animal\cat;
    + `# m- O  {3 B8 t0 f! r

  12. ; T9 Y" M" B; R- v1 c) h
  13. class Life{
    - z# w4 G9 x5 e1 m9 M  B9 `/ c  z( W
  14.     function __construct(){" l9 H( O6 M, ]/ s9 E0 W
  15.             echo 'cat life!';
    + y3 y6 w) R% B6 X2 }: X
  16.         }+ {5 [5 K2 E; T$ q0 F5 m- \
  17. }, w$ ?3 \9 i, G: ]% ^& D% r  Y) s8 d. l' g
  18. 1 X$ N$ y$ K# V2 k7 W0 X! y
  19. use animal\dog\Life as dog;  - L5 o  q2 X8 j: w& o
  20. new dog();
复制代码

1 q7 }) \8 a8 j1 r$ H* C
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

# }* x4 a7 d) S' Y( q* m% E
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php1 ]6 P! A8 s  y

  2. , s% d5 x: c# a5 e' m) ?
  3. namespace animal\dog;" t% E) J/ u1 Z# ?
  4. . O1 D+ S0 R2 I$ X8 v6 B( l
  5. class Life{
    + c4 Q3 Y" O- G( Z. e
  6.     function __construct(){
      d/ O7 }9 t. K3 }
  7.             echo 'dog life!';2 T/ }  S6 T' C8 F# O% b6 |( ~
  8.         }  P3 u5 w# Y, j# w
  9. }2 O) `& W4 O4 F& e
  10. class Dog{! h9 }% n0 ~( O% P5 d1 j
  11.     function __construct(){
      K" F# a5 D* O0 J- f3 y
  12.             echo 'dog in dog!';1 W6 v, j% r9 W- ^" J
  13.         }
    . {' c( v) k+ k
  14. }
    9 q; t7 X  L9 m9 |  U8 w& U, q
  15. 1 ^6 |  ?. h% b7 d& ^1 r2 `. V: l" R
  16. namespace animal\cat;# K, H6 ?3 a7 p( X% l" X
  17. 1 f" z9 m% l6 |) E
  18. // class Dog{
    0 j0 c+ B, X$ c" I
  19. //     function __construct(){
    ' ^% E1 w, ~) R( Y" y+ m' l6 B
  20. //             echo 'dog in cat!';
    8 [  S! r7 |! z! T9 Y
  21. //         }
    , m+ i- |$ l, ?, B1 Y2 c- v
  22. // }
    7 k5 @4 r1 v% `4 A( k
  23. class Life{
    * G* {) I3 ?/ }+ |4 O0 l  g5 u: T3 i
  24.     function __construct(){- W6 W1 T, V' M5 Z& N3 m5 _
  25.             echo 'cat life!';$ q; P4 S, T" X: Z6 M, e
  26.         }
    + g5 x; h" ^5 _* ?' u
  27. }
    % i0 i% f6 _' j1 v  u

  28. 2 d9 |7 @& \8 C% m8 ?% K* S
  29. use animal\dog;  
    % u$ w) g$ a6 ~
  30. new dog\Dog();
复制代码

* X' P( Y* U2 m0 b; A) U: R$ W
如上,使用了
  1. use animal\dog;
复制代码

; \; z  Y. p- ^0 Y- N7 |4 ~
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
/ e- ^% g8 R: Q( K% O9 F- H( t
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
( P0 j' z  |8 h" C* S' Z
! y& d4 l1 D5 Y& V: D
5 ]( ], O! q6 e# [" [
$ [0 E% ?0 R* V$ l, Q" _
! N6 ?4 x5 `2 q1 Q  k8 e( `1 \1 q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-5-2 14:32 , Processed in 0.063373 second(s), 19 queries .

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