PHP 计算两个文件的相对路径
没错这是我目前的得意之作之一,还特地写了CSS,虽然不怎么好…… 所谓使尽浑身解数……
打了草稿,嗯虽然估计过会儿我自己都要看不懂了。(思路,{}
的部分在写下来之后发现了共同点就合并了)
删除 . 和空白数组 比较相同元素,到不同时中断 统计b还有多少元素 不同元素的多少决定了..个数 按序输出不同元素 count数组中元素的大小,取小的那一个作为比较次数 比较一个元素删除一个元素 {如果比完完全符合 则如果b小 返回a剩余元素 b大 返回差集数组计算元素数返回../数 如果不完全符合,则b剩余元素替换为..后加上a剩余元素} b剩余元素变为../后输出a剩余元素 如果输入文件名a/..
为了找相对路径规律还写了不同的……
$a = '/a/b/c/d/e.png' $b = '/a/b/c' 相对路径:/d/e
$a = '/a/b/c' $b = '/a/b/c/d' 相对路径 ../
$a = '/a/b/c/d/' $b = '/a/b/12/34/' 相对路径 ../../c/d
$a = '/a/b/d' $b = '/a/b/c/d' 相对路径 ../../d
$a = 'a/b/d/e' $b = 'a/b/c' 相对路径 ../d/e
我们分解下面来说明。
1 body {
2 background: #F5F5F5;
3 }
4
5 div {
6 width: 400px;
7 height: 250px;
8 position: absolute;
9 left: 50%;
10 top: 50%;
11 margin-left: -150px;
12 margin-top: -125px;
13 background: #eee;
14 border-radius: 5px;
15 box-shadow: 0 1px 1px;
16 }
17
18 form {
19 width: 280px;
20 margin: 0 auto;
21 }
22
23 h1 {
24 text-align: center;
25 }
26
27 input[type="text"] {
28 width: 280px;
29 }
30
31 input[type="text"]:hover {
32 box-shadow: 0 0 5px #000;
33 }
34
35 input[type="submit"] {
36 width: 40%;
37 position: relative;
38 }
39
40 p {
41 float: none;
42 text-align: center;
43
44 }
45
CSS部分我们这次定义了input
的样式,可以看出格式是input[type="text"]
,另外使用了刚学会的box-shadow
,详情在:Box-shadow实现常用阴影效果
这次的居中模型使用了:CSS几个竖直与水平居中盒子模型的第一种(当然好像不大会用啊OTZ)
1<label>保留文件名:<input type="checkbox" name="file_name" value="yes"></label>
2
form
中使用了label
,关于这点可以围观:表单input增强用户体验(label和placeholder)
1 if(!empty($_POST['shot'])) {
2 $problem = FALSE;
3
4 if(empty($_POST['routea'])) {
5 echo '请输入第一个路径';
6 $problem = TRUE;
7 }
8
9 if(empty($_POST['routeb'])) {
10 echo '请输入第二个路径';
11 $problem = TRUE;
12 }
13
14 if(!$problem) {
15
16 $a = explode('/', trim($_POST['routea']));
17 $b = explode('/', trim($_POST['routeb']));
18
19 $check1 = check_route('..', $a);
20 $check2 = check_route('..', $b);
21 $a = $check1[0];
22 $b = $check2[0];
23 $pass = ($check1[1] && $check2[1]);
24
25 if ($pass) {
26 $a = clean_empty_element('', $a);
27 $b = clean_empty_element('', $b);
28 $array1 = search_and_clean('.', $a);
29 $array2 = search_and_clean('.', $b);
30 $a = $array1[0];
31 $b = $array2[0];
32
33 $counta = count($a);
34 $countb = count($b);
35
36 $count = ($counta < $countb) ? $counta : $countb;
37
38 for ($i=0; $i < $count ; $i++) {
39 if ($a[$i] == $b[$i]) {
40 unset($a[$i]);
41 unset($b[$i]);
42 } else {
43 break;
44 }
45 }
46
47 $route = '';
48
49 $countpoint = count($b);
50
51 for ($i=0; $i < $countpoint; $i++) {
52 $route .= '../';
53 }
54
55
56 if (!empty($a)) {
57 foreach ($a as $key => $value) {
58 $route .= $value . '/';
59 }
60 }
61
62 if(!empty($_POST['file_name'])) {
63 if (isset($array1[1])) {
64 $route .= $array1[1];
65 }
66 }
67
68 if(!empty($route)) {
69 echo '相对路径为' . $route;
70 } else {
71 echo '完全一样哟';
72 }
73 } else {
74 echo '请输入正确的路径';
75 }
76
77 }
78 }
79
80 /* 清除字符串与指定字符串相同的数组元素 */
81 function clean_empty_element($str, $array) {
82 foreach ($array as $key => $value) {
83 if ($array[$key] == $str) {
84 unset($array[$key]);
85 }
86 }
87 $array = array_values($array);
88 return $array;
89 }
90
91 /* 清除带指定字符的数组元素*/
92 function search_and_clean($str, $array) {
93 $file = NULL;
94 foreach ($array as $key => $value) {
95 if (strpos($value, $str)) {
96 $file = $value;
97 unset($array[$key]);
98 }
99 }
100 $array = array_values($array);
101 return array($array, $file);
102 }
103
104 function check_route($str, $array) {
105 $counter = 0;
106 $pass = TRUE;
107 foreach ($array as $key => $value) {
108 if ($value == $str) {
109 $counter++;
110 $array[$key] = '';
111 if (isset($array[$key - ($counter * 2)])) {
112 for ($i=0; $i <= ($counter * 2); $i++) {
113 $array[$key - $i] ='';
114 }
115 } else {
116 $pass = FALSE;
117 }
118 } else {
119 $counter = 0;
120 }
121 }
122
123 return array($array, $pass);
124 }
125
php的部分相当长……
首先毫无疑问验证表单是否提交,然后为了避免用户误输入空格,采取了trim()
,作用是消除两端空格(文件夹里有空格很正常吧……)
扩展阅读:http://www.php.net/manual/zh/function.trim.php
然后再次使用explode()
拆分字符串为数组,在PHP检查IP是否在指定范围内中曾经提到过。
接着检查与简化路径(避免用户输入复杂路径)(这是第二版添加上的T T我根本想不到路径会那么写啊)。
然后清除数组中空白元素和带文件名后缀的元素,之后我们使用了一个三元运算符:$count = ($counta < $countb) ? $counta : $countb;
,因为我们的循环次数取小。
思路基本上同前面写的草稿,发现不同之后用break
立即跳出循环。
依次连接字符串。
最后根据选项选择末尾是否要添加文件名。
这里我写了三个很有用的函数,具有推广性,应此在函数中变量为两个,一个是字符串,另一个是数组名。
1 /* 清除字符串与指定字符串相同的数组元素 */
2 function clean_empty_element($str, $array) {
3 foreach ($array as $key => $value) {
4 if ($array[$key] == $str) {
5 unset($array[$key]);
6 }
7 }
8 $array = array_values($array);
9 return $array;
10 }
11
如果发现了和指定字符串完全相同的数组元素,就unset()
释放(销毁)它,全部循环完毕之后用array_value()
重新建立索引。
1 /* 清除带指定字符的数组元素*/
2 function search_and_clean($str, $array) {
3 $file = NULL;
4 foreach ($array as $key => $value) {
5 if (strpos($value, $str)) {
6 $file = $value;
7 unset($array[$key]);
8 }
9 }
10 $array = array_values($array);
11 return array($array, $file);
12 }
13
14
这里使用了strpos()
,作用是返回字符串中指定字符串的位置
,这里我们输入了一个'.'
,又恰好如果是..
的话位置是0
,布尔值是FALSE
,被排除在外了,所以如果想要算上所有的位置,还是得用isset()
一类的。同样的销毁,重建数组。
我们这里还设定了一个$file
,为了便于输出文件名,实现把$file
储存,但$file
不存在导出会报错,所以设定了一个NULL
返回不能返回多值,只能以数组形式返回了,关于返回值,在PHP变量命名规则与范围提及。
1 function check_route($str, $array) {
2 $counter = 0;
3 $pass = TRUE;
4 foreach ($array as $key => $value) {
5 if ($value == $str) {
6 $counter++;
7 $array[$key] = '';
8 if (isset($array[$key - ($counter * 2)])) {
9 for ($i=0; $i <= ($counter * 2); $i++) {
10 $array[$key - $i] ='';
11 }
12 } else {
13 $pass = FALSE;
14 }
15 } else {
16 $counter = 0;
17 }
18 }
19
20 return array($array, $pass);
21 }
22
这是我写过最神奇的东西,曾经想过unset()
加指针移动,未果,报错,于是就产生了这货,这货配合第一个函数使用就能达到简化目录的效果,它的拓展意义不大,主要是检索$str
连续出现数量,然后成双替代,扩宽范围,如果下一个不是$str
的时候把计数器清零,另外如果目录../
出现太多,则会有相应提示。
完整版源代码:
1<!DOCTYPE html>
2<html>
3<head>
4 <meta charset="utf-8">
5 <style type="text/css">
6 body {
7 background: #F5F5F5;
8 }
9
10 div {
11 width: 400px;
12 height: 250px;
13 position: absolute;
14 left: 50%;
15 top: 50%;
16 margin-left: -150px;
17 margin-top: -125px;
18 background: #eee;
19 border-radius: 5px;
20 box-shadow: 0 1px 1px;
21 }
22
23 form {
24 width: 280px;
25 margin: 0 auto;
26 }
27
28 h1 {
29 text-align: center;
30 }
31
32 input[type="text"] {
33 width: 280px;
34 }
35
36 input[type="text"]:hover {
37 box-shadow: 0 0 5px #000;
38 }
39
40 input[type="submit"] {
41 width: 40%;
42 position: relative;
43 }
44
45 p {
46 float: none;
47 text-align: center;
48
49 }
50
51 </style>
52 <title>Route</title>
53</head>
54<body>
55 <div>
56 <h1>相对路径生成器</h1>
57 <p>将生成第二个文件相对于第一个的相对路径</p>
58 <form action="route.php" method="post">
59 <input type="text" name="routea" placeholder="输入第一个文件路径如/a/b/c/d/e.php"><br/>
60 <input type="text" name="routeb" placeholder="输入第二个文件路径如/a/b/12/34/c.php"><br/>
61 <label>保留文件名:<input type="checkbox" name="file_name" value="yes"></label>
62 <input type="hidden" name="shot" value="shot">
63 <input type="submit" value="运算">
64 </form>
65 <p>
66 <?php
67 if(!empty($_POST['shot'])) {
68 $problem = FALSE;
69
70 if(empty($_POST['routea'])) {
71 echo '请输入第一个路径';
72 $problem = TRUE;
73 }
74
75 if(empty($_POST['routeb'])) {
76 echo '请输入第二个路径';
77 $problem = TRUE;
78 }
79
80 if(!$problem) {
81
82 $a = explode('/', trim($_POST['routea']));
83 $b = explode('/', trim($_POST['routeb']));
84
85 $temp1 = check_protocol('http:', $a);
86 $temp2 = check_protocol('http:', $b);
87 $protocol_a_http = $temp1[1];
88 $protocol_b_http = $temp2[1];
89 $a = $temp1[0];
90 $b = $temp2[0];
91
92 $temp1 = check_protocol('file:', $a);
93 $temp2 = check_protocol('file:', $b);
94 $protocol_a_file = $temp1[1];
95 $protocol_b_file = $temp2[1];
96 $a = $temp1[0];
97 $b = $temp2[0];
98
99 $temp1 = check_protocol('ftp:', $a);
100 $temp2 = check_protocol('ftp:', $b);
101 $protocol_a_ftp = $temp1[1];
102 $protocol_b_ftp = $temp2[1];
103 $a = $temp1[0];
104 $b = $temp2[0];
105
106
107 $pass4 = TRUE;
108
109 if ($protocol_a_http || $protocol_b_http || $protocol_a_file || $protocol_b_file || $protocol_a_ftp || $protocol_b_ftp) {
110 switch ($protocol_a_http || $protocol_b_http || $protocol_a_file || $protocol_b_file || $protocol_a_ftp || $protocol_b_ftp) {
111 case ($protocol_a_http&&$protocol_b_http):
112 if($a[1] !== $b[1]) {
113 echo '你输入的域名不相同<br/>';
114 $pass4 = FALSE;
115 }
116 break;
117 case ($protocol_a_ftp&&$protocol_b_ftp):
118 if($a[1] !== $b[1]) {
119 echo '你输入的FTP地址不相同<br/>';
120 $pass4 = FALSE;
121 }
122 break;
123 case ($protocol_a_file&&$protocol_b_file):
124 break;
125 default:
126 echo "协议不一致<br/>";
127 $pass4 = FALSE;
128 break;
129 }
130 }
131
132 $check1 = check_route('..', $a);
133 $check2 = check_route('..', $b);
134 $a = $check1[0];
135 $b = $check2[0];
136 $pass1 = ($check1[1] && $check2[1]);
137 $pass2 = (search(' ', $a) && search(' ', $b));
138 $pass3 = (search('.', $a) && search('.', $b));
139
140 if ($pass1 && $pass2 && $pass3 && $pass4) {
141 $a = clean_empty_element('', $a);
142 $b = clean_empty_element('', $b);
143 $array1 = search_and_clean_last('.', $a);
144 $array2 = search_and_clean_last('.', $b);
145 $a = $array1[0];
146 $b = $array2[0];
147
148 $counta = count($a);
149 $countb = count($b);
150
151 $count = ($counta < $countb) ? $counta : $countb;
152
153 for ($i=0; $i < $count ; $i++) {
154 if ($a[$i] == $b[$i]) {
155 unset($a[$i]);
156 unset($b[$i]);
157 } else {
158 break;
159 }
160 }
161
162 $route = '';
163
164 $countpoint = count($b);
165
166 for ($i=0; $i < $countpoint; $i++) {
167 $route .= '../';
168 }
169
170
171 if (!empty($a)) {
172 foreach ($a as $key => $value) {
173 $route .= $value . '/';
174 }
175 }
176
177 if(!empty($_POST['file_name'])) {
178 if (isset($array1[1])) {
179 $route .= $array1[1];
180 }
181 }
182
183 if(!empty($route)) {
184 echo '相对路径为' . $route;
185 } else {
186 echo '完全一样哟';
187 }
188 } else {
189 echo '请输入正确的路径';
190 }
191
192 }
193 }
194
195 /* 检查协议 */
196 function check_protocol($protocol, $array) {
197 $check = FALSE;
198 if ($array[0] === $protocol) {
199 $check = TRUE;
200 unset($array[0]);
201 $array = array_values($array);
202 }
203 return array($array, $check);
204
205 }
206
207 /* 检查数组中是否含指定字符串 */
208 function search($str, $array) {
209 $pass = TRUE;
210 foreach ($array as $key => $value) {
211 if ($value == $str) {
212 $pass = FALSE;
213 break;
214 }
215 }
216 return $pass;
217 }
218
219 //只检查最后一个的函数 其他当作文件名来处理
220 function search_and_clean_last($str, $array) {
221 $file = NULL;
222 $counter = count($array);
223 if(strpos($array[$counter - 1], $str)) {
224 $file = $array[$counter - 1];
225 unset($array[$counter - 1]);
226 }
227 $array = array_values($array);
228 return array($array, $file);
229 }
230
231 /* 清除字符串与指定字符串相同的数组元素 */
232 function clean_empty_element($str, $array) {
233 foreach ($array as $key => $value) {
234 if ($array[$key] == $str) {
235 unset($array[$key]);
236 }
237 }
238 $array = array_values($array);
239 return $array;
240 }
241
242 /* 清除带指定字符的数组元素*/
243 function search_and_clean($str, $array) {
244 $file = NULL;
245 foreach ($array as $key => $value) {
246 if (strpos($value, $str)) {
247 $file = $value;
248 unset($array[$key]);
249 }
250 }
251 $array = array_values($array);
252 return array($array, $file);
253 }
254
255 function check_route($str, $array) {
256 $counter = 0;
257 $pass = TRUE;
258 foreach ($array as $key => $value) {
259 if ($value == $str) {
260 $counter++;
261 $array[$key] = '';
262 if (isset($array[$key - ($counter * 2)])) {
263 for ($i=0; $i <= ($counter * 2); $i++) {
264 $array[$key - $i] ='';
265 }
266 } else {
267 $pass = FALSE;
268 }
269 } else {
270 $counter = 0;
271 }
272 }
273
274 return array($array, $pass);
275 }
276
277
278 ?>
279 </p>
280 </div>
281
282</body>
283</html>
284
评论 (1)
好长好长