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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

+ S$ u8 _# ^. F- E* L$ A: `! W9 C
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
: F5 V  l! ~9 F

! d( e0 x! ]4 t# Q4 t' O使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
' L$ Q2 Q( Z, V& F) w! n. z- h
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
3 }0 M) w- ^' [5 g" ~# B! _* Y6 K
结合使用方法来进一步理解它的使用目的吧。
( q" r4 H& T+ \: S( @& R5 D

! l( I. s1 D5 Bnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;& Q. O& Y$ Z) K9 ]6 L
  2. namespace One;
    5 X3 @& k+ l3 |; q: \
  3. namespace ONE;
复制代码
/ h4 L% \3 v8 W- `/ U% K1 v; ?- e; O) M
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
+ s8 L6 I/ T0 E+ U: }
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   - E" t4 N8 _5 {2 M1 N/ _0 \
  2. class Person{' K  f7 P9 g0 l% }6 P! U0 m# [% c
  3.     function __construct(){
    0 l3 D9 T6 U: g1 c
  4.             echo 'I am one!';! `* j% x3 ]: D% x9 n0 O) i; b
  5.         }; E/ Q: ~- p% r
  6. }
复制代码
  1. //name.php# H. k5 g: D" b2 \) C
  2. require_once './1.php';4 ?5 R: F- S! N6 I. c/ P) F3 ~0 K8 {; s

  3. ! v; u9 D7 k5 F
  4. new Person();     //输出 I am one!;4 ~2 s. Q# s6 R- `# ]4 R
  5. new \Person(); //输出 I am one!;
复制代码

( o$ h$ z- O; W! ~3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php8 Y; C0 v8 g( l& T% F" b: j  a
  2. require_once './1.php';. ^: p7 d1 d% B# \
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
4 f4 q) o, E" K# w6 W9 `
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   - R+ x( \. b' t: N
  2. namespace one;
    % v! {7 g4 T" ?! B2 M5 N  J
  3. class Person{
    8 L3 B) w" p: H& v2 o' U
  4.     function __construct(){! E4 j8 ]% l' c! T$ g1 K+ k; J6 m( p
  5.             echo 'I am one!';
    / u( f$ F) i. v* G6 @
  6.         }
    ; V2 g2 W. }' ]& c  V
  7. }
复制代码
  1. //name.php5 O2 N$ j; w) X) |) V9 q
  2. require_once './1.php';
    # w1 x4 P' O1 b) H' T
  3. new \one\Person(); //输出 I am one!;1 f3 x, X/ ?6 ~- O0 j( U3 }
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

+ h" C7 [! y$ B  I  c8 R9 _
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

2 [' C7 n! R: ^9 n) T; j# H2 c5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
* Q9 n7 B: N6 R
  1. //1.php   
    - I9 ]; a2 L4 s: k
  2. namespace one;, j+ X8 g2 f# V. ?0 ?( P( q
  3. class Person{
    ! ?, m' Y" \7 P* q+ ?. h, X" @8 n
  4.     function __construct(){0 m7 {3 d% y/ L1 p0 N& \
  5.             echo 'I am one!';
    - K. v7 l4 m7 j! N
  6.         }
    5 ]! q$ y* Y) l8 f% \: o6 H( D
  7. }
复制代码
  1. //name.php( |+ s' c6 K1 \: O- U
  2. namespace test;7 [" y' G* V2 j% q$ Y, Q" y
  3. require './1.php';
    , t# P% _: `5 t  Q# U
  4. new \one\Person(); //输出 I am one!;
    6 Z. s5 h2 g, F* }6 A2 {
  5. new Person();      //这里结果会是什么呢,猜猜看
    5 E3 t3 q; y/ K5 C# ^' J  O
  6. 最后一行结果报错:
    6 g3 a1 K" K0 X# U, V
  7. Fatal error:  Class 'test\Person' not found
复制代码

( H" ^4 d2 N7 I* r! c; k$ _

6 e  V; P% ~7 U首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

$ E7 _) p; |( v" W0 d
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
( X. [! ]/ v& S7 d8 s7 w
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php- U. [# n/ C  Y3 C1 A" i
  2. namespace test;) A7 A  _7 b, W- n9 k3 I
  3. require './1.php';
    4 A- @) ?) Z+ t* l+ o5 z0 l
  4. # ]2 y2 V, U" R& _
  5. class Person{: r/ @( `4 z. f4 q7 w* Y; \
  6.     function __construct(){& g" K, |6 }- o
  7.             echo 'I am test!';  U1 y, f7 M( Z, \
  8.         }+ \$ U3 @3 H+ S
  9. }
    / ^: _# O( ?' |1 _5 Z
  10. - {: j, I/ J( Q+ F( v
  11. new \one\Person(); //输出 I am one!;
    ) U& Z0 w2 _, s; H# M
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

2 @1 A3 d. J) A9 ]9 k) }7 z' y
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php( W0 k8 P9 F6 U- c1 @
  2. namespace test;
    ; U2 u$ @  x3 L( t  d5 H
  3. namespace one;
    % y9 k1 p  E  j) }
  4. class Person{
    ' n" n, N9 [, r  A7 B
  5.     function __construct(){
    , F4 U. j* B6 K) t2 T/ ]+ Z
  6.             echo 'I am one!';
    ( Y- S/ {: ]0 v8 X8 e
  7.         }
    2 I4 F' O( {- f: L! o+ H
  8. }& I# [$ C. z- s% g% U% U+ x  s

  9. $ y7 Y' D$ C5 H2 O7 P; m/ D! M& T
  10. class Person{; ?, {2 {  `; r% [  l' I
  11.     function __construct(){
    9 w$ U8 ]! N% e9 R! `) g5 D0 @( L
  12.             echo 'I am test!';; w5 c/ Y- `! S& j) i
  13.         }
    8 |* d9 m. P( [2 P# \
  14. }
复制代码
2 O( u) H# e) o0 ]3 K6 K0 w
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

5 j; ^$ g, l  B2 c3 d1 E) E
看来简单的把require理解为替换,在这里行不通。
- F, l5 ~; B9 H4 r2 j# v" x
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。+ Z: C. z$ V1 Z  S3 D% q! s- ?/ u
  1. //name.php
    6 H* _3 a% o$ q6 Y; T6 i  v

  2. 5 c5 ^! p+ B4 j% N4 {
  3. namespace test\person;
    % x0 o7 O3 b0 s' {

  4. ' s* G( I. F* s  D4 K: g4 y% n
  5. class Person{
    ( i0 g3 k; K, y! b
  6.     function __construct(){' o+ a+ i2 t6 E
  7.             echo 'I am test!';; P/ v7 S% i7 q7 s9 }) l3 P. [
  8.         }# i2 y$ X. `+ Z' y- V
  9. }9 ]! p: t, F+ t
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
9 g/ N5 X, e* Z  z3 M& ?& ^
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

$ q3 N8 v+ H, d2 H7 ?! t/ m$ ?; \4 ^7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    0 X/ a! N. J% W# Y# }

  2. 7 }& x# x1 ^: R# O5 r
  3. namespace test;5 A6 h$ @9 A5 o5 i( R
  4. echo 'zhai14';  _) M  M1 g5 ]& N( v
  5. namespace zhai;
    / U% i9 a: u+ S5 P' d
  6. require './1.php';
复制代码
1 B, ^. E3 U0 ~9 O3 ~  [
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

6 T/ R6 h- D! C5 kuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。: j7 ?- T0 x% K
  1. //name.php
    : z% f- M9 P5 A3 n* z. Z% D

  2. - [2 r  z9 S& n. a1 |" x; b
  3. namespace animal\dog;
      T, z' p9 I3 E3 [
  4. $ ]4 F4 v2 y# C# J* E' ^* B, ^
  5. class Life{$ {* N  |6 K( R8 V
  6.     function __construct(){' b3 I, k* s3 h9 \
  7.             echo 'dog life!';0 x* b; _9 ~4 J8 x, d$ _
  8.         }8 q3 ?( R& ^1 l3 K0 E* A
  9. }& G1 w8 K+ Y$ ?+ \2 Y! {
  10. 0 t& F$ {1 ^5 H$ k3 J- Q. H
  11. namespace animal\cat;
    + L" k' s1 W1 c4 e

  12. / E* Y* L1 g7 D3 ]
  13. class Life{
    # ]% K( h  [) V8 N; s2 \; W
  14.     function __construct(){8 `1 I  V+ v+ v/ p1 o+ i+ Y! w( D
  15.             echo 'cat life!';
    + \5 ]. M* @$ ]9 r8 W; q
  16.         }) i5 k& {, y6 e$ x: z+ G/ I8 \
  17. }
    & o) V& R8 w$ d- |5 M1 y
  18. + A; |9 t( j+ f9 D' z$ f( A5 g
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间" G: b4 Q) x% G
  20. new \animal\dog\Life();  //A
    1 [$ Y3 c0 n! O" ~6 b+ g. I
  21. 0 Y4 F) F; [6 R# x6 e) D
  22. use animal\dog;  //a1 Z1 v) J/ G) n6 u9 z
  23. new dog\Life();  //B& z  a/ S8 \( m" [; b) ?8 L/ _0 P2 G' E

  24. - R; Y( `7 R+ L
  25. use animal\dog as d;  //b! q# l# _: ?! Z0 w, E
  26. new d\Life();
复制代码

1 V" {3 j. ?. i  Q2 I/ z6 e% q, i
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
( [1 t: k: T3 J2 B5 b+ {
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

& y+ s( u+ |- Z3 V5 u! t7 Z0 |, |( V
相当于
  1. use animal\dog as dog;
复制代码

: @: R$ @. K2 T. d  ?% O+ M2.namespace后面不建议加类名,但use后可以。
: a2 r  F( ~( c. [
  1. //name.php; M. m' a" v1 E- d1 u  S

  2. 3 P4 e% _- U5 n9 M3 s
  3. namespace animal\dog;
    # q$ u1 f; p% F* E3 s/ Z

  4. , P: c  g3 u% X+ E+ p
  5. class Life{
    ; }' d" t# C  L* T7 J3 `4 z, v
  6.     function __construct(){6 E& I) S( J* u1 M' U5 h; S" I
  7.             echo 'dog life!';
    - O8 q$ o# z- u* k
  8.         }. P* D# N7 M. d8 q7 _. E
  9. }
    0 }1 R8 W; r/ g8 C
  10. 1 Q6 S7 R& g0 d* n9 y
  11. namespace animal\cat;
    5 R' D2 ^4 w2 t+ o

  12. 5 _+ q- J/ e9 F3 u% ~; X
  13. class Life{; }. F/ S( I! A: d5 @8 n8 ~/ L; y
  14.     function __construct(){
    ' O% C5 g& ?+ N( j* |, C0 |
  15.             echo 'cat life!';4 t$ v6 T; o+ N" H0 i& m
  16.         }% I1 g9 J; H, `* L( P
  17. }
    ; o2 D! T+ I6 @/ g: O9 b7 G

  18. 5 N1 o$ H6 A+ e2 T
  19. use animal\dog\Life as dog;  % c: f+ d. t1 G8 X& L! W0 w8 e
  20. new dog();
复制代码
/ {1 }1 W3 w" r& D/ c
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

! J1 P* E+ K- N+ {* \
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    ; @9 \3 F+ J7 {3 }

  2. ; r* `3 Y% k2 F' v  }/ P
  3. namespace animal\dog;
    " n8 w2 ~- @! I- c0 g3 h0 M# |

  4. 7 n0 o" |: [. v3 [7 ]
  5. class Life{: b" E+ r! j3 Q7 C% t( _" W
  6.     function __construct(){: s, P% B9 f) v4 ?, l# m  e
  7.             echo 'dog life!';' w3 N2 f( I# ~/ R  R% G
  8.         }" c% V, E9 ]0 s6 D3 ^
  9. }
    + N" S0 v4 e/ [& m: @
  10. class Dog{
    1 u' f% W+ u; r- [. g" `; w
  11.     function __construct(){1 w9 s9 E( k3 D9 G& h) U
  12.             echo 'dog in dog!';, r# P9 y/ r: h( Y6 o
  13.         }
    . p9 P- O1 B$ N+ s$ Y2 l
  14. }
    . ^0 P/ x) p% h, L

  15. 8 J" g) v" u+ i7 W$ S6 _
  16. namespace animal\cat;
    & d/ h8 Z5 X( s( Z8 |, x0 t

  17. ) V% ]: a8 B5 C  m* R2 q
  18. // class Dog{
    7 ?" f, O$ J# q  w% N6 d+ s
  19. //     function __construct(){
    $ l' X  l) G( r0 C% o  L2 G, W3 O
  20. //             echo 'dog in cat!';9 T! s3 e" x1 C$ B, D" U
  21. //         }
    # @6 d* f* W1 p8 e7 b
  22. // }1 ?* ~1 {) T: x/ X6 G8 h
  23. class Life{* g8 Q' O5 H6 u" J# w
  24.     function __construct(){+ P/ M' W8 R. Y9 H
  25.             echo 'cat life!';2 l" y% F1 Z3 c+ t. q
  26.         }# H" K0 C9 G) P; r  {1 Z$ }
  27. }
    # V( k7 v$ b6 q9 Q3 }8 u" j* E' j- d

  28.   g$ B% d9 t( k5 u$ i( U  e+ i
  29. use animal\dog;  
    ; g5 ^% ~( O5 s2 w- Y1 T
  30. new dog\Dog();
复制代码

6 ?  n! x: g; k# T4 Q0 A8 i
如上,使用了
  1. use animal\dog;
复制代码
3 E  }* ]" F7 z
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
  j) X0 S& [# `+ I: F$ p
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
. ^' X5 K- E' a4 }5 Y

( t" J4 J  D" n3 n# G& R7 z! t- V8 U  g# c
9 L  M5 I, ^& S$ T* w, v
( m: M8 f) n, f4 n. m0 p
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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