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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

* ?+ x- p) @/ C3 M; a
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

0 ]. o& o6 Q4 d" G3 ?0 R/ @) w/ S, Q2 Y1 I) W9 i
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

: S& o8 D8 K- J4 |' W6 j- w/ W* o2 c结合使用方法来进一步理解它的使用目的吧。
% Z7 b: A. ~' t9 L2 T( p- t* n2 t
( C& Z, }3 o5 g; U/ q& L; F
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;1 v6 v7 ?$ v! u4 L
  2. namespace One;
    : D/ D! N9 O+ z- \9 S1 W9 P( P; l
  3. namespace ONE;
复制代码
7 H$ U3 D. K1 j; E& |' L
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

2 p/ X  Y# e  L" p4 D- o2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    ( R5 ?4 B% L* J' V( M
  2. class Person{
    4 ^/ P& u3 M( f: a! z% u9 s1 W
  3.     function __construct(){
    " v8 U# t7 W2 H+ L+ N
  4.             echo 'I am one!';# b' u! d4 X5 H7 V0 C9 h
  5.         }& x9 E9 b: u$ K6 W) k
  6. }
复制代码
  1. //name.php
    6 m# A- r7 a6 V
  2. require_once './1.php';
    " q% L3 g; A3 F% s

  3. : Z+ j8 {  y$ f4 \4 N2 n
  4. new Person();     //输出 I am one!;
    . D* S" v# ^* e4 W4 `
  5. new \Person(); //输出 I am one!;
复制代码
/ H: B1 O/ Y' j: k6 v0 n- O: ]
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    & \1 q" T+ V9 a$ A, Q/ T
  2. require_once './1.php';! u2 e, Y) x7 r8 H
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

. `/ r$ X$ E( B4 i3 J1 \* M8 B4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    - f' I& r4 `0 X5 I% i. I7 M
  2. namespace one;3 z+ |: |/ q; R
  3. class Person{7 _6 B2 M0 J) T  D. A  L" M* u
  4.     function __construct(){
    ( d; @6 N; Y/ |' x
  5.             echo 'I am one!';
    ' a2 H% r1 j1 w- K9 S4 w8 }
  6.         }
    + |% U$ N" B/ h+ ]5 h' I
  7. }
复制代码
  1. //name.php
    " Q" [" v; e" [) N
  2. require_once './1.php';( R6 n* E. H( V8 s1 ~7 B
  3. new \one\Person(); //输出 I am one!;
    ' R: ]& Z. J5 n2 V! ]
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
, n- X# Y+ d0 @0 l+ v) x2 o& \- T
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

. p5 H9 ?7 [% w9 R' I9 y5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
3 S/ Y2 Y5 J- i/ Z+ e, x
  1. //1.php   
    : S0 T7 S  T% u  [8 j
  2. namespace one;
    4 _- I* n: R% J! H% C. ?
  3. class Person{
    1 ~( B' t# \. R& K* `
  4.     function __construct(){* N1 u1 ~1 Q6 }, b
  5.             echo 'I am one!';8 @( e) u; [2 Y0 x0 O3 h
  6.         }4 K! Z  @4 c  g; B* D  k7 i+ M9 @* Y
  7. }
复制代码
  1. //name.php8 y5 h( p+ d, ~* U) v6 G3 D
  2. namespace test;8 ^( s6 r; e0 v* I# D: M
  3. require './1.php';
    ! h) z4 r6 c3 d0 G9 J9 O9 O& a
  4. new \one\Person(); //输出 I am one!;) r! R! [" A4 k7 X& h+ Z
  5. new Person();      //这里结果会是什么呢,猜猜看* Y, `: E* ^5 \/ V, \" z% \
  6. 最后一行结果报错:
    ( S; u9 E& B) X
  7. Fatal error:  Class 'test\Person' not found
复制代码

% b. Y" u; D. M9 R
% @/ }4 f1 y9 k
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

. ?. u7 b; {; M% J
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
; }  o5 j$ }  u, V( |6 P% t6 b
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php9 Y4 o# m( {& U4 n) I
  2. namespace test;
    7 M3 E9 c4 i+ E
  3. require './1.php';
    & s  W4 s. {" ^( ?- [% l, m
  4. . O; V8 K8 h* N7 [7 d
  5. class Person{$ z& N9 N9 u- t, J  W
  6.     function __construct(){
    7 R0 X- }/ _( ?
  7.             echo 'I am test!';
      ^4 u: q3 ~0 b; C7 }; G
  8.         }
    ) Q) W) @& X( r  q3 b1 Z1 D9 V) o- ^
  9. }* s- {7 }$ H0 r6 Z/ E4 B! e
  10. ( I! e; O! p0 n% M$ k$ W' d
  11. new \one\Person(); //输出 I am one!;
    * j* t# p; L6 L! e
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

  M& s8 y; L/ Q8 S( E. g$ r6 |
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php  S& J9 _1 W* w$ D& y+ e
  2. namespace test;
    * c/ ?3 y1 I& u1 l' c9 k
  3. namespace one;, V* ]9 T+ ^  I8 u3 u8 Y
  4. class Person{
    7 V4 D( ~' A% D+ T3 ?3 V% p
  5.     function __construct(){
    1 f! y) _) I, C4 o$ J, l9 O5 ^
  6.             echo 'I am one!';
    # d% S: P" ]1 h6 H7 ?+ k
  7.         }
    - F$ L' c! I/ U( L
  8. }% e+ N) n; Y8 g6 I: E; f
  9. 1 T2 @9 R- ^) N1 a9 B  _
  10. class Person{
    / x5 m/ V! T/ u5 Z
  11.     function __construct(){4 Z. {3 L" I4 L- ^( \8 Y
  12.             echo 'I am test!';
    9 F: g. O8 W8 H: r
  13.         }* {4 j; s5 \" `: x
  14. }
复制代码

! @. S* k6 k, j/ d4 J4 M6 a
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

. Z, c9 ^. Q4 y" o
看来简单的把require理解为替换,在这里行不通。

" [+ T  O% ~7 g) ~: b5 Y" v6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
5 o" b9 w, D8 F0 ^8 x
  1. //name.php3 ]* [8 d6 k7 }% |3 s6 {) {

  2. 5 t9 Y# H- F7 x& i: @
  3. namespace test\person;
    ; a  ]  I9 b% l. n
  4. ' N  t% p8 |5 H
  5. class Person{/ p4 |+ e2 S' d/ v
  6.     function __construct(){
    8 E9 j% c4 \+ D  k% Z2 F
  7.             echo 'I am test!';
    " i# {$ @* @+ N9 L
  8.         }& I- n! ]' l: q/ r+ i
  9. }
    . E5 _3 P1 F& O2 E! p
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
: G( D) k' L- i' A* M* Y6 Y
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

% _: z9 C9 ]8 O/ g) r6 Z7 H  k; F7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php$ I5 j$ @7 g8 G

  2. % B+ [# l& N# y) O8 B
  3. namespace test;) E8 k7 V+ {0 G3 |0 y; K" Q+ S
  4. echo 'zhai14';
    8 p6 s* g% h7 D& e) `- }" k3 H
  5. namespace zhai;8 ?3 z8 a  P8 [; ^
  6. require './1.php';
复制代码

4 }2 v9 ]) H5 d; T
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
' x& t+ F/ z; O( G
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
3 A3 D6 ^, L7 Z
  1. //name.php( q2 {3 E5 Y7 S. Q% @* y) c

  2. ; {$ M8 {2 v/ U+ A$ E2 m1 D
  3. namespace animal\dog;
    , H( h+ b. f0 l2 Q1 y- [' V2 K% n
  4. . L2 ?# m) j' x1 T
  5. class Life{7 X! \/ i( d& }8 k% t6 D
  6.     function __construct(){
    / x+ c  Q6 F! ^8 Q
  7.             echo 'dog life!';8 d! b/ c5 K9 D6 [$ B7 |
  8.         }7 m. k! S8 Y0 v4 e& `' @
  9. }
    ( W( t8 O7 q! e# E/ _- l$ r
  10. ! ~0 r9 b' B+ G; D" e7 P9 t
  11. namespace animal\cat;, O& W  m5 n/ U

  12. " H, e  {( X+ ^! K8 j5 n
  13. class Life{
    " Q' H: b+ e& X4 o# h% M6 I
  14.     function __construct(){
    : W' p: z" z: _2 ~, O$ ^* D# R
  15.             echo 'cat life!';
    # W2 E8 e( F$ Q9 G: \  [7 Y$ X* ]
  16.         }
    , N8 ~) O8 u) D" f+ ?
  17. }
    * f2 f: R7 `6 M7 v  A0 ~1 i& a$ S

  18. : g4 a" I3 b; C! v5 f$ h0 l% \* k  P
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    : h% u7 E. I( x! W3 z5 U6 T
  20. new \animal\dog\Life();  //A
    - \7 w. t8 C% T/ v1 y- }+ G

  21. & X$ a$ z+ g# u/ L
  22. use animal\dog;  //a
    ! n+ z9 _% I) B3 T
  23. new dog\Life();  //B
    $ u9 l1 T3 c, @
  24. 9 e% o/ H4 n' x2 o: {
  25. use animal\dog as d;  //b: g+ k5 }, [6 l( e/ q9 Z
  26. new d\Life();
复制代码
- D$ t* H  V" Q$ v" T. p# z7 b
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

1 p% y' t3 f+ R2 m. r7 p; N0 I9 x
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
1 b/ Z; a# q) i9 O
相当于
  1. use animal\dog as dog;
复制代码
3 j- n% O$ U) D& D9 ^
2.namespace后面不建议加类名,但use后可以。
+ P5 _$ }% q: {. E& B) d- `( p+ |
  1. //name.php" L2 ?$ K6 K3 e8 M$ N7 a+ ]) ?
  2. " A2 ?. r3 |$ R* Y* {
  3. namespace animal\dog;
    : h. S0 o6 @: A! Q5 \5 }- ?
  4. / w: `2 |& k& E% p
  5. class Life{7 X8 F: P5 z: {& c: X1 `5 k
  6.     function __construct(){
    ; D; D/ ^5 M5 f. a
  7.             echo 'dog life!';7 b. L3 @+ O0 V5 c; F! a
  8.         }8 D6 ?/ S( R8 p5 k& E1 P: R* D
  9. }6 L; U4 E8 \% {& n! |! |! J5 R

  10. ! A; S- A, ?, f! X2 f- N
  11. namespace animal\cat;
    ( H  [6 G$ c$ ]6 U; ^! l

  12.   C, U1 A$ F1 V5 l! h/ n7 A
  13. class Life{' L+ W, ]# K0 X  d( x5 z$ P
  14.     function __construct(){
    . Q# ^% Y3 ^- f& J
  15.             echo 'cat life!';
      h3 }4 V3 a9 e+ j1 v7 Q6 W; J0 P
  16.         }
    ! |: v" K6 D$ |" V0 c( b4 V, y
  17. }  Y) n3 V4 j2 v, ^+ P2 }: b
  18. . N6 \& w, Q, U! t! i7 V) K1 n
  19. use animal\dog\Life as dog;  & L6 s1 @% H8 H
  20. new dog();
