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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

, n! a! ?1 [* Y
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

6 p$ g0 k4 ^& E6 h" W! Q4 V  j5 ]8 S/ L- N( F% u1 N5 I
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

# C: R* T; h" h+ r
$ D6 m1 S2 C6 }namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;8 ]4 ]% n( c  b/ L  d5 q* L
  2. namespace One;
    5 O# y# y+ O( f/ Z, D. q  r
  3. namespace ONE;
复制代码
  n# ~. ]5 f# }0 z4 E
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
$ A9 k7 m' \5 m8 N: z  R
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   : `5 v6 i# L3 A! i$ H) S
  2. class Person{
    % l$ g' O! K' s3 s1 o
  3.     function __construct(){6 d$ G) o' M% B& |2 K$ k4 w* w
  4.             echo 'I am one!';8 F+ M+ ]$ d! N( t$ A- ~
  5.         }
    + N) g" l) E" i1 e
  6. }
复制代码
  1. //name.php, q( I  s8 ~2 S  o9 v- c, n; O5 y
  2. require_once './1.php';) u* ?  g' J8 z: Q- a( F3 s; q& _
  3. & x  S8 b* `, x3 g4 B- ~9 a
  4. new Person();     //输出 I am one!;; |, p6 D; f7 S* `
  5. new \Person(); //输出 I am one!;
复制代码

( m3 |: _7 J9 y9 S3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    - f- `+ l5 H! d+ s3 ^
  2. require_once './1.php';
    % z/ P5 p5 n& `5 m- u7 E+ M
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
2 m  |7 B% ^* Z8 M* Y
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    ' o  E. F7 w, ~2 w/ |5 W
  2. namespace one;1 ?" }- {3 ~4 U4 n& \' w, D
  3. class Person{0 p. u6 G$ k0 l0 ?
  4.     function __construct(){( R* h+ x  N; B* H6 k
  5.             echo 'I am one!';/ t8 K; }; Y, d3 K
  6.         }4 J4 x, p' f- ?5 L
  7. }
复制代码
  1. //name.php# h0 U6 V% t; _8 |) p
  2. require_once './1.php';
    ) B* J6 O" {( G2 S- S/ m9 O
  3. new \one\Person(); //输出 I am one!;
    7 M8 N$ H7 `% K" K- Y  }5 o- t9 C
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
) _/ n* N1 h+ }, N, g! i/ |
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
+ y3 {* ]+ G) C! }$ c
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
' `5 f/ J/ y5 ]5 }/ W7 X) z
  1. //1.php   
    + Q4 a: M0 x* k9 P; g6 ]  D
  2. namespace one;
    # b! X& z  b- K( ]1 `1 g+ N" t" Y7 P
  3. class Person{
    0 \* ]* S) S3 `4 W8 W7 F
  4.     function __construct(){
    , m7 \+ I" ~3 K. `9 o3 h7 d1 a" p
  5.             echo 'I am one!';
    - h3 \" z  p& }, ^0 Q( L
  6.         }! y. V# M) C# n" i. g* h
  7. }
