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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

: F/ L9 q8 U2 h0 x4 V! D
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
* P$ B( X; m3 h+ t% Y
( `( L2 i$ I: ^
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

6 F! s- Z) y! B+ P结合使用方法来进一步理解它的使用目的吧。

$ P' \- Y; H' f0 W0 o5 g+ y; ]# [1 b  l" s1 v: x
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    4 ]9 W! ^+ {' r
  2. namespace One;5 Q. m8 y$ H, @6 l. b4 A
  3. namespace ONE;
复制代码
0 ]: l! o2 g9 Q3 b
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

) D) `2 x4 n; O& B$ j2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php     i2 A) f+ A/ n. g
  2. class Person{
    ; k8 o1 z* Y, x
  3.     function __construct(){7 Y, ]- A) C  T0 b+ D/ \$ }& @2 _* `
  4.             echo 'I am one!';5 i4 S1 U$ [# s' |# D, e
  5.         }, L7 O* i; O2 f6 M
  6. }
复制代码
  1. //name.php
    % ], c1 A0 H' m
  2. require_once './1.php';
    ( h; @1 F$ _, v7 x2 d+ l. H
  3. ' g. w1 O. N! n! [8 |
  4. new Person();     //输出 I am one!;
    7 O. k/ H: `% u; E% i1 Y
  5. new \Person(); //输出 I am one!;
复制代码
4 ?: k" q7 r( M
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php2 V% Y) L" ~1 n; t' m$ @
  2. require_once './1.php';# Z7 m9 E2 A; `2 O8 A0 P7 x
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
3 u# {" r- C- d8 X
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    / v9 T- q3 |$ t" c; D5 }
  2. namespace one;' w! d# S7 V$ s/ \& J8 f" ^
  3. class Person{
    # `1 M1 }1 j' J- |
  4.     function __construct(){" J' e# O7 R. W, M& w
  5.             echo 'I am one!';9 ~7 f, |" P! w
  6.         }
    ; @# _) Z8 I1 f
  7. }
复制代码
  1. //name.php* \7 J2 _$ E2 G/ ?( s' T3 N
  2. require_once './1.php';) d8 V* F% G/ Q5 z
  3. new \one\Person(); //输出 I am one!;
    , i7 N8 G5 j/ W0 Q: j; t9 ^
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
1 Q# w( f/ C! t6 H' K
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
) H  u3 q! M+ x) r9 y' e( ~
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
. Y# ]7 G# s' @
  1. //1.php   5 c* }- J+ S- p* |2 c, P* K
  2. namespace one;9 Z$ K) w( a1 g4 E
  3. class Person{
    , M' h  v. g3 b0 u$ \  E+ D9 P
  4.     function __construct(){
    , E& y5 ?% n1 Y
  5.             echo 'I am one!';3 u2 y6 Z2 c# m$ z3 c% ]* Q+ u$ E9 V
  6.         }* `! s' n/ p8 \
  7. }
复制代码
  1. //name.php7 o# Z* O# c0 ?/ b* t
  2. namespace test;- J& S3 Z( }7 t% h  x
  3. require './1.php';
    3 V+ q- B' q/ A+ w: P, U+ W3 P. W
  4. new \one\Person(); //输出 I am one!;* d7 B. i1 H# L  E% V
  5. new Person();      //这里结果会是什么呢,猜猜看* M0 j* {& N# j+ [
  6. 最后一行结果报错:: _6 x( }+ m( T) O
  7. Fatal error:  Class 'test\Person' not found
复制代码

" r; r, ^+ u2 v$ j
/ [- S9 Y/ E8 X9 d4 I$ C$ S4 C: W
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
* K. o- \# @! z( ]$ P2 ^1 A
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

& y; m9 y4 \9 [: D2 z8 }! P5 w
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php* V* A  |) B$ D4 X8 }" L5 w
  2. namespace test;
    $ b5 z# A: r. Z
  3. require './1.php';
    ; }/ Q# R( k: D( J' Q% j  U
  4.   m2 `: E, g/ p2 I' q. p
  5. class Person{
    , w) S9 j( M1 ]# l8 Y
  6.     function __construct(){4 h. a" |! v% t' L
  7.             echo 'I am test!';$ w- ~& b4 p) H* Q2 \  s
  8.         }
    ! x0 x: w$ u$ j1 K6 G# E, j4 j
  9. }
    ! j9 L8 i! w9 i. f
  10. . B' z; M  W/ F5 G( _) a! s
  11. new \one\Person(); //输出 I am one!;: b" W. ]7 {' }* @
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

