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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
% p, ?% J9 y/ p+ v1 y6 ~
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
% q0 X7 A1 Z3 e
9 U  u% F9 I5 \' C" H, }
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
( e# G) o( S9 m9 F) N! v
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

& e  B" e  m$ Y5 `2 J7 v6 m8 G结合使用方法来进一步理解它的使用目的吧。

4 N# Y: B0 p' N3 l: m7 W! ~0 \$ l2 V3 s' J! o' [
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;4 [7 g9 p) Q% z) R& E& k* P
  2. namespace One;
    8 [- }/ K9 U: ~5 [# A/ Z
  3. namespace ONE;
复制代码

( Q8 ~# a! [" B# a; _  ]- Q+ `
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
7 k$ ~3 ?/ C, h; V7 P- V
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    % \3 q# b& F$ F" n6 ^8 a1 K* I* b
  2. class Person{
    ( t9 h: j& ]" Z- G& H
  3.     function __construct(){
    ' _. f; a% L4 E' i* z4 U
  4.             echo 'I am one!';
    9 I/ R) Q) ~: A5 p1 `+ r* S
  5.         }; A8 o( Y0 O3 E, [9 A3 G4 o! N/ e
  6. }
复制代码
  1. //name.php
    ' T8 m8 T5 _) ~. j5 O' e) p7 B; k
  2. require_once './1.php';9 ?( X' e7 b% u+ ]
  3. # E. K4 P  K) R
  4. new Person();     //输出 I am one!;
    . g9 k1 {: g: ]  t1 V. c. J
  5. new \Person(); //输出 I am one!;
复制代码

( A- H2 [- n* J9 k! S$ d# n0 L& ~- X. T3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    & O9 S, |  O0 v' ^
  2. require_once './1.php';
    4 @1 _4 S* d' h; F7 O9 I
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

0 y7 z% x! ~& ^5 W1 `3 P. V* ~4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    $ ~" w  ^! a8 O0 J! g, E; E; x
  2. namespace one;
    ) X! O% J( s7 V8 G' i/ m
  3. class Person{
    , t$ I/ b* O! d
  4.     function __construct(){
      p3 M8 O# o7 x$ e3 A3 r
  5.             echo 'I am one!';4 _7 g4 {/ S1 f3 C4 M- l6 S
  6.         }! b' r# K- ~2 V+ p, ?' W. b7 Z; |6 |5 i
  7. }
复制代码
  1. //name.php! I! d! `* B" l& n% _% Q) Q
  2. require_once './1.php';
    " t5 O8 U. X) f" g: _
  3. new \one\Person(); //输出 I am one!;
    5 w, f! L# P/ K% v
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
( g  U( w# x) r8 w7 M( q1 q( ?
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
( O# P: E) v* G6 P
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。( u/ r- L) \' X5 E/ m8 j
  1. //1.php   % |6 S0 O' ]' c& m/ O2 ~8 y
  2. namespace one;' G: Z# w4 R7 d! g! T
  3. class Person{) D3 m* u9 H2 o+ I) |8 N
  4.     function __construct(){* o2 i: `$ H3 G' A# N! u
  5.             echo 'I am one!';2 h; P, J8 N1 x: v8 }1 q
  6.         }
    $ X/ c' j, L& D9 m+ y7 l6 d
  7. }
复制代码
  1. //name.php, s' c( X: s* `) N$ P% |( g4 l+ S
  2. namespace test;9 m/ w, L0 ^# P# @- O% n
  3. require './1.php';
    ; Y* C1 z7 y, q0 E* Q
  4. new \one\Person(); //输出 I am one!;( u: ]7 {" C2 d: t# y: {
  5. new Person();      //这里结果会是什么呢,猜猜看* z$ z  N3 \" @
  6. 最后一行结果报错:1 Z& Q5 K* r0 c; V3 u
  7. Fatal error:  Class 'test\Person' not found
复制代码
" {% n5 T4 h! n' S

8 k4 H! o$ A( D7 o首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
3 u7 ]  X/ N7 h$ V" ?* p5 v0 N9 z
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

  t0 z2 ^  r, h  k, |: g
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php: l- m0 t' V8 a5 w
  2. namespace test;
    6 k2 ~7 a- h/ j7 D  A
  3. require './1.php';
    " s! Y9 k) Z4 U9 {4 E

  4. ' l' T* q/ G: V) V; u( R
  5. class Person{
    ( p! y; y. C% y  I
  6.     function __construct(){9 l) r& {) i* b; S6 l, D' n& @5 ?
  7.             echo 'I am test!';' e$ }' b3 s& B$ ]( O  z
  8.         }
    ; Q) Z- r! z+ ^& P, e( t9 y8 a( \
  9. }
    : B2 j* E8 @  |! u5 _4 N

  10. 2 c( `8 J! z4 G  P8 x
  11. new \one\Person(); //输出 I am one!;
    ; E" A: ~) f) R; `3 f! O7 N
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

4 L7 o: k2 I; t: S5 s$ Z5 }
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php% ]8 d7 S* w* {1 F# Y- G, v
  2. namespace test;# L/ I, t% a4 u! [
  3. namespace one;
    # j3 A0 m$ a! ]3 U( c: x0 p
  4. class Person{
    2 y7 n2 i# E, f! s5 u5 I
  5.     function __construct(){5 P7 t8 z* M% R  s" q
  6.             echo 'I am one!';3 U! t" ~* t8 n
  7.         }
    0 z8 S, P' Y7 G/ R+ O6 f. b
  8. }8 O$ E9 J+ o* W( s

  9. * A* D; ~. V  w* E' _) r* M
  10. class Person{; x/ c6 c/ h5 D5 E4 r, D4 I
  11.     function __construct(){
    ( V3 I4 o( S/ o" v" A
  12.             echo 'I am test!';- N: ~8 ~3 d; L/ R3 c
  13.         }' j" u; U. ?; [
  14. }
复制代码

3 K, U0 ^' u; [& a7 l  a
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
& C3 |9 t& Y3 X: G7 t1 {
看来简单的把require理解为替换,在这里行不通。
, g$ p5 P, t# O9 M4 f/ V' Q- W2 z
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。# A. z$ k! ]& l7 H
  1. //name.php4 X4 g& W8 M4 x0 ]4 k' v! T  Y
  2. - K* b) f; I+ y' b0 ~# X
  3. namespace test\person;
    . Z7 t7 l  F' A0 f  M
  4.   `; V0 z$ S7 w, C8 Y4 [
  5. class Person{7 V  H. y) ^4 I* ~# f( n% q
  6.     function __construct(){4 H$ q0 U/ H. f! h: n2 E7 ?
  7.             echo 'I am test!';
    " @$ [7 r8 {% p9 t, B# H1 c/ b5 O7 ^
  8.         }
    # T! p- i) y( [% F% o
  9. }' c% E2 F8 }' \5 @: K
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
# g4 Y# x" H) c+ W
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

% T) u9 C& I8 r' I. ^7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
      @7 a  }  q. ?3 e
  2. ) c3 T. G+ P8 Z: [0 {
  3. namespace test;
    . v. o4 n5 i0 J
  4. echo 'zhai14';0 {4 Q6 O' `" i1 ~8 _
  5. namespace zhai;6 @, ]/ }, q+ f  G& Z
  6. require './1.php';
复制代码

4 X' o# ]2 @: P
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
7 m: `* t! @0 f+ `+ e
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& [5 a0 v2 j3 K4 S/ g9 l; ^3 j
  1. //name.php$ o7 q& R. @6 n' Q* e: [9 y
  2. ; ?9 l2 f+ G4 p9 z* Z
  3. namespace animal\dog;
    ; s8 O2 c0 ?# F' O4 ^6 _' l. i/ s
  4. 2 }+ q4 v5 r1 _- J2 M7 b
  5. class Life{4 ~- N( P8 u! C" `" R  l' h
  6.     function __construct(){: z  f5 C9 f4 m9 `; V; K2 M$ Z
  7.             echo 'dog life!';
    # |$ e4 d6 ^) c8 H
  8.         }
    1 C+ j4 K2 p; g1 O- P$ D0 @: n
  9. }
    / ^0 O( ~! t% y  {1 g! ?0 t

  10. / [. G0 n# A& c3 L5 n$ Q
  11. namespace animal\cat;
    2 M+ l) i* t+ x& t. [( r% t

  12. ( v& d! W* u% Y7 u
  13. class Life{
    * x) G) n1 A4 t4 m% M/ u
  14.     function __construct(){
    % l, d6 @3 q, S5 E
  15.             echo 'cat life!';2 ~/ ?- b8 K! z& }
  16.         }  ~( _* c# b% t" D8 n+ P- E2 A
  17. }4 l9 ]) l: _5 l  J. N3 f2 q

  18. - t$ ]3 j! Z3 m: v
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间6 {( K" z- V6 [" v
  20. new \animal\dog\Life();  //A
    ! H! h* _4 Y! U: t( i; u: Z

  21. * l; r0 T1 r* M: Y" F9 e  X
  22. use animal\dog;  //a
    8 P$ ^4 [, M$ B3 x# X7 l. @; l
  23. new dog\Life();  //B; ~6 B2 m$ B# v

  24. ) E9 H! N8 k) F
  25. use animal\dog as d;  //b
    + d( G) r7 c' w) l5 e
  26. new d\Life();
复制代码

; V1 {9 _: p* K0 p
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

4 l5 k3 Z/ c( ?& j4 \
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

2 m: n* Y2 N$ Q
相当于
  1. use animal\dog as dog;
复制代码

( K& ]; R1 V; W' X2.namespace后面不建议加类名,但use后可以。5 I9 H& B, p1 C9 L
  1. //name.php& y3 b! [" N/ O* n* l% U% u2 D1 r
  2. . ?3 Q: X: v2 g
  3. namespace animal\dog;
    , d6 ?' K  L* t
  4. , {, v' B" d/ k* `6 W
  5. class Life{: x* X: ]6 Z2 c
  6.     function __construct(){) X8 W& a& B2 t0 B7 L
  7.             echo 'dog life!';  }8 E- g$ s% p6 u+ ?
  8.         }$ U9 x# C; @$ ]1 x. d, E  J
  9. }3 j. [0 K; D! k+ I2 [4 u

  10. : E0 l' d% H4 V- I4 S$ O4 j
  11. namespace animal\cat;. r, J+ M5 [( U4 N) i8 U% b

  12. : C4 F) C4 W% i/ K
  13. class Life{$ L8 Z; j: U4 \: K
  14.     function __construct(){
    4 J6 o- |( v9 I
  15.             echo 'cat life!';6 K' q  X4 [3 l/ e, i1 B
  16.         }2 J% y7 ^; e/ K* @* R8 d
  17. }, C. c' D" p" j9 e; ]

  18. 9 x" q& s( {* {! R2 R
  19. use animal\dog\Life as dog;  
    $ |# B* ^) s. _
  20. new dog();
复制代码

; J( W( U$ P/ P) G1 @6 N, H
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
+ B; f/ B- T* T: D' \2 \
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php2 i8 G: l) l3 p% K2 N8 Z/ x

  2. : y5 I. i. W1 J; m2 a) R
  3. namespace animal\dog;
    , d* K5 B9 v8 v9 \, g8 }
  4. + l: x; k& n: e0 V  B
  5. class Life{
    3 q  G" m  p9 y9 V
  6.     function __construct(){
    ! ?# g1 ]1 M: l/ ~# e2 `; B& n
  7.             echo 'dog life!';
    9 q# _0 S2 d$ y0 C
  8.         }# X& B8 Q: ~+ t: Q3 U4 {6 b. K6 Q
  9. }
    . r/ J6 _5 j2 x9 p
  10. class Dog{
    9 G% v7 b+ x+ c1 {) k# [5 q
  11.     function __construct(){
    8 y! v: J7 M! X6 O: W
  12.             echo 'dog in dog!';
    % l# u. [3 ?8 X
  13.         }. Z8 C" m* I& w3 g
  14. }
    7 z4 w# R0 K% O

  15. : ^4 Y  }/ s2 n+ U# S- D
  16. namespace animal\cat;
      C( N. j: o. p& B4 ]7 a% e

  17. $ V, p1 ^! W$ l: O" m
  18. // class Dog{
    ! j9 f# @& B/ l( g* T( b
  19. //     function __construct(){1 z2 u# {) z9 q6 a" t
  20. //             echo 'dog in cat!';# u& q8 x$ m/ r; ?; N
  21. //         }: {% s. {  G- B
  22. // }
    ; {$ V# H8 ]1 L" f+ y2 A, c7 x
  23. class Life{( ~1 \; }) e7 \% j- V, i6 r2 f9 h: }
  24.     function __construct(){4 A, |5 j: t# W+ O( V  Z
  25.             echo 'cat life!';
    # b) K! c" o8 j
  26.         }
    5 L- b& J: e7 w) a1 J9 P; I
  27. }
    ; j0 _" E4 k  r' Y  F
  28. 0 x7 I$ p' b, Z$ n4 c$ r7 m$ [& O
  29. use animal\dog;  
    . I8 I0 k  n8 [! s; J
  30. new dog\Dog();
复制代码

+ U. ~6 a; R' L0 G
如上,使用了
  1. use animal\dog;
复制代码
4 K3 `2 ^" N3 U- ^& A% N
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

& O1 d* N0 f; h2 F. \: d
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

3 c5 x; {5 f1 f" X4 d! D6 v
7 u" i4 ]6 I# e9 V0 m( e" B# l! Y( o( P
8 M+ m1 M8 L4 O0 F3 n

$ {0 i$ @( B9 t$ D1 r. D
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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