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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

5 L' _' ]2 Q" y+ h
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

7 j; j1 {! C5 d* r" M! j& ], K9 I0 g$ B0 F5 U; a8 C
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
2 q" Z; ]. C$ Y* T+ W/ O6 K9 l# t
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

* [# h8 |5 N2 a" i0 x, ^结合使用方法来进一步理解它的使用目的吧。

; S, {, J% ~4 e7 o5 ?5 t1 R
* ]; O+ J4 o( Qnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;" j. v, D# N6 D7 J8 y+ J  Y/ f
  2. namespace One;
    % @  v$ q: t6 S; H1 v6 j
  3. namespace ONE;
复制代码
- d2 a: B# i6 s, V$ ?5 ~7 i
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
- ~; y4 E; C% Z/ p2 H: }0 ^
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   0 O) V3 r# u. m( Z3 O9 [
  2. class Person{
    - _2 f! {/ W' q6 |
  3.     function __construct(){6 n( t; }0 n( F7 f. O% d2 A
  4.             echo 'I am one!';8 U1 ~6 T- @, x/ t/ F( o+ v
  5.         }
    0 ?! G7 @- _  {  z+ q0 |
  6. }
复制代码
  1. //name.php
    ) G; w+ y8 i" i# {* x: Y; W
  2. require_once './1.php';
    $ L+ |  {0 @8 Z" Z7 K

  3. 1 u6 h2 V2 t0 g( u" W, H3 r
  4. new Person();     //输出 I am one!;
    # |" V7 E' [$ m2 t) F! D4 s
  5. new \Person(); //输出 I am one!;
复制代码
! p1 s- q' P6 ?* s3 C, [' O5 z
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    % T9 I6 R; a  q5 `. f. R, K
  2. require_once './1.php';8 M, E2 t+ M  o% X0 u) F; t5 ?) p
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
6 ]5 k5 |( K3 S- ?, M: n
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   ) Q+ u8 N; t0 i- ?( ]
  2. namespace one;
    * `. E4 i3 }  q7 g3 u3 \: o
  3. class Person{9 W( \8 X5 e/ U* o9 B. C) h
  4.     function __construct(){
    9 v/ D! f# `/ T) n7 J. x
  5.             echo 'I am one!';
    0 A7 I" ~! B# _4 i
  6.         }
    / T) [  R5 V$ H) L) c9 m8 e
  7. }
复制代码
  1. //name.php
    & H3 s; {1 Q- h  P6 r5 D3 y' A1 k
  2. require_once './1.php';0 y3 F" ^9 d9 ~. ?+ E' U
  3. new \one\Person(); //输出 I am one!;
    " e/ a. l, U  }. ~1 S3 \
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
# B+ ^8 P" F5 Z9 o
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
" ^; C0 P8 o% X; ^. L
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。! I8 ?7 l4 I2 T# G9 x0 o
  1. //1.php   
    3 l  T; O0 }. [
  2. namespace one;" s, X* O$ [- Y  K* m/ b
  3. class Person{: }2 r/ K$ o9 }
  4.     function __construct(){
    6 u1 a8 ~8 O8 C) @9 }
  5.             echo 'I am one!';  n" J5 F  [- m/ B$ g3 n) v
  6.         }9 E9 }7 Y: e9 P* q( o1 ?
  7. }
