|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
1 \; I6 G* s" m) Z6 t" m" L T文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
, S6 ]: i0 V! \, x
$ f- p. U; g: W2 h: U0 j, o使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; ! Q, @1 p3 f$ `8 N
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) % x1 L+ Y" p$ O% ~. w
结合使用方法来进一步理解它的使用目的吧。
) n7 }( r4 l: [' g9 W" C1 Z6 a3 |8 {# p F8 ^
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;; D" q# U9 Q/ F, y! Q: A! R! m( J
- namespace One;4 N; X/ t2 Y5 S" e
- namespace ONE;
复制代码
* V9 u B. j& c* G# Q' U {0 d如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
4 r6 B7 g. B: P2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 4 p2 c7 E k) q2 S/ N+ ], P2 T: v5 S( u
- class Person{* D" _" a8 H0 q* `! a- H
- function __construct(){4 x7 p% Q& Z6 P" J2 w3 c) U
- echo 'I am one!';
7 |; u% b2 e- i) ` ` - }# d- e1 h: E3 @0 ]( W8 d4 i: k
- }
复制代码- //name.php
1 J! ]0 ?+ c1 w6 }, }4 M - require_once './1.php';
% h' t' {) g6 _5 u5 ~* s
2 h# v5 e+ J8 z0 Z2 W" f( h3 _3 N- new Person(); //输出 I am one!;- j& I7 k( }5 s( w, f0 c
- new \Person(); //输出 I am one!;
复制代码
9 U) \ X3 h* l4 L7 W3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php4 c3 t5 C9 E |& Z6 z/ v9 F
- require_once './1.php';
0 z& T: x9 j, `. N5 ~. _9 C& F& S - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 ! u0 w" W, M& \: b
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 2 m6 [* h- h# s
- namespace one;
9 N8 I6 ], u* N, e! A; ? - class Person{; u6 }# c$ i" w' O
- function __construct(){
3 f# H% R; p1 D! V; U( G - echo 'I am one!';
: m: H" j k7 c$ N; } - }
& D! i2 R+ q: c - }
复制代码- //name.php9 W3 e! K0 {8 H; a4 Y9 x& E+ _
- require_once './1.php';( h& I& u! V0 W& f8 z( J7 F/ l
- new \one\Person(); //输出 I am one!;
) w1 G5 k6 c9 k9 u4 k - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
0 z/ T7 \: e' X4 s) @! j* e可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 . |/ e* {/ K( u& Z/ k4 t
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
8 {3 Y0 u; j8 r5 b# t3 z- //1.php
1 {( I8 a" o6 N! a, B - namespace one;# ]; `& a7 [7 R7 H, i! [. ] \
- class Person{
* g; |7 g; m* { - function __construct(){9 m0 C; N& e- h8 t) ^
- echo 'I am one!';; u& f+ g' z# ]6 b+ `
- }. |0 e' V" H' M" ?; A5 Y
- }
复制代码- //name.php' r! S0 d8 q) l& y
- namespace test;
8 O- s& D, y7 _- \. @ - require './1.php'; 3 v6 }7 X5 F2 f3 M4 u q% ~
- new \one\Person(); //输出 I am one!;% t& q- ^3 q( U( D5 U7 H& J: \4 N
- new Person(); //这里结果会是什么呢,猜猜看6 y% X9 Y+ }: U
- 最后一行结果报错:
' A. ]: C5 H1 Q$ u2 D- k - Fatal error: Class 'test\Person' not found
复制代码 0 G- i# S, Y& Y6 T
1 n b: a0 c6 X! ?8 J$ Q5 X
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
7 } K/ f9 W ^/ C: R结果报错: - Fatal error: Class 'Person' not found
复制代码 - h8 @" v/ O" F. \! [7 J: u2 y
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php9 U8 r: g0 Y, U) h- ^3 q/ m; `
- namespace test;) B( ^, T3 I9 m
- require './1.php';
' w) \( r/ S: J4 D- ?6 p - - V; u5 w; l& h- F; Q6 {5 ]
- class Person{
, O0 K6 o4 J' M6 u6 @- ~( H# u - function __construct(){
8 {$ @+ `7 L" L" U# ] - echo 'I am test!';8 A& C( G) H. c8 A; L+ W5 g
- }
8 {5 C* M7 X2 j7 S* n6 c% G - }
; _+ }: ~% f# ]
/ H* B5 N, i9 i- l' B4 L3 Y' k- new \one\Person(); //输出 I am one!;
4 b$ d1 X E1 t/ O+ H' W - new Person(); //这里结果会是什么,自己猜猜看
复制代码 / H; k% L- W$ o: I
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php6 k2 L8 W5 F: C0 |+ s. r! l. ?" h
- namespace test;
8 b* T7 ?" i# Y e: v% [- @, Q - namespace one;
3 N* d3 y* o1 G. Y: p8 ]1 [( h - class Person{5 l% {0 G4 R4 W; y9 E" I( Z
- function __construct(){
# x3 _: ~5 l$ g1 [0 q6 N$ u8 X - echo 'I am one!';1 q9 K% [4 u; ^# O- m" _
- }
( u R5 Y2 r7 d; e' W9 j% l. j - }+ z! o2 a' h; E/ W
- + \, G) `# |( J3 e5 p. A
- class Person{5 m0 d& [9 K+ v$ Y
- function __construct(){
3 @: j- }* P7 O3 y/ c. H9 _" p, ` - echo 'I am test!';- ~& m8 P" I! g/ Q6 d7 I
- }
6 S V4 F. L0 \7 i( p2 N! L; f6 V$ p - }
复制代码 ( O. D# D# O( M' X+ V* d/ D
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
9 d8 f/ ?5 `3 B5 U3 V7 j. w0 Z看来简单的把require理解为替换,在这里行不通。
9 c3 K( b& [8 }9 T: {# Q+ O6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。& v) s+ e: x8 `, S
- //name.php- k4 `6 C9 i* `9 c7 a
- & o2 T& h/ G% N
- namespace test\person; w+ m; G8 o/ A& M9 h9 P$ ~
" S7 t" s" d Z; q& {- class Person{4 [- k4 c: O& z- d
- function __construct(){
2 o4 O$ F+ p1 B5 s2 g - echo 'I am test!';8 [1 C2 v+ ~4 l) E2 b3 R; X* e
- }
7 ^# ~1 _; b$ Q, K - }
# ]; A, v x7 T6 r - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
, {! p" Z" c/ c$ Q不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 - L2 }, q% f+ A/ h; X) c/ e
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php8 Z, A+ q# z% f7 q
8 l( F0 P% D) u3 U6 W: u- namespace test;
6 m: g& i4 X( X) U3 h( F! p' a - echo 'zhai14';
- F. V( u: F8 W9 ? - namespace zhai;
o- P) @' s6 m! z - require './1.php';
复制代码 9 o2 b2 G! Y+ D$ y, {' Y) b
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
- O$ D" f Z# W3 o7 ^8 ~use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。7 w( ]% v5 Z4 h; o% M( L2 |% h
- //name.php
5 T. g& f1 d; u! y3 l% a5 ?
" l$ I/ p% f1 a; Q; }- namespace animal\dog;
6 L& I; s6 X& C* n' K3 u2 D' V' P7 E - 4 R0 L7 Z) _: X6 _2 |% n* \% a, {3 |
- class Life{
: f0 G6 S$ D( n% ?8 l% B: E+ N/ r - function __construct(){8 w' }& G8 x$ }
- echo 'dog life!';9 [: }0 v H1 b: _
- }1 J. B4 D+ H! k$ X0 @7 P
- }
) U) E# Y% J {" o& W
2 O/ D7 B m. m( u% T' J- namespace animal\cat;
6 Q6 ^4 s, X3 G/ u" r* @
. \: G3 E2 ^" k+ A, E3 e- class Life{# }9 r: Y( Z6 R1 W: \0 v# t( r
- function __construct(){7 M8 \; p5 d/ b& E
- echo 'cat life!';9 x \! H/ h$ p3 [
- }. o" v8 n s+ F5 R A$ g
- }
$ ]4 M5 u- s4 _ - * a. Z+ `9 \8 o
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间$ {; V: C4 j3 c- U& D
- new \animal\dog\Life(); //A
z+ c! [5 p9 R+ E' M* H
% e! \5 y% V( g/ O: a2 T- ?- use animal\dog; //a' J* _( B a7 O9 {) H. p+ b8 y& m
- new dog\Life(); //B
9 l0 \% A* j/ Y9 d* ~, @1 t
* O {2 u2 t# y2 I- }7 Q# X6 |0 ^6 H ]- use animal\dog as d; //b
' Z" E. {9 U) D9 k# j W# B - new d\Life();
复制代码
# z* {) B$ t) d5 F" [/ E1 [通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
9 K; [7 [- d$ \( {0 R, s通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: ^$ y" q1 W* U5 i
相当于
9 V. X( m a# h' r2.namespace后面不建议加类名,但use后可以。% r. z# W' e6 W& L9 d g
- //name.php
' z% M4 ?2 H* h5 V) j3 E4 L( n - / [9 C1 C/ A. K, _, i/ R
- namespace animal\dog;
. r ]- g; f9 k' G: J
' b; s% z8 r; Z5 n G4 R- class Life{
/ G: W. B6 r% r' U' B, k- q4 q - function __construct(){3 d0 }- l; X8 {# `$ U2 x+ {+ }
- echo 'dog life!';
) x) E# y8 I! o6 e% f h - }& l3 p7 D1 L, D
- }
% M0 Z A8 i: K9 ~3 { - # z/ Z6 R; s% W G" A
- namespace animal\cat;; x9 `. Q2 s0 u* w, Z; f
- . x0 b# J3 H0 \) f
- class Life{7 m4 K8 ~# A& a& |0 ?1 ^0 v i/ z
- function __construct(){( l7 t( ?& b1 D. `# I* _
- echo 'cat life!';
3 ~# R5 `; Z8 m" Z; l6 k2 b - }! r C: f$ E3 i
- }/ p/ O" x! J9 [2 y6 s- E6 x* p8 F
3 t/ J9 _" u2 l9 ?/ r- use animal\dog\Life as dog; 9 d1 J* l& ^; k2 K7 T. ?
- new dog();
复制代码
1 l q( o/ ~/ D* u9 F如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
- n7 a i% ]3 V" z. I" C- j因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php# V* N2 N: Q' U( }( @
- & t8 {, _, k3 x- [/ N' `6 N. r% ^
- namespace animal\dog;
+ C: }4 b1 g0 \& x5 L+ y; m* `- W - - d; ~! F6 x7 E) U5 q" e
- class Life{( k+ {* q2 M1 a6 k" b
- function __construct(){
3 p' `/ p5 f, ~6 ]. z' N - echo 'dog life!';: g( X" M4 _5 R/ [9 A
- }
' t( l: P8 M6 ~7 P$ h - } S7 q1 J3 V& @. P! u/ q' p
- class Dog{9 O9 H1 `- a" R! M( A# e( B$ o3 e
- function __construct(){0 c/ x# K: n% ^0 o
- echo 'dog in dog!';
7 |' S6 [4 E0 Y1 p. V/ X4 G2 R - }# V& e y: u0 R1 r7 |* [
- }
+ v$ o7 N, E' h5 W
- M1 Y$ e$ `! Y1 o7 a8 i- namespace animal\cat;
- s* q: C1 {& j2 U/ K
/ R( P) H# m4 B3 C2 _. w- // class Dog{1 n' ]% A. O3 M/ B$ N7 W) J% @$ s
- // function __construct(){( A( I8 o% U, ?9 Q* E, G
- // echo 'dog in cat!';2 _3 N& E" x) D7 J/ _' x2 |
- // }
/ C# z3 `1 E# x) d2 ]/ T: K - // }
) F" m2 E. ^+ X) [( u, P# a - class Life{
* D7 N# F6 f- r( \; _ - function __construct(){
' }* j3 K4 Z# F3 c0 E6 ], d - echo 'cat life!';5 U8 W A$ c C7 H t7 _
- }: K! ]/ z' k6 R
- }
0 l0 j- C1 I6 ?! L$ F
% E6 A6 S% M+ C& C% Q- use animal\dog; ! i6 @! j6 I" H2 J( x5 |
- new dog\Dog();
复制代码
I; t9 i2 z9 X$ c3 A! Q1 i" Q+ i T. z如上,使用了 # F- y. Q' f2 x" m, d2 o
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 # g3 I, ~2 ^( t. m' d
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 5 x |6 ?+ M. X% i+ O m' L
/ T. B2 n( g2 b7 Q8 h6 N% z* s* ~5 @; \: b4 q" k
" f& I0 P5 u4 \" L2 D: ~/ d
0 t& t. O, n9 {0 ?" w( A3 Q- V" C
|