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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

* i1 u% X( D) K! R$ `3 u* _
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法

% j) M$ l0 Q/ Y! b5 N9 \  @3 J2 \# j+ [
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
6 P0 T4 A5 |% v: d
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

0 ]' W3 S, n8 U7 `2 b1 ^2 I7 K! Z结合使用方法来进一步理解它的使用目的吧。

$ B% x' ]' B* q) }0 W7 D1 R( C& A+ m
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    ) Z7 f( Z, L# L
  2. namespace One;" t, ]& M0 |5 j6 e5 R
  3. namespace ONE;
复制代码

8 t5 B: C0 Y* P1 J+ Z' }
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
* O7 ?4 h7 n! _- h+ q9 c$ p9 q1 A
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   & W3 }# N2 A3 L" J- G
  2. class Person{
    - [9 R1 Q( S. `& i1 z5 h. a" _0 c8 ~
  3.     function __construct(){" l" P! _6 T) s$ s" T5 p
  4.             echo 'I am one!';
    0 t) ]) l' o; k1 E
  5.         }
    8 D6 d, N) o0 \. ]' R& V
  6. }
复制代码
  1. //name.php- R+ |  p5 m3 L
  2. require_once './1.php';% t; H9 P5 s4 K3 d' K( `2 }
  3. - M! L! f. P$ b6 I
  4. new Person();     //输出 I am one!;
    & }& m) S3 u& i8 U" d$ `
  5. new \Person(); //输出 I am one!;
