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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

# D# N# A, j4 F0 b4 o' o5 [. r$ P2 \4 r8 l3 C/ O4 o
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

5 G- e! \) p8 s2 n( c6 m结合使用方法来进一步理解它的使用目的吧。

% b9 z: b, i' E; [$ w
3 C' ?; P& L8 t' g% rnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    ) G- E/ a4 Z1 L, D: c; R
  2. namespace One;
    - o1 V2 r" u: C/ F/ U& I& R
  3. namespace ONE;
复制代码
$ i# D8 G0 O. j% n; K4 S
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
" O, m& x4 O! r5 X- |
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    # c' y/ y. j! f5 e) r( R
  2. class Person{
    1 n1 D& Z! H" F8 F! t
  3.     function __construct(){! U+ E- L3 `$ T9 B7 R. \8 x& I3 h
  4.             echo 'I am one!';
    2 ~7 g# t- p/ j2 v$ W
  5.         }& g; ], M. m$ p2 B  s! ]4 s' {$ _
  6. }
复制代码
  1. //name.php8 Q, S. \: ]; @
  2. require_once './1.php';
    5 k, O& [# y* R/ Z9 i" N3 N
  3. ; H# x. ^2 F9 w: \
  4. new Person();     //输出 I am one!;
    & M$ N* O. ^) d' @& y
  5. new \Person(); //输出 I am one!;
复制代码

! T. v6 y7 [% l' K5 ]; \5 d' ]3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    . w, k, X! c6 L
  2. require_once './1.php';+ W- j4 ^7 s: @
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

( T: ~2 @, Z$ O& ^6 q; P( W8 ^% K4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    7 o& k. k# a% m, v/ e
  2. namespace one;7 \3 j! z% c& U! ]2 [, m
  3. class Person{2 W2 W# u' ~2 t, Z1 Y' w
  4.     function __construct(){
    ' a4 e, E$ ?+ B( D
  5.             echo 'I am one!';% {' @  Q. Q" G- [; J+ k: |
  6.         }
    1 _1 M: ~0 w$ r- {$ q7 v
  7. }
复制代码
  1. //name.php0 {, Y& I; E- O" h% C* z
  2. require_once './1.php';
    # f7 F6 h! |0 H9 W' a: T
  3. new \one\Person(); //输出 I am one!;! l! A. w& j: f* N& a) n
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

4 e' m( E8 Q: p* _! p) ~
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

9 z3 p. v! i+ _* z6 l! E0 R5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。1 c/ C& h0 ]5 f
  1. //1.php   
    # T) @% H1 ~8 y- O8 K
  2. namespace one;
    * v3 _2 @5 [& ^: }( }5 f
  3. class Person{% U. }- F. s, s: W* c* ^* X4 [( ?
  4.     function __construct(){
    / B+ \0 W# z& Z
  5.             echo 'I am one!';
    # R0 o- c% w; a- V2 Y9 \
  6.         }& ~0 M: m( P/ w" Y* ^4 h8 r" ^# |
  7. }
复制代码
  1. //name.php) u% h  n4 q) g2 ^' h
  2. namespace test;' L0 _' Y; b3 s, f  [$ q
  3. require './1.php';
    5 |0 l8 o9 B% A
  4. new \one\Person(); //输出 I am one!;6 @0 C4 R; B: m: H2 p
  5. new Person();      //这里结果会是什么呢,猜猜看
    / b9 m8 ^1 P/ A' O/ J  \
  6. 最后一行结果报错:* `$ k( {9 ^0 m' D
  7. Fatal error:  Class 'test\Person' not found
复制代码
3 A3 l- [) p9 K) k! W4 U  i
( l. _6 _1 S, c% f
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

. Y5 ?2 }2 T* A" a4 G( n
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

' I9 h4 S) V2 r/ Z! l
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    " S- ~! }$ a; U! X
  2. namespace test;
    6 a5 M! j8 @- F
  3. require './1.php'; 7 Z' ^' g4 e, z) F1 _; p1 m

  4. # I) L0 Z# i6 a0 E& u8 ]  q
  5. class Person{" |: k9 g, c: O; H
  6.     function __construct(){( w% w* _% S- D+ f; m" O
  7.             echo 'I am test!';5 a8 }0 s# b3 |4 M
  8.         }
    ' W" n: b2 U8 R+ ~, x
  9. }. ^0 S: M3 h7 C( V, i* v( g3 |% H) J& k

  10. 5 F+ o: ]5 V9 c$ l& j0 p
  11. new \one\Person(); //输出 I am one!;
    $ c% ~1 j1 s6 P
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
2 K) q! h! a# V- ^3 J% \* S5 Q
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php. c% y# G" a/ b4 e% k
  2. namespace test;) o" k7 g) p: ]
  3. namespace one;
    " Y  s4 Q. W) J  }0 ~
  4. class Person{
    * X7 e% J( }1 u( T- E3 m  ^
  5.     function __construct(){
    & J- C: I( F1 [2 w- }3 w. U
  6.             echo 'I am one!';
    # @! G- \6 {' _* j
  7.         }
    8 G% {, _/ E  d; T
  8. }
      k  C0 H6 A/ c8 g4 e) H9 H3 L/ G

  9. # i8 I# P& o5 j/ }) E, M4 k4 s( P
  10. class Person{+ [$ k1 s/ \% Z3 q
  11.     function __construct(){
    2 b7 @+ i  U6 W' Z. i# J
  12.             echo 'I am test!';
    ; ^4 g! G, t" ~- ^6 M4 r
  13.         }
    4 D2 Y6 ?. |9 R  e' z4 W0 K
  14. }
复制代码

, I/ d3 n  E7 E! k
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

0 m$ j/ W% B( Z2 P% r
看来简单的把require理解为替换,在这里行不通。
' i6 K! a% g2 p9 @
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。% H* {  N6 `& X  |
  1. //name.php
    1 k/ p# z" v% E: O0 X8 w
  2. 8 g0 K9 d0 {( C1 V
  3. namespace test\person;
    % S. z9 F: a9 I9 \7 c& c
  4. % M" v1 U' P' _- p1 J% U
  5. class Person{  m& X& J6 f/ J+ L  x
  6.     function __construct(){3 o  d% ]1 O% i8 ^( c0 e
  7.             echo 'I am test!';6 {: B! ~+ j! D" {9 _" K8 r  t; K. h
  8.         }% V# ]9 y0 w2 G- V7 l
  9. }* y9 T  f1 M, ]5 X, v1 t0 D- ^3 K
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

4 S  m& z; Q6 F& c
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
; P2 p$ T$ o* O- n
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php. d2 f2 L$ r1 V  [; x& H" C" I

  2. 8 V9 B9 W9 m3 q. {& y. v
  3. namespace test;/ G4 N) P6 x5 y6 t, }4 h6 G
  4. echo 'zhai14';
    : ]7 K9 d; Q/ z4 ?) L# X. g
  5. namespace zhai;( U; B  e: P' }- G6 W; o
  6. require './1.php';
复制代码
) M; W1 g: V2 J8 @9 `
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
3 t2 m( o- H& E: S
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。: Z! m  U1 r7 Y
  1. //name.php, C- T: o  [  [
  2. 2 C; S- B& I/ q; ?
  3. namespace animal\dog;
    : O& K/ R' z3 T3 B* C

  4. 6 L# c6 t, \% k9 \+ O
  5. class Life{
    $ l8 S; l  S. ]/ O
  6.     function __construct(){
    & a7 Y9 A. T( n7 W' {$ n
  7.             echo 'dog life!';0 }7 n# P0 G" j$ S
  8.         }
    0 z5 ~% ]: O* |
  9. }
    . k; }* O# A8 g8 G# W) @+ ^& x

  10. " B- T4 {" N" Q, ]  U
  11. namespace animal\cat;( O& H' k1 U% n  ~6 @0 z
  12. & Q6 D3 a1 H$ H) ]) ]
  13. class Life{3 q9 a' L7 n- q, S  L  q  w
  14.     function __construct(){6 _( Q9 `6 Z- c" U8 J$ j
  15.             echo 'cat life!';
    . l# p+ `2 o2 ^/ d4 l/ A
  16.         }
    4 x% N) g6 F& F+ a) `
  17. }
    ) z5 D  Z  G( `, X4 A% Z% F

  18. 5 g* f8 k$ A3 ^( i; ?
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    * I3 ]  A8 o. @' C
  20. new \animal\dog\Life();  //A+ I' s; d0 v+ b9 W7 a  s; j5 R+ Q
  21. + v( v. ^( K$ M! P
  22. use animal\dog;  //a+ W" {; @/ ^: r% X
  23. new dog\Life();  //B
    6 H( t+ S( F0 R& C
  24.   i, j6 m* h9 u5 G* G* U
  25. use animal\dog as d;  //b
    ) T2 \4 H5 i+ ?
  26. new d\Life();
复制代码
/ v. ^5 Q) |. o
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

0 I+ g& ?: |# ~; M2 k
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

% x& O8 ]; B' j4 f, r: V
相当于
  1. use animal\dog as dog;
复制代码
+ l  M+ D! V& {. T* M1 S
2.namespace后面不建议加类名,但use后可以。
: C2 O1 Z" @1 i" ~( d! H1 V( _
  1. //name.php6 B1 h0 T: \( u/ \7 l- ?( i5 X: e
  2. # a. k  a' Q4 l; U
  3. namespace animal\dog;( E" i! E& |: m" O

  4. 4 S! T; a% y7 [& r# Y
  5. class Life{* ~$ @, S8 |" p, v% q
  6.     function __construct(){2 D5 e: D5 f+ ^0 I
  7.             echo 'dog life!';
    " p) r; A2 H6 v8 v" d' G  H# T
  8.         }# ?# r' c+ M( r) H) i( a+ [
  9. }
    % x+ e# J6 q1 z

  10. ( a. {) U6 w- J( G& x
  11. namespace animal\cat;. w8 @, b: d# R

  12. . q- |3 ^' p$ d
  13. class Life{
    ) w. F( i+ F! W: r5 b; e. Y, R
  14.     function __construct(){
    # N# B7 N0 D8 g5 ]2 T7 F
  15.             echo 'cat life!';
    / B( j3 V& O8 T
  16.         }9 J% a3 M1 e& b9 W. O
  17. }, j9 E- F3 m' |! _

  18. 6 C6 L# o# J1 H, t+ v5 Q
  19. use animal\dog\Life as dog;  
    ! W7 P# ^( m1 ~& W. v
  20. new dog();
复制代码
! l" m7 c( b2 O# r; B- o) m! B
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

. q4 }; N9 m& \+ O+ e
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php' y$ K* ^( x( C4 L! W3 C, @
  2. 4 T( [+ s. A3 s$ {. q* M+ ]
  3. namespace animal\dog;
    7 y; m) W9 i4 ~- Q

  4. 7 d/ w" z; {7 \) S8 s$ w& ~7 O! `$ B
  5. class Life{
    $ v) ~: y5 V$ I
  6.     function __construct(){6 P( a1 q3 w) L2 R
  7.             echo 'dog life!';
    # U& ~" ~2 q; l! r
  8.         }% s% a: v8 Z/ f  J( q* A- N. G
  9. }: c" z; Z  e* D& Y1 a
  10. class Dog{
    & @0 H2 p' u! h" V3 w
  11.     function __construct(){
    9 E" Q! e" g0 B$ d1 Y% g3 A
  12.             echo 'dog in dog!';
    % N4 [1 t1 m" |8 `) ?$ F; g! q
  13.         }
    " B/ `; p! S' U- H
  14. }* x! Y1 u- F2 W2 I

  15. # R9 ^5 x) @2 D/ v0 W/ l- o
  16. namespace animal\cat;
    : d/ z& x: M7 y4 C0 G' ~, w% g- B! @
  17. ) T, x$ A2 C% x0 d  l" f
  18. // class Dog{* j3 Y' P# j, A5 O8 O
  19. //     function __construct(){. N0 h5 r5 l" Q  R9 A$ L
  20. //             echo 'dog in cat!';. x8 \# L+ Y7 M& W5 b$ Q
  21. //         }( ]  [  N1 I- Q5 n' ^1 B
  22. // }" V+ z) P, L8 @9 F) Q! F% \$ u
  23. class Life{; h5 e' Y' c0 E& ?( a
  24.     function __construct(){
    $ }$ k& Q0 f- u# U, u
  25.             echo 'cat life!';( d7 @4 d1 K( n1 h4 H5 \
  26.         }7 _0 Z6 e" n" ~" ~4 I, C8 T
  27. }+ H* m, M( u6 T" N

  28. ; [; U! j. l4 o2 o5 Y
  29. use animal\dog;  
    7 w. D/ u1 Q  T: \5 `
  30. new dog\Dog();
复制代码
  M& k  W# [0 D. a! q
如上,使用了
  1. use animal\dog;
复制代码
+ y! ^1 u* e9 E. M/ _/ e8 L
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

0 d3 T  o: V3 h
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

* \2 K; t6 K$ y9 l4 i
& J0 V+ X  m! v
! G& ~, b  C, W2 Y& Q7 Y. D/ R/ V+ y
8 m" t) t0 _. X  S
1 l0 x# }$ ~$ L- I% V1 y
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 03:13 , Processed in 0.073617 second(s), 20 queries .

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