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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

0 H, T: O2 o. m/ A* \
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
) D& P8 m! B" U5 }6 Y' |
( o9 e& Q- T1 y
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

# `; T4 C5 A4 X2 a
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
' d7 f1 _# S0 N9 e- o" Z
结合使用方法来进一步理解它的使用目的吧。

0 q" A; x+ R8 `( g* j, @0 [/ B$ ~. i0 Z' C: ?5 @
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;- F$ t& [/ x- f" M' m
  2. namespace One;
    & V  c/ N+ X# f) E& d* y
  3. namespace ONE;
复制代码
6 F8 s. B/ J+ k6 y; s: U2 o
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
6 U% d, O( Y1 @, g2 ~8 M
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    6 [8 w/ `- z" _4 \
  2. class Person{
    & j8 L9 [4 E- Z+ W; o) i
  3.     function __construct(){9 _* |6 G; O1 ~
  4.             echo 'I am one!';: D; ^- g( S+ w- B" {
  5.         }( O* _, }" I! h1 S
  6. }
复制代码
  1. //name.php
    % O' c9 ^4 D7 |1 q' w! J
  2. require_once './1.php';9 i0 _1 n- H! ]: M( F: `3 Z9 {
  3. 2 x  p) g' P$ F  j& ?" n2 t
  4. new Person();     //输出 I am one!;
    - @( _; w1 v6 Z
  5. new \Person(); //输出 I am one!;
复制代码

. ]" X# T4 X4 l+ d5 J# C3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php7 q7 y8 ?# |$ `$ M5 b& K
  2. require_once './1.php';5 `; Z7 n) Y' O3 A& o* ~7 n+ n2 J6 n
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

6 J  p6 [9 `2 U( b4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   7 v; i* r0 B+ i1 {  X
  2. namespace one;
    % n9 |2 _1 R& o0 K1 T
  3. class Person{0 h: w$ U- K  U/ ~2 z' [" ^9 n, v8 q
  4.     function __construct(){
    , z  M4 L) a6 D9 s1 @
  5.             echo 'I am one!';
    , S: j7 g4 t" ]  U$ k$ b  \" L' V
  6.         }
    ( D) N0 ~( R' L5 v. s& x9 u
  7. }
复制代码
  1. //name.php; F% |0 C& u9 {( F# g7 y" {4 W
  2. require_once './1.php';: i, Q" T& Q: W* I1 b, e7 H
  3. new \one\Person(); //输出 I am one!;
    6 t! }( B! W" ~* L5 e
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
# r& o- `& G$ e& W& M
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

1 m+ w' E' z- P$ |, B' n% |  d: x( x5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
/ B6 Q! h/ d8 ^: p
  1. //1.php   ) h9 ?; `) c7 k
  2. namespace one;  R4 b# b8 n) z* g; ~
  3. class Person{. C: Q, B/ k9 \  F
  4.     function __construct(){
      J; H0 ~  f9 D
  5.             echo 'I am one!';
    8 r! N0 L* I+ c+ f0 ^
  6.         }
    : Y* b1 a' o4 n: }! {8 h
  7. }
复制代码
  1. //name.php* \! i) F; d+ @
  2. namespace test;2 `$ Q2 z* L+ y6 w) \' K) ?7 r$ F
  3. require './1.php';
    2 A+ V& }0 ?9 A5 ^+ Q
  4. new \one\Person(); //输出 I am one!;
    9 q+ r) e. c# _0 J$ m
  5. new Person();      //这里结果会是什么呢,猜猜看- t: a; c' Q- x# V3 N0 x
  6. 最后一行结果报错:
    * _5 {/ B- [! b/ P
  7. Fatal error:  Class 'test\Person' not found
复制代码
! n- n3 r' n4 K8 Q
5 B# T6 v6 X+ k; o6 s7 K  S' H& ?
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

6 T3 C' ?3 k8 n
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
# N% T- b2 j2 Z# n
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php# o4 d1 P: y; T  X1 F
  2. namespace test;9 t7 K) g# q6 V$ `
  3. require './1.php'; ) R( J0 s2 i8 q  o$ I+ Z0 y. ~7 p
  4. ( I9 P' r/ {: ~1 `' W3 M
  5. class Person{7 c& h! r! L; Y
  6.     function __construct(){
    / ^" \6 }" B# r7 X
  7.             echo 'I am test!';$ p2 U) Z2 h% T  `- T
  8.         }
    1 U! U! g' f# Y0 d9 r
  9. }) y! }2 m) \1 k1 [( g5 v. |8 V
  10. + b1 j/ d3 s+ x( z8 d1 I( p( Y
  11. new \one\Person(); //输出 I am one!;
    * K7 ?4 m4 N+ Q8 ~! w( Y- E
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
! {4 K4 J% E/ U# l# b1 j
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php, T' b0 {& y* u$ i7 c
  2. namespace test;
    ' @* z) ?" Q$ K
  3. namespace one;$ N/ Q1 G6 {. r2 p: J
  4. class Person{- V/ Y  X& X9 X8 ^) ^
  5.     function __construct(){( D, P' `9 v- c: n5 ]) V
  6.             echo 'I am one!';
      x- y% C, I8 P1 }5 m
  7.         }/ Q" @; ^( n/ W; U7 [6 W& l
  8. }& ?3 f3 p$ Y$ y* X" v9 f

  9. 0 t2 b# H/ o4 @0 B: n/ _
  10. class Person{
    ! q/ X7 y' Q4 |
  11.     function __construct(){/ x7 {# e1 D4 [7 E, z% p* Y. n% X
  12.             echo 'I am test!';  a& h2 J9 ^4 [
  13.         }5 Y8 \- X1 y  z8 V& W
  14. }
复制代码

' K: S' }1 a9 {/ J" E
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
: r1 A0 B' H5 x5 v4 P, I# B
看来简单的把require理解为替换,在这里行不通。
6 R% R5 i" u! R6 f
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
. y! e7 q2 R8 q+ H
  1. //name.php  _# k/ D7 H' @

  2. ' o8 D/ A; D5 N
  3. namespace test\person;: a5 m' @) Q' }0 h9 n

  4. 0 F. v$ R# U5 ]# I2 N! g
  5. class Person{1 S+ K8 M" ~4 P$ q
  6.     function __construct(){
    % |* K; T9 }" d3 b. R% ^) ^
  7.             echo 'I am test!';, K( L& A* j2 E3 A6 |, R* a
  8.         }
    4 r, J4 v3 B) O* V( {( e
  9. }
    + Q  M! Q' M, n' s
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
7 k: [1 j# u8 r) C% f. S
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

! ^/ {) L* C3 L9 }1 o, o5 O6 r1 `7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php& I% q- L, O. h6 q

  2. 7 s2 ?  k# g& O4 \' y0 g
  3. namespace test;
    , i* ~) N. r2 d4 T4 f9 ?
  4. echo 'zhai14';& v9 L' T$ F8 y# f1 l
  5. namespace zhai;
    ! H: ^" h$ E8 b: W9 b6 m
  6. require './1.php';
复制代码
% N$ U/ a9 N0 h9 v$ l, r+ S
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
! F3 e$ Y% X3 x4 d9 [' ]9 S# \9 L3 l
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。0 O' Y# c4 L5 w/ _
  1. //name.php
    5 z% t1 r, p, v& A# e

  2. ) b' `7 Q& B0 F. e
  3. namespace animal\dog;9 r$ Y8 x# F% |9 s6 T% B0 W' x& \+ P
  4. 1 w! ~  j8 F; ^( }2 ~( ]: `( I7 Y- C
  5. class Life{
    ! R6 A5 u  Y& L! V* m7 v
  6.     function __construct(){
    ' N) |' p  d3 ~4 G5 q* U6 k  H
  7.             echo 'dog life!';
    8 ^* }: M/ [: s
  8.         }
    - l3 Q/ n4 y! @5 o2 c
  9. }; R+ D/ i* H& q- {. F+ ]/ ^; V
  10. . Y- \. g! B) P/ E: O7 H4 ^' U
  11. namespace animal\cat;
    / q! ]5 S# B( F
  12. ' J& k9 R# Y. E$ d3 O
  13. class Life{4 D0 a5 w  \3 C, b
  14.     function __construct(){1 b. K7 F: G. r' J
  15.             echo 'cat life!';: G2 B5 l- h7 s3 p9 |
  16.         }  o9 J0 |8 a7 o' h  @# L
  17. }
    * A8 c) L$ R  V. C

  18. ! T8 `, P) M/ s) d+ _9 ]/ Q
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    ) i+ [) V, X' c2 O
  20. new \animal\dog\Life();  //A: j$ q5 G& ~& N

  21. - ]$ _  F2 Q5 V* A9 p
  22. use animal\dog;  //a- A; l! `+ M& _' x
  23. new dog\Life();  //B" z" G/ L! p( }$ U1 l4 V

  24. & \7 h5 n# J, ?! h
  25. use animal\dog as d;  //b
    ' ^  F; G7 T( g( x6 d- a
  26. new d\Life();
复制代码
8 H0 w% S2 d% {
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

- o  H) s% T7 \  I/ p; T
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
7 t, U0 ^9 S! B7 E) U9 ]
相当于
  1. use animal\dog as dog;
