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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
4 R/ R" S/ b1 ?7 `6 k
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
# C$ m5 _& P' P  R& B+ a+ |( O

# w9 |' e5 i( a& p- X! ^4 I使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

" K. Z" r$ K$ i$ M+ d
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
- m1 j8 ?' |1 A* y: R. v
结合使用方法来进一步理解它的使用目的吧。
+ N5 [5 ?1 Q- ]% G3 o% ~* H. h
$ V2 C* R: H; L* R3 G  C) u$ K
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;. C, c' Y+ V- \7 h+ @! J9 r
  2. namespace One;
    5 N5 d; I/ T9 p2 ^2 w9 E: m: R7 V9 x7 z
  3. namespace ONE;
复制代码
3 y# ~" `1 A! H  f1 G" c
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

% ~' n- i7 l4 q& o, R2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    $ w' f7 m5 K8 W; ~; M- K
  2. class Person{
    ) m, f. T5 _: d" u6 h' Z6 _$ h
  3.     function __construct(){
    / S% T, u! T& m0 C: M8 K. l
  4.             echo 'I am one!';
    ; [9 G+ ]2 h; P- w$ U# ^3 `
  5.         }
    , s3 X6 n1 H1 ~
  6. }
复制代码
  1. //name.php* d/ G" q$ E: N6 Z' z  q
  2. require_once './1.php';" M" a; @, x% e( _; J3 ^& X3 Q
  3. + r# C: g5 G$ l+ g! i" b7 f
  4. new Person();     //输出 I am one!;" e6 |! Y6 s! _% [: A
  5. new \Person(); //输出 I am one!;
复制代码
1 U: C9 s  w, C, \/ U
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    1 `, L# b4 _0 F" y+ X
  2. require_once './1.php';
    5 ]/ O( i8 X% B
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
+ E3 J0 Z: C; Y% }- A
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    + r- `2 b4 J$ ^* w  V/ V$ L$ P+ G  w
  2. namespace one;
    1 F* i( Z- R$ j& E: l# X
  3. class Person{4 o- V0 y( L( l
  4.     function __construct(){* ~. t% z& x' R! R7 |' a' p7 \
  5.             echo 'I am one!';
    3 F- n  C8 J* F6 c, |1 @4 ]! o
  6.         }+ _8 O" a: }$ ^
  7. }
复制代码
  1. //name.php% ~0 c# ]( o% V* g
  2. require_once './1.php';* U$ a7 \: n5 C% ]" J9 @& E
  3. new \one\Person(); //输出 I am one!;# P% e+ b1 x" e  K
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
4 y5 c: y; h3 s. e
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

. ^, y) T+ ~+ \' l/ K  E5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。# U) e" M) I! M, `. B2 H& n1 f
  1. //1.php   
    0 Q9 J4 r6 L, m. }7 G
  2. namespace one;( y1 ?; j! \* m
  3. class Person{' w; ?- J" P* k: r
  4.     function __construct(){
      O' f; W" ~! C" ~
  5.             echo 'I am one!';3 |6 B  ]0 y2 [- f8 d0 u6 h* n  t
  6.         }
    ' {$ G) ]9 F# Q8 l
  7. }
复制代码
  1. //name.php
    ( A" D: D4 J2 P0 ^# z( o
  2. namespace test;
    . j& O7 i# b/ \& f( k
  3. require './1.php';
    : T3 N0 d6 Z- w2 N5 H: x
  4. new \one\Person(); //输出 I am one!;, J7 X/ p( e2 _& e  ^
  5. new Person();      //这里结果会是什么呢,猜猜看; R) L, h7 K) Y$ ~) _# l: [
  6. 最后一行结果报错:
    $ m5 s" \: d7 o* K% ^* t& U8 L
  7. Fatal error:  Class 'test\Person' not found
复制代码
: [) a' ^9 l0 ?0 y& i- M" I  W/ e
$ d6 v3 S1 {7 Q2 u4 J- a
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

" {/ S3 J2 f8 o" {: H/ M4 a7 ~
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
9 Q  m8 f& A/ X
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php. i4 }/ l1 w+ |) a
  2. namespace test;8 R9 f# `. h2 `" ]
  3. require './1.php'; 8 l/ M4 D, K/ `' G+ T! [

  4. 0 T1 Y4 A# m+ e4 _, ~$ W( i6 @  O
  5. class Person{) `3 _( c" b% z: I, d. ]
  6.     function __construct(){
    % K: S, P; O6 o5 [; c" v! V/ S, T
  7.             echo 'I am test!';' S3 i2 L1 |1 M5 q% ]
  8.         }! H. i9 K" q# e# A' U- N7 M" C
  9. }
    / g; H' t4 H0 ^* \5 z

  10. . b; O" u+ s. D
  11. new \one\Person(); //输出 I am one!;
    5 a' O% V8 l" h5 u! N- ?
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

8 U  D+ @3 N3 g+ t" L
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    % n& r: s( X+ m. g3 R- A/ M
  2. namespace test;
    * J2 L0 G9 f1 s4 U, o5 ^
  3. namespace one;1 P, V& M4 t2 r
  4. class Person{. y2 |" N% m6 P. w. C
  5.     function __construct(){+ h- P& h$ \% o6 b7 d3 \
  6.             echo 'I am one!';: o; p: t, J* q7 ~- K% H
  7.         }8 z/ h" |' }9 `9 }9 d) }
  8. }' ^; P8 ]# g6 S; C
  9. 5 V2 P) u. b% w# v. u) _
  10. class Person{! I6 p6 C2 _3 }: M( L
  11.     function __construct(){
    ( q& ~! F0 ]& u6 s% c2 J; H7 R
  12.             echo 'I am test!';+ b+ o& ^5 F; U$ t0 H5 Q8 c
  13.         }
    ) H6 H  O% {" c6 r( ^: B
  14. }
复制代码
  J8 u% s4 t2 N6 ~% U, q1 e& o
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
7 Y1 S. w) F1 ]- l' K* s# @- \
看来简单的把require理解为替换,在这里行不通。

& K8 U8 b! t( g; d6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。7 n  H0 f: o. \
  1. //name.php# a3 {% W2 S, J9 M  r8 [
  2. % F9 N2 N7 @8 q' K7 I+ x9 w4 u* @
  3. namespace test\person;
    1 ?  K1 k8 f$ ~0 d

  4. 2 E7 G3 t" X% y- |
  5. class Person{
    6 s# u. h2 ~2 E' l6 A
  6.     function __construct(){
    ' z$ _% l$ }0 a; W& K
  7.             echo 'I am test!';
    6 L1 m/ l& _  a5 A. d1 L
  8.         }
    ; v% ]: G. Y: T$ i' Y4 j
  9. }1 h0 d  l/ q+ w6 Z' ?1 p4 k7 Y
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
0 h4 K$ y. z: D! U" h5 {7 F
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

; ^" @1 l5 q& [4 B; G7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php" \  n. o2 K. |6 ^0 j

  2. ( ]' C' L5 M0 w) \; k
  3. namespace test;6 m/ |# n0 _1 V
  4. echo 'zhai14';
    ! M* Y2 ?1 \7 y9 W! @* J
  5. namespace zhai;2 D! |3 _0 R2 x% f
  6. require './1.php';
