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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

: k% ^( Q/ B& Q, o! v$ [' A$ Y' x& r3 R5 _9 f; W
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

- Q/ g- Q6 H8 l+ d+ m- e/ Z结合使用方法来进一步理解它的使用目的吧。

9 H4 n6 v9 ?( T
: X+ ^, e+ v6 j9 i7 wnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    * |, T5 J5 N2 L- h4 c
  2. namespace One;, B, s8 t+ h/ @3 ~: i. }
  3. namespace ONE;
复制代码

/ g" K0 R$ d# i- v! C6 [
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

; g9 J2 _- I1 s# \3 Q2 _1 b0 u2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   . Z% a9 i0 I# B1 B( D/ r  O: {
  2. class Person{
    $ ^: z( P. r# B0 c* B0 Q
  3.     function __construct(){
    & m$ d  a4 _$ l/ \
  4.             echo 'I am one!';$ ~0 F+ E8 p7 C" m1 A4 b( ~
  5.         }" ^( P8 f+ G  [* ~- G
  6. }
复制代码
  1. //name.php
    3 [) T7 e7 k0 n& T& C3 a
  2. require_once './1.php';% Z4 g) `: s% T3 G* T" }

  3. ) v/ b3 ~! Q7 x8 |
  4. new Person();     //输出 I am one!;
    2 o3 p6 Q  _* f  t( u; N5 f, I4 h
  5. new \Person(); //输出 I am one!;
复制代码
9 {  O! }2 j. V/ D4 A
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php% {. N' C% |1 W# ?( A( W' V
  2. require_once './1.php';  x" |# |8 E; u2 ?. o" _  J+ l
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

# v$ j' w" |: R( Z: a2 g4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   % U" h8 p' T) e! @9 R* q' T4 X7 T
  2. namespace one;
    " |! \& s/ k- w
  3. class Person{6 S# E0 W5 V/ F' m0 ]: K
  4.     function __construct(){+ x! D6 F, R' F1 u
  5.             echo 'I am one!';
    + E) r" `/ c" O4 x3 O& @$ l% f- m
  6.         }/ h$ e  i$ v: p. `' u' A& V6 Z
  7. }
复制代码
  1. //name.php% U' T( G( h: I  l
  2. require_once './1.php';
    9 p9 M4 T. O" p7 \- X" h
  3. new \one\Person(); //输出 I am one!;
    ) {9 j' J/ f! X2 o& M
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

7 V) g, ^+ @) s6 s$ g* h  ~, v
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
/ T( F" g$ [, Z9 U# R; [! ?+ |" }
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
; d! n" E" a, S( l
  1. //1.php   
    0 d9 T* `3 h6 j( M" U  ]
  2. namespace one;% Z% g) s# K0 o6 Q
  3. class Person{
    , d* I& ^, \4 z" H3 F
  4.     function __construct(){
    8 l0 k# o! n7 C2 c" L1 }6 ^4 H( H
  5.             echo 'I am one!';% [5 g& y4 H0 U! p+ M4 C
  6.         }6 r/ k, C! j% K7 p8 E" t3 F
  7. }
复制代码
  1. //name.php1 n. h) e/ d7 b3 Q
  2. namespace test;1 q* l0 n0 I, g- F' U1 l
  3. require './1.php';
    5 e0 H" e: d4 Z* e: U0 ^' J2 b
  4. new \one\Person(); //输出 I am one!;0 o% _4 M7 n4 _. u
  5. new Person();      //这里结果会是什么呢,猜猜看4 z' V" x; l: }- x
  6. 最后一行结果报错:$ ]- F7 j' e& K  G6 i; \
  7. Fatal error:  Class 'test\Person' not found
复制代码

$ p& r) O/ [* [

! j2 ^8 b- t3 x% d首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

0 a2 L, _* f$ s+ ^( n
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
0 B# @9 I6 r* n: M. @: Q1 n
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php+ E! s8 ~$ _% f" J% B, G
  2. namespace test;
    ' z* d" s8 \+ k4 r' k
  3. require './1.php';
    " ?9 |2 v: t7 `4 J, ^# J

  4. 6 T9 P- ~  q7 s5 p8 _- N- c4 x- t
  5. class Person{
    . W) E8 u, `$ {' Y
  6.     function __construct(){
    3 u8 B9 A0 L3 P
  7.             echo 'I am test!';6 q" b- `& q6 q
  8.         }
    1 R2 T+ \+ x7 \0 B" D
  9. }
    6 B" J" U" c4 U3 b  h' r1 B! t/ q
  10. / x9 G- H: P9 d. w
  11. new \one\Person(); //输出 I am one!;
    4 \. k% D5 {( C) M0 X0 B' a' j
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

; R) Z% B7 @  C2 [$ n0 w0 v0 a
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    2 @  G: E1 j1 H# A! z+ Q) p
  2. namespace test;& T/ H0 C4 m( z, u
  3. namespace one;( o! _6 \2 x6 h5 i5 J$ j1 K# e& Q
  4. class Person{
    ; a5 h" q- T) A# V6 t% B% @3 M
  5.     function __construct(){
    # T! S' r: a9 t$ a6 `& _% q
  6.             echo 'I am one!';
    3 V: \/ [( {+ {7 w
  7.         }( z5 t- N4 L- |4 |* R: }! ]7 a
  8. }
    . @6 D, v" \* Z/ g4 x" U) Y1 b4 U

  9. % E7 b( d4 n4 g( ^/ a  v
  10. class Person{
    3 c# \1 I$ t0 w: n& N, M
  11.     function __construct(){
    $ u* H* B. k+ [7 E1 e; ]' q7 X* f; [
  12.             echo 'I am test!';9 s0 y/ t5 l! C! e1 i% k- Z
  13.         }/ J8 k+ g2 ^+ L" b& j9 B- O# o$ K
  14. }
复制代码
2 c, M/ Z% y9 a( y
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
( A# B$ x+ J6 p" X( l! y/ X
看来简单的把require理解为替换,在这里行不通。

0 @6 V+ d. W  ~4 ?8 S& U/ b6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。% |5 ~- \6 Y0 g% f
  1. //name.php
      C- z$ X8 T# v- m

  2. * s6 n+ p' j( m  \) a) E
  3. namespace test\person;- |3 z0 s6 G' E' |7 `2 v
  4. $ c3 o! h5 g' Z. H
  5. class Person{
    7 ]4 k+ H  v" Y2 W0 [  L$ Y" J: J6 ^
  6.     function __construct(){
    * x- N. G& I: R
  7.             echo 'I am test!';
    3 X- B' C( Q  k7 w7 o  q* i
  8.         }7 X9 Z/ A! `0 e
  9. }
    9 F4 L% L, C# x) H9 o+ F9 D" g* f) s
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
7 J: O  H$ u( A- j
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
7 ]- m8 ]; {" w9 B
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    ! E! n8 l8 `) j4 V5 t$ }! l, A

  2. , @$ P7 D" M3 o, H7 u+ v  `& T
  3. namespace test;1 o+ S4 |: N! ]; |' Y8 w2 m
  4. echo 'zhai14';
    3 @2 |; h- w& ]; n2 [3 l
  5. namespace zhai;
    2 T) m& l5 Q. U9 p
  6. require './1.php';
复制代码
' O$ O' ]2 r' H7 F+ g
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

" K* S+ Y3 b# p6 luse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
/ j% \7 u/ V+ k: c8 c- g
  1. //name.php9 E7 n5 C7 C- ~2 q6 A4 Q  i, f

  2. 1 D2 P% v* [0 e8 ^  H
  3. namespace animal\dog;& T, O2 [1 S. i9 s1 r6 Y* `
  4. * _/ x* T/ @1 ^! D7 G- P1 w" D
  5. class Life{0 |$ S2 j' w$ X; v' s* Y7 V
  6.     function __construct(){
    3 ^' B9 i$ X5 f5 i$ c2 n& Y, f% J
  7.             echo 'dog life!';
    / M6 D  I" k' C1 h8 I% G! Z8 i
  8.         }
    + h4 o: R3 a: u" m
  9. }
    $ N. J! r7 K* P- l# V8 I6 V+ N

  10. # N7 k1 U/ K. k: m9 i
  11. namespace animal\cat;
    / P; X, U. q  |

  12. ! k( D+ k- u5 w. s7 s" `
  13. class Life{2 H5 o1 p- p' D) ~( Z! {0 g
  14.     function __construct(){
    - V, W! m0 w0 n
  15.             echo 'cat life!';
    4 E0 D* ^" v. K/ p6 c
  16.         }# O0 t- x+ C# T$ @+ w# U
  17. }
    3 a& ?" S9 p  g# W. W3 f" C

  18. + w$ `( U% u  I
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间" t" E7 d, n. `& p6 N- f
  20. new \animal\dog\Life();  //A3 i$ }; k" M) n9 i3 V7 C4 x7 k
  21. ; p( Q7 ^: {6 K2 }1 q0 r* B
  22. use animal\dog;  //a
    5 E# U  x# q7 p% F& K7 ^8 j
  23. new dog\Life();  //B
    # t$ u" x6 }5 f( z# V0 ^7 a

  24. 4 R4 Y5 ^, S& t# @9 y
  25. use animal\dog as d;  //b; l! C9 c- l2 f: n
  26. new d\Life();
复制代码

: {' x0 c% {+ l: x8 h' T
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
$ ]5 K6 a% h1 ~. d2 \9 Z$ x2 ^
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

5 M; I4 t  N, S% H
相当于
  1. use animal\dog as dog;
复制代码
& U' ]+ P1 U: c) ^1 d% P8 H) y% u
2.namespace后面不建议加类名,但use后可以。
) q6 @# c* e- h3 k9 O
  1. //name.php
    - Z- P2 f' v: }% M! C
  2. 2 `  e4 C% ~# W. H0 p
  3. namespace animal\dog;2 N) ~6 V2 W' {6 }

  4. % Q# H7 y8 Q& w( R; f) E& a
  5. class Life{
    0 j4 G3 S' u- \% q% ?) C1 x* i
  6.     function __construct(){& S8 R1 X& k% _+ X9 O
  7.             echo 'dog life!';
    - j/ a& ?; \: m. ~+ q% b/ ~
  8.         }
    + D4 _9 M4 z0 ?0 M6 x& L
  9. }
    ' H- Y0 o5 q( c
  10. ' U/ T1 K3 H3 k' s% e) Q
  11. namespace animal\cat;
    / y3 e- Q" g" a' P

  12. 3 A+ Q) y1 ~2 F0 Q8 e, H  o$ |; D
  13. class Life{* ], _- f& L" N4 S2 R
  14.     function __construct(){) _- Z7 ]6 o6 q; J. z
  15.             echo 'cat life!';
    8 D( h3 M  [+ F  @6 r. ~
  16.         }
    , v/ t. n! U* r5 ]( R: x4 p
  17. }
    5 E6 F7 q$ I, T3 W
  18. " W, b" Y1 h6 K. V3 a9 E6 |9 |
  19. use animal\dog\Life as dog;  8 G! a' b) I0 T* u- `
  20. new dog();
复制代码

% b  @) O. m0 j
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
/ e# c6 P' y  I9 h" l
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php" a9 }+ z$ [# [3 y( c

  2. 7 ], t  s: \$ [2 T
  3. namespace animal\dog;0 z: p+ H4 Y9 k/ p  K. H: e  }

  4. / o, z. f# O5 {% J  j
  5. class Life{
    1 [  P" K/ \# \0 L4 Y/ [
  6.     function __construct(){, I7 |) z2 z7 X) `
  7.             echo 'dog life!';0 d: c8 p2 G. F2 B( N( ]$ F
  8.         }: h( z4 ^6 g6 g& ?1 X& t$ H5 C
  9. }0 Z8 g0 n/ y$ T& ]5 |
  10. class Dog{
    & |+ V* u$ b  o& E* J% x
  11.     function __construct(){
    ' f- O% U/ l6 l0 ~$ n: ~
  12.             echo 'dog in dog!';: }& w2 i! l1 p/ q' T8 N0 N, z
  13.         }: G9 X4 E5 e1 v) p$ r$ P
  14. }
    , H8 t* a, ]- e: H" }& J
  15. ) `, }  ^; Q9 w
  16. namespace animal\cat;: X* z4 H7 @, @, s4 a, i3 e

  17.   h2 v' j  T" I) h& a1 Z
  18. // class Dog{
      ?3 h8 Y7 w3 J% Z
  19. //     function __construct(){
    # r7 Z( Y1 m& f1 t
  20. //             echo 'dog in cat!';1 l9 I5 q1 Y  E1 O6 ^/ Q
  21. //         }2 i8 s+ ~/ q6 Q! k' h% z
  22. // }( Z7 X4 G( Q, I5 C1 A
  23. class Life{! D2 g5 y$ I: Z7 C6 H: f
  24.     function __construct(){) F' Z7 n1 ?. {
  25.             echo 'cat life!';, S8 c% q0 J6 O9 G; U6 P. B5 o
  26.         }0 }6 x2 h' X  a8 }! f
  27. }  l& ?6 W# M) V* J3 Q" y' P
  28. : [% j6 i0 F1 J5 M
  29. use animal\dog;  . x2 ]; r! o4 t, C7 @$ C
  30. new dog\Dog();
复制代码

" N& ?$ l, [+ V' H' w) S- {* T
如上,使用了
  1. use animal\dog;
复制代码
  E* t+ E# Z7 p4 X" z
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
, t9 x5 r4 e: U1 [9 _
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
# F5 Y! A: E. _! V, D- h

% T, j) M: C, c9 B3 z) R1 ^: ?4 ^
2 f+ n! }: ]6 p) d, G' u& G
; q5 n2 @* R0 Q3 G) J5 B
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-4-28 16:28 , Processed in 0.121900 second(s), 19 queries .

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