复制代码

: A  c. J# ~6 o0 q2.namespace后面不建议加类名,但use后可以。1 A0 o( p$ {; {5 X% }6 x8 k7 j
  1. //name.php
    1 J9 f. x' }: M: z% m

  2. & i: p# q. {% b# J3 @
  3. namespace animal\dog;
    6 d1 V/ l- D; a5 Q
  4. 7 h4 L% G: E6 |+ t2 B. i2 Z
  5. class Life{
    9 K* E7 D3 a) }  B) \+ j8 ^
  6.     function __construct(){
    ' x* u& Q, x3 X4 L' p
  7.             echo 'dog life!';
    # C+ W# C1 I' L7 B  y* D0 b
  8.         }
    " S" Q" c& P. k9 |
  9. }; Q2 m9 N0 D4 r7 U& R$ W- r
  10. 0 u2 u" @5 R1 Y& p) m8 B
  11. namespace animal\cat;, z4 [; u5 e: c

  12. / [3 Q( ~1 E8 H# b
  13. class Life{, C$ @) J) w1 I0 A* J9 f2 G
  14.     function __construct(){. }% ?5 k5 P/ q
  15.             echo 'cat life!';$ O1 ^  M# [4 @! W4 g- L# e
  16.         }0 T( l7 H% z5 j# R7 M! z
  17. }
    $ k$ o4 M" y/ _6 q# {6 a& E: `- a. H
  18. , A1 W5 d1 V; K. i0 ?9 A/ [
  19. use animal\dog\Life as dog;  
    ) G% \, }1 _$ L- K* D) S
  20. new dog();