复制代码
  1. //name.php
    : O/ J$ P/ I$ K
  2. namespace test;% A1 J7 H% }) s* \
  3. require './1.php';
    1 u9 [& b8 W+ |1 G9 N
  4. new \one\Person(); //输出 I am one!;
    0 d2 _6 R& L: D8 @8 ~! ^6 `
  5. new Person();      //这里结果会是什么呢,猜猜看
    " ?9 A9 Z% C* E+ i! s
  6. 最后一行结果报错:$ r) F- T" N1 }: R8 r8 _
  7. Fatal error:  Class 'test\Person' not found
复制代码

+ R4 ]2 @) m0 D" S( T
- B  |  D! O" m. w% l1 _
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

4 X8 X3 q# H, i2 Q0 a1 S$ K
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

5 B0 d# b/ |( l& n8 r% P2 V. |2 n
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    / d5 B) q. N, e4 v3 o
  2. namespace test;7 _0 @# m8 x3 M+ p# E% @+ a
  3. require './1.php'; 6 H# m4 a( l" s+ H" ^
  4. ' H# v: f0 I" X
  5. class Person{
    9 f* s& d5 u1 V  O, @/ M8 ?
  6.     function __construct(){5 n( B. u- c9 Z8 B/ R. ]+ h! N
  7.             echo 'I am test!';
      @. w! \/ \1 p& q
  8.         }* @  S" u- J' |. l
  9. }
    ' Y' L+ S# W" u4 R. U6 a
  10. 6 r7 }* ]6 c; `" n1 h% ^- o) A; m* y2 @% {
  11. new \one\Person(); //输出 I am one!;5 v0 X4 x  ?; W1 Q9 P" w9 H; {
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
) _9 ^/ R( }# M- q
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php' R. }( _& W& C+ C+ i* A1 Q$ T6 N7 v
  2. namespace test;
    1 q3 [2 n8 p/ u
  3. namespace one;+ H3 {( I4 O! n6 b
  4. class Person{
    0 B' ?4 _% L  \) z& i. d
  5.     function __construct(){# O$ P8 L0 f* H
  6.             echo 'I am one!';5 V. a6 E% E, l, @5 B$ J2 D
  7.         }  v* ?7 E0 H( l: q  n
  8. }
    5 A& s& I/ t! B9 q
  9. , {0 c- i8 F, r0 \2 \. g, ^- f
  10. class Person{
    ) I) _4 E# C( y: u! Y9 c+ ^) m
  11.     function __construct(){6 }% p: p  x$ {
  12.             echo 'I am test!';
    8 S$ S% b# I5 L6 D5 e
  13.         }
    ! _! I5 O2 z- H/ h) z6 L# F
  14. }
复制代码
2 q2 n- k& ~) J# T. S
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

0 A8 O' P; {4 G- V# E
看来简单的把require理解为替换,在这里行不通。
' _. D: h6 M7 t6 a: d. t0 p2 R
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
% l; ?2 Y$ r3 S  O5 j2 g+ S4 r+ G# Z2 S$ w- r
  1. //name.php& b* D, S! M- b) I7 j

  2. 6 I" p# S' ]! I4 j+ d7 z
  3. namespace test\person;
    $ m) e! M: d( k" B/ i
  4. # p2 g% g5 s4 d" K
  5. class Person{
    # R' L; h! s. [( u  W2 e% B  _
  6.     function __construct(){
    7 K5 [' J$ X4 w' ?% j7 W4 h7 c- p# }8 d
  7.             echo 'I am test!';
    - o" b1 i/ e7 ~
  8.         }9 l) |1 [- h5 @' |/ O! U" b- m
  9. }
    6 X, K- }* [; ?7 G9 I5 `6 F
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
8 t, j( q! r5 T; x# j+ K$ I
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
$ f6 W1 ~/ _# ~6 t7 |1 R$ q
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    0 ]1 K( F* L# L0 H  K# V9 ~  Y
  2. - O# L$ ^; a0 {* e( Q3 m, U
  3. namespace test;
    - V# D3 o+ D: z/ Q
  4. echo 'zhai14';* }9 p* Y. l- h/ p) W, X' M8 T
  5. namespace zhai;5 y: w  g0 n8 l) {0 P, h
  6. require './1.php';
复制代码

4 T1 a. T, z# a
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

: m! ~6 C8 T5 k) I. fuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。& `; h1 ]2 y1 S# M( X: ^% I
  1. //name.php* p* W  O/ R4 ^# M- ^

  2. 1 Y+ p: f4 g' F) g$ E6 j- P
  3. namespace animal\dog;
    & o$ }& M+ |+ j3 F

  4. ' ]4 i' m5 D2 b3 z( t
  5. class Life{
    : l$ J2 j# j2 O- _# b3 l! B
  6.     function __construct(){& O* u  h0 b8 R2 B5 t( ^/ _
  7.             echo 'dog life!';9 `' B* x* O3 w  f' z9 d
  8.         }
    3 r, Z( _: O, T% m
  9. }
    " X3 G* Z8 e$ E4 B* ], M

  10. , F& I9 F7 y, H% W6 ^
  11. namespace animal\cat;
    % ?* R0 D% q9 ?. Q4 r, o5 R, G
  12. $ h8 }& S: l" m6 G! j: ?2 K  ]) y
  13. class Life{
    1 E( h4 c; I1 k( i; F! f9 \7 q4 Q
  14.     function __construct(){6 ~: G9 I# {/ M" J  f, P
  15.             echo 'cat life!';
    9 b* w, Z5 C+ t3 Y% S2 T
  16.         }
      X. r( }# K- C& R) F: A
  17. }
    3 W4 |$ \. k. ?( m% p1 X
  18. 4 n$ d" ?# z$ {& D$ D! b- E( J
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间  D, Y, V4 f5 q- X8 x
  20. new \animal\dog\Life();  //A
    1 U% w9 X* {' K# n

  21. 8 J8 N% _( ?5 `% P
  22. use animal\dog;  //a- R: D, G/ h; ?* I
  23. new dog\Life();  //B
    $ ]+ H6 L" t* x; P" ~
  24. 0 T+ e0 q9 p: ^2 q3 g. ]
  25. use animal\dog as d;  //b& B0 x4 o: @$ w2 M" l
  26. new d\Life();
复制代码

4 e# k1 P$ \+ H/ x' @
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
7 O# ~% q/ ?9 U6 s4 B
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
: L  H' B) ?/ M" Z3 O
相当于
  1. use animal\dog as dog;
复制代码

. p' x: @8 d0 C. Z$ {2.namespace后面不建议加类名,但use后可以。& J; A- Q9 w) e
  1. //name.php; b1 |" {0 ?; T8 g0 \

  2. % C  n$ g3 J3 F1 Y
  3. namespace animal\dog;/ j( ~5 Q  Z: {5 {
  4. ; |) u7 U7 k* `! [  V" E  o
  5. class Life{
    $ P& @# }, y* U% F" o* w
  6.     function __construct(){8 o) `- q1 }% A" |9 d
  7.             echo 'dog life!';1 b; f8 x- D8 H( v# T! E
  8.         }& U2 t/ M: z5 N. Z2 s) i8 x
  9. }+ s6 J' z3 }' U7 M! D& x" Z, s

  10. 3 K: @; L! [6 D3 _& j0 h' F
  11. namespace animal\cat;
    8 B  D- H! M3 N7 P
  12. , e8 R7 @, ~6 j+ Q' @: M( @3 `
  13. class Life{
    . g( i# i7 J# N4 I; z
  14.     function __construct(){* h7 I) c+ z9 @
  15.             echo 'cat life!';% ^3 w! L$ O- i) z$ y
  16.         }, {9 c$ T. f, L1 v" l8 [  f6 T
  17. }1 G! K  `1 R* \/ [3 H
  18. / {1 [; ^+ ^7 c6 G7 H- @
  19. use animal\dog\Life as dog;  
    ' U3 E5 S/ X/ {, c
  20. new dog();
复制代码
+ N, Y1 w$ X9 f# W9 `* z
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
! M; @6 g  F% a# k) u- h( ~
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
      k; Z3 w) j7 r+ e: B
  2. 9 Y# v% ]5 D& N6 p8 L+ A, X
  3. namespace animal\dog;
    9 r3 }! P: B/ y
  4. * I8 e9 o+ i: f" F
  5. class Life{
    * b! ?4 y  a: I
  6.     function __construct(){" P2 L* I5 X6 Z) ~$ o+ o  J3 }
  7.             echo 'dog life!';
    ) J+ P2 s. g2 w4 R/ x
  8.         }* y3 j! s6 @$ {% l% L8 E
  9. }
    ; ]. m* z0 f* u0 ~/ r" l4 O
  10. class Dog{+ C5 b) `- c# B$ V0 G  o. o$ D
  11.     function __construct(){
    * ?2 \( D8 x' e: J$ t
  12.             echo 'dog in dog!';
    0 l% R: ^& S/ o3 j  m" w
  13.         }
    5 Y4 I& a. o6 N, Y: {
  14. }4 h* r# \5 T% N  w

  15. ( Z% p; e9 i) M) F
  16. namespace animal\cat;
    2 m9 w. |# ^, i! {  S# q" |
  17. # R. [; ^4 O; T5 b  Y
  18. // class Dog{
    * y3 Z& M! w6 c
  19. //     function __construct(){& g" D% W! L7 `5 T- o, ?
  20. //             echo 'dog in cat!';. p% P: n: b% x/ v$ ?
  21. //         }
    $ g/ ]6 T7 `9 q/ O2 P" @) B7 C
  22. // }
    - F( K' B1 [/ V4 |" d" T8 t
  23. class Life{
    + |/ N+ A# D5 y, i
  24.     function __construct(){- {  f& m. T6 `
  25.             echo 'cat life!';& p/ i$ k# d' X: _
  26.         }2 _: \$ I5 n' j" h( ~; P
  27. }/ K% k% {5 q* e. L

  28.   }- A2 F+ i( o3 V
  29. use animal\dog;  
    . E$ r" r) l  q; g. o
  30. new dog\Dog();
复制代码
6 r' j) Q; p9 T+ c' q; \
如上,使用了
  1. use animal\dog;
复制代码
6 B, R) H! V% P, h* e
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
" C% n$ g! Y2 e! \# W( f4 g
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

* S# Y2 z* o: c
: y) g& X* Z0 N# `
( v+ Z7 p: I. z2 K1 D0 Z. V# K6 P/ a2 ?0 {# M  {& i
$ P) Q. B9 V2 K2 w/ B
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 11:40 , Processed in 0.057975 second(s), 20 queries .

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