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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

7 Y0 M  q2 }  H, t2 N
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

, |; S4 [8 T! u+ d$ y: x
4 E* X3 o2 F' N1 K  h使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

7 z8 ]# f0 ~8 Y2 k& y
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
2 Q- N! N& d7 `; o2 d
结合使用方法来进一步理解它的使用目的吧。

5 b8 J5 K. i* Y( @1 E4 A+ A$ ^$ @+ `
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;# u& ]2 R1 ?+ H. L
  2. namespace One;" s7 S2 k! V: l# v7 R
  3. namespace ONE;
复制代码

* \7 Y" X8 n; [8 _5 ^
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

( R. U0 l9 o* v, F2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    : O: \2 ^" E8 R! [* m) O
  2. class Person{- `# l' M2 B6 ]8 S2 T1 e; G
  3.     function __construct(){
    ! E0 W" r/ k' \# @+ F1 E
  4.             echo 'I am one!';9 A2 ^+ d0 H; x' [) `
  5.         }6 C& Z  |" p' O1 G8 \( t6 Z
  6. }
复制代码
  1. //name.php; u7 H5 b4 K1 n( I0 L+ h
  2. require_once './1.php';6 F- o# U3 d! c; @9 m

  3. % r$ t/ Q& n1 Y  Y
  4. new Person();     //输出 I am one!;
    & ^& O0 Q' W6 i: f9 ?+ s
  5. new \Person(); //输出 I am one!;
复制代码

% }: l! K' Y1 W3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php/ }% [, q2 i: @) _! m$ z; J6 S! O
  2. require_once './1.php';! m+ y3 e# V. t/ k
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

# |4 K0 J; n; a4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   ( I: m# u3 M7 x% G# x6 H! @; L6 p
  2. namespace one;6 m5 t+ J% T' L/ n9 H* r
  3. class Person{
    1 z/ c% `/ r# b4 x' q
  4.     function __construct(){% r0 B# v0 v/ O; y: w; f% `" A
  5.             echo 'I am one!';
    * ]7 V% J! w* `; r  V
  6.         }, F' @" C' q( f% V0 }1 X6 ^
  7. }
复制代码
  1. //name.php. h* I# i$ D* k3 Z3 N  Z. k
  2. require_once './1.php';4 m) I0 r" }0 s6 j, L
  3. new \one\Person(); //输出 I am one!;
    ! D$ D1 W- d" x/ T% m: Q
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
, J! Y9 `" u1 ]& o6 q: E% [
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

7 l& j& J6 @# o, H! R' Y- }5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
' H1 {* s7 `9 |$ Z: ~, t
  1. //1.php   ; O; E( a& q- c; H
  2. namespace one;& H5 [/ S: \, g. l4 t' R+ m
  3. class Person{( j8 I& J2 z, n$ j: Y! g0 j
  4.     function __construct(){
    " q4 L# C+ i2 p  g
  5.             echo 'I am one!';; z3 @8 d& V- q+ a  q7 X
  6.         }- V1 D7 U4 a# L" m- e4 P
  7. }
复制代码
  1. //name.php
    0 S* |8 |+ b5 l$ S. ^
  2. namespace test;
    - B5 }2 h9 W9 P- C+ C
  3. require './1.php'; : g% ]" \4 [" d9 w  C$ Q: ]
  4. new \one\Person(); //输出 I am one!;
    0 Y2 J& j: L2 H: t' V/ W' D
  5. new Person();      //这里结果会是什么呢,猜猜看1 @, m% c# L  y  S* x+ f
  6. 最后一行结果报错:& k( F: l  ]. i
  7. Fatal error:  Class 'test\Person' not found
复制代码
' F( y4 {7 e0 B% ^* ]0 b6 _

" [; _* m8 _2 n$ S0 b6 A1 D9 W+ u首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
3 L! f3 }0 t, l9 k
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

