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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

9 F- A5 _8 d( w* E6 R6 g
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
0 q6 f5 }) J: K

) o  z9 M9 X) e/ U9 _4 S使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

/ W8 J" N" P1 T% ~$ h9 b/ q) X
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
. p+ [- j( S* r' v6 N
结合使用方法来进一步理解它的使用目的吧。
7 A' r- g* ~' P# \' e

- A8 h; \  G) Cnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;0 A$ v* i* u8 V
  2. namespace One;  z: ~6 f# _6 Y) G
  3. namespace ONE;
复制代码

1 ~. ~% y4 g9 u
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
! v* y$ P7 I' n$ z! `* T3 R# r8 c
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   , W) G3 _: m' Y0 ?, f- L# D- I
  2. class Person{
    ; r, b2 i3 `1 Z6 `9 l. x3 O' T
  3.     function __construct(){2 j0 {" V# I/ k* E! d0 R. F
  4.             echo 'I am one!';! M( C+ t, m7 i
  5.         }
    1 k6 S4 y) r. ]7 Y) f# c" S
  6. }
复制代码
  1. //name.php+ ^5 ]: j$ q6 s& A. H- P
  2. require_once './1.php';
    - Z* n/ T  s: P8 O6 m. B( o

  3. 1 C% {% K7 J+ l- Q8 ^  A
  4. new Person();     //输出 I am one!;( n( Y: f# `9 a+ T
  5. new \Person(); //输出 I am one!;
复制代码
6 m6 N. I5 w* T# _
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    ' N7 T. ~! ?8 A
  2. require_once './1.php';1 F" A0 W2 Y, v6 d1 M$ {
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
+ y+ E9 D! }9 ~8 K3 E; R
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    7 z; E& z2 H/ ?- {3 [
  2. namespace one;* |3 N# n3 a; {
  3. class Person{3 a# _$ M  z% f7 U) N
  4.     function __construct(){
    $ c: Z# d3 }. ]# @/ M. `! K8 S9 X
  5.             echo 'I am one!';
    + O$ k- h) h) O, M) ^8 \
  6.         }, @1 Z; K+ v! x/ y
  7. }
复制代码
  1. //name.php. H& s: P1 T/ J& a  v
  2. require_once './1.php';; [( ?% t( s) {" f6 ^" j
  3. new \one\Person(); //输出 I am one!;* g$ |. q' V7 g0 k( N
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
9 A; e' Y+ q. p7 P% Q3 h0 n) U
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
8 `; x  b: J% L7 {6 ^
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。2 e- {! j5 t8 D5 w( D5 m
  1. //1.php   
    ! C' }: j0 m2 o( P5 |0 n5 P
  2. namespace one;! y, `3 @: ]- c7 K7 L% Q
  3. class Person{7 K6 \5 A6 y" V
  4.     function __construct(){1 |7 E; W& w- m
  5.             echo 'I am one!';6 E* L& W. l6 U
  6.         }
    + v1 C9 p8 S' `0 m7 g2 H
  7. }
复制代码
  1. //name.php
    $ |3 |3 I1 _. {/ Z" I
  2. namespace test;
    ! P' R6 v' ~* }
  3. require './1.php';
    7 q: |+ B6 Z5 `/ Q4 A, F
  4. new \one\Person(); //输出 I am one!;4 E8 \3 |7 }7 n0 g& T
  5. new Person();      //这里结果会是什么呢,猜猜看, y& M' V' \& A" m( T
  6. 最后一行结果报错:+ \" a% G( c& X+ {7 S9 p
  7. Fatal error:  Class 'test\Person' not found
复制代码

# c! l  x  F- ^0 w
& X9 {! S9 S6 b, {. l7 C
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

' M3 l3 p% b, J3 K  A. H
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

* L: A! Z8 A5 D% e5 K6 o8 O: }! z# e
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php5 J5 r0 h) }; i
  2. namespace test;
    ' E& F9 @1 }+ H" @. e' i/ y
  3. require './1.php'; $ L4 j5 A) _2 l% w6 h5 ]

  4. 4 t( |  x) e. V2 A* U
  5. class Person{! L* c. a; s5 @
  6.     function __construct(){
    ( r. `! @7 p  n& `  V# ]- K! F
  7.             echo 'I am test!';
    % `: u' S7 d7 w! s+ N" h* l
  8.         }
    * N& h3 z  k6 Z* J4 z
  9. }" o7 k* M6 X' D
  10. : S/ E) D9 i+ C3 ?
  11. new \one\Person(); //输出 I am one!;( h5 z# w* ^: o( Q# T1 Q
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

