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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
! B8 i0 ~! ?- t4 \/ }4 f$ h
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

7 B! g8 a) @2 a' f! r7 e* l9 g' k* f
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

/ X8 k1 ^, S) s4 j; b: s结合使用方法来进一步理解它的使用目的吧。

- r' T) }6 _7 Q4 p4 V, p
  l7 d8 U& v$ ]; }  unamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;; E- `& D: H; d5 i
  2. namespace One;' ^* l% X! p4 h. u
  3. namespace ONE;
复制代码
! ~1 v$ v+ ~6 P' x
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

+ U$ |8 ]: X0 T2 l$ s* R# e2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    ; ~- Z; U# C0 ~* f
  2. class Person{
    6 i1 j4 b/ |# d- F" N) [
  3.     function __construct(){4 w6 T$ s: r# ~# D6 B
  4.             echo 'I am one!';
    ' s: Y1 y, M$ M: C# L; {: t, J0 D
  5.         }
    9 @/ I2 T, X2 ]; ?! o/ O! F( m2 D1 z
  6. }
复制代码
  1. //name.php! d' |. S. @9 e8 N9 y( s8 D
  2. require_once './1.php';
    * R0 ^$ `+ ]$ a& c2 Q  l! w

  3. 7 n" T, k1 h# Z  n2 i! z
  4. new Person();     //输出 I am one!;
    * a! x  ]7 N) {  p% J. r. c
  5. new \Person(); //输出 I am one!;
复制代码

4 o, e+ X4 q" {2 `1 q) G7 i3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php3 \0 I0 Y' X* V; x
  2. require_once './1.php';2 J- d- I9 A7 f
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
8 a8 n+ B$ ]. [% n- J1 C
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    $ ?6 C# u% n( c- F' _
  2. namespace one;
    - c4 |" a8 r2 _4 R* S
  3. class Person{
    0 M1 x: @& g4 q/ M
  4.     function __construct(){
    ( ?+ v7 u- T' F; A
  5.             echo 'I am one!';9 t' e, g8 g  A
  6.         }
    0 ]) m" D" [6 r1 x( P2 I
  7. }
复制代码
  1. //name.php
    2 }& }! ?  H9 S1 d- y
  2. require_once './1.php';# X. g) m8 d/ Q
  3. new \one\Person(); //输出 I am one!;$ ?, W1 B# `" q
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

/ v; r: M6 @  E  Q! r6 t
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