2 _5 W2 M" v5 \! o
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php. r( A; j7 m# |8 s# `+ {$ _/ n
  2. namespace test;$ M) l# N$ s% ^) S6 j' [0 T
  3. require './1.php';
    3 R. U6 }2 {9 }: b) h. e2 H3 Q! L
  4. , ?; I9 Q/ @$ \6 y% R2 h
  5. class Person{
    ' `; P" x4 P' H2 S" C% Q6 p& T+ x
  6.     function __construct(){
    1 V2 d$ D0 A# W- O
  7.             echo 'I am test!';
    $ S4 P3 ?$ C3 K' b, x" H
  8.         }4 J# ^0 j" M8 E% H
  9. }; B8 r: {* g) y. M/ m  b
  10. . n! c6 `/ B& h% y
  11. new \one\Person(); //输出 I am one!;7 p" S4 A4 d- h: c$ @2 W
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
8 ]/ z6 d! b) @' l! G8 m
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    ' X! Y6 j& @! Q$ [. I5 m6 [  g
  2. namespace test;
    & G1 h3 \, N7 b' `/ m6 U
  3. namespace one;" ]$ E2 G0 x! G9 q' E
  4. class Person{
    0 ~# j& {6 t# `& E2 F
  5.     function __construct(){
    9 B) t$ Q7 j& k( N. ~6 q1 K
  6.             echo 'I am one!';4 f. j5 p/ E+ g) Y1 n
  7.         }
    + Z; F4 x; b! x( @+ g, g3 Q7 t
  8. }' R0 s4 y# Q$ S# q7 R' C* o" U0 U

  9. . ]! K4 K# y) h3 E) D! c) r5 c
  10. class Person{
    8 T3 Z9 C2 B& ]# j
  11.     function __construct(){8 F5 O; e; X: |; ^* ~2 U
  12.             echo 'I am test!';% K6 I; j3 L: G+ r" a7 R& E
  13.         }
    / R! y1 K& X, C( A
  14. }
复制代码
" ?5 t2 ]0 D/ K3 H$ M* m
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
- _4 m. H% g; Q* B  B% P  ^
看来简单的把require理解为替换,在这里行不通。
" |# n- L  z( X- c/ V5 r" ]
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" h5 K/ A3 q' I* _2 f) k; Q
  1. //name.php& n; X1 |/ a6 \* @2 z4 d+ M
  2. ) d/ T  A; f& t& S3 z5 Y3 R1 H
  3. namespace test\person;, Z& u5 a9 k9 h5 o
  4. # b* b' c3 K" X9 K3 y: H
  5. class Person{( D6 q% c2 y; w  a  R5 o
  6.     function __construct(){! d: _5 S2 y0 f" ~5 S! v4 D9 E
  7.             echo 'I am test!';
    2 X6 i% {( d$ ^2 Y0 C& ^& D
  8.         }
      F2 [& q" ^: j' i
  9. }" b( F' @6 K% u0 @  s$ m
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
. Q6 w' k; {) E" y0 I
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
" p. t- i) e  ?/ z" x5 j% X, J0 h
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    0 l) J4 |+ N; I- z

  2. + }* F" y/ L- J4 @5 `
  3. namespace test;
    7 B' S: X3 h1 y, o
  4. echo 'zhai14';
    ) Y) M$ q" r& q& l) r
  5. namespace zhai;
    0 G1 r! e2 s7 `$ ^9 ^/ `/ g! d
  6. require './1.php';