复制代码
  1. //name.php5 l( x9 k5 `3 `+ `0 `
  2. namespace test;* V4 D# a: i! L
  3. require './1.php'; , x4 g! Z+ r3 z
  4. new \one\Person(); //输出 I am one!;
    + V2 q& P3 E: y, u+ H3 ?4 y- ]
  5. new Person();      //这里结果会是什么呢,猜猜看
    / t. P5 Q$ M/ D. i2 @$ X9 Q& `
  6. 最后一行结果报错:% I- h- \  [; e
  7. Fatal error:  Class 'test\Person' not found
复制代码

, j+ m" z# k3 ?+ w' ~$ k& Q, I
$ x& D  F( M8 O# M7 }
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

7 S0 P7 r; ]' ?: C3 {& M$ j
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
% q: A2 _- h5 }4 A8 e' J  t
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    2 P8 t! V9 W1 m+ r6 f
  2. namespace test;9 S2 H1 L2 k7 A7 @6 F5 I. W+ O. h
  3. require './1.php';
    * _% U9 x- Q% r2 W
  4. 0 z5 @% H+ s. U; v( w+ M& S
  5. class Person{; i9 M! b# A: i9 i% G
  6.     function __construct(){# Y! w7 F* ^/ S& E: H2 g, i  y+ ]
  7.             echo 'I am test!';  K* v, Y$ }& g7 t+ W
  8.         }
    1 _+ D2 m, X" `$ e( B. r  L
  9. }
    ) v8 z; R0 a* H- [5 X$ l1 w3 T7 V
  10. + K$ g2 Q8 _. \' A6 P9 h7 P7 U
  11. new \one\Person(); //输出 I am one!;
    % a7 }) z) T" w' @7 f0 s
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
  M: ]8 T# q1 a; j' E
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    + a9 I) }+ b! z
  2. namespace test;
    1 h! {$ O+ s, H
  3. namespace one;
    7 `  f7 x' D) B0 d9 x$ z
  4. class Person{- W/ r/ ^; y: ]/ I" E; g
  5.     function __construct(){
    7 b: k5 }+ Z+ l$ k2 h6 }
  6.             echo 'I am one!';
    " H# [" V) {0 i
  7.         }: C( t' l& z6 U# H
  8. }2 T  w: r7 |! ]' D, Z

  9. ( A. N0 }6 ?. A4 [
  10. class Person{
    & Y5 {; k8 s2 Z0 a8 p4 G$ u# b
  11.     function __construct(){  f6 @9 ]" h& J" @5 S. g: z
  12.             echo 'I am test!';
      K, |% }( K- n* B
  13.         }, T9 R: K  E$ _! j" h3 R6 b( i, u
  14. }
复制代码

7 u6 A1 J) `% H; ^9 _$ V" m# w
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

" }& r- ]2 k4 s* ^
看来简单的把require理解为替换,在这里行不通。
9 l" |6 k) W$ m, ^
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" l* ^" ~  B+ }& o9 {
  1. //name.php
    / K: W/ j0 ?0 V/ y% }+ v* W
  2. ( G; K2 D- W# f, J
  3. namespace test\person;
    7 l6 b7 k- l* P. g3 ?

  4. 1 @8 P: `5 y- c8 L2 U
  5. class Person{1 Y  T6 d% H9 G
  6.     function __construct(){; ?2 x6 h3 Z3 K+ @
  7.             echo 'I am test!';
    / I5 c# f- u6 D7 b) \& ~( y% P" ~2 a
  8.         }) |# c; ^+ d8 {. z+ s
  9. }( @- z' Z! s$ P7 E4 G1 G) _: w
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

% z' \0 w; N0 l" K( f- Y
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
  c+ Z+ b1 ]$ l9 i# A8 v! N6 W
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php7 L4 H$ n5 U/ f9 n0 D
  2.   n; C! N! X3 C- \8 [0 T2 h
  3. namespace test;
    % r, h+ G. U/ m5 t$ J
  4. echo 'zhai14';  V6 i' M7 ~, F5 r# w$ X5 b6 W
  5. namespace zhai;  s5 \0 R  u/ k; ^' f
  6. require './1.php';
复制代码
: P& }0 z) T4 J$ b. g$ `
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
2 G3 @. V+ M6 s' r4 V. _1 Z
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
  v- @" R# I4 E! H8 O
  1. //name.php
    ! g; a3 _9 u+ X7 |/ d* d+ Y
  2. # [0 F0 e2 e0 J3 i( }. h3 [
  3. namespace animal\dog;
    " `+ ^# n; _0 L

  4. ; s8 O- p$ k. E. @$ {2 O2 Q. I/ p
  5. class Life{. I# M: A+ k$ V7 v5 b2 B
  6.     function __construct(){
    5 Z' ^) ~" E; W9 X/ {
  7.             echo 'dog life!';
    $ u/ g1 K, O4 h) h: |. _4 h# Y
  8.         }: }/ Q& k! \; ^: f8 t
  9. }
    0 {" l$ y  f0 Y+ y) h" o. W" H
  10. 2 x1 U8 Q4 E  E9 K0 ^% e
  11. namespace animal\cat;
    ) b  B( z+ v3 a  G/ V7 y$ z
  12. 0 g/ O6 C+ C) k  Y: {
  13. class Life{
    9 n) v2 J# p% [! |" |, a  O
  14.     function __construct(){2 a6 [* Q/ S! F
  15.             echo 'cat life!';, Z( ?" A, N' ~# \
  16.         }6 G' `" V6 k2 q
  17. }: H! v" d) N7 u- v* R
  18. , l# `. i* }* y# t
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间7 @+ e. f+ `9 A6 M* z7 c/ W" M
  20. new \animal\dog\Life();  //A& q( d4 J+ P8 M+ B

  21. 4 S4 b6 ^1 B0 V; Q( |" D
  22. use animal\dog;  //a
    & o0 U  u* O2 q' l/ g$ u: G
  23. new dog\Life();  //B
    ( T. u4 U* o- K2 j$ w  \
  24. 3 C6 R, |( c* q% k( T5 E
  25. use animal\dog as d;  //b; w# d5 V0 t; D" {1 a
  26. new d\Life();
复制代码
% Z# I0 x- ?, k$ j
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
. V9 ]6 ?% B, ?# V$ Z( t: g
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

) p1 _: d4 M5 E6 g+ v. T
相当于
  1. use animal\dog as dog;
复制代码
( F( Q" P# h% o$ w
2.namespace后面不建议加类名,但use后可以。
5 x6 E$ c2 v/ v$ _  V2 o" t$ I
  1. //name.php
    0 f4 Y+ y( R- N+ Q1 U2 o) i
  2. ( h! T1 c( v1 [- o' R
  3. namespace animal\dog;
    9 \4 v8 l2 B6 M. o( Z. @7 `

  4. & o8 l1 v/ f0 D$ h8 i$ N
  5. class Life{* j$ l7 K8 Y; g. _- [
  6.     function __construct(){7 g1 e. r/ [" R: C: z% H
  7.             echo 'dog life!';
    : ~) c/ e3 }: v
  8.         }. Q3 ^$ Y+ w! ?6 k! e
  9. }2 a' G5 |% p' D8 S2 {7 p- f5 S

  10. # E+ U6 o0 u3 z7 s
  11. namespace animal\cat;; a% t) B3 A7 V$ q5 i# i- s

  12. ! }0 w* ~% F/ y9 b0 i% V/ \
  13. class Life{3 R* Q8 F/ v5 v* [
  14.     function __construct(){
    , w( ]8 ]9 K% g0 Z3 V! ^- ~) R
  15.             echo 'cat life!';
    9 y/ f- L5 g+ X. u; N6 r
  16.         }
    / [# r2 I1 f- `, |
  17. }' g  h, `. ~$ q. N* J( y7 i
  18. + p3 E/ d% q- [
  19. use animal\dog\Life as dog;  0 e" I0 V+ I1 k+ c* r. ~! U9 I
  20. new dog();
复制代码
  D( j3 H" l4 r% w, C
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
  ?5 N5 d5 z5 H( P. E  d5 F
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    ; P( I  T, `0 e: B! e

  2. 0 U3 ^: B1 G! U8 o* d
  3. namespace animal\dog;( j) r7 l6 u6 N
  4. ) \) q) l4 h- F+ F" o
  5. class Life{
    1 b0 B" m2 Y, e0 }1 ~/ x  U, g3 M
  6.     function __construct(){
    3 u5 i& B; p. H% @, a
  7.             echo 'dog life!';3 c8 w* X1 T/ x4 P' M) i+ ]
  8.         }8 I- S- B9 d, M+ k" _5 E) L
  9. }1 Q1 g" N, x( _
  10. class Dog{
    4 V) }$ u( J1 {% N, V
  11.     function __construct(){
    * {3 F) v& A/ r1 {1 W3 ^* T
  12.             echo 'dog in dog!';+ U7 w# a9 R' t
  13.         }
    : d0 ?6 t1 g8 e; Z. P; q$ t4 E( S9 c6 g
  14. }4 m, K, b% |* i6 t. L- H

  15. 6 ^* |5 t5 w4 V) H* q
  16. namespace animal\cat;2 h4 \/ a9 }3 k1 [

  17. $ Y. M+ w, _- Z
  18. // class Dog{
    7 f; @) W# M& f; i& M8 h2 \
  19. //     function __construct(){
    ' O  e+ P; `4 }. N8 q' ]
  20. //             echo 'dog in cat!';
    * ~% b/ R" S1 X0 K0 o' f
  21. //         }; k0 r* Y+ S" ^  ?
  22. // }
    0 k8 q, x) E' A7 V
  23. class Life{
    " c) `5 W* a& b! z5 c, Z
  24.     function __construct(){' e/ Q; Y% D, O  W2 m, o) F
  25.             echo 'cat life!';9 z6 H1 t* p" l) A2 u- t2 b
  26.         }$ M' S* ?8 a& B- [; M
  27. }
    : q& F( W5 P4 |6 M

  28. 9 {9 H; J1 N5 T1 C/ H7 }, |6 l
  29. use animal\dog;  ! G6 L) }- T+ R# Z+ I
  30. new dog\Dog();
复制代码
, Q) R% q2 U3 a' h
如上,使用了
  1. use animal\dog;
复制代码

7 O7 k" f' K8 t" a/ x! k3 v
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
! {$ n) p6 |! |) K
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

1 @/ A7 ]1 d# o6 N5 K/ }+ L
! y: T' t' s, N& h: g1 {/ I0 m* P$ i3 K- X

. Q4 ^" N' Y& o: I) Q1 A% C  L- G4 Y$ j8 z7 M  X
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 02:06 , Processed in 0.058915 second(s), 19 queries .

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