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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

+ l: w& ~: M! y! ], G% B! r+ C& u' t$ \% Z6 T
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
+ \1 K1 z/ ?& ]( R! g
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

+ f9 r9 y4 [! v; h: B结合使用方法来进一步理解它的使用目的吧。

6 S, ~! A$ ?7 b* ^  P5 O8 C* h9 a$ L" i8 P# U, _
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    9 Z/ P' u$ u' U1 M2 Q
  2. namespace One;
    - `, W0 ^% t9 Z! `+ w
  3. namespace ONE;
复制代码
/ z) w' P/ |4 E. R; E9 R0 }1 ^: s
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

# |: P0 b. g! \* X' O2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   / t: X: X/ }1 j. O! N& K' V
  2. class Person{
    / q/ |1 A5 J) j  f
  3.     function __construct(){# V# {/ L& w2 Q' {' {2 A2 N) S
  4.             echo 'I am one!';
    2 P, t- ]( X7 Z: Y( d
  5.         }
    ) b2 b8 [$ s! Z" @0 I8 L
  6. }
复制代码
  1. //name.php
    0 Y, |2 B4 T# {
  2. require_once './1.php';+ \/ m1 |" m8 E( M  l3 {! w( i4 b
  3. & [5 J+ @0 p0 a* x9 o
  4. new Person();     //输出 I am one!;. M, `. B7 Q( g1 n" H) {
  5. new \Person(); //输出 I am one!;
复制代码
* p- g' v3 t3 [( i0 }( |
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php  E4 v) b  J4 e8 u+ M
  2. require_once './1.php';
    1 S; Q, [9 ^9 {" o! r+ [
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
: A- l8 F* c5 V  D/ W, t
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   & a4 L* A# _6 s+ Y! }1 }
  2. namespace one;- a  q6 [" }% b' ~& ^
  3. class Person{, z; v: G2 @$ o
  4.     function __construct(){; ^, X) x3 r5 e: t4 r7 O" Z# }
  5.             echo 'I am one!';
      `* N0 _0 F/ l9 n
  6.         }2 M4 w" _% I6 ~4 W
  7. }
复制代码
  1. //name.php" {# w6 e; o- G8 J+ w! J4 {
  2. require_once './1.php';; z  G3 Z5 |/ w+ a3 Z
  3. new \one\Person(); //输出 I am one!;8 {3 G; ^+ O! h1 [
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

5 u1 t7 }/ j/ ]$ ?
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
0 q& h' f2 N5 n1 I, d$ g5 _
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
' {- b% A* u( }4 C1 J3 c! t
  1. //1.php   
    + ?) d( G4 I; G" }
  2. namespace one;" I( M) U2 ?6 E
  3. class Person{  {8 U, ]+ H2 v0 I+ y/ j% M' z
  4.     function __construct(){
    ) U9 u; F* S# Z7 I! [9 Q2 v, [* D' _
  5.             echo 'I am one!';
    ; b- w: R; d8 `' l
  6.         }
    6 ~; S2 _& K$ c: K) Q6 T- ]- a
  7. }
复制代码
  1. //name.php. u5 Y4 G" k; c4 O4 g9 n5 g" H
  2. namespace test;
    2 W' I1 @) D6 K) U, q" {! `
  3. require './1.php';
    , d& O4 g) j: ]& L
  4. new \one\Person(); //输出 I am one!;
    & X7 m8 S' r' \2 l% C& [% W
  5. new Person();      //这里结果会是什么呢,猜猜看
    6 _7 A/ i! c0 e" C, Z4 Y# G
  6. 最后一行结果报错:( Y* O% [4 u# q$ ^3 [5 e2 e) J
  7. Fatal error:  Class 'test\Person' not found
复制代码

0 i2 H4 k3 a1 F. Z( M$ P+ S

, s+ O5 W2 h# [首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
5 g& f. A) n% ], Q
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
1 N# F4 a& j$ l" U
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    / f1 _; \9 q" h" O( Z
  2. namespace test;$ i& A, w2 i8 T! g9 V
  3. require './1.php'; ' f9 Z$ Q3 B9 w

  4. 8 I9 w7 Q3 U$ f( m- P5 \  Q. F, {
  5. class Person{
    . m" H* Z4 D5 k* i
  6.     function __construct(){. r7 t! W6 \9 _3 I" [# g
  7.             echo 'I am test!';* ?  b- i4 B* g) o. B8 {
  8.         }) v, Y/ @" ]# Y: [' t& Y; N3 \
  9. }7 L3 i" y% z( _3 o* i
  10. 4 v( }2 E. V+ g5 E3 p" L4 _
  11. new \one\Person(); //输出 I am one!;
    8 T3 g9 c& H! \0 \3 ^" [
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
' F; a# E/ S7 f4 w& o3 x* e& R5 B
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    2 v; y) `6 \! ^- V6 A
  2. namespace test;! ^1 Y  h7 U/ f$ r& v6 v2 J
  3. namespace one;
    * ]# {/ n. k$ k7 a$ v* E: y* c
  4. class Person{  d2 b1 }( I7 _( x
  5.     function __construct(){/ y8 x" h" B; l8 L+ I6 `
  6.             echo 'I am one!';# q2 n# b* w) a/ D
  7.         }
    # Y. H8 r( o" W0 {
  8. }
    ) a' j2 M) Z2 e/ v) m6 d( Q; n' S
  9. & _( q- q" _* m; f9 I. e
  10. class Person{
    ' \3 X5 U3 @* @6 d5 b3 c
  11.     function __construct(){9 n2 c% E0 _& V$ M
  12.             echo 'I am test!';! v+ R  V% y% p' e
  13.         }
    & n. {( z/ x% N7 ~& N8 r8 U
  14. }
复制代码

* m; n2 z$ S* a# d- h
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

- l# z' x" C$ [( E  u1 l; J
看来简单的把require理解为替换,在这里行不通。

( o# _! g: k/ o6 @3 ?2 N6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
8 J1 w7 x) p- O2 d7 Y* l7 p
  1. //name.php! L/ G7 O% c% L7 h% L* l  x, _; Y
  2. . u+ m0 |$ {  V" Q4 A5 |
  3. namespace test\person;
    . p( Q$ ]( d5 {+ N* D
  4. # G- T1 N6 S! r/ d
  5. class Person{+ `" z% V8 K5 T' S
  6.     function __construct(){
    + q7 y8 s. @* s% r
  7.             echo 'I am test!';
    * T+ O: P& Y9 L; U% Z
  8.         }8 {$ M1 ?2 u, o+ G% ^
  9. }. z1 d2 m+ f0 b$ u0 G
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
* \, i$ J( h; o3 R2 h! b* l$ R1 `
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
) r/ \" S2 q5 ]
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    . Z; O& Y- F2 k+ x- A( g
  2. ' D2 s# ]0 R- s& d: ]
  3. namespace test;. ~3 ]: L4 J$ x. T7 e7 V
  4. echo 'zhai14';
      K% A* i0 I' _) f5 d
  5. namespace zhai;
    0 u% O$ f: r! T3 M/ x- E, K9 j% _
  6. require './1.php';
复制代码

2 E! H- X3 O% N5 u% s6 g
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
( Q: D3 O3 }6 Y* u- t/ K7 x* Q. _: p. X
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
" r0 [6 x! m6 m0 w) @! V
  1. //name.php
    ' P1 y7 e5 B$ e7 N

  2. 6 b- A7 S1 U* `/ V" H
  3. namespace animal\dog;
    0 B7 J  W# e$ ]- z- b8 {& s
  4. 9 a0 F% W, |: R# H5 l& k
  5. class Life{
    8 d; A: f0 H) [& g) K* g2 l. ^
  6.     function __construct(){
      S% R. V- ?) a7 ?$ B
  7.             echo 'dog life!';
    ; j+ C9 o5 o, }3 G3 f* L: {
  8.         }  y; x& F! ~- }+ _: N# P* m
  9. }
      m6 d/ w/ P  r* P
  10. + Y5 H2 {$ E# Y* g: P
  11. namespace animal\cat;# a& r* V, B5 h6 N6 k2 K: C
  12. $ h( B8 J+ ~& Z- y9 M! z$ k2 d
  13. class Life{
    , y. v' X4 V: M" W8 l% X5 Z
  14.     function __construct(){
    2 p1 S. G) ~* ~' d- o) C
  15.             echo 'cat life!';# m& s$ k, h# ~
  16.         }
    7 R* n. R/ U$ L7 ^
  17. }
    ! ~* k& ?3 n& G6 x7 u* y
  18. 0 `/ P* ~* d* m9 J  y3 `
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    ; A7 P) H8 s0 _+ l
  20. new \animal\dog\Life();  //A
    1 N# z- u4 M! z- M" _

  21. 4 H' Y* u  r- Y
  22. use animal\dog;  //a
    % r4 Z" Y2 Z- [+ `4 R0 R5 f
  23. new dog\Life();  //B7 P: r4 U8 h+ H$ l# B6 u8 J

  24. 2 T0 s& [- M" a1 X3 c
  25. use animal\dog as d;  //b
    * P# T' x: V8 `$ e7 g
  26. new d\Life();
复制代码

) m# D; s8 H* L2 m5 S
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
- c/ n+ G* Y# X: N: W3 I0 O8 s
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
+ ]% k- G" f  J
相当于
  1. use animal\dog as dog;
复制代码

, i9 |7 a8 [+ c/ e' i5 x2.namespace后面不建议加类名,但use后可以。/ ~' s2 [" s7 s- `7 F: @
  1. //name.php4 |& w) c2 q) ^( U- n$ p7 C  l

  2. : H) r9 b* w+ f6 ~% {. \
  3. namespace animal\dog;6 V5 C3 @, l7 B  ~, Z: t, j

  4. / C" B5 x6 @  Q2 T+ z: K2 e
  5. class Life{- z4 J2 @, ~9 c/ G9 _
  6.     function __construct(){1 t7 Y! o( A1 C9 L, c: O4 X
  7.             echo 'dog life!';
    . ]8 v+ Z3 b5 I/ N( J
  8.         }9 H4 R# j2 Q; V
  9. }6 Z6 h9 l8 {8 _5 p

  10. ( F; d& r  B2 [7 l, w( O; j& t
  11. namespace animal\cat;- H' O  o, P1 g" ^) B* l; A% A

  12. 1 J$ D4 O4 e3 U8 M+ f
  13. class Life{5 S3 ?& }5 T* E6 R
  14.     function __construct(){
    / P( U  |( K) D$ O8 {5 k5 j: L
  15.             echo 'cat life!';" o1 G% c" t6 e2 a+ o6 T- u
  16.         }
      _. c. C0 I* D
  17. }
    - ?$ Y+ N) _5 S$ b7 k/ _$ n1 \
  18. 1 `6 s2 f. x7 [
  19. use animal\dog\Life as dog;  
    6 n1 S% ^. I, x4 ~. V" `" Y1 G
  20. new dog();
复制代码
* |6 x" d  s2 c) `
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

; A7 j2 O: D3 I- A/ f  G
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    0 P+ J0 M3 @3 w' a0 v
  2. / l3 f* j2 x: b
  3. namespace animal\dog;
    : e4 |8 G. [2 d6 o
  4. 1 B' |, T' l( v  S
  5. class Life{
    * t/ n! j  B: Z# j8 C3 X
  6.     function __construct(){
    % \1 n+ l* Z: l% g& G
  7.             echo 'dog life!';/ i6 M/ P" g$ x; Q
  8.         }; Q8 v6 v0 d/ |7 m5 B+ S6 Z2 Y
  9. }
      O' x3 \9 i. m" W9 M
  10. class Dog{
    + F' E  ^6 Y1 d$ z; n& @. p# E# V
  11.     function __construct(){: A# J4 K5 m; C+ J- w+ G% Y2 x
  12.             echo 'dog in dog!';3 o9 q. A, V, v# a! L! ]# U
  13.         }
    9 m5 b" \& [* i7 w
  14. }
    / K6 |5 a7 ?" W" _# }  {2 j
  15. " z3 f4 }3 h/ o+ p" u* n/ H
  16. namespace animal\cat;
    - H; D; C# }& q, T% V2 f" X, A, V3 e

  17. 0 x6 f; I" f2 A& v5 g6 t- a+ O7 |
  18. // class Dog{
    . e/ N' J: y6 @  A" \: m4 E% l7 m
  19. //     function __construct(){
    % g4 }6 Z  p3 ~# K' V, R. R
  20. //             echo 'dog in cat!';
    * X2 |) U  s% h# N1 j" w
  21. //         }* g1 q* B; j2 q( ^/ l5 [
  22. // }
    + _2 q2 M+ ?2 `9 e: z6 E& |3 W$ h
  23. class Life{" y1 U; R) T, [" K$ N
  24.     function __construct(){
    0 v* Q: w8 E. K9 N
  25.             echo 'cat life!';
    & f5 Q5 F( R/ W6 w2 j
  26.         }3 I7 J- L3 P' E1 C' _
  27. }
    & i; Z" U6 A7 Y0 P! T
  28. - z$ q3 z3 z$ G# M( S' o( C5 ?
  29. use animal\dog;  6 Z/ Y! J2 }% J- L3 L& B4 g
  30. new dog\Dog();
复制代码

- m* W; n& t: m  J4 c
如上,使用了
  1. use animal\dog;
复制代码

/ Q3 l7 ?; J0 m7 p& A7 S( R
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

6 c  D. v, v  k+ a$ K! G
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
  |6 j) Y9 }# E; ^2 g/ w3 W

# E. O# b: ]8 u+ B) ~/ k
# y4 \9 U- k3 A$ `
  o- n- @+ h3 L2 Q# u' R: w: b2 @4 F' Z  T. [8 Z
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-5-2 13:31 , Processed in 0.083840 second(s), 19 queries .

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