4 }$ V; Z3 }7 n$ w0 W5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
7 Q" H# K7 C6 V5 |) m3 _
  1. //1.php   4 k& [- |/ n2 _" ^% s
  2. namespace one;
    ' J+ Q9 ^& r( \8 b
  3. class Person{. C6 k1 z3 S2 R/ J7 R
  4.     function __construct(){
    - Z- `; o+ u9 m- }
  5.             echo 'I am one!';+ }4 w# J# u) f, R, b5 I4 O
  6.         }
    6 Z; Q5 h9 E$ M, u1 r- S
  7. }
复制代码
  1. //name.php7 `+ |8 J6 C9 C4 ^( d
  2. namespace test;1 A6 g* C2 `* B! L0 W; q
  3. require './1.php'; " u+ x3 x+ d# _& [
  4. new \one\Person(); //输出 I am one!;1 t  ~' E4 F# v  `# z% p
  5. new Person();      //这里结果会是什么呢,猜猜看
    ! K! Z0 T8 E4 \0 R
  6. 最后一行结果报错:2 X8 p9 a; x( I2 ^4 i+ T% b+ I
  7. Fatal error:  Class 'test\Person' not found
复制代码

( x0 ^0 s# @% p4 T) {/ o
% m# ^" l) D/ S% L5 s% x0 k& P- M
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

8 A  m* `, |, R( n
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

: u6 J' b, X4 s- z
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    4 l# q8 q* H  H9 b2 N( R; q# O
  2. namespace test;  \! r0 u6 y; N; n3 e- o$ b0 e) ?; {
  3. require './1.php';
      f: m0 B6 x/ R# c  o

  4. 1 ^7 q  t1 F$ [2 k/ E5 G; x
  5. class Person{$ p9 R: e& I9 x
  6.     function __construct(){& s! v( P2 X& E8 H. L
  7.             echo 'I am test!';' X& z% v& ?1 w  x% W% p7 p
  8.         }$ q1 C! B4 D" r" `
  9. }  @( S8 {, ~+ W- R# J: C+ ?

  10. , a  R" s, X0 G8 N3 c
  11. new \one\Person(); //输出 I am one!;
    % n/ Z9 W& j, W* O% N
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

9 _% A$ @; Z0 P3 m) D$ [
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    - k) n8 z7 j% ~& x
  2. namespace test;0 G: U' m$ D8 F
  3. namespace one;
    5 t8 k4 C  [# L$ S4 E! K9 y
  4. class Person{
    & l4 _! q7 S7 Q4 X+ F3 y/ }5 D7 L
  5.     function __construct(){
    9 d& l8 s+ R7 ~9 E1 E3 c) G
  6.             echo 'I am one!';3 z6 F+ @" @, D. o" B4 a7 `8 G$ I
  7.         }. u$ {: o. q, U7 B' p# _1 x0 P
  8. }$ p7 w( d1 W/ }9 I

  9. , P- \8 y2 q% V/ I3 Q; _
  10. class Person{
    2 ~" t1 c$ `; z, u  m0 A
  11.     function __construct(){3 \* L- }$ ~. t' M5 L6 d* \' D
  12.             echo 'I am test!';* `6 |5 g, x+ [4 c
  13.         }
    7 a: q) Z. q9 p+ d  P
  14. }
复制代码
' v2 ~* J8 M  {
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
) [3 O! q1 `0 g, D# A
看来简单的把require理解为替换,在这里行不通。
) g- c+ m7 j5 B" v1 R$ H
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" e% [6 i* u. p; u
  1. //name.php, F* {; }* c; Y
  2. : ?' |7 |8 W: c6 O5 J! l2 Y
  3. namespace test\person;
      e4 s9 v1 Q' @5 S

  4.   P, F6 a% O  m7 J
  5. class Person{& V" J$ u9 o  _- C
  6.     function __construct(){) T1 X3 f% F  o  J8 }1 S
  7.             echo 'I am test!';
    - Z' Q  z1 \0 J1 i0 O5 z2 j1 Z( A
  8.         }! B) y. c: _) g0 c- m8 l' `
  9. }
    # `- R! L" K$ B7 ?# N
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

( V8 n, e" |& E- A
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

7 W, C/ r  l$ F2 U$ p, V. s7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php4 k7 n% t; a4 j( u) a( b
  2. : p: N6 J1 U; u  r' x, @5 O
  3. namespace test;
      X7 Z- g1 q& L. H
  4. echo 'zhai14';
    & Z* @) V/ f3 _1 N* c! p
  5. namespace zhai;
    " y+ B+ |8 v2 u0 z
  6. require './1.php';
复制代码

- e9 z& {  t. C, g7 `1 u
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
/ l) P. j. M" W1 y( K0 ]' H! e
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。. B( Z, w; T' z5 |9 p' V$ o
  1. //name.php
    / L4 ~, Q8 t  N, [) z0 i! E7 j

  2. : o3 b; ^3 G' x  Y! I0 ?6 V
  3. namespace animal\dog;
    3 v; \  D/ \+ k% K4 Q! m  H8 y
  4. ' Q6 h+ C- a  V4 p! h6 m
  5. class Life{) [8 S$ {( @* w/ G1 I
  6.     function __construct(){4 ]- H0 P! ^/ n8 {
  7.             echo 'dog life!';6 R$ w6 D- k6 l4 {" e5 O) e4 F
  8.         }
    ( T  U0 f$ x6 i: U
  9. }+ t8 r$ s; B2 ]" y- G
  10. , O# V2 K( E5 _  z& M: S2 N% j9 r
  11. namespace animal\cat;1 ?: A/ J" r9 v! C( H
  12. % z/ v2 j6 R, i
  13. class Life{
    9 F" d( e1 j) f2 |4 z
  14.     function __construct(){) n1 |% ?" @2 f2 t) l+ T
  15.             echo 'cat life!';/ R6 K0 p7 _' n$ ?% s6 }
  16.         }
    7 f1 T. \1 c5 W
  17. }
    + I( G0 s; Q+ i: [: K

  18. 9 J4 B: D1 D. s* [+ M5 a0 r: z  l
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    ' V% c  E' G/ c
  20. new \animal\dog\Life();  //A
    1 X$ P9 D$ b& P3 B
  21. & v* f/ U8 ~$ ]) k
  22. use animal\dog;  //a/ U2 B" S) G3 k
  23. new dog\Life();  //B
    5 U1 Y. @' m' i

  24. . S% I' g* @5 J( R$ j4 n
  25. use animal\dog as d;  //b; X0 K2 r4 V1 p8 i3 \* r1 R- d
  26. new d\Life();
复制代码

) I* a; O/ j7 g/ O5 {1 {
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

+ B3 z' H! m6 }1 ^5 [2 w0 `
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
. g/ V9 x+ t1 O% d, k5 ?& X" U
相当于
  1. use animal\dog as dog;
复制代码
6 L: ]' ?9 K  d* s; l5 w
2.namespace后面不建议加类名,但use后可以。
! ~* C- d& T4 U. z2 p1 r
  1. //name.php
    4 k3 S( ]' q% j4 C" f) `

  2. ; Z, u8 J7 @2 c2 y5 F
  3. namespace animal\dog;
    $ U" _/ S! e( W% D; w& `

  4. , A: w) s3 c/ l8 i& ?3 o
  5. class Life{4 l+ A7 ^& r- z
  6.     function __construct(){
    9 X% s4 k$ R2 ~: l' s) i0 O
  7.             echo 'dog life!';
    " o8 l5 ^7 V3 d5 @$ |, e, M; u- v
  8.         }3 i, @! ~7 p; {
  9. }
    " M; y; u4 M) \8 }, c5 T$ y9 K, W- q( Y

  10. 4 Y8 Q' {0 D3 M* Y# O4 t! l
  11. namespace animal\cat;$ ]7 ^6 H7 N+ Z8 X5 U; L2 d
  12. 2 j8 O: |, X7 F. p9 m
  13. class Life{
    ! D) H+ J; ?# h  K) B
  14.     function __construct(){
    ! k( w  u! N; K7 G
  15.             echo 'cat life!';; b. h: R% s! N! J1 |) f
  16.         }: f5 G9 \6 a4 _! |# h5 ]9 ?& z
  17. }
    ; l8 Q# y0 x5 ]# m

  18. " d# o2 q6 U- Z) j# `8 d2 u
  19. use animal\dog\Life as dog;  
    - \3 `0 m) h& b
  20. new dog();
复制代码

9 |5 ]: ?! I) e& n6 v
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
" @' Q) i/ C5 f/ j; I& l, O. t
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    $ T' h/ A4 J  V0 k3 m) V* o2 f0 O) r
  2. $ V# U2 J$ }% k) k. C( j1 L; A# H
  3. namespace animal\dog;
    5 h1 b$ e/ |8 d, f6 H1 O' F( j! W% d

  4. . ]8 ^1 X# n0 w3 c! V$ u& h# h
  5. class Life{
    7 k$ a6 T2 J* g
  6.     function __construct(){8 R; M( B! h( K
  7.             echo 'dog life!';
    9 T& x$ S# h) Y
  8.         }1 F; L! o3 ?  u5 D
  9. }
    3 L2 v6 M  N& h7 C3 }
  10. class Dog{
    . \, y) [' t2 w4 _+ ~$ k& d, p
  11.     function __construct(){& K! A; v/ N8 Q% @) X
  12.             echo 'dog in dog!';1 I9 B6 K  f$ X6 R" e
  13.         }6 }# Q" p" ^$ |% q
  14. }. u: l8 d# e5 \$ X3 w' F
  15. 7 _; F2 d+ n! P+ G% i* u
  16. namespace animal\cat;
    . w& t5 V5 p3 q, Z2 D

  17. $ u" G& z% C3 `# D6 C6 I+ @$ w
  18. // class Dog{9 l  k1 l$ L( W
  19. //     function __construct(){
    6 ^2 ?/ w3 d  k5 T
  20. //             echo 'dog in cat!';4 U( ]8 S1 R6 }. |  z# z' s$ e
  21. //         }
    . d  F" L  {( Y! B2 Z
  22. // }
    0 i' T, M, b! n
  23. class Life{
    4 O3 f: \# p+ l- P
  24.     function __construct(){; v5 v# K  ]6 ?7 f3 s  C
  25.             echo 'cat life!';  n: w: j5 @; y  q+ e# d: c/ Q
  26.         }
    ( `5 V; |: M6 n1 n, b3 K
  27. }
    ' y9 e, S. Y0 t: r: }: I

  28. 5 o; [  a( C: I0 |! q0 a
  29. use animal\dog;  ' v" t) y* C9 n# ]& o; C# c: E$ ~* U
  30. new dog\Dog();
复制代码
- z, G$ _5 G6 j1 R& b* ^
如上,使用了
  1. use animal\dog;
复制代码

$ y) `! q. ]0 Q* D* K! T
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

6 h. Y* s% o6 x' E
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

8 D# b$ X8 t( X6 {* k) U" J# c& T# @# G# r5 C7 h& z

) r2 p- e; T" v
, G1 h  g. [% i8 @4 l
% P7 X- l' P" h' \7 B5 U1 t8 M
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 16:56 , Processed in 0.122353 second(s), 19 queries .

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