0 W. @/ e: z! H" x7 C) J# Z
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php  o* M5 K* ~- {
  2. namespace test;5 Z: ]: M0 V3 N6 K
  3. namespace one;9 O# |; X# G6 a
  4. class Person{# f# v: G8 @# [0 L( k" d
  5.     function __construct(){
    & V  v. q1 `; j; x* Y  m& c+ I
  6.             echo 'I am one!';* w  n( t3 _/ Z3 ]2 u3 X7 h
  7.         }
    . \" j  {) ]4 P: l
  8. }" g. j. s4 ^/ B* r- p

  9. 8 |7 I7 e3 r8 v( e5 l  Y, a) `2 i
  10. class Person{
    5 w  S: p. C. `! m
  11.     function __construct(){
    5 G& C$ [) L  o8 c
  12.             echo 'I am test!';
    : p7 s- z. k0 y1 C# M! a
  13.         }
    3 i; `2 F/ L& w8 `
  14. }
复制代码
& r1 q8 Q- e7 `% w
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

- D  D. M' c9 ^) l5 U6 W  y/ z8 z
看来简单的把require理解为替换,在这里行不通。

1 P2 v& W- b1 x! N6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。+ V1 {) L( i; K# d0 p5 ]" j
  1. //name.php. ^# c0 T5 V  E% i7 L6 k" R, N9 w5 ]
  2. 3 ?& _' b- r0 ?
  3. namespace test\person;2 r- A, M2 @+ t3 \+ L

  4. % t7 R0 B& i! k+ o: j/ ]% M* t
  5. class Person{
    * q6 w& ~. l& l$ r$ o
  6.     function __construct(){
    " e" ]5 }! A! t: |8 u5 F
  7.             echo 'I am test!';6 {3 J9 j. [& ^! @4 f2 N# F
  8.         }: _9 @# ^' r1 `5 O8 |( q. S
  9. }
    1 k4 q& x9 c: T
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
: F% ?  @4 L6 o' f9 X8 G4 T
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

- p1 W7 I- ^8 \$ T1 B! U6 A7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    , b* w  G& v' y# v& j

  2. & _4 z1 @/ |, a) P% _, Q$ _
  3. namespace test;! r$ d* b$ o) W1 j& }- o- w3 \- O
  4. echo 'zhai14';) v8 }  `' H0 v& b
  5. namespace zhai;
    3 e$ X1 x# I3 C
  6. require './1.php';
复制代码

, i( m8 @# Y/ h. q( J! _: Z0 t
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
. d6 W% H, g4 T% l
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。0 L/ K, C  [  c. E/ a; B  A
  1. //name.php
    " p, H1 @" ~% \

  2. ! {6 |1 U% m( M+ L7 Z$ g) o( ?! {
  3. namespace animal\dog;, j( v# Y) h$ g' Z3 M
  4. 9 @% D# o% y1 C  z7 z2 S5 ?3 j' J
  5. class Life{
    ! \( B; {7 ?! q! [, T  G: I
  6.     function __construct(){
    ) ^+ R: M: I3 }2 K; V. {- H0 d
  7.             echo 'dog life!';
    * ^' ?+ I+ Q+ d& p5 _- ~2 P
  8.         }
    0 R2 H: I: j& k+ E# h  k
  9. }3 Z6 E0 T0 Z4 Q0 ~+ W

  10. & w7 V/ {, K/ C4 g& L
  11. namespace animal\cat;
    * k8 M, ^& V8 I0 J( c7 A! V
  12. # H: n5 E7 W. k# V, d; W5 o
  13. class Life{
    ( j! c  c1 y! Q5 _# s' a
  14.     function __construct(){0 p% X6 E8 t1 m5 U# ?5 C/ D; e' T
  15.             echo 'cat life!';; Y1 ^. n" O! N. k
  16.         }, C4 V* ~# J+ I% h  X7 b
  17. }" E0 A3 l" F0 Y! f' q
  18. 7 x8 y: G2 h2 @# p8 |
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间7 Z; G1 c9 d" s' a
  20. new \animal\dog\Life();  //A2 [; W4 V* c& s  X0 \6 w9 r4 C# w. {

  21. : W" c* U3 ^7 P: q. U8 c( A/ K% N
  22. use animal\dog;  //a
    & n  j$ W" Z6 N3 G5 a; H" A
  23. new dog\Life();  //B+ p  P0 C( s  q4 o
  24. 0 f$ O! c% u9 p! t) h( m+ h
  25. use animal\dog as d;  //b) u+ k4 G3 D" [: ]
  26. new d\Life();
复制代码
7 W0 ^( W! t9 q  ?: G' [% ~
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
4 S& c0 H1 e3 R) d4 r+ @
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
: R' E. \2 P( F" `2 L8 @
相当于
  1. use animal\dog as dog;
