empty和isset函数

自己对这两个函数一直是一知半解的,这里小小的总结一下

empty()函数

对于empty()函数,php手册给出的官方解答是:

判断一个变量是否被认为是空的。当一个变量并不存在,或者它的值等同于FALSE,那么它会被认为不存在。如果变量不存在的话,empty()并不会产生警告

也就是说我们可以通过判断与它等价的bool值来判断empty之后的值是false还是true

我们做一个小实验:

1
2
3
4
5
6
7
8
9
10
11
<?php
var_dump(empty(0));
var_dump(!!0);
var_dump(empty(null));
var_dump(!!null);
var_dump(empty(array()));
var_dump(!!array());
var_dump(empty('0'));
var_dump(!!'0');
var_dump(empty(1));
var_dump(!!1);

下图是打印出的结果:

也就是说,empty()函数里面的参数的值的bool等价值为false的话,那么empty函数返回true。否则返回false

isset()函数

对于isset()函数,php手册给出的官方解答是:

检测变量是否设置,并且不是 NULL

变量是否设置比较好理解,也就是给它值就行了(不能是NULL),那么什么时候一个变量会是null呢?

手册里面给出的答案是:

  • 被赋值为 NULL

  • 尚未被赋值

  • 被 unset()

做个小实验:

1
2
3
4
5
6
7
8
9
10
11
<?php
$var1 = '';
var_dump(isset($var1));
$var2 = 0;
var_dump(isset($var2));
$var3 = '0';
var_dump(isset($var3));
$var4 = array();
var_dump(isset($var4));
$var5 = new stdClass();
var_dump(isset($var5));

bind(127.0.0.1:0) failed. Error: Address already in use

最近正在学习swoole,发现要学太多的计算机基础知识了

今天在入门swoole的时候,我先按照官网的例子写了一个服务端的php代码,发现没有问题。但是再次运行的时候,就有了报错WARNING swSocket_bind: bind(127.0.0.1:0) failed. Error: Address already in use [98]

这个意思是说端口正在被占用,所以下次运行的时候会报一个这样的错

那么,我们该怎么做呢?

因为在系统服务中,端口不是独立存在的,它是依附于进程的。某个进程开启,那么它对应的端口就开启了,进程关闭,则该端口也就关闭了。下次若某个进程再次开启,则相应的端口也再次开启。所以,不要纯粹的认为你要去关闭掉某个端口了。但是,禁用某个端口是可行的。因为,linux里面端口的活动与进程是紧密相连的,如果想要关闭某个端口,那么只要kill掉与它对应的进程就可以了

那么,这个端口是和哪个进程有关呢?

我们可以使用如下命令:netstat -anp | grep 端口号来查看,例如,我的9501端口被占用了,那么,我可以使用:netstat -anp | grep 9501来查看,显示如下:

LISTEN说明它是被监听着的,2888是这个进程的进程ID,我们可以通过:kill 进程ID来杀死一个进程

我们执行了kill指令之后,再次执行:netstat -anp | grep 9501就会发现9501这个端口没有被占用了

通过局域网来让手机访问本地的vue.js项目

相信大家在用vue.js写WebApp的时候,都想用手机来访问本地的vue.js项目,但是一般人想到的都是先把文件上传到托管的服务器里面(例如:阿里云、腾讯云等等),然后在通过服务器的ip来访问。这种方法可以是可以,但是非常耗时间,最快的方法还是通过局域网来让手机访问本地的vue.js项目。

那么如何通过局域网来访问呢?下面介绍一种方法。

一、先让手机和电脑连上同一个局域网

首先,我们让电脑连上无线网,然后再用电脑给手机开网络共享,然后手机连上电脑发出的共享网络

二、查看ip

在百度里面直接输入ip即可查看(分别用手机和电脑查看,一般来说查到的ip是一样的)

三、把电脑的防火墙先关闭

四、开启你电脑本地的vue.js项目

此时你得到了端口号(应该是8080)

五、使用手机访问你的项目

你需要在手机的浏览器里面输入你刚才查到的Ip,例如:120.203.28.43

然后在加上刚才的端口号(例如:8080)

也就是通过:120.203.28.43:8080即可访问你的项目了

注意用完了之后要开启防火墙哦

什么是HTML实体

有些字符,例如左尖括号和右尖括号是不允许在html文本中使用的,要在html中显示这些字符,我们必须使用html实体,那么,如何使用html实体呢?在html里面,我们如果要在浏览器中之间显示
,而不是换行的话,我们可以有如下写法:

1
&lt;br&gt;

这里的& lt;在浏览器会输出左尖括号,& gt;会输出右尖括号

此时,你会在浏览器里面真正的看到这个
标签,这个标签是没有任何实际含义的

如果你在HTML文件里面直接写:

1
<br>

你会发现,浏览器里面是看不到任何字符,因为,这里的
是有含义的,也就是“换行”

现在,你应该对实体有了一定的了解。我现在大概解释一下你的博客的那个问题

首先,你要明白你为什么要使用wangeditor那个插件。原因就是,你可以获取到你写的文字的html实体。如果你直接在textarea里面写文字的话,你是不能够提取实体的,这样当你去获取那些文字的时候,你就丢失了那些标签,也就意味着你在下次修改文章的时候,你原来的那些换行呀,分段呀,给文字加粗呀,这些东西都不会显示在你面前,而显示在你面前的是一篇黑压压的字,他们没有任何格式

