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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
7 A3 H% n9 y6 r" ]4 O8 L, P
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
  r; f2 j2 t& H/ R; }( t

- f5 e! _9 K: Q. g, ]9 x, ]' U使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
) i: b1 A. P8 N8 Q0 q! t: g3 I
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

4 h& R7 s$ _3 K% r结合使用方法来进一步理解它的使用目的吧。
) ]4 s4 Z! `& ]9 X

" [$ _& W  ^2 R- n, d: H- C* Knamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    ( d" r) v: I! q% i4 o& t
  2. namespace One;
    ) o3 F+ e8 b( t4 ~0 _0 X! \
  3. namespace ONE;
复制代码

+ A# d' ]: X/ `4 n4 p, V/ t
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

( h$ k1 e% J4 T  Z+ @- Y+ S2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ) k( F; p! K9 v  l- p; ^
  2. class Person{
    7 b% P: V! u& F, S8 l- a
  3.     function __construct(){
    , m" r* T. O' K1 n$ i# g
  4.             echo 'I am one!';
    / m+ ?# m$ k4 N5 A, p5 u* V
  5.         }
    & r+ ^9 b, ?: I; g* |" C) X0 r
  6. }
复制代码
  1. //name.php- A# R( g( K+ k
  2. require_once './1.php';/ G9 O4 M& @0 T+ _
  3. 1 ^, l8 {8 {2 z; [
  4. new Person();     //输出 I am one!;$ I# p% A9 |! m# |  {
  5. new \Person(); //输出 I am one!;
复制代码
9 y' T% Q+ c, L: k; \0 E/ ]" G
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php7 w# z- g- s0 G% w, e; P- Z
  2. require_once './1.php';6 h8 q) U; c6 H/ w: q
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

* t! Z  v5 P9 ]& p* s4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   % p# ~, |1 W6 P/ r$ ?
  2. namespace one;
    3 L$ s/ K) v6 e) n  g" [
  3. class Person{
    3 M/ ?( s8 C+ M8 \& O) s
  4.     function __construct(){7 V! J6 Y3 @% p4 Q9 I- l8 h6 ?
  5.             echo 'I am one!';8 N  F- ~3 N0 Y1 r. X( F: p! B
  6.         }2 ]$ k- D" S3 y$ K! T) B1 h# {
  7. }
复制代码
  1. //name.php2 _9 t! S% k. G
  2. require_once './1.php';
    9 o# r* N& V" I7 l' Y
  3. new \one\Person(); //输出 I am one!;$ i4 P0 @  @% C) ~
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

7 t% T' U3 V0 D% l9 C! }) q- y7 y8 i
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

7 Y1 ]% S; c; ~* M. `5 g5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
. z& O! C" D2 o5 y4 x  F2 P
  1. //1.php   
    3 z- m7 a# P2 F: m4 a
  2. namespace one;
    ' y3 j$ _" V+ j) \6 l5 w! X
  3. class Person{' ?+ N; A9 d8 ^; ]8 E0 P- p0 M3 i
  4.     function __construct(){
    . `$ N' L& p3 @
  5.             echo 'I am one!';0 a/ G; j. Y. ]" R. H8 E% U7 E
  6.         }
    3 P3 Z+ P0 o0 [
  7. }
复制代码
  1. //name.php6 ?6 l' J: E% P) s
  2. namespace test;
    , E# i  h& m. X/ r! H5 ~( f
  3. require './1.php'; ' I: ], [" F' E' \6 y1 S
  4. new \one\Person(); //输出 I am one!;2 ]% |. L5 o! y  `
  5. new Person();      //这里结果会是什么呢,猜猜看: B: }( D1 {4 F3 g
  6. 最后一行结果报错:3 o$ ^! m4 Y9 z
  7. Fatal error:  Class 'test\Person' not found
复制代码

! `" q0 }5 C) C* P6 G) P$ d8 G

* q4 f0 {- `$ W3 m4 h$ _1 T1 Y首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

- F0 ]4 i" |# l- t" O2 r- l
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