9 [. G/ r3 E7 @/ L' M( Y. f/ x$ r# J
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php7 p) g8 j3 u" Z7 e7 C
  2. namespace test;0 L& M- X# G% }9 n2 U
  3. namespace one;% d/ V( ]* y2 U% E
  4. class Person{# s- G2 e" Y. d
  5.     function __construct(){
    0 G& n9 d* y. F* g
  6.             echo 'I am one!';
    % `* @! r4 u! o& M5 z" L- k( u
  7.         }3 P! p! e# J, j3 O4 T
  8. }
    ; n0 t  t$ G, R# E( x
  9. 1 x5 O+ N9 n( T! t5 b1 a* ~
  10. class Person{
    % t: _2 P$ c: i6 ~: \
  11.     function __construct(){
    - Z9 w& Z! C5 s& A
  12.             echo 'I am test!';
    ) H$ r) V; S8 y
  13.         }
    & n6 }) B* L. V. J! U
  14. }
复制代码

2 T& @  b" Y8 t7 n
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
: A$ z! ?: L* q1 D9 x8 M
看来简单的把require理解为替换,在这里行不通。
/ b: C3 _2 b# }4 z; @4 W2 R% j
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。& s7 ^1 l1 U% v) ?1 X( T. ]! X
  1. //name.php
    9 V2 {) u( D& L8 |! w9 ?8 l
  2. 0 T4 }# M6 W2 f% ~/ M3 C- Z6 [
  3. namespace test\person;2 e  G2 U. I+ _. \1 P, W: O
  4. : Z; E9 b% M6 ~) ^# b( ?
  5. class Person{' r4 K; h% H( G5 f7 G
  6.     function __construct(){# [* W6 G0 l5 V; ]: W. F$ e
  7.             echo 'I am test!';
    ' p/ T! U, Q) h. C  ?& H
  8.         }
    + |$ o5 D+ o2 {+ l; W& Y
  9. }+ ~1 B3 B: i+ w
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
2 c3 q  _; G; Y7 m
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
* A! {8 c) S: f- @4 `6 D" z
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
      m6 V3 ]: Y) s4 r+ k
  2. + d. O, l2 x  h( W* s: b$ }
  3. namespace test;
    ! q- k* a1 a6 F' I
  4. echo 'zhai14';
    " h' M; B4 O. v; z
  5. namespace zhai;
    ' w) |+ i- A; Q$ q  X
  6. require './1.php';