复制代码

5 g: ~# @* v& g2.namespace后面不建议加类名,但use后可以。  \/ l- Y3 c/ o/ Y' B4 z/ N
  1. //name.php3 ^. M! D! ~. Q+ @% ]& k

  2. 7 s! n. l  g/ @. E$ q/ W- C
  3. namespace animal\dog;* S$ |6 X3 q% ]
  4. 9 Z( v; g/ s' O; ^+ ^% j  o6 b
  5. class Life{
    - R: g3 A! W7 e
  6.     function __construct(){0 p4 ~! p; A; h  m, \- J
  7.             echo 'dog life!';$ L) H" s0 E! t! ]
  8.         }1 [1 O% a. g2 O% c
  9. }
      ~; L  Q9 `. c* X2 M- x
  10.   o& ^" T- s* M- F2 [, W
  11. namespace animal\cat;1 u" p0 r2 w: U8 ?2 e

  12. ( b. d9 r0 r1 I% K
  13. class Life{  i& g' p" D: u( h' @' q* U( L
  14.     function __construct(){4 Z5 e$ h1 N/ ]9 b
  15.             echo 'cat life!';$ t1 ~; _6 R4 @. Z; }( Z; `
  16.         }  t% c% i7 r* n
  17. }
    5 V! n5 I" q6 w% @! M: P

  18. 4 N0 b- w" _; a( J: i& T2 a
  19. use animal\dog\Life as dog;  
    8 P5 `; [1 X5 V  }- V9 K/ g
  20. new dog();
复制代码
0 H* P  q, }. y9 j
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

  v0 g8 s( l/ \* R) v, m+ E; F( r
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php( L7 Q" Z2 A2 X7 ^, d. N( v1 `

  2. 1 x0 s7 |; X" i4 T. [& o+ T
  3. namespace animal\dog;( k' ]1 f0 u/ b0 y
  4. $ \* y# }9 Q9 y9 X& W
  5. class Life{& k  {. a. l; U! k+ Y' ^
  6.     function __construct(){
    ! S* A/ s/ a; V; A6 [
  7.             echo 'dog life!';& ]6 Q- r* D& t% [4 r
  8.         }5 Z' z, a& ~1 N" o5 x2 A1 I- E
  9. }
    $ X+ u. i0 T6 m6 B# s$ g! w$ h
  10. class Dog{/ B2 S% b( M' h. F
  11.     function __construct(){
    # H6 ?, r0 z) \$ \1 x& C6 K
  12.             echo 'dog in dog!';0 l9 g4 v( k' Z1 W) e
  13.         }8 m; Q1 b2 ]6 W
  14. }
    4 q1 }) L" L& x4 B2 w- b4 [- N

  15. - U; h  G" J  G4 |1 V7 e  P9 S, e
  16. namespace animal\cat;
    6 }+ ?/ a4 g% Q7 p; O/ m
  17. 5 D% x. v+ H. Q
  18. // class Dog{3 @& X2 c% I5 I  Q* o! J1 J( b
  19. //     function __construct(){
    ; d' v" ?$ a4 N+ V' k! p& E6 w, f1 i
  20. //             echo 'dog in cat!';5 M& M8 U6 D1 M& W1 \
  21. //         }
    % f* b; B( G$ |4 R5 A5 `
  22. // }
    8 L0 v5 V- e. f( C" ]9 `" b: v! u6 p
  23. class Life{
    9 {1 n5 M2 Z$ @* I1 C: X$ U  [+ W
  24.     function __construct(){
    , t# D7 @1 p  Q1 Y# L( X2 M
  25.             echo 'cat life!';8 u! o1 G0 W" ^! U5 V
  26.         }8 J( J! p7 \! `3 I( I" A
  27. }
    4 a  ^: t7 i+ A8 L; u3 ?; U
  28. 8 R2 Z* `9 A: J$ b9 t
  29. use animal\dog;  
    7 b* u) o" v# }0 }
  30. new dog\Dog();
复制代码

7 O7 C3 }' ^1 D- Z4 H) J
如上,使用了
  1. use animal\dog;
复制代码

, Z' [: L  r# s" C/ P/ R& E
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

9 _" R4 w. i% j' n+ o
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

! P  ~2 g3 }2 H! z  d8 X  o. w0 @: U. F5 b  ~+ _: y

5 G5 m* N& E- Z/ v; j, ?
9 c8 e9 v: @: Q! E' S0 f  t/ \& L2 D; p* h* ^* v
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 07:08 , Processed in 0.057519 second(s), 20 queries .

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