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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

* K; k' D& a4 z3 O
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
# S* _/ `. e% r
, ^  W! D2 H% {0 |% f7 {. y
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

/ Q9 X7 r' K; ], p' ]2 U* }
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

; p1 f  ~* A3 n" P0 f* |" I结合使用方法来进一步理解它的使用目的吧。
- d( D2 L1 W, V

+ [( x7 \9 j2 |# t# cnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;  w3 r+ a& q" M9 |1 e7 D* [9 d
  2. namespace One;+ ?! u- D: ?0 G# f0 x" c
  3. namespace ONE;
复制代码

  u$ ]4 ~6 I% E+ m9 w
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
: i" F9 O" \- G! d8 j1 L
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php     F  f- G! ]4 E: P& `
  2. class Person{- B; a* w& ^$ j" o4 t" H
  3.     function __construct(){( a) H3 w2 h6 E
  4.             echo 'I am one!';
    7 L6 b+ @3 @2 G" z0 j3 S, X
  5.         }
      }' b7 t5 j. e0 N7 A2 p2 A8 G
  6. }
复制代码
  1. //name.php+ V5 ?7 ]& _' W! b! S
  2. require_once './1.php';; Y' y# `. G( Y; M) f3 S4 ~

  3. ' @9 W" P: `) Z! D
  4. new Person();     //输出 I am one!;! _% C5 W3 m0 B( E" B- H
  5. new \Person(); //输出 I am one!;
复制代码
! h( R) }' D) q. D1 D5 j
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php1 d8 G( Y6 J& M, H" C
  2. require_once './1.php';
    - B5 t, M3 |- t" k- g0 x
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
1 O% D3 [( Y1 U- t( e6 [
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    2 S3 b: u7 s: a1 O3 x. B7 R
  2. namespace one;1 {$ U3 k7 e& p9 U" U
  3. class Person{
    8 o5 R7 {$ p) X- |6 m% e- F5 W
  4.     function __construct(){
    , Q0 ~5 _# i: [* U
  5.             echo 'I am one!';
    $ D% d" C  H& j  z
  6.         }
    # v# {5 e( M- I4 I  D+ h
  7. }
复制代码
  1. //name.php, Z+ Z( [5 l# r) u3 [1 a/ ]  u5 z
  2. require_once './1.php';
    0 m3 y1 Z2 }' ^; E6 k* O
  3. new \one\Person(); //输出 I am one!;# g: `" q/ a+ G% ~7 C$ h: V2 C. p
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
3 c- C$ g; y# o3 n  ^% L: A
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
  d1 K- c5 A1 {% e: N2 W
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
8 [" t6 D! O6 s6 N7 u0 S
  1. //1.php   
    / j; ~! p0 E1 l% B8 g
  2. namespace one;4 L) A# Z7 M1 x+ `* Y; {0 p; s
  3. class Person{2 _/ i( K* e! F
  4.     function __construct(){
    : T4 n6 v( l% q/ P9 Z$ k( Z9 L' J
  5.             echo 'I am one!';
    ! m" q+ t# I* ?( W4 [
  6.         }! i5 |0 j5 o  R# Q
  7. }
复制代码
  1. //name.php$ A; W4 c6 p# u: C4 K: ?& v' V
  2. namespace test;
    4 N7 a( B2 {' C9 @: v
  3. require './1.php';
    % ^; K% E* V2 {+ R
  4. new \one\Person(); //输出 I am one!;
    & Y. |1 [/ M! i' e
  5. new Person();      //这里结果会是什么呢,猜猜看
    / X9 N7 I& S# A
  6. 最后一行结果报错:
    ) z8 ]/ u3 k( t  c+ e4 @
  7. Fatal error:  Class 'test\Person' not found
复制代码
& z0 n4 F% i* \
/ _! q3 O4 l! Z9 w
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
( A. d  n. h" P+ |
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

, {9 [7 J' j* ^
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php& k" @3 e3 b4 n, M9 E5 P, E2 Z
  2. namespace test;
    1 s+ I8 Z0 w# X8 `" F
  3. require './1.php'; ( Z+ Y* M% o* h& m. y
  4. , A+ F7 z$ B4 z5 }
  5. class Person{
    : ~3 y! i% u7 ]5 P& y3 [
  6.     function __construct(){
    $ q, B; l/ S" E( r$ S& {+ E: B
  7.             echo 'I am test!';
    + U  w( L5 l7 z8 L7 e$ r; U  R5 ~; U
  8.         }" f& B# S9 M8 {) z. M
  9. }; r( j' d; A3 R

  10. 4 F0 K: c( Q1 B$ r/ D: R
  11. new \one\Person(); //输出 I am one!;5 j; _# Z# ?: q( \8 P& S3 A( i# b
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
9 @8 W! k2 i# S3 D
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    ! z" F! A$ G# i6 ?1 Z8 u- }7 U: n
  2. namespace test;
    : R/ U' K# g' m& `. {
  3. namespace one;
    5 X8 ^; K* T4 }/ l
  4. class Person{2 c9 x& B% S7 c/ E) g+ ^( I
  5.     function __construct(){' ~" c  S! H% \. o! Q
  6.             echo 'I am one!';; c4 @8 `" a! t# {/ x
  7.         }+ P! J# u, \9 I. Q
  8. }
    1 C" r0 r7 ~# p4 i
  9. 5 \- h: V) }2 l6 ?; m3 v$ o
  10. class Person{
    : g8 o* h5 @0 I  H4 t
  11.     function __construct(){
    6 d, |. h4 K+ a% q  l: R, n
  12.             echo 'I am test!';
    9 T" i! Y/ w( Z( h$ k, k7 t$ m& A
  13.         }. `# c/ v* |" X' r2 ^
  14. }
复制代码

- C! S7 I" H# P' G5 m
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
! @/ L2 F$ d( m3 `+ u( n
看来简单的把require理解为替换,在这里行不通。
* x) f* h2 Y4 y* g2 c3 F
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。' [" \$ r9 G- o# V
  1. //name.php+ B8 x% n0 i6 p/ I: Q3 J
  2. 4 `" {) m: `" z  T; W/ V" ^
  3. namespace test\person;, f( Y4 k/ `9 R& [3 z: y

  4.   v. C" C, [3 l: l
  5. class Person{
    ! R) f6 j; ^7 ~$ R, R1 C
  6.     function __construct(){# u& d7 ]. r0 ^2 \
  7.             echo 'I am test!';" }# m2 q0 X2 R
  8.         }! T4 r1 U! _" N) s7 S! m
  9. }
    8 C1 {* {+ C0 n8 G. D
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
4 w" I4 L0 M: A& u8 K
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

+ l) r; M* t6 E7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    : k. J7 x8 \2 G- i/ F
  2. ( M! x3 i- J+ z
  3. namespace test;
    ) S3 i8 ]. `: [; b* U
  4. echo 'zhai14';
    6 e6 u: k1 h  J& v2 j/ [; g% w
  5. namespace zhai;
    . {/ W$ ~5 z% G7 I
  6. require './1.php';
复制代码
5 Q8 h  E6 p6 w$ d) ^+ f
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

6 ]- ?; d" j7 P7 |9 Y8 ]use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。8 p3 b' N1 ?! l
  1. //name.php! R: [% y! m* ^
  2. ; `: o1 T' h- t, M
  3. namespace animal\dog;
    , y: F+ R5 X# `- b4 K

  4. ; f9 ~' m5 R7 a: Z- v
  5. class Life{
    9 P# s3 U' ^1 w0 u7 t& T- s
  6.     function __construct(){! _& n8 e( {0 u- o% N
  7.             echo 'dog life!';: k' S: N, S, r4 |
  8.         }
    . t& ^8 H6 B. Z8 B) ?6 u5 F
  9. }# i# k: u, ]9 V. ~7 N( z
  10. # @% _5 r2 q: u$ |2 i: z2 i
  11. namespace animal\cat;( N6 W- u6 X) f, K) E

  12. 0 }1 p9 N1 d$ M/ f+ J
  13. class Life{9 w% T! e  m, w
  14.     function __construct(){
    0 O$ H8 Z% ]# U
  15.             echo 'cat life!';3 T' B% a4 ]' x5 q
  16.         }
    3 {8 N  L; I  y# Y4 I/ v8 ^; J
  17. }
    % \7 [# C7 Y# Z/ N  H  C
  18. 6 b7 |  `2 O! s2 m' f& @" u5 p
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    ' m5 A: X( d% |! S
  20. new \animal\dog\Life();  //A6 F- D' D: f. m' c# T
  21. ; m: X& {2 S5 f9 J* X5 h1 t8 t
  22. use animal\dog;  //a
    ! [1 j! g0 U; r  H6 E5 v: \
  23. new dog\Life();  //B& ^  p$ C- {* `1 _
  24. ! H5 Y0 O6 g( @* Q1 ~
  25. use animal\dog as d;  //b/ j$ T) Z; Q3 J7 H* r% o  s. w8 n
  26. new d\Life();
复制代码
3 f. w- x3 S7 d8 i) ?
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
2 d& @6 Z2 Y4 ?/ s
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
+ b/ E1 r, \3 f0 y# C/ X
相当于
  1. use animal\dog as dog;
复制代码
7 p" ^+ [- G+ _$ m' d
2.namespace后面不建议加类名,但use后可以。
5 [! \! J' ^: I
  1. //name.php0 ]- B! A& X; U9 B
  2. $ r7 H. f& h; n9 U
  3. namespace animal\dog;
    6 b  Y! m: w* C! A1 m  m

  4. + X4 t( t$ M, p; f7 E5 E  R0 D
  5. class Life{% {, B+ u8 s& _8 A: K
  6.     function __construct(){
    " N. t: h! j2 C8 y; Z
  7.             echo 'dog life!';
    $ I1 @4 O, F5 H4 j5 q- I
  8.         }
    3 H, k2 p6 t6 x6 X5 R2 o3 X! ~
  9. }8 z8 i" \3 ~2 O5 j3 y
  10. % i; H6 A% V% X* p! ~) Q
  11. namespace animal\cat;, O* y! C. o/ A+ o$ u+ f1 O

  12. 9 x& W$ a9 A6 `0 u7 x' ?
  13. class Life{
    ; \7 O) v& L  o- r' P2 @
  14.     function __construct(){
    # J1 Q, f& S/ G& L5 F5 O( v# s- F8 ?
  15.             echo 'cat life!';
    5 f1 h) b  n) }3 e: R1 D
  16.         }
    8 _4 a7 W' E' v" o/ L- a8 r
  17. }( }! K9 O. \& |' w

  18. ) S* z: W3 C( w" B8 [7 J
  19. use animal\dog\Life as dog;  
    , T8 A" O% B0 J, k9 s
  20. new dog();
复制代码

: \" G3 w4 H! v
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
! M% K% B- a  q2 {
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    & u  x/ Y$ B# I( P$ R4 G
  2. * J  V/ U) Z- l5 H* I
  3. namespace animal\dog;( w4 K; D" ]- ~4 x* f- D: e- j
  4. ; N7 A( k2 o: r7 n
  5. class Life{
    * w) u* c3 z. K# m. q
  6.     function __construct(){! `/ g" n/ f& I6 q/ @
  7.             echo 'dog life!';
    : X+ f$ S* Y& j1 _8 A
  8.         }6 K! I+ L$ t. O1 O9 @
  9. }
    ! T6 a. R! \: `" U: J
  10. class Dog{# S3 l, @; G. W9 {7 a4 `0 Z; S
  11.     function __construct(){! Y8 {. i: Q( J
  12.             echo 'dog in dog!';; ^/ I) \$ l" t; i# t. g! c
  13.         }
    ; X5 O! N& a/ i8 X' ]2 v) B% ^
  14. }
    . k( s9 X  D8 z- v# R* I& o) d

  15. ( b0 U# ^. r+ c, n8 P' r
  16. namespace animal\cat;
    1 [; S+ n" v- A: L. a

  17. 4 X3 y2 b! L9 r8 p2 _* @; e( k4 y
  18. // class Dog{
    " f0 n6 E0 t* @. m3 [
  19. //     function __construct(){
    1 p" n0 l0 ?3 @$ M1 Z5 J( b( s
  20. //             echo 'dog in cat!';
    . h4 j' N4 w: Y. W, X" m& e' t! r
  21. //         }
    * T: n$ x; q' f3 [" e
  22. // }0 ?# F: e0 F3 {, p6 X
  23. class Life{$ ^# g" v) Q, H. }! x
  24.     function __construct(){) z7 h5 t% h8 z& E: [1 [1 _
  25.             echo 'cat life!';
    3 i# H9 y" O+ ^* |6 u7 N7 ~
  26.         }0 J$ b* M/ c. x* h& b, Y
  27. }4 H9 z  N" z% }* _, A1 i2 u8 }
  28. / X. ]$ w" D* H- a" {+ [1 Y2 G
  29. use animal\dog;  
    ( p" I) T3 o% {4 _
  30. new dog\Dog();
复制代码

3 d3 q" B9 \4 n( |* g
如上,使用了
  1. use animal\dog;
复制代码
4 V, Z3 b; ~) D. y% _: I% F
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
) @- D2 y5 c$ r4 s, o$ B
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

0 L4 \- U- ^2 L$ D( B: E* O
9 K5 m  B; w7 F+ |. {4 ?% z7 F3 ^+ c) ?% `; x
5 i0 j: c( T. c4 u" V/ J2 A* y! }  i% A
! I7 \* E' n9 k
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-4-30 16:18 , Processed in 0.054558 second(s), 20 queries .

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