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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
; X: I+ |5 i2 |9 n: C% c) {
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
( k9 S$ }% @+ r2 D3 F
4 L- @& s9 u+ J* E  ^
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
2 |4 j$ b* c9 I3 z( U
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

3 c% `$ H- z$ g+ g$ h结合使用方法来进一步理解它的使用目的吧。

% ~7 u# |. P0 a& K' \7 N; m( J% m$ e+ f3 r
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;) N# z. A7 j, b, [
  2. namespace One;: I7 d! c! Z* ?. |" t7 X
  3. namespace ONE;
复制代码

# Y" E4 W  [  E5 @2 _
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
7 P, x; a& B/ @1 x2 @& t5 ?& D
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   0 R) q7 e: ~( [/ g* X+ p2 `0 F2 w
  2. class Person{# K! E7 q. u0 V) i- A* j
  3.     function __construct(){
    9 [9 N8 ^/ v; h" l
  4.             echo 'I am one!';' }, C& C( s1 b
  5.         }9 R. Z# D+ O( x6 A6 s2 O
  6. }
复制代码
  1. //name.php2 a7 \- S8 e& i# W0 a
  2. require_once './1.php';
    , s! j- c- X6 t4 }- B

  3. & U8 w$ }; g5 P6 Y5 [* N, z
  4. new Person();     //输出 I am one!;  f6 g& m7 d0 P: h. I  p* a
  5. new \Person(); //输出 I am one!;
复制代码

  ]' k+ M$ f' \3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php( N& t1 H: I" N9 e: j/ ?: s
  2. require_once './1.php';4 D) h& X3 P8 f" {( Q0 ~1 B
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
1 M- n& f. ?- V
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    1 T! c3 z6 r% Z" ]
  2. namespace one;
    9 [$ v: D5 g% C& ~' _, d; ^
  3. class Person{$ r! Q7 X& ~# X, @
  4.     function __construct(){
    " T+ p( G7 h  N& ^
  5.             echo 'I am one!';( j( L! j/ {; ^5 @
  6.         }
    1 A9 x3 n6 L/ z. O/ u
  7. }
复制代码
  1. //name.php
    7 t# i# s% ?- t2 i# \2 F5 l
  2. require_once './1.php';) E; i; i0 x. m. R1 p/ V
  3. new \one\Person(); //输出 I am one!;
    " Q. M* C+ C: e  X' }" \
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

; e( I, T8 E& R8 _' b% Z
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
3 ^. \3 G! W, P! m' ^3 c
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。- Q! i. I3 D2 o0 V
  1. //1.php   
    # I* D' d- B' K# L
  2. namespace one;' S5 Z6 q  q2 ]/ D: h7 N5 O
  3. class Person{
    , |2 D8 r! X2 E: D8 |: y# h4 O
  4.     function __construct(){% X% T% Q" ~' R- i  k
  5.             echo 'I am one!';' |9 p! D. `- ~; p; c7 s9 H% H
  6.         }  G* b. Y- g  l
  7. }
复制代码
  1. //name.php
    & _8 k3 S5 K2 \, h4 _. k
  2. namespace test;
    ( G) q4 n# S' j3 j1 [
  3. require './1.php'; 9 R( g* j- x* U. s
  4. new \one\Person(); //输出 I am one!;( Z3 B  p# g; Y9 h8 Q* p
  5. new Person();      //这里结果会是什么呢,猜猜看
    ' I! E" J; t: c& T( [; @" R* L
  6. 最后一行结果报错:
    ( }$ h( _( r3 g  s4 u1 ]
  7. Fatal error:  Class 'test\Person' not found
复制代码
! f* a2 M* B1 Z: X- R: w2 D
3 [( X5 ~" I0 U) ^
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
* H" m1 a, T  d! M
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

, X; E, ]% @- S: X9 c
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    ) e7 r  n; v! ~( g5 \. i' |* j* e
  2. namespace test;9 v) k, X. V" |
  3. require './1.php';
    6 R" F( w2 y$ l- `! U4 v

  4. ' w1 n6 J3 n* x' b; s
  5. class Person{! N9 J' ^; v6 t% a
  6.     function __construct(){  u; j) v# Y# h3 u' u8 m
  7.             echo 'I am test!';4 Q6 Q3 i4 O) Z' b9 r
  8.         }
    6 F: v) Z5 I. `3 Y9 r; @
  9. }
      n; b% }: g1 S4 K* |) [

  10. 9 C7 v( ^; Z8 w2 W# J9 l
  11. new \one\Person(); //输出 I am one!;
    8 k+ x( j' m% e
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

+ X2 o8 B( b2 o0 d1 k
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php; u! q' x5 h" u, F( |  G8 B$ \. @! Z
  2. namespace test;- b( y1 f6 E- r7 r
  3. namespace one;
    ( W4 w6 F( W& h. U, v
  4. class Person{
    ! J' @$ J1 R  n
  5.     function __construct(){& i; l- Q( P. x  y8 E$ Y2 b: O* H
  6.             echo 'I am one!';
    " T* L2 a" N: r$ I; m
  7.         }4 D  i; t) s6 X  y  V  v2 Q
  8. }
    % }4 R2 \' G( g5 A+ N6 D
  9. . d# i, i6 {. N
  10. class Person{5 W3 P: B; v; w0 n8 e$ h6 C
  11.     function __construct(){$ o* j, L1 `) f. a7 D; I
  12.             echo 'I am test!';
    $ s7 B9 ^) S' G% O% p
  13.         }
    0 J  J* }0 h; J2 s# R
  14. }
