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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
0 e/ K( O- g8 b, b5 g6 g
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

0 Q; y* c" T0 I6 P; C  D. ~5 _1 Q- s3 I' q, R! [# e
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

5 v  T6 O2 e$ o7 L
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
: \! ~3 _0 @0 C# n, n& s
结合使用方法来进一步理解它的使用目的吧。

  B; Z/ P4 v+ o% H5 `, D# G: q7 a( c& O3 ^1 N- M- w' p8 O0 g
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;' |" c7 P2 ~. ^
  2. namespace One;
    2 V) C2 Z3 E' y
  3. namespace ONE;
复制代码

# u& G8 E9 h8 J3 ]
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
% s$ ^& \3 y9 O1 L- L
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ' J3 V0 L3 _8 i% }! @. K
  2. class Person{% p) ^% y6 e+ r( @* E) C
  3.     function __construct(){9 t2 K8 {% x" ^8 p2 [: S% s
  4.             echo 'I am one!';
    % y; c- V5 q' B+ W7 n$ o  X
  5.         }  F" [0 \: x3 d& V$ M/ Z
  6. }
复制代码
  1. //name.php4 u+ q" @8 b0 r) z, d
  2. require_once './1.php';/ D. h8 X: k; x- Y/ A$ c/ j$ A
  3. 8 K% N& r# p" i  |8 E
  4. new Person();     //输出 I am one!;
    # x2 r! r. r5 i6 i. C) F
  5. new \Person(); //输出 I am one!;
复制代码
( y4 l3 v7 d8 T% T( q4 B
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    # m5 R* q% v2 U  |
  2. require_once './1.php';. v8 |) T  o1 D- Q
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

( }2 q1 L! f# A# g% \9 D4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    + [3 l) x; m" M' a  g+ T
  2. namespace one;% v: T( ?2 G: D7 c- q( U% U* x% A
  3. class Person{
    ) o, ^% D# m  u. ]+ z
  4.     function __construct(){
    # B3 }5 N& }9 N3 E$ h7 ~3 g( A! B
  5.             echo 'I am one!';- a( M' V3 W! B! w, V' L
  6.         }
    ! d' v  z" C" v! X
  7. }
复制代码
  1. //name.php. G. n! h7 i5 G( f# u4 x
  2. require_once './1.php';
    ( _) y) h. r( D$ N( S
  3. new \one\Person(); //输出 I am one!;3 k* X) A$ @+ M- ^
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
3 u: l) v) t; h4 @- u- G1 ]  i
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
& x% K- Z9 ~) d
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
3 W/ }8 ~8 I" [8 I, q
  1. //1.php   
    ' r; _& F8 |& |; L7 F
  2. namespace one;
    # n' r3 O5 t3 G' `5 f
  3. class Person{
    4 ?( n! x5 o* R. D$ O/ ?6 p, V3 S
  4.     function __construct(){
    2 C. P. P& t3 Q1 g
  5.             echo 'I am one!';3 u6 j6 S3 v" [
  6.         }
    / E3 x  k1 N. r9 d$ N4 h- a
  7. }
复制代码
  1. //name.php
    * d4 f" Z4 H' o' d% s6 v
  2. namespace test;. q" i6 q5 v% O/ f) @
  3. require './1.php';
    7 i2 K' E: [2 n2 p; \1 [- w6 B$ ~- p
  4. new \one\Person(); //输出 I am one!;9 J: V! ]+ K. O& m! E9 s0 a' F
  5. new Person();      //这里结果会是什么呢,猜猜看
    ' X6 a( C" l" h# H% J: _- K; j
  6. 最后一行结果报错:& |: J/ {8 f& W& _
  7. Fatal error:  Class 'test\Person' not found
复制代码
  X& }6 t% k0 E* L3 b

4 s; a1 a( w; J* P* d4 N! m首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
7 u' u" [1 ?+ d6 K. o5 u6 u4 t& O
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

, M9 x+ I- h) {
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    0 `* _! _& O2 y# Z/ B
  2. namespace test;
    % Z% U5 `, C- |
  3. require './1.php'; 7 v7 }( E) l6 W
  4. ; h* x6 R( C# H, `  ]5 f
  5. class Person{% R% x" S- b- ?  {- U1 i
  6.     function __construct(){
    . y/ m! i$ K0 C' L
  7.             echo 'I am test!';
    ! C$ l. }% k4 X/ o5 ~! n
  8.         }5 q; s9 P" m6 m' x5 u7 _% x- u5 h
  9. }
    * n1 g. C3 c5 ?8 U; F" c9 t
  10. 1 J$ y: x0 f9 a# i) A. P; Q
  11. new \one\Person(); //输出 I am one!;, i) ]" V- K( w# H+ W
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

6 d, B7 `" j) S( x
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    8 O, k" P5 C- E8 N: W
  2. namespace test;. K" r2 V' F5 v' S" ^" F
  3. namespace one;
    : l( |' A  |) j1 r$ i) }
  4. class Person{
    3 A4 \3 I- k' v2 c
  5.     function __construct(){
    9 l6 k6 b5 o7 ~
  6.             echo 'I am one!';* g) q! H9 Z# Z9 l; W
  7.         }
    8 g" `( i! v8 q0 A( q
  8. }* M1 P6 O( `+ F- O2 b5 [" C, R8 J

  9. % L7 j& o5 v* S8 a  V
  10. class Person{% Q6 A, W$ ]" W# u. p
  11.     function __construct(){, p8 Y2 U- X/ s
  12.             echo 'I am test!';
    * G; w- M( N4 e: J; k# {1 b7 B- x
  13.         }1 S' U+ D# d- S
  14. }
复制代码

/ i7 L- S* E1 S* b: S
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
# J4 l: l/ ?, i6 j- L( _6 {
看来简单的把require理解为替换,在这里行不通。

; i- z7 W* N0 }6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。* q6 T* }* V/ b/ d/ t
  1. //name.php; k7 I/ b2 ]) E/ q- Y  }& ?2 R

  2. 9 N) c& r; h  N( c) B( u3 e' h
  3. namespace test\person;' h; V' \- G; f

  4. # d$ d, v# L" _7 ?
  5. class Person{
    , b! ?1 b1 d% p9 ^" [% }
  6.     function __construct(){
    % O- R; K( F, K: {6 N
  7.             echo 'I am test!';- n0 n6 E4 o9 h& P
  8.         }$ }6 U! ^- P5 D( R, z% L
  9. }
    $ g" }5 ^+ z1 E8 t1 p
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

$ _2 y2 a5 D1 Q5 C( z
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

; A3 L/ v/ U% z% \% I# [7 u" I. I7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    8 \/ z0 E0 q7 P7 X$ }) Q8 v" r

  2. * S5 E- h* E% ?- h' `) J  O( T7 l" t1 t
  3. namespace test;
    - W5 y7 W5 b, b# b5 B; L9 U2 S
  4. echo 'zhai14';: O4 l5 l8 r3 a6 j
  5. namespace zhai;* P4 T0 O7 t5 \! |$ B& f  h! K
  6. require './1.php';
复制代码
) W- h; ^& d, v& Z0 t2 F6 k  F8 {
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

# }9 b( `6 z% O5 F" o. Duse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。8 a% i. |# ]0 K
  1. //name.php, l1 l" i; ?: J
  2. ( u$ y* D6 ?; G9 D) h6 u
  3. namespace animal\dog;7 P8 L& X, t, D
  4. 6 [: z2 b7 l/ ]7 W2 }2 J% l
  5. class Life{
    & P! t7 S% p: n
  6.     function __construct(){" H! p4 k6 C7 L- E1 A4 \
  7.             echo 'dog life!';1 o1 ~! G% z4 q9 J3 h
  8.         }- O; {& o5 S5 T$ b1 {6 p
  9. }! ~  G4 H4 y  I+ a% G1 @/ [2 b% P3 L

  10. ' Q% X- Q0 v$ Y1 ]) v
  11. namespace animal\cat;
    2 [* {4 {5 K0 k  z% j
  12. 5 L3 {2 G* S  j, p* Y
  13. class Life{
    & J* @" t, r5 v3 C
  14.     function __construct(){
    . W$ U& V+ K3 S8 T8 F7 C
  15.             echo 'cat life!';
    - {: T+ I% d, ?* P
  16.         }! @: h5 ]3 L' n$ x5 `# C9 |/ W
  17. }
    + |/ D+ J, Q9 }, s; `+ j

  18. % J0 I6 ^% Q$ R* g; t
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间/ j: ?7 X9 V' i3 D
  20. new \animal\dog\Life();  //A6 ~, V  O& V  [/ M" y0 ~

  21. 0 {0 G- n/ n7 D
  22. use animal\dog;  //a
    - b6 @; l& _' \$ W
  23. new dog\Life();  //B8 ^9 V7 p) ~7 `& ?7 F/ E

  24. $ O1 ]4 \! k  V) K
  25. use animal\dog as d;  //b2 p# L& q. [# R7 I4 |4 J! V* G8 \
  26. new d\Life();
复制代码
7 Z7 Y: l# f1 [% o6 F3 r* a9 Q
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
9 ?5 n% W/ S! S) E) p
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

5 d+ V# @) {4 ?: n3 ?% |
相当于
  1. use animal\dog as dog;
复制代码

- y; J* }$ o* T8 n7 {2.namespace后面不建议加类名,但use后可以。
: Y7 G1 E2 @$ O4 c  ^
  1. //name.php
    4 ^/ k+ n& B$ D0 {/ K# ~
  2. 1 M0 \; G6 @' N8 v$ G2 W2 C/ s
  3. namespace animal\dog;$ j/ h) K; `3 `$ k1 o

  4. & `; _) E( a' n9 A  A3 @0 i
  5. class Life{" ]0 U9 F, E2 l9 t" r
  6.     function __construct(){4 S# {; L  B; N# o1 Z2 ]
  7.             echo 'dog life!';
    ) H0 D) f7 U% l) X
  8.         }
    8 \) H5 G( ?6 c- L5 b5 Z/ J
  9. }
    ; S4 i7 t# g3 s

  10. 7 |4 ]/ T4 T8 T0 M5 |& `
  11. namespace animal\cat;
    : s5 A( T7 a/ X. q$ E. ^
  12. ' t2 I1 t! V7 F$ L" }$ w: B0 P' F
  13. class Life{
    3 E+ ?6 s. l. T, a
  14.     function __construct(){
    0 `- N& E# y0 @$ [
  15.             echo 'cat life!';/ _. q, k9 ~# u9 m  c! B& k+ H
  16.         }  C2 L2 n7 c: D% @
  17. }5 J( d# g9 `8 I, I2 T

  18. . [( c+ t4 H2 v  F+ ^1 P# A
  19. use animal\dog\Life as dog;  
    0 W1 ]6 `# D) m: ~7 O& Z
  20. new dog();
复制代码

8 m" p! y4 N$ b4 ]
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
/ i1 m* e& ], S& D8 @/ ]: X- e* e4 B
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php: y( C  |7 o# r! q( V) n8 v. s
  2. ' z) ]: {* o* q# I' x& f2 Z
  3. namespace animal\dog;7 P7 k! _9 w9 F: ]8 a

  4. - |5 |) P8 }; v' o9 j
  5. class Life{$ E* D; O# `" e5 o; s/ E
  6.     function __construct(){  S! a4 f$ s' k' L
  7.             echo 'dog life!';1 a0 O  }7 S1 W9 u$ B5 G/ ^# P
  8.         }
    2 |4 L7 V( H3 j
  9. }
    # ~0 ?: K4 p8 B. M$ e
  10. class Dog{
    & X$ [. V1 w" H4 n
  11.     function __construct(){
    3 w) p/ M) P- J
  12.             echo 'dog in dog!';3 e1 U8 I7 }6 E6 f$ ^6 y0 L
  13.         }/ Q6 n4 E( K- {% u9 p4 o
  14. }" I# m) j2 t. o

  15. 6 C# b8 K" U$ L+ Y3 u! W
  16. namespace animal\cat;3 R+ l6 c+ E' b& b. B, S4 S

  17. 2 o2 d7 K5 S: C% |. ~6 \; b
  18. // class Dog{; x+ {% }" \, n; n+ u
  19. //     function __construct(){
    9 }: Z6 N% o5 S# K( `
  20. //             echo 'dog in cat!';+ H0 g' }3 y- B: _) r! i$ P; ?/ u
  21. //         }
    ! j- e" `& p1 D2 O, u6 h
  22. // }
    . p6 C( l. j6 s6 a# ^9 `
  23. class Life{
    ! k# i7 j4 W$ j- v/ S' _! W7 y
  24.     function __construct(){3 _8 g) p0 v1 @2 s, n) r
  25.             echo 'cat life!';
    + b4 i& G* `0 `' H
  26.         }
    2 r7 w$ I$ n# y1 s; e/ `. l* p( B
  27. }
    2 ~7 ?/ @5 b9 Q2 A, \3 Y$ \+ B/ g

  28. " w  R  d, }7 y, x" m- Z
  29. use animal\dog;  9 |. s5 j7 I  u. E
  30. new dog\Dog();
复制代码
7 I! T" K% R4 t' d/ g
如上,使用了
  1. use animal\dog;
复制代码
6 V  O1 v5 r/ f1 \
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

- b1 u  [8 r- g7 H# P- X* s$ Y4 r
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
/ ]7 j1 v; F/ b
4 o0 V# h0 B% d. n0 `

, A7 B- N! s$ E3 t- v3 o& x4 Z  |
% j/ A# [. ]/ D
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-17 16:06 , Processed in 0.055031 second(s), 19 queries .

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