|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 6 G( E% h! v% P( L% D c3 B$ r
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 ! ]* V4 p0 @6 n3 _( j+ m( T. t& u( V
) d2 l3 \# ?( T% q使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; . ]' I- ^2 [3 M! |& t1 m2 J
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) ! w3 R' ? x* t f
结合使用方法来进一步理解它的使用目的吧。 : k" \$ V8 x |6 i) P9 x/ R# c
7 I4 J, d! |: _* n% J+ W2 z1 t9 Y
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;' d$ F s- O s3 ]$ x0 C
- namespace One;4 ^- [, a# a9 X; U: m4 ?
- namespace ONE;
复制代码
% s( y4 R0 J& ?) b如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
" o! t; w* Q3 I1 k7 h1 m0 c2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
`, ^$ g* V! G - class Person{/ y- n4 B9 Z( G3 B3 y) S
- function __construct(){
/ d' [$ m w( q) M9 | C& H9 l% R - echo 'I am one!';
7 S r3 L$ V' X. p: i; h - }' d7 T$ X; z+ ?6 H) G( q a
- }
复制代码- //name.php8 S0 X- W; ^1 S5 P2 d% e$ `
- require_once './1.php';( J: b" i1 d( z4 F
5 l% E; f. q, z3 J- new Person(); //输出 I am one!;* y, G4 ?# a+ \6 f; G4 g* [
- new \Person(); //输出 I am one!;
复制代码
! M7 {5 C2 L+ t6 B+ Q* L3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
# w" X+ C. m6 l% I - require_once './1.php';" a) L% i4 F4 ? l1 i
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 4 J/ M$ o9 @: `. f0 a$ P
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php " }- B$ c8 {$ \+ R9 n. _, }
- namespace one;
& @+ v( u$ h+ P$ M# D8 [/ { - class Person{& u. q8 m7 b( P
- function __construct(){/ e% _' J) s7 Z! [
- echo 'I am one!';$ j8 i$ j! V9 I% @7 ]# }2 W, w4 X
- }) J+ x- {* f! V$ Z
- }
复制代码- //name.php3 I& j- Q% c. y& d! x
- require_once './1.php';
; L: M, n/ r/ ^ - new \one\Person(); //输出 I am one!;5 u& S8 b; y% K% e7 @
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
8 j n9 V8 R: A; k! y+ n1 l: ~可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
@' l/ H- r5 }7 G$ F* G4 X5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。$ T) w, U$ I5 o
- //1.php
* s9 g$ Q& m5 Q- l: T) W - namespace one;/ F& l: A0 m; p/ f* U- j7 \
- class Person{
# l0 ?/ ^' E. C. [- i% O) J - function __construct(){
* K e `7 t0 P - echo 'I am one!';: L2 K* R5 Y; t1 |, _& y
- }. ^: s1 f0 L2 K9 S l
- }
复制代码- //name.php
0 X, f4 ?6 `! q) M- ~' ~/ }/ ] - namespace test;- n$ l4 X! b. c Z' J9 f: \7 S9 J$ z) Q
- require './1.php';
* `' G/ N5 x$ u9 w. F$ E - new \one\Person(); //输出 I am one!;1 v9 j% }3 v# \& y" h Q
- new Person(); //这里结果会是什么呢,猜猜看
; c/ Q& C0 S/ Z. K4 g - 最后一行结果报错:+ `- g( B8 M$ W* ?2 O" Z5 L
- Fatal error: Class 'test\Person' not found
复制代码 ) D: E2 [/ A+ C4 X
; I/ |' U& g2 v1 h9 W首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
- g$ B- ~/ Y+ s结果报错: - Fatal error: Class 'Person' not found
复制代码 " j0 J& s* O( B! s9 w: R" D
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
4 B, n6 K& [. \1 B& ]5 a" k8 Z - namespace test;
/ t- U, l3 Q5 o - require './1.php'; + `, U/ U1 r/ Y) c' E
! O$ @5 d# i2 e& Q3 W( T1 `' C5 N- class Person{
# T9 M- Y5 K6 @" y2 x& H - function __construct(){
9 f- T' y2 r" H1 d* H - echo 'I am test!';$ m0 c0 g* Y5 H8 k$ C1 R- e
- }
( H& a# T. g2 M& t$ d8 s! z - }
2 j) t2 r% W8 q8 |5 J% W/ z - / D- z3 `0 b! Q$ d A' T! _* g' [
- new \one\Person(); //输出 I am one!;) @% a& r' n$ {) B$ |4 i
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
: {; E/ W: h( C$ d最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php# u7 Q/ H* m/ {- |
- namespace test;: @5 E7 C3 }) j" X
- namespace one;* _3 Z& |. X) `7 h6 k3 E
- class Person{, T* g) u0 P- s. V& V
- function __construct(){" J' h' C7 [7 Q2 u2 V2 w/ w
- echo 'I am one!';
+ v; Y; z! V) G: H - }
8 r3 B% h; [4 c! G - }
. \0 [/ z N* a6 O2 l$ N' y - : @# a$ V+ Z7 k
- class Person{6 h2 q5 ~+ A: U& n8 U
- function __construct(){
0 \; @+ G! z+ j - echo 'I am test!';
+ E3 ?$ I; @0 ?/ y" w* L# S - }
; q ^1 w# G, v; z2 E - }
复制代码
; ~6 J6 o d) T. r2 V: S+ r无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
, r' z; @/ v1 [' ^" }看来简单的把require理解为替换,在这里行不通。 5 w& F. T& C. W/ F3 b! z
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。$ g8 e* D+ y& b# h; _- E0 N
- //name.php- B: p- ~/ D! H
2 y. a# [8 J$ b1 X8 V- namespace test\person;
2 k2 C+ @ f2 M! B* V6 d9 t ? - ( w& |. @ L8 ~- h m
- class Person{
& T: J y O, ~8 @# S1 d. h - function __construct(){( a0 [. W* r1 d4 W0 ]- t, u0 b) R
- echo 'I am test!';
+ v& c4 Z. A8 Z) r s2 W5 Y - }* K8 ^9 ^5 J7 t/ i' N- m
- }& D8 |2 L! \* y4 t2 w0 p( q: u m- c
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
: W1 a* r6 ?: {' i( }$ Q( n不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 8 f/ f+ d1 h' g8 y1 z$ H5 W$ T
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
" a) R1 z3 g2 ?9 }) l! j L: ` - % m: s% N' d0 f3 K/ O, q
- namespace test;. ?5 ~6 B/ s0 E) i9 d2 T. F) g. d3 u
- echo 'zhai14';
3 A1 j5 Q" v. @( c' J) g$ f9 ^ - namespace zhai;' V: q# C8 n3 S5 c6 I- h
- require './1.php';
复制代码
! s- N6 n! E% Q- X/ vphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
9 o9 E' i* T" e$ v# E& Suse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。# J! h1 \7 u( d7 a$ t3 ^; w, {
- //name.php% B! i3 X1 n7 T0 i6 h
- ; _4 _4 g" N# v& [/ j, R
- namespace animal\dog;
$ ^+ l1 Y7 D9 c3 D" ^2 E. i - ' R) L# r, {: [) I. T# W: d
- class Life{; W9 S4 ?! x7 Y# {: Q1 C
- function __construct(){$ h# l. P- K% j/ N
- echo 'dog life!';
! O" O* P8 ^, Y( f4 Q7 n - }2 I1 J1 u; `7 }
- }% d Q2 u4 T( ]% w' U1 b+ |3 d0 z
- 2 y" z0 N4 M, Z1 _- I, S
- namespace animal\cat;& W8 ?: E+ l/ h) j1 w
1 m) Q/ } ~6 |4 e, n/ ~- class Life{
V4 J1 C1 J* S. f1 t& A( `4 i - function __construct(){
) N8 o6 S1 l0 i: T* G - echo 'cat life!';
- L) A. }6 g' x5 e4 t6 P - }
# d8 C+ |3 W% }! m9 Q - }- h( y3 f5 s5 z8 ^+ P" e
' L8 U$ R& I, F2 N; `" P6 h; o- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
' N& b6 B( q" G. k6 N0 s p8 M - new \animal\dog\Life(); //A
, t7 q9 W0 o8 m8 y# B6 Y( z# J: G
* Z" `5 P5 |9 m8 `, J; n1 t- use animal\dog; //a7 H5 S" b% T% h# I* I* c
- new dog\Life(); //B
( R, O& R# N- N$ K8 `' ? - ; l7 J7 {& f2 E9 }2 H8 w4 C, M. ?- X
- use animal\dog as d; //b, k5 }1 r: ~4 Y7 ?, ~2 y) q+ P
- new d\Life();
复制代码 / L7 L) p+ |9 A
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 ) [( ]2 ]/ m0 N
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
" O( L5 g$ N: e# W相当于 ( z* k1 |# |) E+ t
2.namespace后面不建议加类名,但use后可以。5 v9 q- g" R6 j$ Z7 x1 [7 R3 _' G
- //name.php7 @ T. s- e# \- k: ^
- g( C" ]5 E7 W- namespace animal\dog;
* e& y( z7 L) I: t8 z
9 z$ M, R ]: g. v# q- class Life{
' s! G- h' K( M8 g! Y - function __construct(){3 L) G2 l& R! u6 j7 A4 a( z
- echo 'dog life!';: z* R8 B2 U6 A; o, z
- }( Q6 l) h& f* x3 h; Z
- }
, Z- f+ t; z$ F8 V0 C
5 t y7 O9 {2 u" d- namespace animal\cat;. {+ X" H/ [, y: x% M- q4 }. b
; A( P- H; F4 C' u8 l# U- class Life{
; t0 u6 \8 c# X: N& z; } - function __construct(){3 I/ C0 F- h" _/ P6 f
- echo 'cat life!';
5 r1 v2 B0 g. o; ]7 {0 i( o - }0 S9 M( D3 f) y# e+ G, M, D; W6 T" o
- }( r/ l: h8 \* r; f9 r
- ?1 G2 M- E) x, C- use animal\dog\Life as dog;
# K: {% i* | ?0 ]/ g7 l - new dog();
复制代码
o( g& F+ i/ x/ ]如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 0 \% A* K$ ?5 G
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
0 r% b# u! {1 e2 ^5 u' }
( i, R$ R8 q, H( D \2 P- G- namespace animal\dog;' | r- a- r) m( ^* S
+ O+ [4 I$ i$ [4 v# u) n- class Life{* s6 r( N4 y+ E" x3 [% c
- function __construct(){
: i6 c9 a! C4 [5 P2 h6 o: j5 J - echo 'dog life!';
* a# t. H; q8 c7 G, \5 g1 \ - }5 u5 J2 E5 i4 D X; u8 e* U% j! P' q
- }( O4 g# C9 q' @. W# ?
- class Dog{
& X `, S* t5 T( I4 T - function __construct(){
0 Q( F: l& G3 Q- J- l - echo 'dog in dog!';$ Y1 f. u" M1 `7 B$ F$ l
- }
$ G2 s' y+ q& R5 {6 u - }6 `" S; O5 l" `2 v1 f
5 P5 F) k8 _) o) M- namespace animal\cat;5 ]4 n( x* j. ~: j F. u
- . b& M8 c! p0 d0 i( |: t
- // class Dog{
) o; V' |' u' K - // function __construct(){
3 Y7 q X0 ~) {7 p. X - // echo 'dog in cat!';
Q' M5 G6 B1 C2 |/ [0 t" ? - // }
6 ~& C4 ?# A# |5 Q) h2 w' H - // }
' i6 b/ i& ~9 q, h- C; C& F - class Life{
- [& t5 e' @1 T- A% E& ^8 e - function __construct(){
# }- p; [1 h+ W' Q - echo 'cat life!';- h" X1 k4 }& Y: U+ a7 ?' Y
- }
, ]; c( y! i e; R Z, v) x - }$ T; S: k8 z2 A; s+ h7 Y9 U7 @
- 9 F; O3 u* N0 T" l
- use animal\dog; 1 n) {6 C. w: q% G4 A1 H
- new dog\Dog();
复制代码 - {1 w* I6 H3 H8 f5 d. Z
如上,使用了
1 L4 o# ^& s) i, g! `0 kcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
; }; r' Y7 R2 [ D0 O简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 : [5 E; ~* e. ?2 L N
# g( p+ s3 D5 K9 y) B3 ^/ W# O! x- N) f2 s8 e8 z8 t0 d
3 j! {1 G& y. V/ {+ d/ }' y7 F% U' g1 k4 ^8 _
|