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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

8 {3 K) }3 [, l  H! r0 y( H& N
; f( A  j7 b* S* w, N5 t8 z使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

6 x. T, u& T& L* I) n
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
: d. ?2 g& x6 U/ F
结合使用方法来进一步理解它的使用目的吧。
( A7 T7 e$ t. Q- r7 u- ]
. J# s1 c; f+ V
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    6 M5 N: j1 U! n; A/ |
  2. namespace One;; P7 V- G9 w2 A' b9 ]
  3. namespace ONE;
复制代码

+ s4 m" f! Y* K3 s5 b8 s
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

0 R( R; J* I4 m8 s8 s7 s2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    . v, I6 R* ~" B* N
  2. class Person{4 N* K- X6 O# l; b- f; }
  3.     function __construct(){
    : @) x/ `: q3 r" j3 B" W
  4.             echo 'I am one!';
    ) J7 n2 T' d8 h5 o( q
  5.         }
    # |: p- V/ ]5 p5 x# N& n, Q+ C8 c
  6. }
复制代码
  1. //name.php& J# f/ V# Q3 Q7 i7 A- k0 _% E
  2. require_once './1.php';( P! G- a3 v) B1 s& e
  3. " P7 D' E# E8 a/ b" ?+ ^  P! s
  4. new Person();     //输出 I am one!;
    % Q$ U& x7 ^/ x. z* x
  5. new \Person(); //输出 I am one!;
复制代码
" P% O7 Y/ M7 L& H& v
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    9 E1 G& u: C/ n5 g; }( i
  2. require_once './1.php';7 [# b& x$ I5 k* X# ]
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
1 h& Q2 y/ \3 U! ]1 ~. s
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    ) e* x9 C$ ?5 b4 {- G
  2. namespace one;6 m; [& B2 G* o# d0 E
  3. class Person{
    9 |' |7 q8 u+ Y7 ]' y5 j! I
  4.     function __construct(){8 A  s8 ]7 D) @+ M, J# V
  5.             echo 'I am one!';
    , g* V9 F9 k7 @9 \7 v' B. e
  6.         }
    - m( V" M3 p+ I
  7. }
复制代码
  1. //name.php
    3 U' g) b- n0 N1 |, ], e0 J
  2. require_once './1.php';
    # L8 `# k  {: x! K& s0 f
  3. new \one\Person(); //输出 I am one!;; c- d  r  R% e! @% W/ _. g" H4 H
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
* L9 y, a1 M7 c& Z& B
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

1 w& H% J, P1 W2 l9 n5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。) b7 h! b9 b, {- c+ O) S% U
  1. //1.php   
    3 X/ F; N( y1 Y( D9 |
  2. namespace one;7 l! F3 L4 E, h* r" `; C
  3. class Person{3 k% P5 t: g" B2 W
  4.     function __construct(){: F5 a/ i5 u( S% n; Z$ n9 y& z
  5.             echo 'I am one!';, h+ B: K- P$ @9 J
  6.         }
    - y; s- J+ i8 C+ F- A$ j
  7. }
复制代码
  1. //name.php& [6 m! B  g" y3 R
  2. namespace test;
    ; L* a% Z9 E& T4 U
  3. require './1.php';
    , Q; S0 L9 \, E* U# D9 T2 e! [: o9 n
  4. new \one\Person(); //输出 I am one!;
    % I) J* }1 [, y% O
  5. new Person();      //这里结果会是什么呢,猜猜看# a7 ]% Z* k: h6 I* z3 `* V+ b' }
  6. 最后一行结果报错:( n8 r( h) q8 a: X$ L/ A
  7. Fatal error:  Class 'test\Person' not found
复制代码
7 V" E3 Q8 U9 d5 c4 g! g, v2 m

+ V' H  E( L( ], f& K首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

* y& b$ ~" \, q* h5 ]+ ], Y
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

) @' }( g2 s. f% i3 ^/ Y! V
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    1 @+ I6 ~. a/ y3 R" _2 X- T; h2 O
  2. namespace test;* i8 K& a: W0 x
  3. require './1.php'; ; q( `/ j7 i. `  e

  4. * R. M2 D8 p# E) U
  5. class Person{
    , D  S6 x$ |8 y+ U6 }5 e/ {, i) H
  6.     function __construct(){7 o  ^( |/ Z( R2 h5 q+ N
  7.             echo 'I am test!';
    : U$ a) ^/ k8 }9 G8 b1 E* x5 o# ~
  8.         }
    2 |" k% X( F1 i$ n, ~
  9. }8 O7 f1 }: `+ ^4 ]

  10. " f- N) n# t& [2 b( t2 p/ w
  11. new \one\Person(); //输出 I am one!;5 X* h5 P9 m, p" L# w
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
2 g; j9 h( S; l  E* k6 o! |' k
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    2 i9 M& f* C& m( i# u  Y
  2. namespace test;
    : e& ?0 C1 j: m* T  X# a
  3. namespace one;' c6 \! Y; V9 }
  4. class Person{7 h. g* C: o0 q7 p' v& X! \
  5.     function __construct(){& _0 [7 }) m! n$ p5 y. H
  6.             echo 'I am one!';) {' u' e: ~4 ?, A) a+ \
  7.         }8 y$ q6 e. i: r* ^0 m7 s
  8. }0 |" A/ V' X* t  w) J

  9. ; t# ?  I# {' X
  10. class Person{
    ( r/ T* ~) Z! S! S1 q3 {8 p
  11.     function __construct(){
    8 D9 L( v( i# j
  12.             echo 'I am test!';$ l0 `: J" b  ?5 |
  13.         }
    , R; r- I9 s+ u' l' W
  14. }
复制代码
8 A  s' _" A, e
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

3 W4 n' ?6 ]" V5 |4 F$ u, \
看来简单的把require理解为替换,在这里行不通。
* S% M4 N9 B1 e! [  `
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
9 j7 j/ h( O% ]5 W, s( p0 C
  1. //name.php. v1 M- G2 j) p/ l* d$ U0 A

  2. - v& [" z6 h5 f$ n: l, a
  3. namespace test\person;
    * N+ u$ K1 I8 F
  4. % A9 K: G4 Q) O; J
  5. class Person{; b4 b! F7 d6 w, C9 k
  6.     function __construct(){
    9 U0 B) J! k% Y- D1 c2 T1 Z
  7.             echo 'I am test!';
    - B+ k6 r! A5 q7 D3 s3 A2 ~
  8.         }
    * i# p; f: i4 D
  9. }/ \# S" p$ f4 A+ c3 W$ e
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
7 r- q5 r! E, o$ `1 r
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
5 b5 v$ G6 v8 |' e
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php4 z7 M2 S, @3 e5 [" B6 Z
  2. ! M0 F" a; b$ n2 p: c7 X7 C
  3. namespace test;
    ! f& y% ?) @# E" N- J0 K; A( V& O
  4. echo 'zhai14';/ a. q: C& V2 H  k, J1 ^) ~& x
  5. namespace zhai;
      x! P+ b! z4 z$ q6 p& t2 F1 A; y4 ?
  6. require './1.php';
复制代码
2 J1 J, b+ o, J) F
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

8 s& S& U& ]6 ?use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
" Y2 C1 g0 n$ L1 p
  1. //name.php
    * @& A* i* i" M* v) _- S8 d
  2. % s+ _/ Z, I; F5 i" m5 T9 G
  3. namespace animal\dog;0 [3 v2 S& O& g( e2 k' m
  4. & W* a1 K5 j0 G( Y, R
  5. class Life{
    # ~$ [; w4 X3 i
  6.     function __construct(){
    1 }- ~' h$ `8 C/ k; _- g8 _& Y
  7.             echo 'dog life!';
    2 f) `9 y% b+ w* x6 z: G2 {
  8.         }, {( F  l8 A: y8 L* |
  9. }
    & g8 s8 h/ z+ Q- r6 ~4 X% h8 X3 G
  10. . l9 `9 E! n. f6 I& D
  11. namespace animal\cat;/ b# s! L% I8 u, j# j" M0 T
  12. 3 Q2 e  V8 ~1 g/ x
  13. class Life{
    - j, E' ^) J& ], p& }! t
  14.     function __construct(){
    7 Y& @- N# `( ^
  15.             echo 'cat life!';
    3 y2 f! ?: i6 N: j) g6 k% }- S* a; P
  16.         }
    7 B$ o" ?$ g* @$ ]: B! ^! Z
  17. }& _; C' l$ B% I0 f
  18. 1 ]7 ~, _+ p" [' G- n5 ~
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    # h; L4 L/ O8 d$ ?, ]: o7 y5 {7 w
  20. new \animal\dog\Life();  //A: s/ t. Y) y; |/ ?1 |
  21. & b% Z* F( p% W  R! E8 m8 b1 _
  22. use animal\dog;  //a! N' F- `! U6 @% L6 t8 h/ S
  23. new dog\Life();  //B+ p- Z, f* w, F/ j8 n
  24. 7 w3 M0 }1 |4 f
  25. use animal\dog as d;  //b
      }' t8 q/ ~* A0 T6 f7 R9 ^
  26. new d\Life();
