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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

; r6 ?2 N6 ^: U% P- Z4 M  d+ l4 b; ^
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
+ T( ]/ m+ @, m0 o" s4 q
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

, d5 O, l7 {1 J* [( t8 v结合使用方法来进一步理解它的使用目的吧。

6 l4 S4 E, `; a( ]' l$ O  c
/ k8 Z6 h& r4 @5 ynamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;1 q  X4 j' h* v: z
  2. namespace One;
      g) n' W% s" b* u
  3. namespace ONE;
复制代码
' C" i4 c7 |* l2 C4 X
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

; h) |+ y, }7 T1 x( {0 t4 Q% x2 C2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   % K9 E3 a- Q& M9 p' C5 L! r2 r
  2. class Person{. i& J! i& u1 g5 @
  3.     function __construct(){
    9 Y9 q. f4 v; y& J/ X
  4.             echo 'I am one!';
    ! S( ]) z$ A* `. O: v7 c' W4 `
  5.         }
    : ?2 ]) f5 E+ v; H" c
  6. }
复制代码
  1. //name.php
    % r2 p- A2 M6 U0 ?2 @7 S. |" h' R
  2. require_once './1.php';
    1 a* \- B; M7 n( I% ]! s% q
  3. 0 s4 M  N, Y% p$ A# j% \7 B+ o% N
  4. new Person();     //输出 I am one!;
    , x. T9 y/ a+ s) X/ F3 g( S
  5. new \Person(); //输出 I am one!;
复制代码

' Z( P- ^/ C% q7 ?0 S: R' }2 |3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php0 K. e, J( B/ o* ~/ B
  2. require_once './1.php';  Z# m. p8 t7 @8 b6 P% o' S5 o0 {7 h
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
% _. q, S4 e; _% ^% r' |- W
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    7 `. X1 I6 b7 o
  2. namespace one;
    ' H) {' G  D7 i) [" m3 a
  3. class Person{
    # k' t2 {$ A- j- G  D
  4.     function __construct(){
    & s  T4 F( x6 s; |: y3 s% x
  5.             echo 'I am one!';
    : v2 h. H# W) [. J3 F5 l
  6.         }) Y# Z  g) c" C; ~+ i
  7. }
复制代码
  1. //name.php4 ~/ w8 u7 m7 W4 }
  2. require_once './1.php';
    ) a- W) r- v! e" l6 r+ h
  3. new \one\Person(); //输出 I am one!;% K1 }1 `" [; e! F5 ]. t  k( ]
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
0 |* \; |& t$ j& n! N
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
/ x% A( ]2 H, G7 N( m! }! c
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。% x! k. b6 U* w2 j; G2 e4 q& j
  1. //1.php   
    $ g0 [$ V4 C1 G3 P
  2. namespace one;5 A- ^0 W8 O* Z5 ]- m" J
  3. class Person{/ j' v2 I' z& @8 T1 z# n
  4.     function __construct(){3 h  q; U1 I8 ^+ E- _- q
  5.             echo 'I am one!';: C# m6 M7 C6 n8 u# `; {
  6.         }; x4 B! d1 |. J
  7. }
复制代码
  1. //name.php
    2 E$ m8 b/ o4 \4 Y
  2. namespace test;
    ' k' T0 H' @3 j$ Q5 T
  3. require './1.php'; 9 n5 U/ s, p3 @9 J" c' ]0 o. R
  4. new \one\Person(); //输出 I am one!;7 Z. }0 C6 E) Z) V, m
  5. new Person();      //这里结果会是什么呢,猜猜看) }+ I, B4 j; D; `) E( J
  6. 最后一行结果报错:
    & p# H+ ?+ y& u6 _
  7. Fatal error:  Class 'test\Person' not found
复制代码
9 {5 f' S8 j" [) ^) H4 d) `

- H9 ~4 o4 z8 E& d首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
0 L  l8 K0 Z: E9 k
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

( p* [- w/ e; _0 x, m
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    , N  s/ O6 J0 H: f' x
  2. namespace test;4 T* h6 f& K2 ^; b
  3. require './1.php';
    " \+ [  x  o9 n; I

  4. ; H+ c5 B' c" S1 j
  5. class Person{
    7 o* o# _; C9 r& C8 d) A
  6.     function __construct(){2 {! x0 l" j) v  O
  7.             echo 'I am test!';
    3 |  i& X" K) r3 z( R6 O( d
  8.         }# z" l. [3 A7 ?" |+ v* a! X
  9. }7 ~& w% K* Z1 ~) g' d# k5 N
  10. % J0 F! c$ E2 p9 I( D8 m
  11. new \one\Person(); //输出 I am one!;  n& N/ b( X* F( I/ e- |9 c
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
" o* y7 o% N# H2 {
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php$ b1 k6 r( H9 w8 K
  2. namespace test;2 ?4 c# y9 Z, M: \3 D' c, g$ P
  3. namespace one;8 ~- }1 I2 a& m3 @9 Q
  4. class Person{
    0 g) D  M) y0 {1 H' f
  5.     function __construct(){
    6 V  I3 i) y  Q7 d% `7 k# e
  6.             echo 'I am one!';
    & q/ |, T' X* F2 S. A- l% b
  7.         }
    7 x$ r  E8 E" K$ F& l2 q
  8. }- G3 b3 e, ^; I; ?% D& `- S

  9. 9 \& a2 |/ R! r9 m/ E2 V
  10. class Person{! V4 O& }- q9 q, l/ P+ ~% X
  11.     function __construct(){/ i9 ?- P! _; t8 o" x: D
  12.             echo 'I am test!';7 R/ f& l, C& w2 |! ?( N) f
  13.         }8 c* a; _! O* s) _2 r
  14. }
复制代码
9 X6 N) E' T# z: Q+ Q0 y3 L- o
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

; c9 ]& H$ Y' P* a. j9 D4 R
看来简单的把require理解为替换,在这里行不通。

0 W: v7 v  ?/ y0 S4 ?6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
0 J: B3 G7 H0 p' k: {0 ], Y5 k2 J9 p
  1. //name.php
    3 H' O0 {: a. \* B$ `* U6 ~

  2. 7 H* w9 E- w" x0 C% ~( x& k# P+ C
  3. namespace test\person;
    2 V; P& V$ s5 _7 v

  4. 6 F+ @% W2 ^0 p' \0 m' }& g
  5. class Person{# g- J  e* M: ?- K/ Q. d" |/ Z7 T( D
  6.     function __construct(){
    , a7 I% h4 ^  g7 N5 m' O
  7.             echo 'I am test!';
    - e4 T  P: P% j4 T% S  v, l  p
  8.         }1 P1 U6 ^5 u3 Z, _8 n7 o1 }
  9. }9 ^% Z$ ?. g2 ]2 u9 P$ A4 Q
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