但是,如果你使用了那个插件获取了HTML实体的话,你就可以得到那些标签,这时候,你就把这些HTML实体(也就是那些标签)连同你写的文章一起存入数据库中。当你下次修改文章的时候,你可以从你的数据库中获取到带有html实体的文章。但是,我前面说了,实体是没有任何实际意义的,它是会直接显示在你眼前的。而你是不想要实体显示在你眼前的,所以,需要对实体转化,转化为标签

记住,你在数据库里面存放的一定不是标签,否则,在页面上是不会显示标签的。你在数据库中的标签一定是以实体的形式存在的也就是下面这种类似的形式;

1
&lt;br&gt;

Vue.js路由报错:TypeError: Cannot read property '_c' of undefined

错误详情:

像上面这个报错真的是是十分的蛋疼,根本看不懂,也定位不了,所以只能一行一行代码的去寻找可能出错的原因

先来看看我的代码(在main.js文件里面):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import Vue from 'vue'
import App from './App.vue'
import VRouter from 'vue-router'
import Apple from './components/apple.vue'
import Banana from './components/banana.vue'
Vue.use(VRouter);
let router = new VRouter({
mode: 'history',
routes: [
{
path: '/apple',
components: Apple
},
{
path: '/banana',
components: Banana
}
]
});

new Vue({
el: '#app',
router,
render: h => h(App)
});

仔细排查错误后发现,routes里面的components多了一个s,正确的应该是:

1
2
3
4
5
6
7
8
9
10
routes: [
{
path: '/apple',
component: Apple
},
{
path: '/banana',
component: Banana
}
]

所以一定要细心!!!

php实现评论功能(仅有两层)

目前做的一个项目涉及到了说说功能

以下是我的数据表:

其中可以看到,我只有两层评论,并没有那种很多层的复杂的树形结构

我现在想把这个杂乱的一系列评论分成一组一组的评论,其中,parent_id为0的作为第一层,parent_id与talk_id相同的作为第二层

开始我想的方法是递归来分出两层来,后来还是用比较暴力的方法来解决

以下是我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getSubTree($data = array(), $pid = 0){
static $tmp = array();

foreach($data as $key => $value){
if($value['parent_id'] == $pid){
$talk_id = $value['talk_id'];
$value['child'] = getSubTree_1($data, $talk_id);
$value['childCount'] = count($value['child']);
$tmp[] = $value;
}
}
return $tmp;
}

function getSubTree_1($data = array(), $pid){
$tmp = array();
foreach($data as $key => $value){
if($value['parent_id'] == $pid){
$tmp[] = $value;
}
}
return $tmp;
}

思路是先在getSubTree函数里面找出parent_id为0的说说,然后再得到它的talk_id,然后再为这个说说(也就是这个parent_id为0的数组)构造一个一维数组child

接着再调用getSubTree_1函数来找出parent_id为$talk_id的说说,也就是第一层说说的评论

一直循环(找出parent_id为0的说说,然后再找这条说说的评论)

最终,我构造了一个新的数组(这个数组是三位数组,原来没有分类的时候是二维数组)

用PHP实现删除数据表中的一个节点(记录)以及它的子树

我们知道,在评论区中,经常会看见一个人评论之后,后面有人艾特前面的那个人,对他进行评论,然后又有人对上一个人进行评论
我们叫这种结构为树形结构,其中的一条评论我们可以称之为节点

这张数据表对应的树形结构是:

如果我要删除节点16,那么,这个树形图会变成

不要在意树的箭头方向变了,我们关注的是树的逻辑结构的变化

接下来用代码实现这个删除操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php

$con = mysqli_connect('localhost', 'root','');

if(!$con){

die('没有连到数据库'.msql_error());

}

mysqli_select_db($con, 'test');

$sql = 'select * from treeNodes';
$result = mysqli_query($con, $sql);
if(!$result){
die('查询失败!');
}
$row = array();//用来保存从数据库查询出来的记录
$i = 0;
while($da = mysqli_fetch_array($result, MYSQL_ASSOC)){
$row[$i++] = $da;//一条一条的保存
}

delete_child_tree($con, $row, 16);//删除父id为16的子树


function delete_child_tree($con, $data, $pid = 0){
static $save_id = array();//用来保存需要删除的那个节点的id的数组
$new_data = array();//用来保存删除节点后的新的数组
foreach ($data as $key => $value) {
if($value['pid'] == $pid){
array_push($save_id, $value['id']);//保存需要删除的那个节点的id
$sql = 'delete from treeNodes where id = '.$value['id'];
mysqli_query($con, $sql);
}
else{
$new_data[] = $value;//如果这个节点不用被删除的话,那个就保存他到新的数组里面
}

}
var_dump($save_id, $new_data);
if($id = array_shift($save_id)){
echo '<span style="color:red;">'.$id.'</span>';
delete_child_tree($con, $new_data, $id);//递归调用
}
}
mysqli_close($con);

?>

执行这段代码之后,数据表变为:

至于id为16的那个节点,大家可以自己动手删掉它,也不难