复制代码
! p4 ^7 ~2 F( Y
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php, C+ F; E( h" \$ h; c, N# a
  2. require_once './1.php';
    % I" {0 r. N% J; w
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
( Y& t$ K1 Z7 Z# {
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    ) W: g9 H4 q' k8 m1 ^9 {+ D8 T, b/ J
  2. namespace one;: n% p/ f2 E  X$ K' j# J* L6 E& X
  3. class Person{
    ; d6 B. W4 j* b" `5 p% b
  4.     function __construct(){$ d( e( U# C5 Z9 X* N. K' I& @+ q
  5.             echo 'I am one!';
    ; z( l. t' j% v9 [( L
  6.         }$ B* I9 ?: U" J- ~2 E8 Q
  7. }
复制代码
  1. //name.php* E$ R4 [  w- j) I  e& y
  2. require_once './1.php';
    1 g, P9 M# z1 z. o
  3. new \one\Person(); //输出 I am one!;
    ! e3 h8 O9 y( M" T% p
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
4 E9 y; K/ i3 j3 k
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

' n0 f  u5 E8 k. r  e8 H& b5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。" J+ k) }8 q% l; Q* M7 F8 C7 ?
  1. //1.php   $ F8 h. b# j4 U  g; U# G6 A! y2 M
  2. namespace one;+ y: D( ?* A# K
  3. class Person{+ w4 R5 u1 C) [4 M& K9 V
  4.     function __construct(){  q2 J( ]/ L( _2 M4 f
  5.             echo 'I am one!';
    - Z3 Q" Z% Y: U8 U5 e  ~. J$ p
  6.         }8 |, {+ m/ b6 p8 M1 x+ y  N
  7. }
复制代码
  1. //name.php2 I6 o/ S7 B  V: U
  2. namespace test;
    / w+ f  M& a' a$ M
  3. require './1.php'; , \( y- s! T9 E4 T# e9 t- A. x
  4. new \one\Person(); //输出 I am one!;
    # B; g. ?* a, ~" s
  5. new Person();      //这里结果会是什么呢,猜猜看
    , {5 Y9 s; j+ A) e/ n; }2 A
  6. 最后一行结果报错:! d" x3 Z7 Y5 |8 i6 x
  7. Fatal error:  Class 'test\Person' not found
复制代码
% Z$ ^! P6 @, t; }( q6 R
+ m3 S) U  u$ f5 t& G6 I
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
+ @) N& X& i5 y8 l$ S+ s# q- Y
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
7 O' R( _6 }+ ^' N* I
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    : t( T# X5 j5 W
  2. namespace test;
    0 g# V8 k# s; |& P2 t# h
  3. require './1.php';
    4 Z3 d/ y4 v0 M. K0 H+ R* B
  4. ' k: A& a0 p$ h/ f2 P4 G; U
  5. class Person{
    & X0 [+ ^7 ?9 r0 W' y7 H
  6.     function __construct(){
    8 r# s1 J  c% @6 v! Y% W* _/ t/ ^0 t
  7.             echo 'I am test!';) K4 e9 K. p3 F. h& Q! v
  8.         }
    " {( H' \& u& I
  9. }
    * T. \1 [8 T) L, }3 q1 C3 T4 Z) a
  10. 9 a& j: `6 a& U
  11. new \one\Person(); //输出 I am one!;3 ?" o' x6 K2 f2 l+ ?4 S
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

0 y+ W- U4 Q) a" N# ^( f
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    2 y# U4 f2 O5 H5 W- i/ a
  2. namespace test;% h& }$ T: F% e; m/ c1 T
  3. namespace one;
    3 |5 Y5 y" g3 D, N% B% j( g( \/ V
  4. class Person{
    0 ?* f, P# E' k
  5.     function __construct(){: s  j* \/ @5 \1 n
  6.             echo 'I am one!';
    7 h+ J8 s% b6 I. H( Y/ b$ I% U
  7.         }
    # B( a+ p, C# O, D
  8. }
    ) b+ X# Y* x' B( c, j
  9. 3 h8 {/ F7 O: k2 e, K
  10. class Person{
    ) t9 {3 b  \2 b" U$ d
  11.     function __construct(){
    # X: R1 l8 z) f' Y; c
  12.             echo 'I am test!';$ h, L) u! J: N" {
  13.         }
    ! w2 d8 A( K' b
  14. }
复制代码

. V$ K5 N* A* p: x
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
3 H. Z: W1 H  N
看来简单的把require理解为替换,在这里行不通。

7 O$ R0 R2 _  \7 E! e% w4 Q6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
' k/ E5 U# q# H# u+ m  h. }
  1. //name.php8 }' {" e3 W! b3 n* z) X  H# t

  2. : H- x. C4 U0 m/ l
  3. namespace test\person;5 z; p/ S5 h9 U8 j/ U' d

  4. ) N0 ?! b/ i0 `, L
  5. class Person{/ y' ?% `+ x2 ~' Y! b) T  k
  6.     function __construct(){
    # H+ o# p) E# C* ~' [( t! l
  7.             echo 'I am test!';
    3 m9 H7 a! {* |. I8 u
  8.         }
    8 e# m( ?8 O3 A2 U! l  y  h
  9. }& ^& |( |6 Y( k0 x3 C$ U
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码
- c: }5 H& T3 r4 y% V! s: i
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

4 E  b6 ?! W& j/ q# Y" l+ a! I/ K7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php& _# k; Z! {$ Z, a. T
  2. 4 N/ i# S- Q+ {, v; n
  3. namespace test;, R) S7 U/ S5 N2 [' b$ Z
  4. echo 'zhai14';6 z! p8 @- b9 s& \: M/ s
  5. namespace zhai;+ u' T) S+ {3 N
  6. require './1.php';
复制代码
2 F$ E: V& `9 t! W& Y1 i, X
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

7 H3 G+ ?) w2 n. R, vuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
* U9 y4 `; ^% t3 I) I
  1. //name.php
    4 Q6 T1 ~% Z# B- ?

  2. . Z( k5 M; ~. @! U+ |/ F
  3. namespace animal\dog;
    4 m2 m1 C- u1 a7 W- E' L% D* C8 O( L, c

  4. 2 [# s9 ?0 o  M$ ]* A/ n, m
  5. class Life{
    % \. Q' d6 c$ }1 Q4 o1 y# @4 ~
  6.     function __construct(){) @1 j2 y: {0 ]/ n# w& p/ _
  7.             echo 'dog life!';1 I6 v. q# @! `% p
  8.         }7 h6 g; f- z  w# }- A
  9. }
    / I9 F) `6 A7 C. _& _2 o% e1 t

  10. 1 d" s, }% ?2 O  G6 P1 |1 l7 [4 M
  11. namespace animal\cat;
    1 M3 c" {: E4 z2 T4 `: U  }3 S

  12. ' i1 ?" |! x: H9 V/ o! A0 _  f
  13. class Life{1 X0 j, s1 x+ \0 [9 N
  14.     function __construct(){
    & L: ^' P: m0 w) E1 t; q  d
  15.             echo 'cat life!';+ A2 p5 k! l( N5 Z
  16.         }2 y- y; r) e8 ]' L- f  e, c+ x; S3 O
  17. }
      s9 ]4 m  e4 Y9 \3 L5 ]

  18. * A' i7 U  x4 u$ {: E0 t$ T1 u2 D
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    . w/ T& l* l9 b$ S1 s5 W
  20. new \animal\dog\Life();  //A
    # q1 V' V1 ?0 J: P, I2 J$ D
  21.   O( n& g' O: [' F
  22. use animal\dog;  //a
      r+ {! j1 r' k
  23. new dog\Life();  //B
    8 q( \: n3 k$ C7 Y2 t5 _- q, N  D

  24. 3 R: }( V8 h& o5 g! L
  25. use animal\dog as d;  //b3 U: V  Z& _+ p( v0 c9 X  s
  26. new d\Life();
复制代码

" @4 f  {7 }/ ^
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

# Q6 q  m% z3 F2 c; ~8 m  ?: A1 t
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

1 E) Z6 B" A" m' R, e9 k: c
相当于
  1. use animal\dog as dog;
复制代码

7 o: U6 |+ G! `" O: S5 f7 Q2.namespace后面不建议加类名,但use后可以。
& b7 }0 e+ ?0 ]5 y- S( X7 v
  1. //name.php! r) L  i4 f& v7 m) o8 v

  2. , A" P4 |$ J- X& p
  3. namespace animal\dog;
    # x0 b, ~5 R3 r* K% N) y+ q9 o7 `% d7 K+ G
  4. 9 q3 N3 y) _( N% ~
  5. class Life{& L) D  d) H2 E" R, a1 e
  6.     function __construct(){. y. U! L: p. p
  7.             echo 'dog life!';
    . H1 O% Q" E8 {& n$ D, L; f
  8.         }: A4 H& K/ @$ X' d3 m% a
  9. }
    7 r: H! C( d1 n5 Y3 Q& O

  10. 7 L6 x1 i, i4 u) [5 ]/ q* E
  11. namespace animal\cat;
    3 q: W2 P7 i8 ?7 ?* o1 D
  12. 9 \; g3 W  e: q6 U9 G( p( @
  13. class Life{
    3 e/ O  g: U& y0 q1 o6 _
  14.     function __construct(){
    7 @3 Y4 O, e0 [9 _; v+ _
  15.             echo 'cat life!';
    5 O. }0 o" D' ^1 N/ ^
  16.         }
    % I( E$ N- J3 C9 D0 Y7 Z+ c" i" I
  17. }
    * C' K+ M! L; B4 ]4 g

  18. 2 c+ K6 R. e. ~6 _" ~
  19. use animal\dog\Life as dog;  
    # E) v; Y& @+ S) E( p/ ]3 t( K3 [- Y
  20. new dog();
复制代码
$ |' ^6 p; s8 s9 K
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

0 ?6 Y) d( c3 H/ {
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    8 U0 S/ L8 w6 F8 x( _
  2.   Y, S# p; i" D* m
  3. namespace animal\dog;  x* O* k: L  P5 u
  4. , _- A; O$ V# E/ R
  5. class Life{1 V- @6 n1 T5 r
  6.     function __construct(){& u6 A* I! J( v
  7.             echo 'dog life!';+ M. g( @0 _/ L6 B
  8.         }5 A$ ]3 z) e' I3 v
  9. }1 k, H6 \, a' M( X& i
  10. class Dog{& D& }7 p1 ]/ n6 w5 {) {( Y3 k
  11.     function __construct(){
    - ]. Z" W0 i! s) S/ h+ t
  12.             echo 'dog in dog!';' s+ A6 w/ a1 W8 C/ F% c
  13.         }1 S/ w. |+ z7 n' T+ J) ~! i. d/ O
  14. }6 G2 P8 [, G5 @
  15. : ~' Q' i) [: F7 }1 }' |
  16. namespace animal\cat;
    : |- ^) X1 D1 J2 J; o; D+ O
  17. % @4 ]! i  e2 Z2 ~0 _9 W
  18. // class Dog{  g: a* s, V6 A5 d
  19. //     function __construct(){+ \" J# k- t" g  P
  20. //             echo 'dog in cat!';
    4 {( ]% R7 x/ X' g# S1 u% r
  21. //         }
    1 n. J) ]& N9 ~! ^
  22. // }) G/ J1 X0 b/ j- j
  23. class Life{& _, D' f# v; D9 H5 s3 O
  24.     function __construct(){
    + Z7 q4 _; F0 j- H9 q$ S* L- {% K
  25.             echo 'cat life!';7 S1 {! I$ [0 G: f; k: n" E
  26.         }2 ]0 E8 R6 \2 D+ ]) b- V( ?# Y) P: f
  27. }1 j/ N& T" a* S
  28. ! t; H: i/ h8 H) _. f0 M. h6 U: g
  29. use animal\dog;  
    & t% T& C6 v, b  p7 R+ B: Z
  30. new dog\Dog();
复制代码

( A% p# r8 V- m- l+ U4 i
如上,使用了
  1. use animal\dog;
复制代码
  X) i, \6 p# j& }% c
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
, B8 U% w6 F3 }' r8 _( ~
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

1 r" R) Q) x1 `( V  b' w5 V, e$ q3 A7 {% T
7 y6 L7 U# s  c2 [3 a) u5 k

" B! X+ C: J# c) e; J6 a# |4 y( B1 G9 Z1 }5 N. C, c% ]! L
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-20 01:28 , Processed in 0.166343 second(s), 20 queries .

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