复制代码
  u0 B' L, |- c; ]: G, q- n" J
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
/ Z" L; F' a; z, o& F9 e
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& x% I: m& {& F: P
  1. //name.php. r$ |% z5 M7 n
  2. . H4 `$ L( M8 T" x' h6 j8 }7 f
  3. namespace animal\dog;
    / Q* V/ M$ J! F9 L( A4 \3 m9 b

  4. , ?7 ~. ?7 l& c. J1 j; V' _  s; v% V
  5. class Life{! p3 O, d, _! Q
  6.     function __construct(){2 P, h9 @5 T, y
  7.             echo 'dog life!';/ c$ ]! I# P# \) w6 ~$ U  X
  8.         }
    * ^" s( k+ M5 B% f# M
  9. }. a2 ^0 o6 Z0 [
  10. ( S9 r2 m0 ^  M- T
  11. namespace animal\cat;2 E; o% I* R6 @/ v( f) P) B
  12. * i. U; U6 B: o  H" Q; z9 B
  13. class Life{0 ~4 j5 |- [9 H7 q
  14.     function __construct(){
    3 L! ~/ i7 t" u9 J: y+ l9 ^6 @
  15.             echo 'cat life!';
    - ]" \0 @% D. ?4 l& u, I6 n
  16.         }/ ^' I* g- h0 J4 f2 j: m$ D
  17. }
    1 n2 {. [% i# J# g; p4 Q6 z
  18. : m. P3 k; C$ j, s
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    ) C3 R: c8 p! Z2 z4 C! x( ]
  20. new \animal\dog\Life();  //A0 k* K' u6 x3 r) R' y0 m/ a' A

  21. ) q, B5 }8 U5 w- z
  22. use animal\dog;  //a% }' z! r6 ?! P' z) k& a
  23. new dog\Life();  //B; o: r$ z9 l: _# q2 S+ _; ?
  24. # l# G# M3 ~, A3 E, r2 g
  25. use animal\dog as d;  //b" T3 J$ S: V4 |( C* R
  26. new d\Life();
复制代码

2 Z9 v" W) g' R/ [( E' ?3 r! S
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
$ f) l' z' b% k
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

" }5 s5 u# L+ W; Y# u6 @
相当于
  1. use animal\dog as dog;
复制代码

  H; ^& |1 G% v; c4 [& z/ e2.namespace后面不建议加类名,但use后可以。* W9 a) X) b  Y/ t  g. [# l
  1. //name.php4 \* k* `4 X1 l6 v. v
  2. / ?6 }4 ~3 z0 L! w# S. V" }
  3. namespace animal\dog;  u$ X# `9 l% E' n0 k

  4. : r6 u# ?0 z* y( D
  5. class Life{1 l  ?* R) q0 d: m& ]$ n
  6.     function __construct(){
    * q( v" D, |1 l' g
  7.             echo 'dog life!';
    ( b5 G  x7 a2 b6 |1 Q6 F
  8.         }9 f$ _* q6 y: h5 f
  9. }
    2 g9 K5 [# I6 e' \2 _, D. q
  10. / g0 i: l8 P; ]" H% S4 D5 O! P
  11. namespace animal\cat;  U) {& F" r+ V' h
  12. ' i; R: `+ c' f* z( j
  13. class Life{% w5 I; y7 v& ?  H
  14.     function __construct(){# t* E0 C; p, Z2 `( t
  15.             echo 'cat life!';2 S: L; u$ N: T
  16.         }
    ! l) Y8 f9 ?6 X4 R( Q8 x0 ^2 W. [/ Z
  17. }
    . n& H6 ?! A  x

  18. - _# _9 X, O8 j! Y. N( `2 v  \; O9 q0 T
  19. use animal\dog\Life as dog;  
    $ p$ S7 S: Z$ B# f. W
  20. new dog();
复制代码
6 `. b- T2 B; U& s9 C' Q: S5 d
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

) `" n9 P( F* z3 H* m0 |; E/ P
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php+ p5 Y- j# a6 Z' E9 Q7 Y
  2. + [$ c5 T- X" h% @
  3. namespace animal\dog;9 A) z8 v  c: H  P

  4. & S2 O6 J, M! R  |% C) A; t0 @
  5. class Life{: p  h( e# b$ J* u5 }
  6.     function __construct(){
    " Q# T1 o! X% E' `
  7.             echo 'dog life!';
    ! x. c) Z7 G" P9 p( b
  8.         }
    9 V7 J1 |' @( R' p/ X* m
  9. }2 P( t$ ]1 }# }
  10. class Dog{: {. I9 k4 f3 L7 }  @( d( L
  11.     function __construct(){5 _7 K  h, P7 n5 P0 Q
  12.             echo 'dog in dog!';
      c$ @; [. p& m( I  h/ x
  13.         }" U- z% m! P1 @* W. W* J( R, b; P
  14. }
    7 s4 q( W8 w6 ]* }9 ~

  15. : O8 e; a* G; l3 I/ E. Z' d
  16. namespace animal\cat;
    & }! A# c& _7 N  Z
  17. + j1 r/ a8 I" [9 T- p6 ]
  18. // class Dog{
    " V4 \' x9 V2 \* Y
  19. //     function __construct(){
    - ~% `/ x* a& |9 s
  20. //             echo 'dog in cat!';
    0 Y" p4 {9 \" x) y$ O
  21. //         }2 ?) S* ~& w" }. v: P/ w
  22. // }
    4 h) J  e2 ?7 U* z7 ^% ]+ p
  23. class Life{
    . L: E' ]3 E$ D" T# T1 F
  24.     function __construct(){. i9 D  G% m% M) w3 I! @0 `
  25.             echo 'cat life!';6 h+ K3 h2 n' a/ E
  26.         }& O0 w1 {0 `- a: e  ~7 s
  27. }5 ^! V8 Z- W7 K5 g+ k

  28. 0 K$ z. j- Z) n3 C2 R7 ]2 p
  29. use animal\dog;  
    + ]8 q5 C3 }9 X6 F2 U
  30. new dog\Dog();
复制代码

& `. v# E; |0 S0 k$ o* {
如上,使用了
  1. use animal\dog;
复制代码
! a' U6 u5 v! {; C- c; P
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
3 m( F5 k/ u, |! C$ z
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

: v0 z6 D% k0 F3 }* v. x! c  I1 R: M; F+ C' d9 n
1 Z4 ^% |7 g. M& M: A
" S" Q% ~- c2 t

* F1 k0 s- ?3 R' g2 ]: _- |9 _: [
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 10:10 , Processed in 0.060252 second(s), 20 queries .

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