复制代码
% l4 G- z2 {( C, w# A
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
6 }, i) f7 ]- a( Y8 m( k
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

0 W& v. T2 H+ ]) I5 J: S2 U: W- z
相当于
  1. use animal\dog as dog;
复制代码
/ E! y$ q# m! `# M" y
2.namespace后面不建议加类名,但use后可以。; l$ \8 t( j: O+ t9 q. ~4 }+ S
  1. //name.php
      H5 a! t6 m+ [8 X% }6 c

  2. . c! ?# T$ Z/ i1 ~( l
  3. namespace animal\dog;
    ! J  i) G; q$ T# I: Q6 p

  4. 5 {7 a* a$ F" }. m! Y5 A( m3 @& T
  5. class Life{
    $ w' g  H% e. r, r( r
  6.     function __construct(){' b, {' F* f6 }4 |
  7.             echo 'dog life!';) p! L! o  V# z- @9 @! d
  8.         }
    " |/ U3 S5 r9 Z/ d+ h% X: @
  9. }
    8 n  l/ z# f! t) Q
  10.   V6 t$ O* P0 i& D
  11. namespace animal\cat;/ r1 q) O% \- R- v; {% n' a; q8 S* r9 g

  12. $ B1 E) k1 p/ J5 _- g' q
  13. class Life{
    ' i' Q5 q# R- f: {$ N/ E
  14.     function __construct(){
    5 Q1 t6 H( o9 w1 X( M/ h: D4 o
  15.             echo 'cat life!';
    0 Y$ x2 @$ s$ X( t. B7 C; b
  16.         }1 ^1 T' W  v, l' N4 M
  17. }
    8 T5 e; M$ _$ S

  18. 3 O  k9 Q0 s0 M. D
  19. use animal\dog\Life as dog;  ; o4 M  ^5 ~2 p, D
  20. new dog();
复制代码

9 N5 f, q' ?8 ^! o* R0 j
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

* _% Z* I7 K! S* t4 H: o; i
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php" r6 K) \- l  O3 t4 o7 ?% e

  2. ' \7 C1 e% X2 O7 d! k
  3. namespace animal\dog;3 h6 z/ r8 W# j1 n& }
  4. ( a1 F6 f6 a% W
  5. class Life{
    % K2 M  A4 r' ]3 s
  6.     function __construct(){. y* y8 r$ n' V/ V
  7.             echo 'dog life!';
    1 i( `2 @0 ~. o
  8.         }) ]' ^! h3 W5 `& X5 `
  9. }
    9 Q5 p) [! l3 h- R. s* _+ b7 P
  10. class Dog{
    " g8 d# x9 }' \
  11.     function __construct(){
    2 X5 x9 Q, h8 w3 T$ K8 u+ c# y
  12.             echo 'dog in dog!';$ y% D8 w. P5 Q) N" K4 w
  13.         }
    ( T7 ~. K% G3 `3 W' m
  14. }1 v/ H' A2 u. j  l  ~
  15. , {( ~3 [; g  Y- l
  16. namespace animal\cat;
    ) K+ Z5 }4 K3 Y% a/ \0 ~" p4 H6 l% h

  17. ! E- ^8 d. |/ [' H( K
  18. // class Dog{1 C, r9 A6 q3 j
  19. //     function __construct(){6 v/ w& [9 F. Q( a8 v; Z
  20. //             echo 'dog in cat!';: g3 d/ {. L2 S& I- M$ v/ p3 z
  21. //         }
    . w4 g& D. }, X6 r9 W
  22. // }
    $ s& t1 C0 ~. K  K
  23. class Life{7 N# {- q0 i* j! y6 y1 ?4 c, Y
  24.     function __construct(){! `9 |6 b1 N& x; ~1 c/ [
  25.             echo 'cat life!';  F7 N9 z7 I, N6 ?6 E9 b" n
  26.         }4 h7 e# ?, j( j+ X, Z3 i' R. O# C
  27. }  e/ o! u- I" k: v: \; {

  28. ) S9 v0 F2 m& X* A8 u3 m
  29. use animal\dog;  , x& |1 p+ H! z( ?, S
  30. new dog\Dog();
复制代码

1 ]' O% V7 g' ?
如上,使用了
  1. use animal\dog;
复制代码

9 l9 [0 q  r' G6 x1 _- {
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
7 K( l# d# n! ^2 }/ A; W  x" w
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

! `2 K; v0 |  n; |* b
, |; S: [+ n$ X( Q- I. f1 K5 @% S2 d4 k! ^+ i+ e  _) v3 t
) y) L, V7 u& [* o' g2 _; s
7 A1 f) v7 |4 |( `8 l* A
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-19 21:04 , Processed in 0.053755 second(s), 19 queries .

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