复制代码

) o0 a" b6 w7 l5 U0 I) G, E+ x
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
, s7 a3 X1 C" Y
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    $ H1 Z( c% Q( k) Q0 G' A; G. H, {5 P

  2. 9 r& D' }: f, i4 k1 \
  3. namespace animal\dog;
    % f5 A& i" B1 L' w& Z
  4. 0 S' O: b  T/ W/ ?
  5. class Life{. A7 E; n7 R" M0 T
  6.     function __construct(){, U8 w7 S% ?1 [! p- }
  7.             echo 'dog life!';
    $ T2 F6 V" s& h
  8.         }( Q0 X0 j* ^3 b: L* ~3 T8 v1 S
  9. }+ Z- i) s* y7 B3 e
  10. class Dog{
    1 Z8 ~% k: [% _
  11.     function __construct(){5 B0 a/ x# d9 o' W9 L' Y
  12.             echo 'dog in dog!';
    ; z7 M: |. @5 v" n* l( v+ j: i
  13.         }$ u, U& }& a, f8 ^5 o8 t
  14. }4 B. G7 r4 j5 W$ X+ ?
  15. 6 [- x( M9 _5 d+ [. w
  16. namespace animal\cat;7 {6 s  h! h: J+ ^( D5 Y3 M2 c
  17. % f6 T9 f' N7 b% [7 ?
  18. // class Dog{
    6 n7 |" g8 q) L7 a" p2 y9 N
  19. //     function __construct(){
    2 i7 o" u9 B: C1 r' K' @
  20. //             echo 'dog in cat!';5 }1 [: U' Y1 f( F$ }) V
  21. //         }0 Z# Q9 {2 s% O" k8 y
  22. // }
    # v# Y2 h. P9 S; k/ P& o( v
  23. class Life{
    8 ~% ^7 ^" s9 U# Z3 c2 X
  24.     function __construct(){
    + G7 u' r1 l' r4 m  r0 r
  25.             echo 'cat life!';
    - k4 c: q% G. R3 w. U6 y: Y* a
  26.         }
    7 _0 F5 c9 ^* g% o% a$ Y8 H, k, A
  27. }0 H% c" Z, ]  C& Q

  28. * O% N& n4 U' X, c
  29. use animal\dog;  2 X& V$ v) R# {$ m/ J" E* ]1 M
  30. new dog\Dog();
复制代码

% Z4 ]* R. W& C3 S0 K: n: W6 u% i; `
如上,使用了
  1. use animal\dog;
复制代码
* c. m+ l( k  b
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
4 z9 T  M5 e6 g; H; p$ z4 v
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
. o1 a6 s' Y. M5 J

$ I+ n% e) A* u) w. Y; s
0 O9 Z5 a% W# i; `4 o* ?) p8 v% v; ]- d1 `) \1 [: q2 z8 l/ e& ?' U

1 K% d6 O. S5 d, z
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 11:57 , Processed in 0.125971 second(s), 20 queries .

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