3 V. }* t7 D- s3 N
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
  I- f$ q: F8 m2 N$ o' C
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php+ X1 i& F$ Q/ N8 ~9 T
  2. " X, M/ L- _) I: D& [6 X0 H: p
  3. namespace test;& O, ?9 E2 s' ^3 e* D$ i
  4. echo 'zhai14';% [1 t$ W. K, y9 t9 ~9 j
  5. namespace zhai;
    ) e& V8 |/ u. B3 C. P9 }6 x
  6. require './1.php';
复制代码

6 M2 D) O& \, `8 _0 z: J4 i
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
2 z) |2 r) b& n6 i! _
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。4 i& q) d2 _2 T9 Y7 s) u( q' x
  1. //name.php- n' x: r. b" H* w8 Y/ M: B

  2. : X" g" u+ a; o6 s0 E
  3. namespace animal\dog;
    6 R  b3 C* U! Y5 {  P; _: N# O$ l
  4. , ~- j9 h+ e* _: s, j
  5. class Life{7 y/ o. I  v( a' q
  6.     function __construct(){
    0 n. @$ A% Q  d: }. x5 {+ `
  7.             echo 'dog life!';- U1 V+ T, l" M+ D" ^: `
  8.         }
    0 _- I: T6 I% O) Z8 @2 y
  9. }( e* S- K: f8 w8 U) B& h3 V
  10. ; I6 n: R* _$ W* ?2 J8 q  k
  11. namespace animal\cat;
    3 R( u2 d4 v: R9 A0 ^) A2 W
  12. 3 U! H. i, N( w* O6 H8 K, i
  13. class Life{
    * O1 h+ ?+ p+ w5 ]
  14.     function __construct(){( Y& \. U9 w! {, G4 Y; u
  15.             echo 'cat life!';
    ( i8 m5 N. U/ W: ^# d6 l3 A- B
  16.         }* W, P& L% U) S& k
  17. }
    - P6 a  d5 @' c* F: s" z! }

  18. 9 {0 q* j7 L2 [: X
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    + z! L/ @: e) r2 A; c8 l" u9 }- T
  20. new \animal\dog\Life();  //A0 F, j4 g0 F! }! O! ], z
  21. 9 z" q$ Z6 V! b
  22. use animal\dog;  //a
    2 D0 ~: P2 K: Q/ ?' ~, `* \, F& P% s
  23. new dog\Life();  //B
      }( d& {# s0 {4 Z6 |  r* x$ l
  24. 7 E! M, H! L3 C2 O! @+ O& \
  25. use animal\dog as d;  //b
    , s4 L0 a# X( \- x) w6 O
  26. new d\Life();
复制代码

3 z% f4 n$ z2 J
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

5 M, [7 V; l% ]3 }# _- T
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

2 k" ?- [) Y+ x
相当于
  1. use animal\dog as dog;
复制代码

; @: L0 W- Y. {3 h+ U( I; Q3 E9 m2.namespace后面不建议加类名,但use后可以。
8 g$ Y4 S. e& s& o! Q; |8 r2 b$ I
  1. //name.php
    $ E% _4 C: k  P( J. w# Q

  2. ; v2 W2 ~" E4 {4 u) t
  3. namespace animal\dog;8 m3 D7 A. I: H4 V& n

  4. 7 s# e9 w0 b) {" y8 \! n
  5. class Life{
    9 O9 O$ ^0 o( G3 x' [. D  a
  6.     function __construct(){
    : I( X& i4 `+ F  G- H% t
  7.             echo 'dog life!';4 ~; K' b- M& K$ Q; G* K) o. S
  8.         }/ ]  \  L: y4 p& k, F. q8 t$ @
  9. }0 X4 D( G7 B% Q$ p. S
  10. 0 c: z& g; E$ p
  11. namespace animal\cat;
    . W, b6 R5 a: }1 C* G

  12. * [# p9 e) Y$ u$ G$ i/ X5 S
  13. class Life{+ Y: d$ [7 _+ _$ C
  14.     function __construct(){
    " O2 `  [/ q. B1 ]
  15.             echo 'cat life!';
    : K4 e) y  y/ e, [+ k5 b
  16.         }6 m2 |: ~2 o1 B1 T+ X
  17. }! y! m$ W8 A; m+ F6 s9 V

  18. ) S# V. p3 O% c0 b
  19. use animal\dog\Life as dog;  
    : [" l5 t2 K! }8 I. c( J7 ~* b
  20. new dog();
复制代码
* n9 Y$ d6 j2 \' J$ G8 I' k
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
: R" ?# U6 o& W2 i1 \
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    % \. A7 ?( H& {: r- L- Y& q

  2. 1 O: T) n! ^- A1 T4 E
  3. namespace animal\dog;& f7 F6 u7 U  m, V8 c

  4. ; i' k, a1 Y, |7 e+ F
  5. class Life{) B7 W; T% H5 b( v
  6.     function __construct(){
    3 }2 ^, j# R+ p# U8 m/ X
  7.             echo 'dog life!';. r, K0 J+ ]7 S: N: U& p/ u
  8.         }
    + Q" q+ Z  x8 b, y
  9. }
    % K5 z& ~; v) x; g. S9 X" o$ {
  10. class Dog{
    1 |' `( D6 O) G+ |, g4 H. y
  11.     function __construct(){; ^7 q: \5 ~5 P% C
  12.             echo 'dog in dog!';; h- g4 U' j" p
  13.         }  ?8 o$ h8 f  x& L
  14. }
    8 B* L. E8 ?* |& g+ ^, D1 y

  15. 3 d0 K8 K4 A: _# g/ S% `' Z
  16. namespace animal\cat;
    : H8 G, O' A: t' U1 w

  17. 4 H( l. e& }  }6 P
  18. // class Dog{8 u* Y! T. ~9 C- W5 e
  19. //     function __construct(){* h. n' j4 w$ L& {8 M# G  ^
  20. //             echo 'dog in cat!';- a% u# q5 h! \
  21. //         }- [. m2 ~( }. @7 }$ O. q. ]
  22. // }" s& l% \. w$ w/ G
  23. class Life{' N0 a: l. f" w' ]
  24.     function __construct(){
    6 Z$ Z1 _4 t4 M) ^
  25.             echo 'cat life!';
    ) Y- w1 @6 d9 v0 Y
  26.         }4 k3 y: P/ R4 i
  27. }
    ( I: q0 m- o+ E" U. f0 ~
  28. " @; z8 r$ D- f8 I
  29. use animal\dog;  % u$ @% g. Z; i1 G" b7 R& `
  30. new dog\Dog();
复制代码

" d& G, h+ [' r/ P4 U4 v2 P4 l
如上,使用了
  1. use animal\dog;
复制代码
9 N5 X6 n5 Y: t; B: r0 ^! Y
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

  y( I8 [3 h# S; S
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

0 W7 H  Q; \4 m0 P4 U" _: a' b* S( F5 w5 E; c8 Y' V; o

! g" f- ]6 e* p! x5 M( B& q
5 t8 M' Y$ j7 I! }+ ^  l$ J/ v! Q& T  ]. x/ }5 t- ?9 x5 S# g4 ]
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-20 08:57 , Processed in 0.150103 second(s), 20 queries .

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