复制代码
0 s1 d+ b( B9 \- H) `
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
6 B' Q2 j! @7 W: R) x; I
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
% D; ?9 Q7 b+ U9 w$ Z; ~
  1. //name.php& H2 ~2 q. c# d
  2. 4 s! z+ A6 ?% H' G" U
  3. namespace animal\dog;
    0 K4 g- r2 k' v' }  Q1 n. S# ]8 L
  4. . z) ?. j) l/ e# d+ m& V' N" e
  5. class Life{
    7 s+ w0 r' S, X- k1 `: d& t" k6 C2 I6 T
  6.     function __construct(){) K  ]! y$ S. O3 ]$ v
  7.             echo 'dog life!';
    0 o7 w( [& z+ I' J
  8.         }- J/ B" u/ |, i
  9. }
    & K0 k% N  n8 b3 H; u

  10. / E1 H9 B0 y3 r7 q0 v2 j6 z* K9 g
  11. namespace animal\cat;( z6 }3 x! \8 d
  12. ) g, Z# i# W. L) U
  13. class Life{
    ! x5 k  g* G0 d5 P
  14.     function __construct(){
    2 g+ X  Q9 K8 f1 Y
  15.             echo 'cat life!';$ o9 K/ ^2 {) K# {
  16.         }5 Z, O1 P- e, `
  17. }5 o7 ?0 L# }) i2 m& R0 R1 [

  18. ( M( n: h8 W2 l2 V! |) D0 P
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间! ]+ F. A3 H* ]
  20. new \animal\dog\Life();  //A
    ! w( J3 B- @; e% p9 Q+ y! K. o

  21. - Y- O0 f7 ?" v: {  M, J  k
  22. use animal\dog;  //a9 @% Q, J' G# X' t/ A. `
  23. new dog\Life();  //B
      z. T0 S# Z2 V

  24. 6 `$ S4 C: r# p- Q# @8 d
  25. use animal\dog as d;  //b
    $ M7 `9 H& |) O$ g1 y; Z
  26. new d\Life();