. `4 i9 c+ Z: o- x0 x& O
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    : h5 N. @$ p( ^! G# \! ^
  2. namespace test;
    7 Y8 l6 B# F0 V! i+ I5 ^
  3. require './1.php';
    4 q" }$ N% u2 q1 V
  4. ; V/ m; m$ o" _0 l, t, r
  5. class Person{
    + ]+ |5 a/ H6 c5 I" c' ?( X
  6.     function __construct(){% l) [) W0 j& U) u
  7.             echo 'I am test!';! {% ^5 t1 w4 ~9 r  i
  8.         }& a3 J& u. m* |6 p
  9. }+ H8 U# K' S' g: t' p4 w. u0 |

  10. 8 d+ s# `, A1 f( H6 e
  11. new \one\Person(); //输出 I am one!;0 W6 a4 x6 t  A8 e
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

) ^, m& H( j! {% T: z% _! q  t3 r
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php0 ?" a2 H$ E" b) ^/ L+ K) {0 A
  2. namespace test;
    ) _, J3 p0 q! D  {# |
  3. namespace one;2 z* d  Y% E) X. o! S2 R
  4. class Person{3 W; }0 M- m1 N5 ^; T
  5.     function __construct(){, U- c' G8 W% ~; T
  6.             echo 'I am one!';1 {! l& G, P; L% c7 l3 X. v
  7.         }
    7 X& L  ~, N% A  E5 P' A  W. _
  8. }
    ' `9 _1 U0 p, h, [9 c

  9.   n. `4 F5 D7 m' \
  10. class Person{
    5 r3 }$ f  Y9 h; ?2 ]0 ?
  11.     function __construct(){0 w) Z" C2 f2 z6 \2 z
  12.             echo 'I am test!';
    0 d' P2 S% ?: C* a
  13.         }! \% T. c3 I# d. |1 f( t
  14. }
复制代码

3 N3 A$ |- ^" J* ^+ Q$ S
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

$ I# t  J( U: _" U7 L' S
看来简单的把require理解为替换,在这里行不通。

: i6 e' X1 J6 j. P8 _6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
* U) K4 X) Q. U! i: i
  1. //name.php
    - }! \6 b! L& x# T+ J6 o( p/ z! E1 J0 p

  2. / q  ~" B2 Z! i
  3. namespace test\person;! j7 \& S* E0 i0 I
  4. $ p# ~) \$ D8 X5 x. }* @
  5. class Person{& `6 @! K( h% R
  6.     function __construct(){
    * y8 ^: J. f$ Z9 Q* V2 @
  7.             echo 'I am test!';% P0 b. z' |- o0 ~( C, G
  8.         }" }% B  N3 l1 @
  9. }
    / t- A, d7 |: w* a& c* X/ l
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

