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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

3 f' p+ d5 u9 ^* [- ~
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
" Z9 I8 c: A: T, D& Y. y, _7 r
" T0 H+ |$ I4 n, |1 g* I& b
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
9 g, u+ E' W: m! n. u! K0 j
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

' d) A! W$ q; \, i. ]0 y结合使用方法来进一步理解它的使用目的吧。
- f, r2 E/ V' r3 |* `+ x
5 q7 t' p3 V% P0 z1 `; z% {, g
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;6 U3 Q! b; N0 ]" c: p" w0 g
  2. namespace One;" C. g5 G, s+ P' C
  3. namespace ONE;
复制代码
& N, D. h5 d' O5 T. K9 W4 `
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
8 Q7 x8 c8 {9 B( M
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    + c3 ^4 l8 a! f4 t2 z) p
  2. class Person{
    : N5 `! g8 `# y3 e2 ?2 v! U6 F9 r4 D9 u+ r
  3.     function __construct(){6 ~( k$ S% M* s  I5 m+ {
  4.             echo 'I am one!';- p( ?- k) t+ e7 f" m
  5.         }& U8 ~, m  g* v
  6. }
复制代码
  1. //name.php$ N! Q' ^! k: ?4 `: R0 m! d
  2. require_once './1.php';
    " W. w) M5 ?3 V5 V- @- |/ Q
  3. " Z$ s/ x& e8 e) L! u" y$ a: {* {
  4. new Person();     //输出 I am one!;2 k& H- D, v+ O* G
  5. new \Person(); //输出 I am one!;
复制代码
' }5 A  [* T& O9 L. i8 X1 Q
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    ; h8 C  @* E$ @6 l- J
  2. require_once './1.php';& f# X* U- e1 d4 s$ a
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
" ^, ~8 H9 M- r9 r3 s' I# _. S; x/ K
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    & g7 x- `# x2 f
  2. namespace one;$ i) l3 N. R8 _
  3. class Person{0 ^( b3 q/ e6 L  B; i
  4.     function __construct(){
    ) n$ N" i; Z3 o- k, @7 ]
  5.             echo 'I am one!';
    " y2 p8 O! s: \, z0 z. X
  6.         }6 X3 f0 {" E- D1 g; J3 `8 `
  7. }
复制代码
  1. //name.php
    8 A+ }! r6 S) V2 F& k/ s
  2. require_once './1.php';
    # q' ]; p8 @9 @0 j* i5 v/ A
  3. new \one\Person(); //输出 I am one!;7 x" O- `' W4 v, I. W0 e
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
% L# E4 B% S( C9 E+ A/ P0 Y5 t
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

" f) J( V( P/ s6 |) P5 K5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
0 k, I" F, x; X* M" H
  1. //1.php   $ N" Y- I2 `& u% z$ v& ^
  2. namespace one;( b: B, J/ R4 B+ |
  3. class Person{. J# L1 f+ J* X: @
  4.     function __construct(){/ v: J. i9 u# |* w$ v
  5.             echo 'I am one!';4 k( ^8 s5 y3 {
  6.         }; Q; N2 f0 Y; r, c, `
  7. }
复制代码
  1. //name.php
    . }' R8 i- o; A$ X$ L$ y
  2. namespace test;
    : B2 S! i/ l1 @. j
  3. require './1.php';
    6 P+ `' \5 g8 r& F$ ^
  4. new \one\Person(); //输出 I am one!;
    9 R9 _: R' o  @+ Z/ |, `* W# F% h: D
  5. new Person();      //这里结果会是什么呢,猜猜看- g5 A) P, s) i: Z
  6. 最后一行结果报错:
    / \; {/ `! F9 ?% a1 H' A( C
  7. Fatal error:  Class 'test\Person' not found
复制代码

4 ~9 L' w5 q3 w# R  R) f9 F

+ ^2 M, y; C6 h+ E3 p首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
" S6 e1 b/ K8 a8 E( u: c! M
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

% g# [) ~4 ]- ^0 J
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    . x% I  ?( |" E' F
  2. namespace test;2 x4 E" l  u7 t$ o& T: p
  3. require './1.php';
    ( g$ B& [& n" c& l9 \

  4. # x0 Y8 K2 c& G6 {: s
  5. class Person{' a% f! y% {, F3 ^% O+ }
  6.     function __construct(){' [8 z% |, B2 x7 G( F' \8 ]
  7.             echo 'I am test!';
    2 H' n9 L/ n" K7 e, R5 A- ?6 M
  8.         }
    . K7 j3 ^3 d& J, L
  9. }
    " t5 `0 f! F: v
  10. 2 E5 F/ ^/ l/ ~6 f
  11. new \one\Person(); //输出 I am one!;
    $ d/ V8 v/ a, P& |1 ]) h# {# i& N
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

) y  v. R; w9 ?: G: r9 g; V
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    $ k, E8 h, J" Q5 ], m& c7 r
  2. namespace test;
    4 T/ ]0 u5 ^; K7 i) z) I3 V
  3. namespace one;* E9 y0 ^- D; J# }! w5 p
  4. class Person{
    2 [8 v) `0 p9 C6 n9 p$ i- N8 s1 ^
  5.     function __construct(){( f" ], D( b/ a0 l
  6.             echo 'I am one!';
    : i/ T# I6 w+ c8 s% T* f
  7.         }
    & {- p8 l# t  {; o9 O; M! a$ [
  8. }
    - w  ~- w+ D- `8 n
  9. 4 m. @5 [& T& J7 O% L
  10. class Person{
    ( [2 }7 ^$ v+ }  O
  11.     function __construct(){# ^; K- \+ Q9 L) B3 }
  12.             echo 'I am test!';
    ! m6 l  N/ e, B, u* l4 X" M
  13.         }) \3 x2 ]8 p8 B4 B* X6 w" Y
  14. }
复制代码
6 o% H" c) N3 t2 X1 p% Q
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
" k+ O6 J' }. E2 v0 U# y
看来简单的把require理解为替换,在这里行不通。
) z/ ~5 R/ }) b2 @% e! p
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
  c5 J: b4 l' l: P" S% u
  1. //name.php; f9 E1 c5 @6 d

  2. ; u/ A0 ^. g% A
  3. namespace test\person;
    2 V: B8 C" @! L6 D4 M: ?8 n5 I
  4. ; `" W+ {+ q/ W( K* R* @4 H
  5. class Person{: H  _0 E+ D0 G/ [6 J" N: j
  6.     function __construct(){
    9 e/ l0 ^) Y6 U9 `
  7.             echo 'I am test!';" N4 Z. n# `* w+ e" u) P2 b
  8.         }* |$ \; U9 O8 k( I7 u) ?, U- ^: o
  9. }
    9 `) j& ~* g6 `2 D% A" ?
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