复制代码

* b. g; f: q8 B" H
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

  I0 \! ?7 q. Q9 q0 C0 p6 Q* F- L+ J
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php& Z& B# X5 _$ l0 g+ a

  2. / s. _2 R& ?( j  z& d1 N* M
  3. namespace animal\dog;
    % A! o* [& X9 `& D" w  ?
  4. ! a$ \0 T  ]5 G( U
  5. class Life{
    $ ]- q( w  s! ^
  6.     function __construct(){
    ' O4 N# Y5 |/ N* s" E: ~. g9 c
  7.             echo 'dog life!';$ X+ x# M: W: ]: ]+ Z* r
  8.         }9 e% k/ [5 K1 f
  9. }9 k$ H. z  m0 i! e( {
  10. class Dog{
      J2 g7 |: c0 ~7 c. i' {9 T
  11.     function __construct(){
    5 M4 ^8 J9 [& z6 C3 k" f
  12.             echo 'dog in dog!';, x4 X9 h3 y0 l9 G. w3 _" a9 @
  13.         }
    ' N( Z* e, y% `
  14. }) J- b: e( N" ~, U% g6 ]6 A

  15.   @" i% G# t7 e; Z: I  g' x, y  R* U
  16. namespace animal\cat;
    , [0 C8 M: V& C6 T% B2 K
  17. 6 X5 `4 x& b  I$ x. `/ f: [, t8 @
  18. // class Dog{
    2 L+ a7 [& @4 T4 l, T+ l5 Y5 w
  19. //     function __construct(){9 \7 N4 d) k! k# i# O
  20. //             echo 'dog in cat!';9 ]$ @- S% S: e  p3 R
  21. //         }) P) e, _5 M+ E$ `8 c' o- Y2 M
  22. // }, u( m( N2 |$ Q9 a' a+ ^
  23. class Life{
    : v7 a2 n; O: h6 V; s9 E
  24.     function __construct(){6 I( E/ G3 B& F; T) t
  25.             echo 'cat life!';' T8 l2 E- U. u4 S3 J) q
  26.         }
    0 b+ h3 q7 f- _! ]) b9 Q* h
  27. }* u: J8 ^- m- H+ `" X
  28. ) \/ T$ _3 x2 O, ?/ l
  29. use animal\dog;  . i: @( S) M! D6 X! a9 _+ [  k& _
  30. new dog\Dog();
复制代码

1 Y7 \" x, W- T9 D
如上,使用了
  1. use animal\dog;
复制代码
7 e! h/ x! P0 d% W; W% Z1 {, s
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

- z/ G+ Q- S7 E8 G  |6 l% D% _. C
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

" Y* u9 ]( c- I% e, E
  l. K5 O4 h$ h" `% a! i; V, x5 R/ @+ t; _+ Y) S% I' }

3 U- ?0 y- z  e) I( W1 x# L& ?" W6 N$ e  v1 A! ^& C; h; N
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-8 08:33 , Processed in 0.119835 second(s), 19 queries .

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