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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
) F: _+ w( m( N" ^
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
5 w5 b: `+ H" N& |/ m9 u

, V! H: n: \. L. j. A5 N使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
4 N0 j# R# h& ?9 }( a; R4 {
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

1 i% i! Y- ]/ c( r0 t6 b8 e结合使用方法来进一步理解它的使用目的吧。

' I1 X% a, K  t5 i9 @0 `" U# \3 v# Y1 R/ Q( ^7 m9 p. C
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;: s$ H* a4 T; z: ]% o% }
  2. namespace One;; }" |$ t* h6 I3 f4 p2 l
  3. namespace ONE;
复制代码

5 P! M5 b' L8 e# S' k7 x" l4 h* z. Y) W
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
6 [& s* ?, h6 X2 [* S* B
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    ; Q  a' u; d" p: P$ j) @. [
  2. class Person{
    6 z! N5 C" {4 {4 o; ~; o
  3.     function __construct(){: D8 \) ?- I+ ^% v+ Y
  4.             echo 'I am one!';
    + H! S- j4 g% Z! r7 v8 v
  5.         }2 j6 g2 y6 V; I  q5 {6 e* N
  6. }
复制代码
  1. //name.php
    ) v6 k# L9 u) M4 [
  2. require_once './1.php';- z# M5 n$ y" a
  3. " L  p7 e! {) Q2 t( O
  4. new Person();     //输出 I am one!;
    4 d; a  l$ f3 A
  5. new \Person(); //输出 I am one!;
复制代码
  I) W0 {! G! n$ G  Q* W5 [# ?
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php0 z4 D0 Z3 t3 h2 m3 h
  2. require_once './1.php';
    # F$ |0 O0 ^5 {; g1 H
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
  B) N6 z6 f4 m" V3 O0 V( {' z
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   ( G, {$ U7 Z) B4 p
  2. namespace one;8 @! q: F+ K* {( u8 f: r+ M
  3. class Person{( w* U' y, k# h9 H
  4.     function __construct(){2 {6 T; m( `3 }5 L- `
  5.             echo 'I am one!';  s6 o0 G/ t7 m$ h* `# c
  6.         }$ f9 F9 k: ^! u: x  R6 o: ]
  7. }
复制代码
  1. //name.php: Q1 D  d* `: C* M' s4 t5 j8 E
  2. require_once './1.php';
    $ B7 b" {3 {7 I; `. P3 l7 N
  3. new \one\Person(); //输出 I am one!;
    3 t& h( K1 x. E# `
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

* K  N6 y. M% v. G! M
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
# `8 ?5 F  S: f1 q! t7 j: T
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
1 F5 z- J" Q/ n- F- Z
  1. //1.php   " A- E/ \; M2 c; S
  2. namespace one;
    1 s6 O3 T; ~- Y) J5 U
  3. class Person{
      I. u( o7 X1 z: M; r
  4.     function __construct(){
    ) J5 `  E2 i1 `/ X2 i5 O
  5.             echo 'I am one!';
    0 R. q, B3 R9 B9 H
  6.         }6 ^' }! H9 Z3 ]4 [: U( R" ]
  7. }
复制代码
  1. //name.php+ d. j1 a  F7 v# r
  2. namespace test;/ h# v% {  y% t7 v! Z
  3. require './1.php'; + N& q! x. q$ A* U
  4. new \one\Person(); //输出 I am one!;" q" F$ [" W% B) e
  5. new Person();      //这里结果会是什么呢,猜猜看
    / M& I' }. Y! r6 @  L& [) j
  6. 最后一行结果报错:
    # I$ o: a' P- G, k
  7. Fatal error:  Class 'test\Person' not found
复制代码

* \- ~6 I0 }4 s0 o& d6 a

7 I# ]* |2 R  q  N4 c. C$ r+ ~首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
2 m6 K/ {) W( p2 Q" k
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

+ u6 X; F- s' j$ r) \$ m9 c5 C! |
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    9 q* a4 ]# z: t7 m( y
  2. namespace test;) p* U  Y; T, J) m$ j6 L; T
  3. require './1.php';
    1 g4 x2 n1 ~: `6 {8 I8 }
  4. ! e8 k, w7 C$ Q7 W1 a
  5. class Person{
    6 z  v+ o) c( F! N6 C, g
  6.     function __construct(){! |6 O  X0 J4 @" J9 Q! u
  7.             echo 'I am test!';
    ( F9 E1 I7 `) ?5 q5 r) P% U6 {
  8.         }% B# O9 Q7 C3 J, m  W5 c+ `
  9. }9 f+ i* Y: ~3 K8 n" u4 H, t

  10. ' Y( ~3 @# b- C  o# i1 Z8 |
  11. new \one\Person(); //输出 I am one!;
    # F- }) z) v2 ^$ u" y) `
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

% x7 g3 O% K0 U( u& s
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    4 S8 p; N4 L( [6 f. w
  2. namespace test;1 C1 A- R6 |' m. D
  3. namespace one;
    ! g" f" M& _+ [, b1 }8 S6 T
  4. class Person{. |4 X" k  t. p' ?$ W3 z
  5.     function __construct(){
    & w) |+ o9 ]* D- G: t- c# p1 y% z# d
  6.             echo 'I am one!';
    6 h9 }, p4 I! A7 @1 Q- z
  7.         }7 ]; L  p& E4 ?6 I" m! A
  8. }8 ^0 k+ X8 j) A' x

  9. & m6 G" B% j* x! A3 L- F
  10. class Person{' d" ]. F1 {- u! y2 R
  11.     function __construct(){
    $ b* N5 T  ?6 a
  12.             echo 'I am test!';& x+ [, A3 b: Y5 k, _6 ?
  13.         }
    0 x  I4 @! X! f/ p$ h4 n% D
  14. }
复制代码

; T8 b3 w$ F/ q/ F/ h+ |
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
* S. M  r. ]) B2 m" ~. {
看来简单的把require理解为替换,在这里行不通。
; N4 t  `: P& ?3 j7 B
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。$ w+ f# k. F3 S( |6 i0 M0 {$ F) ^: P
  1. //name.php# r" k8 Z' p( t7 ]3 W
  2. . g  \& D$ }' {' m7 A% ^
  3. namespace test\person;$ Y2 z) @8 {0 p2 k$ S6 z$ l
  4. 7 g! I- x, ^) X- d
  5. class Person{
    / c- S7 {: y! _* Q% p4 q* E
  6.     function __construct(){) W) l$ X) m+ j6 ^5 g2 X+ e
  7.             echo 'I am test!';
    ' Z% L( Z' m1 `. x4 J# Q2 E
  8.         }$ l( {8 q  M4 t9 M( i
  9. }* m" a/ E/ h( V" W' }5 K7 M
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

# n3 Y' d6 P6 S9 t5 _" c8 r% }
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
6 g2 h* i" |" _0 Q& n+ y3 C; g
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php% E% Z8 t3 S! Z+ v3 B
  2. . O, y) P; V; V; S
  3. namespace test;
    $ S3 m. p, j2 ^- r
  4. echo 'zhai14';* c& H8 |( ?! p  w  e* e0 |$ n
  5. namespace zhai;
    4 R7 R- \# [% E& U- R. ?
  6. require './1.php';
复制代码

! H2 X6 m6 y, B3 I* N2 x
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
- @1 l# X: h" s% K) S) v
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。5 i- k6 U4 ~8 \- t' o
  1. //name.php2 N# v! z! ?4 {

  2. . O' l" I/ U- O3 u3 B- |- D
  3. namespace animal\dog;
    , ]0 O7 j& C0 e/ }5 n4 Q% e! Z

  4. 8 s; c# Q9 \8 D' J
  5. class Life{
    ; K( z# ^3 w( S( I9 k
  6.     function __construct(){; K! r: S! d& N' J; F
  7.             echo 'dog life!';
    - }2 `3 Y7 H- r# E/ n& M# |
  8.         }0 z0 J+ m( \0 b# i  v4 i
  9. }: l8 B; D, c0 a2 i9 U$ z

  10. ) ]1 Q5 b% x; x  u
  11. namespace animal\cat;/ N% g' f2 q5 M$ P

  12. 8 X) G( F' J8 u: X0 E
  13. class Life{  M( u% b9 ~1 s- W* }
  14.     function __construct(){
    * I5 @: j: F. K8 G1 x
  15.             echo 'cat life!';
    6 L& y2 c& I& V3 p) W" \
  16.         }' U# `8 u9 q- m/ G7 g8 `
  17. }
    1 o& E& o5 G4 m

  18. 5 Q8 I( n# _: {6 x$ J: @
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间: W2 s1 t- k" O
  20. new \animal\dog\Life();  //A( m: t" E; h1 E0 K8 f
  21. 0 W( C4 U2 V+ ]$ ]9 ^- G! F
  22. use animal\dog;  //a% r$ i6 S1 W. F
  23. new dog\Life();  //B7 L' [! i! `  T" q: E" I" h2 e4 i

  24.   ~! q. l7 f  S6 f
  25. use animal\dog as d;  //b
    ) C4 g' ]8 t" o7 P+ [: m7 _' w, M# X' e
  26. new d\Life();
复制代码

! s. k. {! _& Q8 w( z# z7 ?" D, O
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
2 x! s0 \" b2 Q" x, v# I' T
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
2 m1 d( @& e( z4 N1 P# L/ K+ E% i
相当于
  1. use animal\dog as dog;
复制代码

) v9 n* n' t  y- X2.namespace后面不建议加类名,但use后可以。
( D: _, j8 x& P* r5 J
  1. //name.php; Z( _$ T& {. B& l

  2. ! @( m/ V1 H7 J: l) G3 d: f
  3. namespace animal\dog;
    8 A+ T: k$ ^* z$ {0 C

  4. : _6 c0 i6 l& A6 Z
  5. class Life{: e1 o) V" w% D
  6.     function __construct(){
    / r, d2 Q' c% Y; q9 C  |2 m3 X
  7.             echo 'dog life!';+ ?1 d9 G6 i! v; f! A0 H
  8.         }
    ; y; W# M8 w* X7 q# ~/ Q6 U* B
  9. }0 I" I; d! J) ~8 A

  10. 8 w& V: X! a- H- \
  11. namespace animal\cat;4 K$ v( F% H+ [5 [0 C" {

  12.   {& s8 W' \$ a( m& P5 E) E$ ]
  13. class Life{
    4 M" o: ?& r& f! l
  14.     function __construct(){  V) Q  {9 Z; ~. e; J  k) g& T" H
  15.             echo 'cat life!';
    3 C# s1 G9 i8 f+ d& C% j
  16.         }
    ; a8 v8 l: d4 s
  17. }' U$ r" _+ _) p/ P4 o6 v, B" W

  18. . ]& y: Y3 u3 u. q2 `
  19. use animal\dog\Life as dog;  & M1 x: L: K$ K
  20. new dog();
复制代码

7 ~' C: L* l$ t7 ^
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
0 ]5 L/ k" p7 _3 Q1 P
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    + y* h" [+ f+ }
  2. 8 u7 o7 t. }7 ^# X: _7 W" [; Q# y; e# b
  3. namespace animal\dog;7 t! ^8 Y- `  {9 X  M' M6 ]
  4. $ ^9 Z/ m; i7 F# n
  5. class Life{6 ]3 y' k1 o; S' @# M( \
  6.     function __construct(){8 O9 y, |6 I5 o$ X, u
  7.             echo 'dog life!';
    2 O9 x* w2 E  d0 x6 I2 g. |* p
  8.         }
    . b" D% u+ y* o2 [
  9. }: z5 m$ ~- E/ {' F5 P- `4 A
  10. class Dog{
    3 o7 f- F3 L$ Z- X. ^! x* V6 ]2 g$ I
  11.     function __construct(){6 y* V; F5 G* V  D
  12.             echo 'dog in dog!';
    % n- h) o4 r% W& d
  13.         }
    , p, l9 S; s. O6 p: P9 ]* g7 g; {
  14. }
      f$ U. E! K$ q! V3 ~4 p* d3 Z
  15. 4 }4 `) a/ c( J% N6 J, s' W4 m% T5 X/ r
  16. namespace animal\cat;( h, o8 f5 Q! z7 g, Q
  17. 3 _! V% M0 ]* ?* u
  18. // class Dog{8 ], m8 O/ I) G3 A; A
  19. //     function __construct(){
    7 @- E; J9 E/ u: b! c5 x, a
  20. //             echo 'dog in cat!';
    ( B' Y- i8 x" h0 B8 ?
  21. //         }# q" |- D. {4 n! A
  22. // }
    1 \% ~/ `5 L5 r- @3 t: J
  23. class Life{
    % W& D. n+ e# c' O! c7 s
  24.     function __construct(){
    # D3 V! G+ @* j/ M9 v9 O; b" v
  25.             echo 'cat life!';
    8 E! l+ U- {! k* }% O0 }
  26.         }. r) z% e4 W' d
  27. }* L  {  r' U! f, K. y- t9 r" V

  28. - z  b4 y, g4 ?; U# k3 h
  29. use animal\dog;  * {8 [) d6 c3 w; \- l0 c) _
  30. new dog\Dog();
复制代码

8 Y- i/ X3 |) X2 m. R5 d
如上,使用了
  1. use animal\dog;
复制代码
8 \- x0 B9 V( j5 z1 |" A/ p- t4 ~
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
8 n/ F- E" M6 Z/ l8 z7 f
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
  y4 [' F0 [$ @( Q' D: O$ Y
  P: T8 k  q, s4 M
. \; X! o. @* a6 A

. W) Y9 }) j9 a$ Y$ i- s! r0 w6 F2 e* T2 ~8 W% J4 N9 s, Y
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-19 22:29 , Processed in 0.058745 second(s), 20 queries .

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