2 [+ k0 R% S0 Z7 R" j7 f
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
+ Z6 w# o$ @" w# {/ ]# o! y
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    " p$ Q3 x: |! A9 }* e: `8 d% W* {

  2. 9 L3 C3 j. s. R/ H6 c
  3. namespace test;
    7 L, A& Y+ d; r
  4. echo 'zhai14';4 D* Z! V! d& m. ^+ y4 k
  5. namespace zhai;1 t& K- y, p4 e9 l. D, Y
  6. require './1.php';
复制代码
% B3 r, y; H8 N
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

9 k( e9 F& R$ I; u4 Nuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。$ u& b/ F& K; N( @6 `
  1. //name.php; ?5 ]! A; ~- ]# ?9 J
  2. : g% |. M+ K" z6 x
  3. namespace animal\dog;. S% U+ [' o. u2 E3 H8 A  i7 q, N2 @4 d

  4. , {4 S0 V' q& E, q  c9 r
  5. class Life{
    - h+ ]' k3 f& l0 c7 b5 [
  6.     function __construct(){
      V, U) _7 e$ r3 a
  7.             echo 'dog life!';
    ( a4 I$ W& K' C+ D6 F" B
  8.         }2 p' [9 Q# H: w+ M
  9. }
    ' _' r1 M4 y* [: o" B( v0 o

  10. % r" p+ h$ }$ y% b
  11. namespace animal\cat;
    / l: K" [2 a6 O; l% n, X  U# O

  12. 0 x# W1 M# |3 k( }9 L* U: i
  13. class Life{
    ; c' V# T  K5 H; K* C8 a2 k
  14.     function __construct(){
    $ K: y; ~. m+ u& _
  15.             echo 'cat life!';0 N1 E' G5 z- S; Z  x" ]( \
  16.         }; }( j8 v6 B. v2 O
  17. }  _. m2 i0 U+ }+ O+ {" d5 X9 U
  18. 2 O9 l& g" W) l7 P1 v5 S
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    7 H/ ]; `. Z+ \1 W
  20. new \animal\dog\Life();  //A
    9 A% p* `; R9 j. d8 e

  21. 9 m) ]: k# ~: d1 f; Z
  22. use animal\dog;  //a
    " u0 W8 K- Q5 g5 A
  23. new dog\Life();  //B
    . X. Y2 z3 w9 Z8 [( }, Q, L

  24. 1 p, _1 C5 S* {5 h8 O
  25. use animal\dog as d;  //b6 `/ w" z+ I8 m: R8 d1 h5 J5 P; C
  26. new d\Life();
复制代码
- [, y! j8 I5 P' v/ @2 R
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
* {, \0 ^, }, U! u7 n3 J- t' k$ s
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
- o6 }/ h& B% l1 k3 T+ P2 ^3 E
相当于
  1. use animal\dog as dog;
复制代码
# M0 ]/ ~6 ~) \& Z* T
2.namespace后面不建议加类名,但use后可以。
. l4 S6 m8 }6 J) _3 y8 J
  1. //name.php" q0 g& U2 \# Z' Z  c

  2. 4 U- O8 ]4 [( g: \
  3. namespace animal\dog;+ ^6 g4 F. ~3 y: ~- B' u! C

  4. - D+ v! \0 n/ x' X. S8 U
  5. class Life{0 i5 Q3 [- h) j, _& o; @2 M; Y
  6.     function __construct(){
    - s3 o& f/ a! K5 C) e% Z" @2 I
  7.             echo 'dog life!';
    0 c9 l/ K& H% ^8 h7 B! [; D5 l2 }
  8.         }
    % E2 R- _1 \2 l. i3 l) w
  9. }. {* ]6 }) t- ]) a' i3 f& T9 Y( ?

  10. 6 d1 j) H# I# Z& x
  11. namespace animal\cat;
    8 h/ q) D5 A+ h$ U3 ~6 R- {
  12. % n( @! e: y) R" A4 W! j
  13. class Life{
    . C  Z! T% R9 `
  14.     function __construct(){
    5 S' m  ?" \$ {& z0 h6 p! ?
  15.             echo 'cat life!';
    % ?' V9 B5 v- Z% b- A
  16.         }
    6 l  {, E- \* n8 A
  17. }
    9 l0 b: A! w+ Y2 h' w/ @

  18. " U% D( T: I7 S
  19. use animal\dog\Life as dog;  1 O6 G: q4 B. j
  20. new dog();
复制代码

6 n6 F, r1 n& Z2 f1 t( W! v
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

' q$ H' ^5 m) p
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php4 H1 e# N) |- x" l5 \5 C* x
  2. + a6 n) N5 _1 y+ V$ v2 _: Y' \. i) b
  3. namespace animal\dog;
    , K- I' |2 u# ]; z$ s) Q: I
  4. ( J8 d. n8 B, v9 D. \: |3 A
  5. class Life{! Z" j' u' J; Q/ V9 O3 ~/ J
  6.     function __construct(){5 E- O& i9 x# }2 v
  7.             echo 'dog life!';4 G' i* V' G' b$ ^0 T% {6 B
  8.         }! Q6 \1 q5 s; t2 ?, G4 o
  9. }
    ! Q  L- [* E  m* ]' i
  10. class Dog{# X( w( u1 u. J1 {1 `3 B, N6 G
  11.     function __construct(){
    * r$ B0 u- c% n" {) m4 p8 v
  12.             echo 'dog in dog!';% l0 q) n$ w2 h$ B% v
  13.         }
    & `6 }; R4 G" W
  14. }9 W  G; l8 G, g4 ~
  15. 3 K/ _3 f. ~* @+ Q/ M4 I+ ^* a" J
  16. namespace animal\cat;
    , w. f8 c$ S; Z& I: F
  17. / S9 p- E- Y( V+ B# Y4 a; ]4 x$ l) m! Q' D
  18. // class Dog{# t2 H0 C2 d; c5 O/ h4 O) y
  19. //     function __construct(){. ^! B. ?4 o0 n
  20. //             echo 'dog in cat!';" o2 |+ H3 t2 q! Z* q0 N
  21. //         }6 I+ p/ V+ H( G0 R9 j* J: \/ i
  22. // }
    ) U( {+ f- O2 m% x2 ~: B1 Y, w
  23. class Life{/ Y7 {0 m, Z) U- U0 h6 n5 a7 x
  24.     function __construct(){
    , Z& k; y  t; w. h6 d3 `
  25.             echo 'cat life!';; B. I8 [, Z0 g! k* x! d% M' L, n
  26.         }
    2 a+ G4 s2 j* S" s! o7 J- b
  27. }
    : R( {4 s" |7 ], _& }

  28. ; v/ M) P2 ?" {  Q1 {
  29. use animal\dog;  
    $ C9 E! ]2 f6 G3 Q
  30. new dog\Dog();
复制代码
& w. J" g& o( i# E8 |( L) z* L
如上,使用了
  1. use animal\dog;
复制代码
- F/ u+ r: [8 t: n: ~0 g! Z9 o
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
3 |1 |* ~& b, b* @) f6 Y) W
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

: ?3 E5 E$ |) V; [( S( l
# U! b/ L' E0 y7 ?
, s8 u6 q6 y3 V7 p7 J) n) z  c7 @0 F
+ G" g9 G$ N9 {
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-20 00:00 , Processed in 0.146360 second(s), 27 queries .

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