复制代码
! t* o% q. |+ t1 {% @8 C
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
4 M$ U6 R" I5 \# |
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

- d5 c& q# Z' R7 @% i
相当于
  1. use animal\dog as dog;
复制代码

9 i, V$ Q. r0 g2.namespace后面不建议加类名,但use后可以。
" b) Z, I' a% {0 W- o
  1. //name.php
    3 n8 ?  @2 z* I8 [+ F7 }

  2. 6 C5 a& ^/ p; D- t& n/ K
  3. namespace animal\dog;: k8 |/ w; M2 R+ [- c: R+ C- d0 b2 W

  4. ) m7 n: w3 \+ _. V' L5 ]
  5. class Life{
    8 A7 m- y8 r' N- V) s
  6.     function __construct(){
      w# x! t; S7 V
  7.             echo 'dog life!';
    ; E: X- i/ F( D
  8.         }( k$ M6 M  E4 u* \% B
  9. }. F' p2 }" I  Q4 `" u# c; ?
  10. : ~9 \9 o1 e( F* v
  11. namespace animal\cat;) c; V; o8 q4 M" h: k2 Y. N% D
  12. 5 p( z* R! [* I1 W4 m: B& W
  13. class Life{
    4 W1 W! K$ b  ]
  14.     function __construct(){6 p% f; @; E- y- ^
  15.             echo 'cat life!';
    2 g' f2 `0 W  n* t# u: H0 h
  16.         }% M% A( e! ?' y2 X1 K) ~+ a! P
  17. }) m. i0 Y/ o8 P. ^; q( B" |. _! `
  18. ! V+ t  g5 o' W) x- J& k. l
  19. use animal\dog\Life as dog;  ( M+ f1 n# _1 O- U1 \) F8 n" Y: D
  20. new dog();
复制代码
0 h3 c# B( ?1 q( t0 u
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

7 D1 w# Z) I8 M0 w5 h
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php+ ]4 t. @& J4 r

  2. ) y% ~$ Q- u. B  D  I% E
  3. namespace animal\dog;
    0 w* |2 T" z5 B! @7 ?4 g% f
  4. 5 }% ?& j0 x) _4 R
  5. class Life{& k* _# E/ C" C8 U
  6.     function __construct(){
    / {3 U, [  R$ N8 f# a! Y+ @
  7.             echo 'dog life!';8 H  [- R3 j0 t$ p7 A8 _3 m9 A
  8.         }) y; V8 _6 {$ z( B- h( c, [" B6 }
  9. }6 S; D) F/ V7 V8 }  z1 ~
  10. class Dog{
    , B4 }) ]6 X$ k7 i7 v5 `( i
  11.     function __construct(){' Y# q4 F. O* M
  12.             echo 'dog in dog!';
    ; O( h0 ^+ u0 Q+ w1 Y
  13.         }
    ! ^+ {9 T7 S0 g# Q( D$ b) A
  14. }$ Y  h% U. k; I" J8 I3 c
  15. 3 s  r: }) z9 r% o6 ]' J. M- C
  16. namespace animal\cat;. q& r  m# Y% y% A; z6 f& F

  17. 2 @! z3 ]& d" B7 I4 F
  18. // class Dog{
    4 R7 t0 v6 _% K& Q, a7 Y6 N# H
  19. //     function __construct(){; c' \7 ]# m1 H3 y+ M
  20. //             echo 'dog in cat!';
    3 g- T& _8 b, P- s& y
  21. //         }) r7 T( F. f, W: X* P' F& Y. b
  22. // }
    ( ]6 @+ Y- X- u8 G# ?
  23. class Life{
    4 F# p0 c! j  _1 x, c1 F
  24.     function __construct(){% v( f! n9 Z+ z/ \% l
  25.             echo 'cat life!';
    * x8 T; v6 o  e+ F( t7 v! W7 q
  26.         }, ~6 y" K- u& `1 O6 t
  27. }
    5 Q& P7 m4 b* d6 p+ J: i3 `: H
  28. 7 t( U5 D& @( c& b8 O3 j4 l
  29. use animal\dog;  
    " Z% q/ O4 R9 v( V5 \
  30. new dog\Dog();
复制代码
2 Z$ H! |9 a0 P7 \
如上,使用了
  1. use animal\dog;
复制代码

7 i( m- R  j+ H
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

; K; Z/ S5 l' Z( F
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
" R) z% \; ~0 v& v* I7 n4 I! n

( v1 f: Q& I: Q' ~4 j& X& r# S( _; n: D
3 c9 Y3 S9 O0 X" v, q. w- `" c
* [& m$ e) Z/ k; Z9 R* R
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 10:10 , Processed in 0.069095 second(s), 19 queries .

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