|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 % m3 W# d: a" U
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
+ Z0 N6 W& {# A5 w1 {1 C- x; p( Z4 y' \; Z2 A
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
; D- t; H: [/ V/ U- t: K: T7 y据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
+ h+ T5 D- ^+ k- Q2 e结合使用方法来进一步理解它的使用目的吧。
1 L/ q5 m0 ?1 [) r5 g) i5 \5 ^ P- a
2 I/ V9 B$ _- ?& f+ Bnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;- ~. w' h# Z0 P1 Q' S s0 u0 `1 ^
- namespace One;% J) ?2 ]3 h% W/ U! z$ |/ f. l
- namespace ONE;
复制代码
6 f* V9 }$ @* V3 l& e7 f/ V7 o如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) - Y* j( W0 I) r! u
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 7 E; e7 \' T$ c* T
- class Person{
7 b* M/ Z7 b+ R - function __construct(){
1 J7 g ]* R1 v* G: w7 A1 g - echo 'I am one!';
w) s# c ^# [% C- m! y' T - }
* I% J3 \& R9 F- A3 a - }
复制代码- //name.php- I% [3 H# Y+ C4 `5 L- E
- require_once './1.php';
$ ~. D: D) m8 `6 ?# d - & B8 @. e- d/ Z9 p7 p
- new Person(); //输出 I am one!;3 ?" F) T7 C7 j: S+ e
- new \Person(); //输出 I am one!;
复制代码
& p+ b! w/ V7 Q; ?; C# ^9 N% W3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php T' I6 T' ]3 M
- require_once './1.php';+ V8 \+ G: ]+ O9 t+ k) P" T
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 % ]) N) F7 \# Y, M: Z
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 3 l5 {& H. o8 M: |9 Q" l
- namespace one;
! X( U6 Y. y n) h8 x, g- }7 W - class Person{5 ]8 o4 t; e3 @
- function __construct(){
- H" D6 T0 ^, M- W( K - echo 'I am one!';
; c# z/ y% Q- f7 y - }
6 y' H5 U# P1 _# j) f - }
复制代码- //name.php
& Z5 w% u1 T/ F0 Z1 z. B - require_once './1.php';% j3 ~, ~; r7 X, T ~
- new \one\Person(); //输出 I am one!;
1 k6 [2 R, [! o1 E6 K- C5 |4 U$ O) P - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
+ a( D* l7 Q( }7 f4 u# Z; t可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
t3 Q3 p9 N: O5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
! P2 p0 k2 a9 k- //1.php
: p) q% P" H- }/ _5 b - namespace one;2 e% I0 i" j$ n/ ^3 b# `
- class Person{: Q& {' m6 g' I# ?
- function __construct(){( h" U+ C! D- j, w, L
- echo 'I am one!';9 {/ V3 i3 ^' a7 G7 f" P* _ F" h a
- }
* D6 X3 K8 d! |) i - }
复制代码- //name.php' r# [. Q6 }3 ]4 @, W. R* U$ e
- namespace test;
$ \! D2 K4 r4 E) H( J4 v* S - require './1.php';
6 ^" S/ H) A* p# g" c% W/ D - new \one\Person(); //输出 I am one!;
& T1 z# \3 \% P - new Person(); //这里结果会是什么呢,猜猜看5 g9 [3 [1 B( ^$ m# h% h3 v$ G0 z
- 最后一行结果报错:6 B1 |; O2 Q A& s% \$ B
- Fatal error: Class 'test\Person' not found
复制代码
+ `( _: a( w u3 X! ?
7 I# q" A7 Z9 j( A+ r首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 3 p: n7 I/ G! d- u# n
结果报错: - Fatal error: Class 'Person' not found
复制代码 0 W0 W" Z2 z. f- b% s
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
. v4 l. {3 o- e8 a' L - namespace test;
* b4 N) p) P/ `$ K' f - require './1.php';
' K% G- d$ R: \/ b' q - . I/ c; U- X ]3 {
- class Person{& f8 A' J$ G2 C/ ?# f1 W# R1 W9 V
- function __construct(){
8 `: X% V i2 a$ o7 s4 h) ?5 m5 o - echo 'I am test!';( n8 R5 V* f* G& t0 J
- }
# l: {$ S- i9 H6 y4 z# v$ D - } H( r) H4 ]/ j Z3 }
/ X; w/ ]( j5 F5 e, b- new \one\Person(); //输出 I am one!;3 {" D* o8 `% R, s; Z
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 + R% H& D" L3 y# p* \1 N0 d1 w
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
; A$ G* f# m$ U8 [ - namespace test;
) g+ Z/ L8 P$ Y2 R& P - namespace one;
. ~: y2 E O$ |! g' [ - class Person{" u! i# f# g3 F! {& ^
- function __construct(){
9 w w5 y: {7 _( ?3 c$ K - echo 'I am one!';
* R. I) g' D- Q _; `. ]& Y4 r - }) y0 ?- a% m9 _5 g% Z
- }
3 L! H$ ^2 ^5 t; W& S& A% d6 [9 g - ) E4 G) [1 `! |3 O( F) p
- class Person{; { k A4 u7 i7 B
- function __construct(){
: n) f; I* h$ Q" ~8 C; [ - echo 'I am test!';
8 r9 D k/ j6 A% t' F - }
; b8 s x3 J3 _8 O+ ^3 V: Y1 D - }
复制代码 & d5 f3 D1 H( e( o4 o# q: l3 ^. Y
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
+ Y& L4 N* h0 H6 V z; D看来简单的把require理解为替换,在这里行不通。
$ g0 h; N. W& C7 N6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。 T9 B+ E' m" T. v: _
- //name.php* e4 m' A; q, J5 n" R- r- N
5 G' g4 {+ C' t& ~) [8 e+ k- namespace test\person;
' I/ ~5 A8 k% Y, ^1 g' m: b0 S$ m - / m; g) c; u" S* `, b0 g* ]
- class Person{
1 t# l0 p+ B+ G; U& u - function __construct(){% G7 V8 |: K7 U9 j4 Y* {
- echo 'I am test!';
9 G0 W5 {, j* T, j! z - }; e1 \) m/ j- t8 v: i6 U
- }1 F6 v+ j2 m: i& p. T+ Z
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
) g9 w# B. @. F: ] b2 l4 {. h不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
7 N1 Q3 Q9 s9 H# N( `9 O7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
% X) ~' O1 u9 Z# P - ! x; Z* j2 D# y) ?' J! N: I7 y! _
- namespace test;
7 }7 c" b. ~ z9 @9 s: F y - echo 'zhai14';* a- `* |7 h3 [- o7 t
- namespace zhai;" e8 _; @. X p- i, z9 F9 _
- require './1.php';
复制代码 ) S5 | ]8 E( a2 e( v$ }
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 k% S; a0 L0 l
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
2 c: |7 n9 e8 S3 z- //name.php! t# N" P# G( Y2 z
' H) P6 I) r! |1 Y- namespace animal\dog;
6 c6 P0 W3 k- d* ?: E& y' T3 n
8 L5 ?5 F: P, Q0 F- class Life{# D0 u! ^6 S& k0 [
- function __construct(){
/ L: _6 Q" A& d3 D$ H( B. s - echo 'dog life!'; y1 J5 ?& V4 X& X' n
- }/ v. R V' H( M3 O; g5 w
- }& l0 \" e& z8 g" x
9 z; q. o# Z3 N( n5 V. ^. _; e% _- namespace animal\cat;
7 F1 u& S$ q9 W S( |( W, f$ ^& _) F - O# b5 U( j# j& B3 X4 m
- class Life{
5 c' n2 r3 R5 |. C% C! C+ @% S - function __construct(){
8 J. H$ Z) Z5 b$ x - echo 'cat life!';
$ {2 m9 e' X% U - }
4 A9 T* U, r9 _* d, x - }
" E$ D; ]- B* {( D: Y: A8 o
6 o$ a. c, @7 p$ b- a3 a- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间4 \: i8 }4 d5 @$ A# v
- new \animal\dog\Life(); //A
" {6 C5 A: d+ Y; Q( z- w1 x - # r% g5 _# I2 l2 V
- use animal\dog; //a
; u1 S" ~; _. A3 J - new dog\Life(); //B# }+ S/ S- f }7 _1 K
- + e: G; m/ b8 M" W$ [6 @, g
- use animal\dog as d; //b5 A/ {- K7 u& f4 Y9 g6 I# V- C
- new d\Life();
复制代码 4 ?( \. j8 F# U
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
9 D8 h2 i) t2 ~; W4 D3 H& L通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: # i- B a1 A1 _
相当于 ( I6 x( [& T, @2 U' W
2.namespace后面不建议加类名,但use后可以。* j5 Y/ i, g1 X6 V7 X
- //name.php( A* f5 p5 y4 x. m" m: h
/ S$ E, \" _ w% A! x: P- namespace animal\dog;
8 P E2 V; n$ q1 G, ] - 3 }7 {8 L& S9 ~! q' a
- class Life{. c! e1 k. L7 @* }4 U! C% n/ a3 q7 f
- function __construct(){
- n; V% x/ K2 r - echo 'dog life!';
' D; `. w( g* ^ D( k# | - }8 L' e6 t! w8 u0 D/ K
- }
" g9 F( }/ u. T5 s% a
- c5 Y1 l- r5 N1 E1 ]! M- L3 q- namespace animal\cat;2 d+ y9 s( h1 Y' M. X5 g I7 y
- 8 C: ~! h6 \ K
- class Life{3 {! L- l3 A9 m
- function __construct(){& r9 G1 f8 m5 U" R
- echo 'cat life!';( q( ~# ?8 Z1 o* R4 `3 n
- }( \8 q7 C- H8 o* `0 p
- }
/ y1 N+ C; \+ j) \+ M' a7 R9 T - * `' Y& K: c" \/ ]& c
- use animal\dog\Life as dog; - I8 {+ H7 G3 @8 l! G0 j
- new dog();
复制代码
: s; l, v6 D" d: B3 X如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 2 M# B( T3 o c; I
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php5 k6 o" H8 b7 }8 x4 x
( |7 t- t5 A8 P. d* X) v- namespace animal\dog;( d% f+ Q+ i; S6 e
' D9 H. J% z# z9 u- class Life{& L% `! n; a8 K3 Z" t. f
- function __construct(){
/ t) Y2 p: S4 R/ M! k" X& Z& F - echo 'dog life!';0 q0 H4 J. ?0 p$ N4 `$ V; y- ^
- }# \* D2 M% D1 |, Z9 q2 b- D) d
- }. [3 Y& a; ]* W0 I6 t: B
- class Dog{
9 C8 U5 a& m4 p) [ - function __construct(){' f- `& k- j* q" L
- echo 'dog in dog!';/ Z, }+ G' J+ g( `( M( g
- }
8 j( ^7 @+ y9 s% D8 |/ Z - }* ]/ B$ f) q6 @! n+ @7 ^& }+ j
- D: o1 l; V5 q! }6 Z, D
- namespace animal\cat;1 f/ Q0 x# [. P7 }+ G# w. J9 e
- 4 H+ V$ ^0 S" r
- // class Dog{$ i1 \5 L* c8 b4 |0 v2 g: N
- // function __construct(){: d: m/ W# _. K4 g
- // echo 'dog in cat!';
; C( C: }* e$ b - // } H* y) D0 R9 F
- // }
% B' Q6 O, b8 ]: V) C - class Life{
, y( \7 N& [* T0 o) ~! O" D# { - function __construct(){+ M' ?" D3 S* q3 D+ B
- echo 'cat life!';: n$ s& w# Z4 n! K3 f
- }4 P( v- i& _: l3 C, w, J5 h) L8 A
- }
7 f+ Q* l' ^7 ~* h: T* X - $ `/ U2 |4 q. L1 g: A
- use animal\dog;
! L3 a- B# J l3 |, W0 i, C - new dog\Dog();
复制代码 & ^/ S! y, k4 m1 B: b3 Q
如上,使用了 / q+ E: t9 }$ q
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 # G* [ F L" z$ {2 `# h
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
) V# Q5 r. M/ z
2 H V6 o4 D4 K1 [$ \: _1 h: q' Z- q) t, n/ a$ g: S6 M
/ }& S# x5 u8 z
+ `) h+ S5 t' x: u+ h
|