|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
: F/ L9 q8 U2 h0 x4 V! D文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 * P$ B( X; m3 h+ t% Y
( `( L2 i$ I: ^
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
0 l( D( }) r. m7 x; r( m% r据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
6 F! s- Z) y! B+ P结合使用方法来进一步理解它的使用目的吧。
$ P' \- Y; H' f0 W0 o5 g+ y; ]# [1 b l" s1 v: x
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
4 ]9 W! ^+ {' r - namespace One;5 Q. m8 y$ H, @6 l. b4 A
- namespace ONE;
复制代码 0 ]: l! o2 g9 Q3 b
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
) D) `2 x4 n; O& B$ j2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php i2 A) f+ A/ n. g
- class Person{
; k8 o1 z* Y, x - function __construct(){7 Y, ]- A) C T0 b+ D/ \$ }& @2 _* `
- echo 'I am one!';5 i4 S1 U$ [# s' |# D, e
- }, L7 O* i; O2 f6 M
- }
复制代码- //name.php
% ], c1 A0 H' m - require_once './1.php';
( h; @1 F$ _, v7 x2 d+ l. H - ' g. w1 O. N! n! [8 |
- new Person(); //输出 I am one!;
7 O. k/ H: `% u; E% i1 Y - new \Person(); //输出 I am one!;
复制代码 4 ?: k" q7 r( M
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php2 V% Y) L" ~1 n; t' m$ @
- require_once './1.php';# Z7 m9 E2 A; `2 O8 A0 P7 x
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 3 u# {" r- C- d8 X
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
/ v9 T- q3 |$ t" c; D5 } - namespace one;' w! d# S7 V$ s/ \& J8 f" ^
- class Person{
# `1 M1 }1 j' J- | - function __construct(){" J' e# O7 R. W, M& w
- echo 'I am one!';9 ~7 f, |" P! w
- }
; @# _) Z8 I1 f - }
复制代码- //name.php* \7 J2 _$ E2 G/ ?( s' T3 N
- require_once './1.php';) d8 V* F% G/ Q5 z
- new \one\Person(); //输出 I am one!;
, i7 N8 G5 j/ W0 Q: j; t9 ^ - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 1 Q# w( f/ C! t6 H' K
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 ) H u3 q! M+ x) r9 y' e( ~
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
. Y# ]7 G# s' @- //1.php 5 c* }- J+ S- p* |2 c, P* K
- namespace one;9 Z$ K) w( a1 g4 E
- class Person{
, M' h v. g3 b0 u$ \ E+ D9 P - function __construct(){
, E& y5 ?% n1 Y - echo 'I am one!';3 u2 y6 Z2 c# m$ z3 c% ]* Q+ u$ E9 V
- }* `! s' n/ p8 \
- }
复制代码- //name.php7 o# Z* O# c0 ?/ b* t
- namespace test;- J& S3 Z( }7 t% h x
- require './1.php';
3 V+ q- B' q/ A+ w: P, U+ W3 P. W - new \one\Person(); //输出 I am one!;* d7 B. i1 H# L E% V
- new Person(); //这里结果会是什么呢,猜猜看* M0 j* {& N# j+ [
- 最后一行结果报错:: _6 x( }+ m( T) O
- Fatal error: Class 'test\Person' not found
复制代码
" r; r, ^+ u2 v$ j/ [- S9 Y/ E8 X9 d4 I$ C$ S4 C: W
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 * K. o- \# @! z( ]$ P2 ^1 A
结果报错: - Fatal error: Class 'Person' not found
复制代码
& y; m9 y4 \9 [: D2 z8 }! P5 w接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php* V* A |) B$ D4 X8 }" L5 w
- namespace test;
$ b5 z# A: r. Z - require './1.php';
; }/ Q# R( k: D( J' Q% j U - m2 `: E, g/ p2 I' q. p
- class Person{
, w) S9 j( M1 ]# l8 Y - function __construct(){4 h. a" |! v% t' L
- echo 'I am test!';$ w- ~& b4 p) H* Q2 \ s
- }
! x0 x: w$ u$ j1 K6 G# E, j4 j - }
! j9 L8 i! w9 i. f - . B' z; M W/ F5 G( _) a! s
- new \one\Person(); //输出 I am one!;: b" W. ]7 {' }* @
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
9 [. G/ r3 E7 @/ L' M( Y. f/ x$ r# J最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php7 p) g8 j3 u" Z7 e7 C
- namespace test;0 L& M- X# G% }9 n2 U
- namespace one;% d/ V( ]* y2 U% E
- class Person{# s- G2 e" Y. d
- function __construct(){
0 G& n9 d* y. F* g - echo 'I am one!';
% `* @! r4 u! o& M5 z" L- k( u - }3 P! p! e# J, j3 O4 T
- }
; n0 t t$ G, R# E( x - 1 x5 O+ N9 n( T! t5 b1 a* ~
- class Person{
% t: _2 P$ c: i6 ~: \ - function __construct(){
- Z9 w& Z! C5 s& A - echo 'I am test!';
) H$ r) V; S8 y - }
& n6 }) B* L. V. J! U - }
复制代码
2 T& @ b" Y8 t7 n无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 : A$ z! ?: L* q1 D9 x8 M
看来简单的把require理解为替换,在这里行不通。 / b: C3 _2 b# }4 z; @4 W2 R% j
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。& s7 ^1 l1 U% v) ?1 X( T. ]! X
- //name.php
9 V2 {) u( D& L8 |! w9 ?8 l - 0 T4 }# M6 W2 f% ~/ M3 C- Z6 [
- namespace test\person;2 e G2 U. I+ _. \1 P, W: O
- : Z; E9 b% M6 ~) ^# b( ?
- class Person{' r4 K; h% H( G5 f7 G
- function __construct(){# [* W6 G0 l5 V; ]: W. F$ e
- echo 'I am test!';
' p/ T! U, Q) h. C ?& H - }
+ |$ o5 D+ o2 {+ l; W& Y - }+ ~1 B3 B: i+ w
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 2 c3 q _; G; Y7 m
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 * A! {8 c) S: f- @4 `6 D" z
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
m6 V3 ]: Y) s4 r+ k - + d. O, l2 x h( W* s: b$ }
- namespace test;
! q- k* a1 a6 F' I - echo 'zhai14';
" h' M; B4 O. v; z - namespace zhai;
' w) |+ i- A; Q$ q X - require './1.php';
复制代码 u0 B' L, |- c; ]: G, q- n" J
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 / Z" L; F' a; z, o& F9 e
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& x% I: m& {& F: P- //name.php. r$ |% z5 M7 n
- . H4 `$ L( M8 T" x' h6 j8 }7 f
- namespace animal\dog;
/ Q* V/ M$ J! F9 L( A4 \3 m9 b
, ?7 ~. ?7 l& c. J1 j; V' _ s; v% V- class Life{! p3 O, d, _! Q
- function __construct(){2 P, h9 @5 T, y
- echo 'dog life!';/ c$ ]! I# P# \) w6 ~$ U X
- }
* ^" s( k+ M5 B% f# M - }. a2 ^0 o6 Z0 [
- ( S9 r2 m0 ^ M- T
- namespace animal\cat;2 E; o% I* R6 @/ v( f) P) B
- * i. U; U6 B: o H" Q; z9 B
- class Life{0 ~4 j5 |- [9 H7 q
- function __construct(){
3 L! ~/ i7 t" u9 J: y+ l9 ^6 @ - echo 'cat life!';
- ]" \0 @% D. ?4 l& u, I6 n - }/ ^' I* g- h0 J4 f2 j: m$ D
- }
1 n2 {. [% i# J# g; p4 Q6 z - : m. P3 k; C$ j, s
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
) C3 R: c8 p! Z2 z4 C! x( ] - new \animal\dog\Life(); //A0 k* K' u6 x3 r) R' y0 m/ a' A
) q, B5 }8 U5 w- z- use animal\dog; //a% }' z! r6 ?! P' z) k& a
- new dog\Life(); //B; o: r$ z9 l: _# q2 S+ _; ?
- # l# G# M3 ~, A3 E, r2 g
- use animal\dog as d; //b" T3 J$ S: V4 |( C* R
- new d\Life();
复制代码
2 Z9 v" W) g' R/ [( E' ?3 r! S通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 $ f) l' z' b% k
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
" }5 s5 u# L+ W; Y# u6 @相当于
H; ^& |1 G% v; c4 [& z/ e2.namespace后面不建议加类名,但use后可以。* W9 a) X) b Y/ t g. [# l
- //name.php4 \* k* `4 X1 l6 v. v
- / ?6 }4 ~3 z0 L! w# S. V" }
- namespace animal\dog; u$ X# `9 l% E' n0 k
: r6 u# ?0 z* y( D- class Life{1 l ?* R) q0 d: m& ]$ n
- function __construct(){
* q( v" D, |1 l' g - echo 'dog life!';
( b5 G x7 a2 b6 |1 Q6 F - }9 f$ _* q6 y: h5 f
- }
2 g9 K5 [# I6 e' \2 _, D. q - / g0 i: l8 P; ]" H% S4 D5 O! P
- namespace animal\cat; U) {& F" r+ V' h
- ' i; R: `+ c' f* z( j
- class Life{% w5 I; y7 v& ? H
- function __construct(){# t* E0 C; p, Z2 `( t
- echo 'cat life!';2 S: L; u$ N: T
- }
! l) Y8 f9 ?6 X4 R( Q8 x0 ^2 W. [/ Z - }
. n& H6 ?! A x
- _# _9 X, O8 j! Y. N( `2 v \; O9 q0 T- use animal\dog\Life as dog;
$ p$ S7 S: Z$ B# f. W - new dog();
复制代码 6 `. b- T2 B; U& s9 C' Q: S5 d
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
) `" n9 P( F* z3 H* m0 |; E/ P因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php+ p5 Y- j# a6 Z' E9 Q7 Y
- + [$ c5 T- X" h% @
- namespace animal\dog;9 A) z8 v c: H P
& S2 O6 J, M! R |% C) A; t0 @- class Life{: p h( e# b$ J* u5 }
- function __construct(){
" Q# T1 o! X% E' ` - echo 'dog life!';
! x. c) Z7 G" P9 p( b - }
9 V7 J1 |' @( R' p/ X* m - }2 P( t$ ]1 }# }
- class Dog{: {. I9 k4 f3 L7 } @( d( L
- function __construct(){5 _7 K h, P7 n5 P0 Q
- echo 'dog in dog!';
c$ @; [. p& m( I h/ x - }" U- z% m! P1 @* W. W* J( R, b; P
- }
7 s4 q( W8 w6 ]* }9 ~
: O8 e; a* G; l3 I/ E. Z' d- namespace animal\cat;
& }! A# c& _7 N Z - + j1 r/ a8 I" [9 T- p6 ]
- // class Dog{
" V4 \' x9 V2 \* Y - // function __construct(){
- ~% `/ x* a& |9 s - // echo 'dog in cat!';
0 Y" p4 {9 \" x) y$ O - // }2 ?) S* ~& w" }. v: P/ w
- // }
4 h) J e2 ?7 U* z7 ^% ]+ p - class Life{
. L: E' ]3 E$ D" T# T1 F - function __construct(){. i9 D G% m% M) w3 I! @0 `
- echo 'cat life!';6 h+ K3 h2 n' a/ E
- }& O0 w1 {0 `- a: e ~7 s
- }5 ^! V8 Z- W7 K5 g+ k
0 K$ z. j- Z) n3 C2 R7 ]2 p- use animal\dog;
+ ]8 q5 C3 }9 X6 F2 U - new dog\Dog();
复制代码
& `. v# E; |0 S0 k$ o* {如上,使用了 ! a' U6 u5 v! {; C- c; P
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 3 m( F5 k/ u, |! C$ z
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
: v0 z6 D% k0 F3 }* v. x! c I1 R: M; F+ C' d9 n
1 Z4 ^% |7 g. M& M: A
" S" Q% ~- c2 t
* F1 k0 s- ?3 R' g2 ]: _- |9 _: [ |