复制代码

" A/ S3 o8 K4 Z+ G
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

+ }, E1 s: R* D' u2 ?
看来简单的把require理解为替换,在这里行不通。

' D- O, z2 ~9 C- b$ ]( i6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
5 g7 ~" ^/ }) g" p, o+ x
  1. //name.php
    * H& q: {5 |: `! d% a

  2. / K) ^8 \7 B  M- R# w* X
  3. namespace test\person;" G. `- |& c6 ^$ U8 M2 }! G

  4. 2 i7 S  r6 M: l* Y
  5. class Person{
    2 U/ H# m7 A9 w+ Y6 T$ X
  6.     function __construct(){
    9 U1 U8 t5 v; G: I" g; T
  7.             echo 'I am test!';; b# I! K; Q; [; T* D3 B
  8.         }2 F9 i0 S$ {; T* ?  k- o5 f7 P
  9. }. S" v4 W' ~; j4 u
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

7 p, h& q) \9 l8 p: M: g
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

/ i. k. q) ^1 L! A! I7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php( r$ I+ @- L8 Z
  2. ) I+ }& y" f, J, B8 Y
  3. namespace test;+ ~+ L4 d3 F% Q6 a
  4. echo 'zhai14';: X% w" s- }* r. e5 T& U) u
  5. namespace zhai;
    * H2 z" C1 X5 f- v4 v7 U
  6. require './1.php';
