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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
2 b6 i) x4 _3 o* u
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
" H6 n+ ?: O  w& k% ]$ C1 a

( g; C, |5 A; U+ R使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;

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

( G- B( r/ i/ W$ l. u4 _/ \# ^结合使用方法来进一步理解它的使用目的吧。

' t% |4 P) X/ ]5 g; ~0 m( L. W1 ~: {0 n( ^2 ?
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;! t5 x) M# O7 }' u. L8 `1 z
  2. namespace One;% W4 [0 j* [, X1 X  y
  3. namespace ONE;
复制代码

# I9 ?  ]- K6 f* B! O
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

3 m9 Y* ]: P* b& c2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   6 [' @, v; p$ t8 V
  2. class Person{7 G, B) h, k0 g1 O
  3.     function __construct(){/ J0 A- Q/ a& L+ N
  4.             echo 'I am one!';. D7 M; U+ _! y9 y; ^) k1 g
  5.         }& `1 h+ @, f; A3 Q, X+ E! S
  6. }
复制代码
  1. //name.php  h  T8 Y& B" z
  2. require_once './1.php';: A8 F5 L' g. g

  3. 5 h* R- V* n; K) O
  4. new Person();     //输出 I am one!;2 d/ D* K: F; j7 s" D/ V
  5. new \Person(); //输出 I am one!;
复制代码
9 O5 s3 o. m+ ~( _0 U  A6 v
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    3 @  w1 h( t( {" k
  2. require_once './1.php';
    ! R$ H$ C$ ?1 s. E
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
, G9 k& A. g' Z2 n
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   . ~* u9 ~, Y; ]4 i: Y! f
  2. namespace one;' p6 q3 }0 K0 a6 w
  3. class Person{
    $ U" E' R1 p6 t/ f7 v  r: T
  4.     function __construct(){
    $ u& {( H5 b7 H) F/ k5 x  A
  5.             echo 'I am one!';
    + C- X9 N) Y1 w
  6.         }* H- U( _" P0 p# y  V  j% ]" x
  7. }
复制代码
  1. //name.php' f5 I, u6 W  d7 R! H" e/ z2 i
  2. require_once './1.php';+ s! s$ u) d! Z
  3. new \one\Person(); //输出 I am one!;
    ) q9 }3 k1 ~' `( I! A* Y
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

7 Y9 U' f4 ?4 a& c9 c
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

6 i# E0 H3 W7 I  I: |( M) k5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
* {1 ]! j% P" t7 i! L
  1. //1.php   ( ]- ^4 x1 t5 K
  2. namespace one;0 s) j$ G! H( o8 Y' H( r3 j. @& q
  3. class Person{
    ; @" N+ U! D( L, e. }
  4.     function __construct(){, w/ D$ |0 H6 O2 q1 P  [! d
  5.             echo 'I am one!';3 X& F! I* n2 s& j8 t
  6.         }
    + _) `6 W! P0 e, F0 ?" ?
  7. }
复制代码
  1. //name.php
    % p2 V( w5 l" j
  2. namespace test;
    " I( L1 U* u- E( H
  3. require './1.php'; 3 c0 c& f5 {& K+ f4 [3 X& N
  4. new \one\Person(); //输出 I am one!;
    + a2 ^" C4 V6 M' ]$ L
  5. new Person();      //这里结果会是什么呢,猜猜看
    9 @# T" d+ G$ g
  6. 最后一行结果报错:
    1 A' s. J' m+ K2 n1 |
  7. Fatal error:  Class 'test\Person' not found
复制代码

- K* V5 q0 Y% j5 N8 Q

, ^9 B6 T6 G7 }# l6 _, ?( Z首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
- [6 w) O+ s. I* F% @; S$ U
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
+ [/ m2 W4 S* w* R* J1 p8 M
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    7 B* ?" k$ R7 D* B- V
  2. namespace test;+ R+ A: Y( h$ |
  3. require './1.php';
    ! e! T: H' ]3 D4 Q3 d- |  x

  4. ' L. k# T0 a( h! H6 B) ]! t. J: O' w% P
  5. class Person{
    8 F% r5 ~" O: l, d2 ^& N1 y/ g
  6.     function __construct(){) K) A8 E8 [$ O) |
  7.             echo 'I am test!';; t! A2 L/ ?4 Q5 A0 {; r/ h# i; _
  8.         }
    . i$ }' P! [+ f1 g3 D1 ~
  9. }6 l) t) O6 p2 P  t/ E, a9 Y
  10. / ~+ ]% E4 ^# P0 K6 a
  11. new \one\Person(); //输出 I am one!;
    $ \  f: H5 M: T. D0 F6 ~# Q
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
  e$ ]8 T& R6 c7 M% p! `
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    ' m! E# h7 E# ^0 o2 T) Y! L
  2. namespace test;7 x- L9 Q  t  m- L/ \/ v: H5 J8 z
  3. namespace one;
    " Q$ n$ d: p% D+ p
  4. class Person{, P. N6 M! y+ {
  5.     function __construct(){2 b2 e# r/ p1 l% d. M+ C$ p
  6.             echo 'I am one!';
    . [' o$ F% o# E
  7.         }
    * Q# r! p. j  B. t3 Z
  8. }# U* r* L' s1 s2 X4 @

  9. / v( ~$ a4 Y' W6 q
  10. class Person{( i$ r5 K+ |' ^5 P
  11.     function __construct(){
    / L  @& ^- G3 a1 M" E# F; o
  12.             echo 'I am test!';
    9 T+ V" M4 O; J, a
  13.         }
    # A/ q( @2 d' _. ^' q. x
  14. }
复制代码

+ l0 l$ E  F2 M# v% E
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
& T7 @5 F& T2 H" H. `% a3 B
看来简单的把require理解为替换,在这里行不通。
0 m6 `0 F6 s+ [0 A% M/ b
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
! Q8 O$ F. I- _2 k: n5 T7 N- H
  1. //name.php" M4 ^9 }4 h! J' Q1 Z
  2. * \) e" w7 f/ X& U# K/ t' j
  3. namespace test\person;: N  a) r$ {4 V; u$ W# p% g+ U
  4. 0 y" B! w- D. i! f3 M
  5. class Person{' W: ~# D; @4 C7 ^% f
  6.     function __construct(){3 S5 }; v8 u1 Q: e
  7.             echo 'I am test!';
    ( O# S9 I: B0 K9 C8 _( m: _
  8.         }
    # j  j6 g( @9 K0 w7 M
  9. }4 X7 b3 R- S, t- N* m! F
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
1 \: f' V7 b5 H7 p5 C/ E& C
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

& i/ x* V0 I: |7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    2 a# y6 U6 [4 G9 `
  2. 5 D0 Q0 r" }2 U3 K
  3. namespace test;5 j; \1 `1 S2 D1 [+ E. u! b# h: s9 |
  4. echo 'zhai14';3 D3 t. \0 e, J
  5. namespace zhai;4 u) c9 C* f6 `) c3 V
  6. require './1.php';
复制代码
7 H6 L! ^2 V- Y) W
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

; i! ?" W+ P2 Ruse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。  T! H  l9 V% b
  1. //name.php
    - W4 ]% h, G0 V# g: Q) d  \* k4 T
  2. 0 f) q6 i6 p$ U
  3. namespace animal\dog;) V' w  M) [9 L* j3 w. Q
  4. 2 i' D9 b9 s7 Y6 h
  5. class Life{
    ; e$ b! x: {* Z# S. t. |. F0 ~# l' a4 u: y
  6.     function __construct(){0 K; p% C7 y7 f: ^) ?9 N0 R
  7.             echo 'dog life!';
    # Q* v9 h3 b- Y: ]6 x7 X, C# ^" m
  8.         }& b8 J3 ^. W0 A/ g* U
  9. }1 u; ]8 J0 `# [1 `# t
  10. % d& l1 Z) ?8 v( c( i8 f0 C  U
  11. namespace animal\cat;
    6 F& J0 ]0 a, z( \. ^
  12. 3 u/ I9 ]/ D% F
  13. class Life{
    - G. _- }2 X$ M
  14.     function __construct(){0 y. I, y6 ~7 c" r0 G5 U7 F7 D) d
  15.             echo 'cat life!';
    . p$ u/ i) ]" V( P' ~
  16.         }
    & Y; P" E* f, H+ B8 d
  17. }
    7 B3 @: `( ~+ S3 V7 P# U) s9 u

  18. 8 M# n5 [& X4 u2 I, L
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    + q% E0 u( j+ Q, p5 Q( X
  20. new \animal\dog\Life();  //A) _4 d. @: V7 U5 W, D4 x" H
  21. 3 `( J) F; ]) m0 j7 j2 {. ~$ p( x" P  f/ ^
  22. use animal\dog;  //a0 l: n8 R9 L. [$ ]
  23. new dog\Life();  //B
    ' v; b* M( H) i  W! L8 K0 p6 T
  24. 7 Z) X" u8 y/ q$ h& n, U7 g
  25. use animal\dog as d;  //b
    . P. c& j4 H" J3 f+ `, [
  26. new d\Life();
复制代码

, G  H  Y7 ]8 k* t2 w3 W7 W' }
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
  ^- Q5 m) i, q8 `9 k7 n* e- K
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

: O( x0 P( @0 p1 q
相当于
  1. use animal\dog as dog;
复制代码

! n& r" O0 }: o% K. ^. Y+ [( C2.namespace后面不建议加类名,但use后可以。
: j( o" @6 j# t  M) {
  1. //name.php
    / o- d, r& h$ c5 P
  2. * Y1 b- @. ]8 o# x% e8 J
  3. namespace animal\dog;
    " b7 Z& `" A8 [
  4. / b# B7 `4 B  l
  5. class Life{* g: G2 Z, r- u0 c1 B
  6.     function __construct(){% l1 a/ F  v  n
  7.             echo 'dog life!';7 j# B8 Y5 m2 R5 f. S
  8.         }
    - l6 Y- U2 s/ P" E" e1 N; E
  9. }
    8 ?! u6 C8 j* t
  10. % @- M% H! m9 y- X/ w+ V: s% p( a
  11. namespace animal\cat;2 ~8 G7 \) m' p: {0 N( K1 _) Q
  12. % E, t9 d0 L, G# m! T0 L8 A
  13. class Life{
    , Y, |" y6 h2 s0 I( X
  14.     function __construct(){% u1 Y+ W, H. {+ m% {- T, `2 I8 w# K: O$ ?
  15.             echo 'cat life!';$ L6 T& @/ q/ i$ O! F* V
  16.         }! W6 J7 \- I- l! Z1 \
  17. }  }3 V" ?2 m4 e" j

  18. ' s4 A. \0 X7 x
  19. use animal\dog\Life as dog;  
    ; v5 y/ A8 Z3 F0 l  N
  20. new dog();
复制代码

7 X# t6 t$ G; y3 x9 k2 M9 y+ E
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
# w/ \- j( z, c# o
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php. w0 {8 ?: b' {, o6 ~$ O
  2. $ t9 Y9 |' I) b' f
  3. namespace animal\dog;
    & Q# T5 z8 `  W' J" B$ s; R
  4. 2 G, x8 _( y' M& r/ [" K
  5. class Life{
    " H" N) C8 ?# N  Q0 b
  6.     function __construct(){
    # d6 `, ~: Z4 {% j1 P  p: l  v
  7.             echo 'dog life!';2 F6 V( S$ D6 g( I
  8.         }
    ! B0 |! M4 W# ^0 J; ]2 B" {0 a
  9. }$ m, m/ l0 s7 ~8 W9 Z  ~
  10. class Dog{. n8 ?' f6 r- d2 ?& |+ P
  11.     function __construct(){
    , J: S& y  F( N: \0 j8 d
  12.             echo 'dog in dog!';6 t* L$ O5 L3 y/ M. \6 U; t' V
  13.         }
    7 G0 O# W! t, x. o4 b0 ]: X1 @; i
  14. }
    * J( E5 j0 U3 x) t
  15. 7 L2 ~: ]$ x4 K) s' Y- Q/ J9 o8 D7 y  z
  16. namespace animal\cat;
    & |# `  h5 ~! g0 L. ?  ~5 ?9 x' i
  17. $ r% [) q; ~" G7 p8 l; O+ g
  18. // class Dog{- [' O" T3 @: l
  19. //     function __construct(){
    * Z% G/ ]2 {. d" `4 N; w6 C" T
  20. //             echo 'dog in cat!';8 `! v4 M9 i8 s: |7 C7 b5 ^
  21. //         }+ |: z9 m8 [5 K0 J  c
  22. // }
    ' ]' R' F2 G% ]! z7 Z( T6 X7 Z3 F
  23. class Life{
    # ~& D4 g& l% X
  24.     function __construct(){
    . h. f- W$ a- c0 b  ~. [% t, V& B
  25.             echo 'cat life!';" A, J# z. G, a5 e2 g& P
  26.         }
    ; f1 j7 Q" d& G7 ^! `
  27. }
    ( |( B% b. E5 Z6 ~. c' o9 q2 D- F

  28. " _+ U* A( ]3 Q- L9 _7 x4 N
  29. use animal\dog;  + X5 L7 K, r9 n% o( `0 c* c8 ]
  30. new dog\Dog();
复制代码
7 b' ^- {7 f. W8 B$ H
如上,使用了
  1. use animal\dog;
复制代码

4 ?. _  Q# I& c$ A! G
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
! I% S% o' _+ V! b: M
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
6 k; P7 y7 R1 B5 S

! a: H; v$ a# k* j6 w8 J) Z- z" K2 @* C2 k) q* M1 A

* Z; n; Y( {9 W8 s1 ]3 x
3 b9 x, m# C" ~5 O; ^" r5 o* V
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-20 09:19 , Processed in 0.109851 second(s), 19 queries .

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