; n; n1 D& @3 p% n: o2 P4 [
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

6 Q- G$ g& Z8 N2 {7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    # c) X7 `  s8 s# S% z8 z
  2. ; h1 T: a4 m7 b9 l- ]3 P7 `
  3. namespace test;# X! k2 q% L( R- L3 O0 f0 ?- Q
  4. echo 'zhai14';
    # w7 c1 O) T/ Y
  5. namespace zhai;" B9 p  K  c- t
  6. require './1.php';
复制代码
# I2 r+ F6 P1 f# s
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
4 H& \  N7 k! B
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
' ]- \$ h) z& c( A; V
  1. //name.php. U# \+ |, B, D& B! K- ~. N
  2. 8 z4 L; }( t; J1 X
  3. namespace animal\dog;1 J& {8 N& Y7 ^: c

  4. $ r$ M, ]" B) H8 k$ [: h
  5. class Life{
    ) c' f, ?5 y1 B
  6.     function __construct(){
    9 B1 D# A: K- y6 |* P
  7.             echo 'dog life!';4 l3 e1 Y- I7 l+ T$ _+ p
  8.         }  Q2 m$ C' U4 r6 u
  9. }
    5 S  B+ f+ m1 g0 S

  10. . T; C! f5 C. B) g, ?& B6 _) J3 ]
  11. namespace animal\cat;
    $ L4 E* v* P* Q1 u$ ]
  12. ) ^- d- D# U+ M$ u" W. b, J& t
  13. class Life{3 A$ A' |6 O: Q/ j. l, u; q' i
  14.     function __construct(){3 x' C3 ]/ {0 Y- I) ^; L5 |" t
  15.             echo 'cat life!';
    . s1 h: A/ a/ j; M; Q) i
  16.         }
    & q- I- @. O- f% D# @6 c
  17. }
    $ Y+ ?- P- o0 C$ b( @

  18. ; z' C( ?* P6 R7 m& C
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间, v$ ~( a: _# e: @/ b; C" `
  20. new \animal\dog\Life();  //A% N! U$ S/ b) c5 Z, ?+ ^

  21. # S! F8 I3 H( p  g8 u8 T
  22. use animal\dog;  //a
    6 N3 T* b$ g1 p( s1 e8 s: n
  23. new dog\Life();  //B
    & F) s6 W- H! {2 k  i& u
  24. + I5 O# g+ i! V, V! M) C2 W
  25. use animal\dog as d;  //b- G( m6 Z) ?+ d
  26. new d\Life();
复制代码

% q' A4 L' h2 `" w" b' W4 d; S0 ^1 l
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

' f( O$ b6 Z4 d; }! M; L. e
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
' [, X2 T$ r. X$ I' [! ?
相当于
  1. use animal\dog as dog;
复制代码
, K: N2 g$ r/ N# _) H  H" O
2.namespace后面不建议加类名,但use后可以。8 V! j3 G% ~7 W$ w
  1. //name.php
    9 B+ {; S' a' u  ]; ?4 W

  2.   _, n' P1 B. `' I
  3. namespace animal\dog;+ C/ |0 G: Y, s% U1 v
  4. * f! G/ Q. ^' m; ?; ^5 M1 t, q
  5. class Life{
    2 h, K! _( o$ [  ~
  6.     function __construct(){
    8 q, o9 O; t# p. ]$ v- m5 q) q
  7.             echo 'dog life!';
    & L' I: V! w# w! j: m0 L
  8.         }
    ! h! t& R1 S  k
  9. }$ k; ~8 Z3 \4 L" \# z- |( {" f0 ~/ x
  10. ( r) n6 M% u" F/ [
  11. namespace animal\cat;
    4 Q( c  d/ T9 p$ k) W8 p: b4 z

  12. 5 O/ P! S1 [, ~' `
  13. class Life{
    & P8 S  _1 O1 w2 _7 i
  14.     function __construct(){) ]7 }; r2 g" Z$ F; `
  15.             echo 'cat life!';
    : @0 T2 @" Y$ y% ]* ~, Q
  16.         }
    0 {1 ^- d! ^6 f$ m0 f' T
  17. }) l  c1 a3 i7 s5 q
  18. 8 i; r; Z8 ~& F
  19. use animal\dog\Life as dog;  
    # H! ]% Z+ W; v" J- [3 u
  20. new dog();
复制代码
6 e# L" B: l2 \" g2 S8 s
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
( Q& c3 n9 R1 f! ~6 O5 B) s2 I
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php0 s% I  }5 g3 [; X
  2. , l4 @/ G& w! _* r
  3. namespace animal\dog;4 V! N4 Z) ]7 j( y  F# h
  4. ) D' `3 k, H. O* ~- E5 S2 v. A9 e
  5. class Life{
    ! U: D4 K7 ~' _7 I/ k
  6.     function __construct(){  ~. K* ^4 ^1 U0 F3 s
  7.             echo 'dog life!';
    / ]) A  \8 H$ S0 ^
  8.         }4 m# K) W" q! F. m
  9. }
    . E4 H- a( f. v9 \* [4 R
  10. class Dog{
    + r8 w1 Q1 d3 f  O- n( `2 c+ q
  11.     function __construct(){
    $ Q. g) q1 q  [5 B" a+ S2 R2 d
  12.             echo 'dog in dog!';4 _' B2 K4 R# d9 S+ p" S. x1 y/ `
  13.         }
    0 ?1 A: \1 p, b3 N0 F
  14. }
    0 [: Y% d9 @( {: F  M$ |+ u
  15. 6 ]& o2 L4 M+ s" K( _/ [8 l
  16. namespace animal\cat;0 H5 @! Y6 e- E/ H
  17. 5 I# G6 u' \% l5 s* X4 l" A
  18. // class Dog{! G- g% |3 t& c2 b; s  H
  19. //     function __construct(){9 Q2 W1 r' B/ e' i' j
  20. //             echo 'dog in cat!';
    - o* d6 J* N( H" F- [) z9 l
  21. //         }
    / w5 ?9 X% ]  Z
  22. // }
    - g. Z+ s9 ^2 K+ [0 P, h7 k
  23. class Life{5 i3 o/ Z% w8 H( Z
  24.     function __construct(){) f- [* m8 Y" l1 M: E' a4 X1 m" Z# n
  25.             echo 'cat life!';
    3 U0 Y+ i/ B: H" s" q/ ^% }
  26.         }
    % u3 x2 ~  q. j, v( W* L& R' g
  27. }
    . ]9 G" m8 C2 V+ l# w

  28. 8 J& L+ E! {% v! t- O
  29. use animal\dog;  
    & h( ?, \7 ?! Z& B  H, u' N2 }# `! s/ \
  30. new dog\Dog();
复制代码

! c4 K# P) E4 P- Q- K. I" p
如上,使用了
  1. use animal\dog;
复制代码

7 m4 {" S- M1 N) k  t
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

$ d# B7 H) }) S2 P; `
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

( D( w+ K3 {0 p1 r
7 q' G9 l8 _$ t7 w0 k
6 U& ]! Y+ S+ n: z- L
( F, R4 |! i( {: z9 @9 d' Q# O7 K0 E5 o, B) w
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-17 11:58 , Processed in 0.112079 second(s), 19 queries .

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