复制代码
& W: x* y( z- w3 b/ `
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

  r7 n9 W0 R6 @" Duse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
' Y( Q2 e: d4 j9 S3 i# a/ N, e2 ^: [
  1. //name.php7 x- i# V+ n7 W( ]2 X& h
  2. ; a( o9 \0 o3 }* N
  3. namespace animal\dog;
    $ u9 `; ]: o; F) b" k2 _2 O2 M

  4.   Q  I# V( A6 \# {( D6 t4 X1 s8 Q& N
  5. class Life{
    ) {! k! j9 s) p. `- q/ y
  6.     function __construct(){
    3 R. b, w/ @# u* v/ Q; P( i4 u
  7.             echo 'dog life!';5 L8 J. V: _8 J6 [4 l3 K; q6 t/ n
  8.         }
    3 Y% f$ Z& B9 |8 w1 S1 I, r
  9. }. s0 G/ F7 O; s( J% P

  10. 2 f( K6 E5 A% U. ]% k  \! P7 F: ^$ V
  11. namespace animal\cat;
    * u# P* K5 i& c: c9 c

  12. 0 [! U5 s( @" D+ V& `
  13. class Life{/ P4 ~# N) `% J2 S% K7 Z( D
  14.     function __construct(){7 Y% P$ ~. O) ]3 U% @+ j9 m0 P+ A
  15.             echo 'cat life!';! G' }8 i. u, G" u2 C5 c8 p/ I
  16.         }* s" @& r( g/ f& p  G1 U
  17. }- b  `- c0 [2 X( O! q0 X3 N

  18. , K1 K, B3 j8 z' {
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间( l+ }0 b! c6 S( e$ ~& i) @. O
  20. new \animal\dog\Life();  //A3 N0 G% T1 z3 ~- j; b4 X5 w
  21. # U7 r5 j* w& X+ H
  22. use animal\dog;  //a
      b% H  R6 E1 Y' \
  23. new dog\Life();  //B: S, H$ |% J& f& {8 N2 t1 p$ r
  24. + g* F3 \/ p' y1 J/ Z
  25. use animal\dog as d;  //b/ O- h5 U1 S1 P; K, M
  26. new d\Life();
复制代码
: `$ l( o, \' U# O
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

  h: o( I3 d/ w5 W+ {2 X
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
' x5 G" N4 s- C( G3 w" t# x
相当于
  1. use animal\dog as dog;
复制代码
. M% b' f2 R2 K+ }9 V) c
2.namespace后面不建议加类名,但use后可以。
$ E2 ~! ]4 F2 C5 u, |
  1. //name.php( L) u( h+ t3 \8 t

  2. ( r$ f9 R6 q1 N9 n# @! @
  3. namespace animal\dog;; [$ O* J5 i1 m* r1 H/ b0 g

  4. / |  K8 V4 x$ Q. R5 A
  5. class Life{$ g: p0 ?0 W+ k0 b  A: [
  6.     function __construct(){8 W1 K8 M' A7 O
  7.             echo 'dog life!';
    4 ~* F0 ?: u# P5 |! o  j6 m
  8.         }
    3 n# w) T* I2 ]2 C2 U! W& g. ^
  9. }
    " u; ]5 F8 h% X7 g6 _

  10. % {7 ]4 i4 [6 S+ h* Z
  11. namespace animal\cat;/ {, Z/ r7 C) ^6 h

  12. ' c) j( m) e4 G, Z" _  G5 F: ~
  13. class Life{. s0 ?4 j, U4 c9 T* U3 ~. Q; d1 {6 f
  14.     function __construct(){  t% F0 \7 ~7 {2 e( c
  15.             echo 'cat life!';
    8 Y, t% D+ R+ S% P1 C8 `2 u
  16.         }
    : E+ ^, K* c7 f8 n/ s, y; F+ G
  17. }6 e/ ~2 W* d5 _0 \
  18. 9 T) m  S# C+ ?
  19. use animal\dog\Life as dog;  
    & X4 o. |! S% r* k
  20. new dog();
复制代码

: i% ?' ]  ^: d& P! d
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

3 p1 \+ B. v9 p
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    , R9 J- Z, |2 `( j9 d6 v
  2. " J# C( p( W0 |( Q6 G
  3. namespace animal\dog;
    2 b$ i3 d& |& q; o
  4. . [. N" p% K- ^& y  ^' T! v1 c
  5. class Life{
    1 F; o* K$ n6 R# c5 {
  6.     function __construct(){# F# Y3 M. L0 _0 D
  7.             echo 'dog life!';: [  g6 ]7 E+ E: H' @) g
  8.         }
    6 r; x+ N) ?2 t. R5 Q2 [) b# ^
  9. }
    4 J- d* S* t5 \1 \
  10. class Dog{+ N. j* ?5 e8 o0 B+ Z- L' Z
  11.     function __construct(){
    4 f- f" Y+ i, S8 |
  12.             echo 'dog in dog!';2 H1 |2 i  I1 S# h* a
  13.         }
    2 {* a, A* p* i% k- K' g% i) X
  14. }
    * y( s9 Z3 P& O% @' e1 _+ i

  15. # `7 w% ?( e" f* N3 e. w. V( ~
  16. namespace animal\cat;
    + x: s# T. W, V: W' k

  17. " u7 H  [! s% _" l* Y
  18. // class Dog{5 R% j9 j( r, r: L
  19. //     function __construct(){
    ) Q" i- t! v9 Q! @% L; |+ s5 ?( T+ j
  20. //             echo 'dog in cat!';
    ( j& [: a$ I4 Y  Q
  21. //         }
    ; @% D9 _7 ]$ Y, {9 b0 \
  22. // }
    + X# ~# V* N) T& t0 ?* s
  23. class Life{) v+ K  k5 b' }! g4 j
  24.     function __construct(){4 _6 Y7 }( g. d
  25.             echo 'cat life!';) K7 @% @7 R; k; |5 ?% j& T) a  \
  26.         }
    " I# _6 j- Y8 d0 f  s6 @
  27. }" Z' r, t, h# p9 R1 O

  28. - Y: O' h1 s3 A4 S: U& }2 g
  29. use animal\dog;  & n5 Q, ]! }  K" m% k7 m  S- G
  30. new dog\Dog();
复制代码

" {9 @5 N- l8 s$ D' o- T  x9 b  z
如上,使用了
  1. use animal\dog;
复制代码

4 Z1 V& P0 }" q
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
; Q1 L; l6 [- @8 s7 _
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
+ e/ J/ y. ^2 [5 ^; `1 n

0 O+ L8 e# n* g0 K1 j# H3 N6 P8 z) b- C* o' I8 n# m2 S4 x
. |6 u3 W/ D# S  |2 ^! R- o+ h
. R: O! t. f1 B0 u! A# W/ \* e& F
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-16 15:23 , Processed in 0.059305 second(s), 20 queries .

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