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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
/ K% p1 j! L) s: E) [
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
) I! \' T+ v" c# O' z: Q3 g1 L
. Q* t) Y9 F& t$ f' Q- U5 @9 s& H
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
8 q: ]* S! Q' x* r& C& v. m0 M
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

: z0 R( Z+ E  G/ S% D- F6 O结合使用方法来进一步理解它的使用目的吧。
5 q1 B. _  t: s. U

' U5 `0 Y+ x1 y, a1 W  }namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;) c  o7 {* a# M! q9 c8 d
  2. namespace One;1 E7 s' i' @; e! M% T7 ~" m7 w+ M8 L
  3. namespace ONE;
复制代码

. U! Y) @7 b7 F: n- @
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

% E# |: v+ V* E) ~% O# i9 ^) Z2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    * z) U7 I3 B& E0 _* \. y0 N
  2. class Person{4 N/ Z2 F  s# p* K; {' Y
  3.     function __construct(){4 }. L' S! m5 J+ t; l" J
  4.             echo 'I am one!';
    8 G5 G8 h% m, T- }4 ]) Z4 w
  5.         }
    ' w0 V4 ]  z  T- W
  6. }
复制代码
  1. //name.php( m# D2 v3 i& K7 _2 y
  2. require_once './1.php';9 B* @) Y# a9 z/ U, ^

  3. 8 K% P5 j( d+ @# {
  4. new Person();     //输出 I am one!;: d2 G* D4 Z- r0 w8 J# Q
  5. new \Person(); //输出 I am one!;
复制代码
$ n9 \0 ^( |. D4 p! B& y' G' m
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php, x1 \% j- j- r( L
  2. require_once './1.php';
    8 V) f$ Y* j/ T; b# f* j& Y+ r
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

' A6 e% l# U% ^* ^- `4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    " r+ c- t3 _0 d
  2. namespace one;
    9 [( q' x" O  ~- _! M
  3. class Person{
    " K: |( t& q3 T% k) S0 K3 C( t
  4.     function __construct(){/ g4 m( H/ p9 d1 z' Q
  5.             echo 'I am one!';
    1 U- Z- `3 |- O7 p& ?
  6.         }
    7 v! |0 e* _% Q$ K7 h1 O
  7. }
复制代码
  1. //name.php
    , r' k; K* l/ `
  2. require_once './1.php';
    / x6 J0 h, T& y9 I% d
  3. new \one\Person(); //输出 I am one!;! G- R8 U; R9 @5 a0 y& ^: L
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
6 a: O, E2 W+ R; z
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
- J& N5 Z- t: _2 [5 v$ G$ w; k
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。1 o5 j( v( H- X9 `" y
  1. //1.php   5 U  P3 M2 l& f) ~( N7 k: \
  2. namespace one;
    - l0 B" q- @& W/ o' H( f+ {
  3. class Person{
    " h8 a% S  s2 U6 {2 a  d8 {
  4.     function __construct(){
    ! ^/ ]: J$ V  F& p4 E
  5.             echo 'I am one!';% b; E0 J8 k4 P' N- G, x
  6.         }1 _" i9 K, L+ m4 D; p! E4 t
  7. }
复制代码
  1. //name.php3 i& d$ R/ n4 E; U
  2. namespace test;7 d7 G" _& {7 h3 k1 x, I8 I1 ?
  3. require './1.php';
    2 x) r1 I& Z( f
  4. new \one\Person(); //输出 I am one!;$ k6 }" I$ b& N  |
  5. new Person();      //这里结果会是什么呢,猜猜看4 O* p2 i! G' E/ {' h% i# k
  6. 最后一行结果报错:
    ! Q$ `, A$ m$ d; |  p0 f
  7. Fatal error:  Class 'test\Person' not found
复制代码

- g4 M5 @( j7 F1 x8 |) A  |
8 Y5 q% D' m( @- P) K+ h
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
8 c2 J' }! i4 L& q3 Y7 [: U
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
2 y' p3 ~4 l6 U; B
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    & b7 n; \( j2 B9 k
  2. namespace test;0 j: p2 W; O2 m3 X: z! }6 o
  3. require './1.php'; ( t# F- r& c* t) V/ \2 x" P
  4. , C3 _  c: y8 n+ V: \: E
  5. class Person{
    9 X/ {' e1 b( p$ p5 [
  6.     function __construct(){
    " B* Z9 a9 O, k8 o2 I9 ^
  7.             echo 'I am test!';; k# y3 O# t5 s+ ~- x9 o' a
  8.         }9 C; \% I) q6 _4 X+ h- B; v6 L4 b' M
  9. }- |  H9 ~* ~* g0 _' W

  10. ! l, L3 n4 }2 T7 A$ i
  11. new \one\Person(); //输出 I am one!;- g# r& U# S6 N5 \: B/ U- i
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

0 z& O8 h% \; {: r7 j' g7 Q
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    - Q0 {/ C* @" u2 X4 R8 ~1 ~
  2. namespace test;5 \/ e, r9 \* t
  3. namespace one;3 |- X0 G' f% B# F" R
  4. class Person{7 p" O& T; W1 y  x+ |/ C
  5.     function __construct(){
    % Y# s+ I6 [0 N8 H0 ?
  6.             echo 'I am one!';
    : Q  q4 L( |8 n  L  p
  7.         }
    1 W8 L1 b' `1 J* R1 M+ w2 \
  8. }
    . c( g: ^( ]' V3 W9 c
  9. 9 H! b. l; }9 X* C9 A
  10. class Person{
    ) A8 t- C: I. i0 C
  11.     function __construct(){
    % t( ]" }! L+ V: b' t% K3 X% K4 n
  12.             echo 'I am test!';
    6 G$ U  f6 M7 [$ D* _0 c
  13.         }! }. v- U( _! f: d
  14. }
复制代码

: |5 ^7 Z) y3 Y: i
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
8 m! R: f/ J. z8 p$ l: ?
看来简单的把require理解为替换,在这里行不通。

* `% a( d, F8 ^- Y* F" A  K; T6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
0 n2 L* z5 n3 ?$ @( Y0 z( u/ _- b7 t! ?
  1. //name.php
    6 B9 f4 a( y" O3 A7 U" J2 H! [

  2. 9 P8 R+ f1 a# g7 P+ p
  3. namespace test\person;, Z4 f+ L3 V$ @) t0 c$ r; [
  4. & s) V: X: B1 J& u' e! \3 [
  5. class Person{
    9 Z8 V' n' `- h% Y- g0 `" m( C% A  A
  6.     function __construct(){
    % R) b0 {. i+ J; n9 U7 s3 l9 {
  7.             echo 'I am test!';
    ( i% ~8 Q! w. g# X7 `
  8.         }
    : P3 o; k4 l9 Y
  9. }
    % S* ^6 p% z0 k% C6 n* E+ r) }( @
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

  ?+ l, @3 u$ m4 l, \
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

9 Y4 ^: f  e3 X4 F7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    3 B5 C5 `! n) _7 W: Y" e
  2. 0 V; s1 v% Q, \! B: E' w
  3. namespace test;3 A3 A6 _* n: |' v
  4. echo 'zhai14';3 l. H: E7 a: }1 t! }7 J: T5 g/ |
  5. namespace zhai;/ ?! z+ x7 n# J6 R- q
  6. require './1.php';
复制代码

6 N' X1 k/ f  A* s: R* m" g* R
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

, I' }( f; l3 t/ P& j% Y0 [use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。  X5 ^* C- v1 _7 \$ G
  1. //name.php
    * Q" Q$ W# I5 O7 m0 x( g8 `
  2. 8 J( s3 s' O" R
  3. namespace animal\dog;2 m, @' {4 k" a; j: [+ Z

  4. 6 w# `9 `7 d) v/ r& V% c% G: ^; h
  5. class Life{7 `6 [  v: L3 `! |- G9 P" ^) l
  6.     function __construct(){$ c# j: L/ y# f
  7.             echo 'dog life!';" O( R/ |- a# T6 T
  8.         }$ R% e$ S$ i8 Q. U& m
  9. }
    : e# a+ Q+ ~" v, C6 }

  10. ! J. g2 h8 Z. A) J" t
  11. namespace animal\cat;
    % Z' F/ D& u5 ~* Y% W  Q
  12. & o4 ~7 c& o+ h/ _- ~' E
  13. class Life{4 I6 z6 H5 U9 O, i3 Q5 f3 h! E
  14.     function __construct(){# F5 w+ x. @9 d# r4 z8 b) g
  15.             echo 'cat life!';
    3 s! t0 d6 e$ F0 p" v
  16.         }
    2 g# t7 t! T$ N, ^
  17. }# W/ {5 ^- f. f0 k" v: m; s% j
  18. 4 X1 z. n# N: t* K1 r( h2 U
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    / Q: Q1 ?( }9 y( ?  K8 I. ~
  20. new \animal\dog\Life();  //A
    7 N& f" l* b9 X/ q# C
  21. 9 O; r. k" X* \
  22. use animal\dog;  //a" Y. h  n* |+ w! x  b5 l
  23. new dog\Life();  //B
    $ S  S8 q7 w8 K. E* U4 w: G
  24. ( V8 W. O0 B, j# s+ O5 G
  25. use animal\dog as d;  //b8 e' W& O6 \; H5 b9 E- Y
  26. new d\Life();
复制代码
8 b* l' [1 M6 J0 ^" @$ G, R
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
7 D6 L, x" m: A1 O% v+ _
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

2 d. [* e  N* W. [: i4 G) N* Q
相当于
  1. use animal\dog as dog;
复制代码

# c* ^' D+ p% k6 b8 C2.namespace后面不建议加类名,但use后可以。6 b) _+ H5 ~- j3 J; U
  1. //name.php
    ( L/ y8 U  q* M& ]0 y

  2. * q2 y) d. o( ^0 w; P
  3. namespace animal\dog;
    9 C+ `0 w) z* \- p1 i+ Z: X+ ]

  4. + l5 Y% s( p7 f0 P0 n
  5. class Life{4 F) d* v1 q8 T5 B
  6.     function __construct(){) u, u, y$ \" i8 N
  7.             echo 'dog life!';
    2 ^3 M0 b! _. z& x8 }$ F! I7 ]6 N
  8.         }1 a4 f: f$ E2 s3 C- q
  9. }6 c; l( o( k9 r
  10. 8 I; e3 E) c5 n" M) O" ~; o% r$ D
  11. namespace animal\cat;
    % |% t0 B7 ^9 C
  12. ' A8 X) H" p2 d1 E/ a
  13. class Life{/ R: ]7 }, E+ P
  14.     function __construct(){
    7 v4 H' [0 C+ X' p1 m* U. P+ r
  15.             echo 'cat life!';5 A$ \: }8 \: B
  16.         }
    8 y* a, b) e3 O* T
  17. }
    - D7 R6 j! S/ U! k
  18. * V/ e5 K2 s: _6 ~; R/ r
  19. use animal\dog\Life as dog;  . o0 I2 q  t  m( @' D
  20. new dog();
复制代码

0 a3 W% M5 B5 |& n0 F8 S  @( z
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

% K+ N5 @1 x, T6 P& A
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    9 g. U$ p$ V* b) [4 V

  2. 4 {0 a2 ~7 s) k! h/ v& G/ b+ n
  3. namespace animal\dog;; N- u9 ~" P" i3 Z3 W

  4. 2 d1 k+ V" I3 M  v8 S
  5. class Life{
    7 R# n3 Z; m; x8 E  W) D6 E5 r9 @
  6.     function __construct(){' I; J9 n) s3 ~$ E* t4 |
  7.             echo 'dog life!';0 l' _% ~1 H# o  f& ?4 H1 @
  8.         }0 m$ q' i; k5 w  q: R+ S7 ~8 z
  9. }% D! h1 T9 m8 v8 V: j5 g' r/ _/ |/ Y# `; @
  10. class Dog{9 R. Q; X9 B! R+ s7 N
  11.     function __construct(){# ^( W& ^) ?2 y+ `5 b; b
  12.             echo 'dog in dog!';; {$ c# {# |0 p' b
  13.         }
    ! t: s4 n# h; @3 f
  14. }
    4 e% |, o; s; V
  15. 7 {+ M/ b& h0 o0 v# M
  16. namespace animal\cat;
    , q  S9 ~9 t) U. `

  17. 4 I; f' A* B! r
  18. // class Dog{
    - c6 a1 o' q# _4 Q" |" I6 ^
  19. //     function __construct(){
    # @0 G5 |! |9 n( i- z
  20. //             echo 'dog in cat!';
    2 S, R- @1 Z8 x. B4 D. v- E
  21. //         }+ C+ P: r1 J, A5 [% e. o3 }
  22. // }
    " i! a( r7 h' ]# x5 O
  23. class Life{
    " q" N! }# J! `7 f' U
  24.     function __construct(){' e( Y) z- L, y3 M3 f  o
  25.             echo 'cat life!';
    4 A0 k0 [3 Z: i9 X: l# H6 a- w
  26.         }
      \- W% U2 r/ h/ a) @
  27. }
    " v9 `6 ?; A- v
  28. ( ~  ]8 x7 f' `% u; n
  29. use animal\dog;  
    * x0 B4 b9 g/ u* ]* J6 U% _
  30. new dog\Dog();
复制代码
3 {! a) m: u0 x6 w
如上,使用了
  1. use animal\dog;
复制代码

) U* k# z7 U# A
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

) O; d# \" L: o4 W: t1 [, i1 ?' f
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

3 O& k/ [* Q8 ~1 i8 c- A( q1 K
' h" e4 |! @( Q( ^/ Y% g
4 w; `7 S  g. w0 d$ Y0 [
* f# a" [5 x4 q" W2 N& c
$ n. e4 h* N- v1 ~2 ?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-17 16:08 , Processed in 0.060419 second(s), 20 queries .

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