复制代码
2 h$ ]$ G% J6 f5 L
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
. ^( z& `( j5 G0 _3 _& j
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
0 f0 a/ {2 \1 t; c% U" l
  1. //name.php
    ( p1 W' a3 f) y
  2. 0 L. |: A0 W7 s* q) q
  3. namespace animal\dog;
    % A% B. O! r7 l+ n; k

  4. ; c: X2 H6 I! p) r
  5. class Life{
    + {# d1 S+ P; b3 f- M& x/ y
  6.     function __construct(){
    3 I1 n, x4 ?7 F0 e0 y
  7.             echo 'dog life!';: J: w' t! h1 {1 }$ Q6 X
  8.         }
      x; ^: p4 R4 E9 M
  9. }
    ) E2 ]* |5 b+ S

  10. * g  V+ E& `/ _3 I% B( o/ w% Z& c
  11. namespace animal\cat;
    / \9 Z2 o, P" V7 f3 S

  12. # {- w- U6 G9 q) s& e! [: w
  13. class Life{4 X. B& p, D! n. g
  14.     function __construct(){) Q& F3 S8 }5 W6 a( A: [; c
  15.             echo 'cat life!';2 P7 \( W; V3 Y0 T
  16.         }4 N; D6 d' g. ]( J" |/ L9 ]/ a
  17. }
    0 I; c( L7 l# ^/ K: m) o) d
  18. $ S: ]1 V7 _8 y
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间8 ^) R4 {2 R( V& R2 K4 {
  20. new \animal\dog\Life();  //A
    / E) t8 C" r8 i3 S0 g2 l1 l4 V* L
  21.   A. x- M& i- I" s5 Y6 J
  22. use animal\dog;  //a# S, Z! ~0 ^' j; t0 V
  23. new dog\Life();  //B4 J8 A1 ?4 T5 j, |& D* v

  24. - s/ X, c# ~* \4 I: J
  25. use animal\dog as d;  //b8 T5 x# D" w' M6 ]
  26. new d\Life();
复制代码

8 U) Q! W0 V" \) |' l/ n
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
$ U+ F( z# G/ p( ]( {
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
8 H) |2 [( d( k  b+ |
相当于
  1. use animal\dog as dog;
复制代码
% ]4 n/ X' r. V( h9 Y! s
2.namespace后面不建议加类名,但use后可以。2 a5 M; G) Z  ]. E7 J
  1. //name.php
    ) p# P# D9 h% c* x
  2. 1 r  \$ K( ]7 @: P5 d# J
  3. namespace animal\dog;
    - N) z8 K9 C. b4 B
  4. 7 F- b0 ?* d9 V7 r/ H+ }
  5. class Life{! G2 q! q6 a5 [8 k- N  _
  6.     function __construct(){% B& v5 s& l. F' Z: [8 o
  7.             echo 'dog life!';
    " P8 k/ N7 c3 U7 s
  8.         }  S- K9 Y! o  P: K- x& }4 y
  9. }
    + q4 {5 B/ h& `4 u! j

  10. ) u7 Q! N( A, {$ S3 V) q1 I4 l
  11. namespace animal\cat;
    # m6 ^$ s! m7 t. U' Z

  12. - `9 S/ }  v) B
  13. class Life{" e% o' @2 m$ w1 @
  14.     function __construct(){0 _: q  O) E& K; Q  e/ L
  15.             echo 'cat life!';2 |# J3 a- g  r) }  K" L$ L
  16.         }
    4 l) f7 h8 U, o6 D5 Z; Z, f  [
  17. }1 Y/ {( [! Y$ H4 e3 d# H
  18.   C: R2 g' q) d( g- v4 r
  19. use animal\dog\Life as dog;  
    ( B) [2 v" W, C) c) p5 k
  20. new dog();
复制代码
. F% j) C+ ^7 U
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

, p, Z+ m3 t- M1 x4 N
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php5 ?& a+ G0 Y1 S9 X- k' [
  2. ) W1 ?: ]" G$ L! u: {# ]" W* d
  3. namespace animal\dog;0 D" y4 l2 O! u  b3 ~: k
  4. ' p) E& ~! I/ ~$ S" y9 t  o
  5. class Life{
    0 u- e/ T: L: _% `. T; @1 m
  6.     function __construct(){
    # s' f( S: I6 e6 ~' D8 T. K7 j; ?
  7.             echo 'dog life!';
    : M6 }4 X' ^  G2 G) O
  8.         }
    ) v+ E/ v: K5 }) O1 F7 e+ @
  9. }
      m+ m8 @3 f; k( \6 L: E' S
  10. class Dog{+ r# ~1 z! I! R9 x% j
  11.     function __construct(){& }5 N) @6 ]& w% E
  12.             echo 'dog in dog!';
    + U4 _. |) `3 Q
  13.         }
    " Z$ |, P8 L( E
  14. }
    5 I  b- s1 [7 |* u  W9 {

  15. 0 i" v8 C# ~  {- S( p
  16. namespace animal\cat;' f0 l0 G5 R  ^2 l5 a& q* L

  17. , B5 W- x$ V4 O& _' J; E) k
  18. // class Dog{" {+ d. f3 ]1 n4 b5 K
  19. //     function __construct(){
    4 G0 p& v+ I! G9 q! t. R. ?" S1 `
  20. //             echo 'dog in cat!';
    ) ^& y! T5 ]) t' t- b% I
  21. //         }
      A6 ?: b! k2 E# K4 Y
  22. // }
    1 Y- f$ N0 S4 V* w! }) h7 ~1 ~
  23. class Life{
    8 V( s! a' r1 F; L4 X
  24.     function __construct(){
    : w7 O9 C" P+ M' M7 O# l
  25.             echo 'cat life!';5 A7 h& k  e/ ~- t: k
  26.         }1 A) M) S$ k7 d% l# L  K9 w
  27. }
    5 C: p) i' C$ T
  28. 2 h% I1 S6 W4 n  B* p: r6 w4 G4 Z
  29. use animal\dog;  8 i$ x5 T1 e% D" e/ k2 ]
  30. new dog\Dog();
复制代码
0 \- y+ [: J& G  d% d/ }- e% o
如上,使用了
  1. use animal\dog;
复制代码
; [# l$ n* Y' I& e$ D+ m) K
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

" B2 g; Q; C$ u, x' J9 [
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
1 \: o! R3 w  k& B2 t

+ @, I/ D: N9 m& k4 _4 F6 X  \6 v0 t% H& M- K0 D
, a/ w% o% _8 d1 d9 Z
' f8 G0 \* e, H! x! [# v% D
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-4-20 19:08 , Processed in 0.119349 second(s), 21 queries .

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