豪翔天下

Change My World by Program

0%

垃圾框架,用了Laravel过后感觉其他的PHP框架都是垃圾。但是由于生活所迫,不得不研究一下ThinkPHP框架了,哎。

配置

数据库配置放在database.php

1
THINK_VERSION = '3.2.2'	# thinkphp版本

帮助函数

1
2
3
4
$this->redirect('')	# 重定向
Log::record(''); # 记录日志信息到内存
Log::save(''); # 手动将保存在内存中的日志信息写入日志
Log::write(''); # 实时写入一条日志信息,不受配置的允许日志级别影响,可以实时写入任意级别的日志信息

数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 定义model对象
$model = M('Product')

# 直接执行sql语句
$Model = new Model()
$Model->query(sql)

# 获取上一次执行的sql语句
M()->getLastSql();

# 查询数据
$model->select() # findall功能
$model->where('name="haofly"')->find() # 查找满足条件的第一条数据
$model->where('name="haofly"')->select()# 查找满足条件的所有数据

# 创建数据
$model->create(['name' => 'test']);

# 更新数据
$model->where('id=5')->save(['name' => 'test']); // 根据条件更新记录
$model->name = 'test' && $model->where('id=5')->save(); // 使用对象的方式来操作

# 删除数据
$model->where('id=5')->delete()

模板引擎

1
2
3
4
5
6
7
# volist: 用于在模版中循环输出数据集
# 首先有$this->assign('list, $list)
# 然后在模版中这样写循环
<volist name="list" id="vo">
{$vo['name']}<br>
{$vo['pass']}<br>
</volist>

此时此刻,我正在市二院里写着文字,我不知道这个医院的太平间在哪儿,但是想起了前不久我那去世了的妹妹。

妹妹与June的中文音同,不是我的亲妹妹,只是在上学的时候认识的一个好女生。她爸爸是学医的,所以她很会照顾人,人也很温柔,很善良。那时候,每天中午睡午觉,她都会主动给我一床被子给我盖好,每次我有任何健康方面的问题都会问她。我也会经常给她买糖葫芦,给她买好吃的,我知道这不是爱情,就像哥哥与妹妹的感情一样,所以,自然而然我们就成了兄妹了。高中的时候,我们很幸运能在同一所学校,虽然没有在同一个班级,但是,那三年,我们依然在一起照顾对方。那时候,我谈恋爱了,不知道她有没有,但是她总是会说班上有人在追求她,我好担心,担心我这么善良的妹妹会被其他男人骗,担心她不会处理感情中遇到的事。虽然那时候我也不太懂怎么谈恋爱,但身为哥哥的我自然有强烈的保护欲望。我们还认识了一些对方的朋友,那时候真的好开心,那时候周末放半天出去和女朋友买奶茶也会单独给她带一杯。

可是后来,毕业了。毕业以后,我就很少和他们联系了,可能,更多的,是我变了。我不知道她在哪里上学,不知道她有没有找到男朋友,连她在哪儿都不知道。只是在后来的几次电话中得知她已经找到男朋友了,并且,男朋友的老家在东北,几千公里呀。我不知道她那些日子都经历了什么,我不知道为什么她那固执的爸爸会让她一个人嫁到那么遥远的地方,只知道后来的后来,她突然结婚了,她说是“奉子成婚”。我由衷地祝福她,只是在心里却很难受。一个人在那么远的地方,如果娘家人对她不好,可怎么办呀。我没有说出来,只是叫她多看看书,因为我知道,无论一个人在什么困境,只要还会看书,至少心里面会知道什么叫做甜。再后来,只是听她说她生了一个女孩子,然后过了不到一年居然又怀孕了。她说通常是她一个人在家里,老公在外面打工,娘家人在不多远,只是没有过来照顾她。再后来,就是听到她的死讯了。那之前她还发了说说,心情不错,应该是刚生了第二个孩子。据说是在散步的时候失足掉下去的,也有人说是娘家人看她生了两个女孩而不是男孩而产后抑郁的,甚至有人说是谋杀。至于到底什么是真想,我已经不想去深究了。我的妹妹已经走了,再多的真想也换不来她的重生,只希望,那么善良的她,现在已经到了天堂,静静地看着我们,祝福着我们。

我觉得我十分对不起我的妹妹,在那边她一个人的时候,我没有经常去陪她,她只能靠和远在故乡的父亲通通电话,而我,作为一个同龄人,却没有给她带来任何的安慰。这是我一个哥哥的失职。大概有两次吧,她回到家乡,我都说要去看她,但是因为这样或那样的事情,最后都拖到她的再次离开。那几晚,我挨着给我的姐姐妹妹以及那些曾经说过“下次见面一起吃个饭”的朋友都问候了一遍,还好,他们在电话或者QQ里,心情仿佛都还不错。我不希望还会有人从我身边离开,但,哪怕是离开,我也希望能看到它们现在是快快乐乐的。

妹妹,哥哥不知道几十年后还会不会记起你,希望你不要把我怪罪。再见了,妹妹。我已经好几年没吃糖葫芦了,以后可能也不会吃了,我好想下一串糖葫芦,依然是买给你的。

昨天,终于完成了人生中的一件大事——买房。以前觉得买房,看着好就买,应该不是一件麻烦的事情,但通过最近几个月的看房经历来看,其麻烦程度完全超乎了我的想象,甚至给我带来了极大的心理压力。我不知道现在买房是不是好时机,但是我愿意以后花更多的努力来将损失降到最低,来让房子带给我的是更多的幸福感,而不是一辈子的压力。这两天想了很多很多,或许也是我的一次比较大的成长。

最累不过买房

从我毕业开始,父母就开始问我什么时候买房,我知道他们一直都尊重我的意见,我也觉得不用那么早买房,毕竟我和女朋友结婚,可能要等到下一个猴年马月了。但是,今年的重庆房价仿佛一下子变成了网红,国庆前后,当20个城市开启“限购模式”后,仿佛所有人都把焦点投向了重庆,质疑这座新一线城市为何房价迟迟配不上自己的地位。作为一个土生土长的重庆人,我由衷地感谢市政府的能力,也深刻的意识到重庆的房价,可能不会再那么平静了。我和我的父母,以及周围的好多亲戚,都认为,重庆的房价肯定会继续涨,虽然没外地涨得快,但涨价是肯定的。当然,按照往常的规律来说,涨价一般发生在四月份和九十月份。于是我们就决定慢慢看。但是由于我对房子要求并不高,每看一套房子就觉得喜欢,父母就得周末专程从老家跑到城里来看。上周末一连看了两天,每天看个三四套,耳边一直是中介的各种吹嘘,简直筋疲力竭,我也不想再看了,于是匆忙之中选了一套。额,最终我买了最偏远的一套,远离喧嚣,旁边有公园,交通还算方便,我觉得,那才是我理想中的房子。

最愧不过父母

确定买房的那个夜晚,我侧夜难眠,自小时候得的一场重大疾病过后,我就从来没有一下子向父母要过这么多的钱。这让我感到很大的心里压力,我也知道这套房几乎会花光家里所有的积蓄,但是,面对突如其来的房价泡沫,我也不得不硬着头皮下手,哪怕我心里也觉得这个泡沫可能会破灭。本来还说这周末带父母去做一次全身体检,结果没想到,反而让他们这般劳累。没想到,即使是毕业了,也没能让他们过上舒服的生活,现在的我,只希望从装修完了开始不再让他们花哪怕一分钱。不花父母钱,这个日子我已经期待了那么久,也延迟了那么久,希望这次不会再延迟。趁着父母还健健康康的,多让他们享福,最不想听到子欲养而亲不在。

他们没有给我最好的,但给了我他们所有的。

最傻不过曾经

果然,到目前为止,还是有些事情我无法控制。从大学开始,我就努力地提高自己,以使得自己能够在面临两难选择的时候能够轻松应对,比如大二分专业,我已经锻炼到无论哪一个专业我都能应对自如,比如毕业后选工作,我也自认为锻炼到无论哪一个公司哪一个地方,我都能继续成长、持续学习。但是,当面临买房的时候,我软弱了。没有足够的知识去确定哪个房子最好,也没有足够的面对未来的信心,这一次,我没有了当年的豪言壮语,多了几分面对现实的无奈。

还记得曾经的曾经,我们傲气冲天,敢说出“上大学以后不再要父母一分钱”,敢说出“买房完全靠自己”,敢说出“毕业的时候开自己买的车出去”这样的话,但是后来,多少次凝望西边的天空,心里无不充满遗憾,如今的我,依然能说出这样的话,只是已没有了当年的底气,潜意识里否定了这样的话,否定了现在的自己。

是啊,没想到,成长为了曾经讨厌的人。成长怎么会是这样的,难道成长不是一次又一次的实现曾经许下的梦想的过程吗?

最美不过将来

幸运的是,买房确实给我带来了极大的安全感。我曾经以为,女生眼里的安全感就是男生要保护好女生不受伤害,但后来又觉得是感受到自己的男朋友不会离开自己,再后来我又觉得是看到男人的努力觉得以后会过上好日子。女人我永远不懂,但是,买房让我体验到了什么是我的安全感。不用再担心房价是上涨还是下跌,不用再每天去看哪个楼盘更好。买房的第二天,我心里就放轻松了许多。既然买了,就不要后悔。接下来,我要和爸爸妈妈还有我的女朋友一起规划新家的样子。这套房子离我上班的地方很近,但是离女朋友上班的地方很远,所以,希望明年能买辆车,当然,依然只能贷款😂。以后,我们的宝宝会降临在这套房子里,可能要一直等到她上小学才会换房子。我是买了房,但是这样一个我每天居住的地方怎么能反过来把我奴役了,我会把它装扮得漂漂亮亮的,一起走过接下来的几年时光。不做房奴,美好的未来,才刚刚开始。

最好不过现在

我很幸福,从小到大,爸爸妈妈哥哥一直没有离开我,并且现在的女朋友居然是自己的小学同学,并且我身边所有最亲近的人都健康,都很幸福。我们挣的钱不多,但不至于每天为了钱焦头烂额;我们的学历不怎么高,但不会每天找无趣的事情;我们没有住在一起,但都在一个美丽的城市里。想回家看爸爸妈妈,长途车2小时,想去看女朋友,高铁2小时,基本上,随时都能找到理由去看看他们。我和爸爸性格一样,为了多陪陪亲人,宁愿不去外面挣大钱,就过过温馨的小日子,一辈子这样平静,多好呀。现在这么美好,为什么不珍惜呢,我还那么年轻,为什么不趁现在就努力呢?

此书采购于Amazon的0元限时购活动,同时,我表示很激动,终于能拜读期待已久的“初代程序员”王小波的作品了。第一次那么想了解王小波是在我读了《把时间当作朋友》过后,果然,不出半年,我就读到了王小波的作品。和《把时间当作朋友》一样,《人为什么活着》也是一本杂文集,署名只是取了其中某一篇的标题,当然是最富有吸引力的标题。

在我的关于王小波的种种映象里,他应该是一个,很正统,并且很有写鸡汤文潜质的那么一个伟大的作家,不过在阅读了这本书过后,我只想说,这TM是怎样一个有趣的人呀?他反对儒家思想,反对道德至上,以他独特的眼光反抗者外部的不解,哪怕他用脏话骂一个人我都觉得毫不做作,反而要拍手称绝,骂得有理有据,骂得头头是道,骂得真爽。和近现代的一些作家比起来,他的人生经历了这个国家太多的路程,但是作品却没有流露出太多的历史厚重感,没有那么多的包袱,他的文章读起来便有趣多了。看到不到十分之一的时候我最大的感受就是,这个作家,太接地气了。

也是通过这本书,我第一次,对孔孟时期的思想有了深一步的思考。求学的时候,我们只知道这些名家的思想中最出名的几句名言(这就像我每次看完一本书,下面都会摘了很多名言一样),却不了解他们的知识体系,体系必然有一个中心,然而,孔孟思想的中心,似乎都不太正确,或许只能说是政治正确。他们为我们当今的世界定了太多的规矩,其中,很大一部分是我们一直沿用的,只是,很少有人去问对不对,反正周围的人只是认为不按照那样做,便是不对的。

最最让我佩服的是,他一个经历过文革的作家,居然也是一名程序员,他对知识的涉猎程度完全超乎我的想象。首先,他是我知道的唯一一位经历过文革的还会写代码的人,其次他还是上个世纪的程序员,也就是说,电脑刚在国内发展起来的时候,他就已经开始使用电脑,并能自己编写软件解决自己的需求。放在今天,这完全就是一位极客了。肯定会有无数的粉丝。今天的程序员作家也不少,但是经历像他这么丰富的人,肯定是没有的。所以关上书的时候,我感慨了一句:经历丰富的人,写日记都像是在写诗。

最后,这是我女朋友最近和她母亲聊天的截图:

宝宝真的好庆幸,我有这么“不管我”的父母,让我从小能拥有一般农村孩子无法理解的自由,他们带给我的不仅仅是生活上的轻松,更是我一辈子的财富。也很高兴女朋友和我一样能有自由的思想,而不是唯父母命是从。

看了全书,我还是不知道人为什么活着,或许,好好玩儿,活在当下,这才是人生的答案。自由,哪怕仅仅是思维能够自由,那就足够了。

名言
  • 只希望你和我好,互不猜忌,也互不称誉,安如平日,你和我说话像对自己说话一样,我和你说话也像对自己说话一样。说吧,和我好吗?——《孤独的灵魂多么寂寞啊》
  • 我不喜欢稀里糊涂地过日子。我妈妈有时说:真奇怪啊,我们稀里糊涂地就过来了。他们真的是这样。我们的生活就是我们本身。我们本身不傻,也不斤斤计较大衣柜一头沉。干嘛要求我们有什么外在的样子,比方说,规规矩矩,和某些人一样等等。有时候我真想叉着腰骂:滚你的,什么样子!真的,我们的生活是一些给人看的仪式吗?或者叫人安分守己。不知什么叫“分”,假如人活到世上之前“分”都叫人安排好了,不如再死回去的好。——《人为什么活着》
  • 理性就像贞操,失去了就不会再有;只要碰上了开心的事,乐观还会回来的。——《积极的结论》
  • 我现在所教的数学,你们也许一生都用不到,但我还要教,因为这些知识是好的,应该让你们知道。——《跳出手掌心》
  • 在文学艺术及其他人文的领域之内,国人的确是在使用一种双重标准,那就是对外国人的作品,用艺术或科学的标准来审评;而对中国人的作品,则用道德的标准来审评。——《跳出手掌心》
  • 我最赞成罗素先生的一句话:”须知参差多台,乃是幸福的本源。”——《思维的乐趣》
  • 能够带来思想快乐的东西,只能是人类智慧之高的产物。——《思维的乐趣》
  • 假设有某君思想高尚,我是十分敬佩的;可是如果你因此想把我的脑子扔出来挖掉,换上他的,我决不肯,除非你能够证明我罪大恶极,死有余辜。人既然活着,就有权保证他思想的连续性,到死方休。更何况那些高尚和地下完全是以他们自己的立场来度量的,假如我全盘接受,无异于请那些善良的思想母鸡到我脑子里下蛋,而我总不肯相信,自己的脖子上方,原来是长了一座鸡窝。——《思维的乐趣》
  • 于是人人盛赞节烈妇女。翻开历史一看,女人味了节烈,割鼻子拉耳朵的都有。鼻子耳朵不比头发指甲,割了张不出来,而且人身上有此零件,必有用处,拿掉了肯定有不便处。若是为“节烈”之名而自杀,肯定是更加不妥的了。此类行为,就像那条抽疯的海豚。——《西方快乐观区别之我见》
  • 罗素在讨论伦理问题时曾经指出,人人都希求幸福。假如说,人得到自己希求的东西就是幸福,那就言之成理;倘若说因为某件事是幸福的,所以我们就希求它,那就是错误的。——《西方快乐观之我见》
  • 大多数人在受到重视之后,行为就会好。——《居住环境与尊严》
  • 从孔孟到如今,中国的哲学家从来不挑担、不推车,所以他们的智慧从不考虑降低肉体的痛苦,专门营造站着说话不腰疼的理论。——《人生的逆转》
  • 假如从整个人类来考虑问题,早就回发现,趋利避害,直截了当地解决实际问题最重要——说实话,中国人在这方面已经很不像样了——这不是什么哲学的思辨,而是我们的生活经验。我们的社会里,必须有改变物质生活的原动力,这样才能把未来的命脉握在自己的手里。——《人生的逆转》
  • 花钱不说,还下了很多功夫,现在用的软件都是我自己写的。——《从Internet说起》
  • 不知为什么,傻人道德上的敏感度总是很高,也许这纯属巧合。——《奸近杀》
  • 我既不是同性恋,也不想自杀,所以我对计算机没兴趣。得的全是三分。但我现在时常用得着它,所以还要买书看看,关心一下最新的进展,以免用时抓瞎。这是因为我写文章的软件时自己编的,别人编的软件我即使不惯,也信不过,就这么点原因。但就因为这点小原因,握在编程这件事上,还真正有点修为。由此可见,为研究某种学问这件事感兴趣和对这门学问本身感兴趣可以完全是两回事。——《苏东坡与东坡肉》
  • 有人告诉我说,没你这么写杂文的!杂文里应该有点典故,有点考证,有点文化气味。典故我知道一些,考证也会,但就是不肯这么些。——《有关天圆地方》
  • 罗素举这个例子是要说,人们的见识总要受处境的限制,这种限制既不知不觉,又牢不可破——这是一个极好的说明。——《有关天圆地方》
  • 很不幸的是,任何一种负面的生活都能产生很多乱七八糟的细节,使它变得蛮有趣的。人就在这种趣味中沉沦下去,从根本上忘记了这种生活需要改进。——《有关贫穷》
  • 古人说,食色性也。想爱和想吃都是人性的一部分,如果得不到,就称为人性的障碍。——《从<黄金时代>谈小说艺术》
  • 我们的生活有这么多的障碍,真他妈的有意思。——《从<黄金时代>谈小说艺术》
  • 我相信如果不能把已写出的每一根线索都记在心里,就不能写出好的结构;如果不能把写出的每一句话记在心里,就不能写出好的风格。——《<怀疑三部曲>序》
  • 当然,人有贤愚之分。但一个人认为思维是快乐的,那他就可说是热爱智慧的。——《<怀疑三部曲>序》
  • 我认为没有智慧、性爱而且没意思的生活不足取,但有些人却以为这样的生后就是一切。他们还说,假如有什么需要热爱,那就是这种生活里面的规矩——在我看来,这种生活态度简直是种怪癖。很不幸的事,有这种怪癖的人是很多的,有人甚至把这种怪癖叫做文化,甚至当做了生活本身。——《<怀疑三部曲>序》
  • 细读过《孟子》之后,我发现里面全是这样的一些想法。这世界上有很多书都是这样的:内容不可挑剔,只是很没有意思。除了显而易见的坏处,这种书还有一种害人之处就在于:有人从这些书中受到了鼓舞,把整个生活朝更没意思的方向推动。——《<怀疑三部曲>序》
  • 一切人间的荒唐事,整个社会的环境虽是一个原因,但不主要。主要的是:那个闹事的人是在借酒撒疯。——《肚子里的故事》

数据类型

  • print(e)打印变量
  • 在类型后面加上?表示可选项,由于可选项可能为nil,所以在使用的时候要先确保其有值,这时候需要使用!强行解包,例如number! * 10或者使用??避免空值(number ?? 0) * 10
基本变量使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let a = 1	// 声明常量
var b = 2 // 声明变量
var c: String // 声明变量类型

// 可选类型表示允许常量或者变量没有值,即nil,可选类型用?表明
var d: String? // 可选变量,会自动将其值设置为nil
var e: Int? = 404 // 可选变量,这样可以把nil赋值给该变量
println(e!) // 需要!来获取值
// 隐式解析可选类型,用!声明,表明强制要求该变量一定有值。一个隐式解析可选类型其实就是一个普通的可选类型,只是可以被当作非可选类型来使用,如果该变量没有值,那么去获取的时候就会报错
let f: String? = "test"
println(f) // 不需要!

// 三木运算符
?: // 和php一样吧

// 空合运算符
a ?? b // 如果a包含一个值则是a,否则就是b

// 闭区间运算符
for index in 1...5 {} // 返回一个a到b区间的所有的值
// 半开区间运算符
for index in 0..<5 {}
字符串
1
2
3
4
5
6
7
string.isEmpty    	// 判断字符串是否为空
count(string) // 求长度
let g = "\(var1) 呵呵" // 直接将变量的值插入字符串,用反斜线为前缀的括号中
string.hasPrefix("abc") // 判断前缀
string.hasSuffix("def") // 判断后缀
string.uppercaseString // 转换为大写
string.lowercaseString // 转换为小写
数组
1
2
3
4
5
6
7
8
9
10
11
12
13
var strList = ["A", "B"]	// 直接定义
var strList: [String] = ["A", "B"] // 定义
var strList = [Int](count: 10, repeatedValue: 0)// 定一个一个包含10个零的数组
var StrList = Array(count: 10, repeatedValue: 1)
strList.count // 数组长度
strList.isEmpty // 是否为零
strList += ["C"] // 可以直接加
strList[5...7] = ["E", "F"] // 能这样插入
strList.insert("G", atIndex: 0) // 也能这样插
strList.removeAtIndex(0) // 删除一个元素
strList.removeLast() // 删除最后一个元素
for item in strList {} // 数组遍历
for (index, value) in enumerate(strList) {} // 遍历的同时获取到当前索引
集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var h = Set<Character>()	// 定义
h.insert("B") // 插入
h.count // 数量
h.isEmpty // 是否为空
h.remove("B") // 删除一个元素,返回值为该函数本身
h.contains("B") // 集合是否包含一个特定的值
for item in h {} // 遍历
for item in sorted(h) {} // 有序遍历
h.intersection(i) // 求两个集合的交集
h.symmetricDifference(b) // 求两个集合不同的
h.union(b) // 求两个集合的并集
h.subtracting(b) // 求在h集合但不在b集合的
h.isSubsetOf(b) // h是否为b的子集
h.isSupersetOf(b) // h是否为b的父集
h.isDisjointWith(b) // h和b是否完全不一样
字典
1
2
3
4
5
6
7
8
9
10
11
12
var z: [String:String] = ["A": "a", "B": "b"]
z.count // 字典元素数量
z.isEmpty // 是否为空
z["C"] = "c"// 添加值
z.updateValue("C", forKey:"C") // 更新值,返回老值
z["C"] = nil // 移除值
z.removeValueForKey("C") // 移除值
for (key, value) in z {} // 字典遍历
for key in z.keys {} // 遍历key
for value in z.values {} // 遍历value
let a = Array(z.keys)
let b = Array(z.values)
函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 简单定义,函数的参数默认是常量,如果在函数题中更改参数值居然会编译错误,如果要传入一个变量参数,可以在参数名前加var,加了var,就可以在函数内部进行修改,但修改后的值并不能影响函数外部该值的原来的值,如果真的要修改外部的,那么要将参数定义为inout,表示是输入输出参数
func sayHello(userName: String, second: String = "默认值") -> String {
let a = "B" + userName
return a
}

// 多返回值定义
func count(string: String) -> (a: Int, b: Int) {
return (a, b)
}

// 提供外部参数名的,在调用时必须提供外部的参数名
func function(externalParamterName localParameterName: int) {}
// 调用时
func(外部变量名: "abc")

// 好吧,这样就不用单独定义外部参数名了,外部参数名和内部参数名一样
func function(#string: String) {}

// 可变参数
func function(numbers: Double...) {}
结构体/类
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
50
// getter/setter
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 0.0, height = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
var square = Rect(origin: Point(x: 0.0, y: 0.0),
size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)

// 属性观察器,每次属性被设置的时候都会调用属性观察器,有两种
willSet: 在设置新的值之前调用
didSet: 在新的值呗设置之后调用
// 直接在定义结构体或类内部变量时使用
class Example {
var test: Int = 0 {
willSet(newValue) {
println("hehe")
}
didSet {
println("haha")
}
}
}

// 下标脚本
// 构造器
struct teset {
var a: Double
init() {
a = 12.0
}
}

参考实例

Prodigal-iOS: 音乐播放器

AMM: Aria2 Menubar Monitor

CSRF(跨站请求伪造)

通过手段欺骗用户访问第三方页面,通过用户在第三方页面执行常规的操作来进行欺骗,这些操作包含了用户已登陆网站的一些请求,当用户点击该请求时,请求会发往原站,同时由于用户已经登录,所以原站是能验证用户的,通常会判断为合法请求。防御:

1.表单增加hash值,就像laravel和django自带的表单csrf验证一样,而这个hash值和用户是对应起来的,第三方是无法同时拿到这两个东西的

2.验证码

最近团队由于项目需求的增多,需要单独设计一个权限系统出来,参考了网上很多的权限/访问控制系统以及一些设计原则比如RBAC(Role-Based Access Control),这里,记录一下自己对权限系统的一种构想。需要注意的是,RBAC中也有分组的概念,但是它的分组仅仅是为了将相同权限的人集中在一起。我的构想虽然没有分组的概念,但是也符合RBAC原则的,只是因为我做的更彻底,不仅将角色与权限直接关联,更是将用户与权限直接关联,产生了一定的冗余,更适用于人数少但是权限多的情况。

实体表

应用表

字段名 字段注释
id app_id

角色表

字段名 字段注释
id role_id
app_id 应用ID
name 名称(英文)
beta 备注

权限表

字段名 字段注释
id privilege_id
app_id 应用ID,不提供表示通用的权限
name 名称(英文),例如projects表示项目相关的权限,这里如果想要有更复杂的层级关系,可以用点号进行分割,但不建议增大权限的层次
beta 备注

操作表

记录一些通用的操作,例如增删该查等。当然,这里的操作表可以省略,而直接将操作以父子关系放在权限表中。

字段名 字段注释
id operator_id
app_id 不提供表示通用的操作
name 名称(英文),例如: add,delete,edit,query等,或者页面上index,create,admin等
beta 备注

关联表

用户与权限关联表:此表与角色权限对应表之间是有一定冗余的,但是考虑到个性化需求以及第三方APP的需要,所以在可以忍受的范围内

字段名 字段注释
id
user_id 用户ID
role_id 角色ID: 为0表示该权限是独立分配的,独立分配的优先
privilege_id 权限ID
operator_id 操作ID
disabled boolean

角色与权限对应表

可以将用户与权限的关联表和角色与权限的关联表合并,使用target来标识

字段名 字段注释
id
role_id 角色ID
privilege_id 权限ID
operator_id 操作ID

用户与角色对应表

字段名 字段注释
id
role_id 角色ID
user_id 用户ID

常用操作

添加权限: 直接添加,并设置好其
给单独用户添加权限:保存在角色与权限表中,这样用户的实际权限就应该是用户绑定角色拥有的权限与用户单独分配的权限之和。
给单独用户删除权限:如果是单独添加并且绑定角色所没有的,直接删除关联关系;如果是绑定角色所关联的权限,那么将关联表中的权限标识为禁用;如果是单独添加并且绑定角色也有的,同样标识为禁用。所以最终,用户的实际权限是用户绑定角色拥有的权限与用户单独分配的权限之和减去禁用的权限,当然由于有冗余,直接在关联表中读取没禁用的权限即可。

删除用户角色: 直接根据role_id进行disabled,添加了就不直接删除
删除用户权限:直接根据role_id进行disabled,也不直接删除
其他平台登录:只需要在登录的时候获取该用户在该平台的所有的额权限即可,连分组都不需要,因为权限都是在权限系统中进行统一登记注册的,所以其他平台不用单独存储权限列表,而只需要获取获取当前用户的权限,放到缓存里面即可,例如redis,可以直接存储为一个列表user:privileges []

gulp

前端的自动化构建工具,能够自动化处理一些常见的任务:

  • 搭建web服务器
  • 修改文件自动刷新浏览器
  • 预处理Sass、Less
  • 优化资源:CSS、Javascript、图片等

安装方式

全局安装:npm install gulp -g
当前项目安装: npm install --save-dev gulp
安装后,会在当前目录生成一个node_modules目录,然后执行npm init初始化当前项目,根据提示输入一些项目的基本信息,然后会生成一个package.json文件

目录结构

app/        # 开发目录,存放源文件
    css
    fonts
    images
    js
dist/        # 存放生产环境下的内容
gulpfile.js
node_modules/
package.json

gulpfile.js文件

var gulp = require('gulp'),    # 去node_modules下导入相应的包
    livereload = require('gulp-livereload'),
    del = require('del'),
    notify = require('gulp-notify'),
    browserify = require('gulp-browserify'),
    jshint = require('gulp-jshint');

gulp.task('scripts', function(){
//这里可以不用把所有的.js合并成一个,而是可以按需合并,比如每个文件都需要用到的就合并成一个,其他单独的则单独合并,不许return,写两个gulp.src即可,比如gulp.src('app/js/base.js').pipe......和gulp.src('app/js/new.js').pipe...
    .pipe(browserify({
        insertGlobals: true,
        debug: !gulp.env.production
    }))
    .pipe(concat('base.js'))        // 这是把上面所有的js文件合并为一个文件
    .pipe(gulp.dest(DEST+'/js'))
    .pipe(rename({suffix: '.min'}))
    .pipe(uglify())
    .pipe(gulp.dest(DEST+'/js'))
    .pipe(notify({
        message: 'Scripts task complete'
    }));
    
gulp.task('clean', function(cb){    # 定义任务
    del(['dist', cb]);
});

gulp.task('default', ['clean'], function(){
    gulp.start('scripts');
});

gulp.task('watch', function(){
    gulp.watch('app/js/index.js', ['scripts']);    # 见识文件,当监控的文件变化时执行相应的任务
    livereload.listen();
    gulp.watch(['dist/**']).on('change', livereload.changed);
});

在命令行执行gulp task_name就可以运行该任务了

其他插件

  • gulp-jshint: js代码校验
  • gulp-concat: js代码合并
  • gulp-notify: 更改提醒
  • gulp-uglify: js代码压缩
  • gulp-livereload: 自动刷新页面
  • del: 清除文件

这本书在最近一年里面特别火,以前好多从来不看书的朋友都在朋友圈里发这本书的照片,仿佛大家一下子爱上了文字。我当然不会因为人家看我就看的,只是每次一看到这本书的名字,就不由得想起日本的情感电视剧《深夜食堂》,不知道为什么,就感觉他们可能会有好多相似的地方,应该会和《深夜食堂》一样,在很平淡的叙述中体会其中的韵味,引人入胜。于是最后,我还是看了。它和《深夜食堂》有相似的,也有不同的。《深夜食堂》是把精彩的故事写平淡,而《解忧杂货店》则是把本应该跌宕起伏的故事写得平淡,然后一步一步将错综复杂的故事串起来,功力同样深厚,毕竟是东野圭吾的作品,不得不叹服。

浪矢杂货店,一个连接过去与未来的杂货店,连接了一个老头与三个坏孩子一起帮助别人排忧解难的故事。通过几个矛盾人物与他们之间的书信交流来推动故事发展,更精妙的是几个矛盾人物之间又刚好有一丝丝的联系,联系虽然不深,但是却足以让人看到其中环环相扣的逻辑,被作者的思维所震撼。

我一直都像很多国人一样,哪怕自己过得再堕落,哪怕自己不相信大道理也要自以为是地告诫别人,偶尔,也会很认真地回应别人的玩笑,因为“我们也要尽可能帮助他人,你没有无视他开玩笑写的问题,而是认真回答,所以才回一直牢记在心里”。我希望自己能力所能及地帮助他人,特别是刚入编程领域的小学弟们,我很希望他们来问我问题,哪怕最简单的,哪怕最幼稚的,我也要认认真真地回答。遗憾的是,我并不是什么大神,所以找我咨询的学弟微乎其微呀。

人生,重要的是选择。作为一个挣扎于选择困难症不能自拔的天秤座的我来说,其实,很多时候在犹豫不决的时候,决定其实早就在自己心中,只是,要么因为各种客观原因,要么就是自己主观上的回避。最常见的莫过于购物的时候,说简单点就是没钱,所以才会犹豫不决,这个倒很好解决,多挣钱就行。又比如人生中的抉择,月兔想参加奥运会,但是怕选不上所以找了一个照顾男友的理由;克朗想成为歌手,然后又以照顾父亲为理由放弃追逐梦想。追逐梦想,能够轻松实现自己想要的,谁又不想呢。只是现实很多时候过于残酷,我们不知道继续坚持会不会得到自己期待的结果,只是从现在的情形看来,结果肯定不会太好,这个时候如果来了一个很合理的,连自己都能说服的理由,又何尝不想放弃呢,放弃多好,努力不一定成功,但不努力,一定很轻松。似乎,只要不是自己的原因,这样的理由就非常容易被接受,也不至于被身边的人嘲笑。但是,终究不过是自欺欺人。明明知道自己想要的,但还是选择逃避。不要轻易被自己的努力感动,真的,你做的努力相比于真正成功了的人,是微乎其微的。

常用快捷键

Mac自带截图功能

  • Command + Shift + 4 普通截图
  • Command + Shift + 4,然后按空格,对指定窗口截图
  • Command + Shift + 3 全屏截图

finder显示隐藏文件

Command + Shift + .

Mac瘦身

  • 最好的工具mac-cleanup-sh

  • ~/Library/Application Support/Code/User/workspaceStorage: VS Code的工作区文件夹唉,但是所有的扩展都会重建这个文件夹,把年代久远的删除了

Shell配置使用

Mac使用Iterm2的Profile功能实现类似ssh标签/xshell登录的功能

Preferences中不仅可以设置默认Profile的窗口样式等,还是通过新建不同的Profile来实现自动登录。例如:

这样如果想要进入某个服务器,只需要在iterm2中点击顶部菜单Profiles->aliyun即可直接进入服务器。对于复杂的输入密码的场景,可以参考Linux 手册expect进行配置

mac shell使用rz、sz直接上传或者下载服务器文件

  • 需要注意的是在使用except登录服务器的情况下,使用lrzsz不会起作用

首先使用brew install lrzsz安装命令行工具

然后保存iterm2-send-zmodem.sh 和iterm2-recv-zmodem.sh两个脚本/usr/local/bin目录下

打开iterm2Perferences->Profiles->Advanced->Triggers->Edit,添加如下trigger

1
2
\*\*B0100			Run Silent Coprocess	/usr/local/bin/iterm2-send-zmodem.sh
\*\*B00000000000000 Run Silent Coprocess /usr/local/bin/iterm2-recv-zmodem.sh

Homebrew配置使用

  • brew如果加cask参数表示下载的是.dmg/.pkg文件,不需要install等操作
1
export ALL_PROXY=socks5://127.0.0.1:1080	# homebrew走ss代理

查看每个CPU的负载/GPU负载

活动监视器->窗口->CPU使用率/CPU历史记录/GPU历史记录

修改终端欢迎字符

1
vim /private/etc/motd	# 直接输入即可

系统管理命令

1
2
3
4
5
6
7
# lsof
lsof # 查看所有进程打开的文件
lsof -i # 查看有网络连接的应用程序列表

dscacheutil -q group # 查看所有用户和组

sudo shutdown -h 2306132200 # 定时关机,后面是年月日时分秒

更换文件图标

http://www.cnblogs.com/wormday/archive/2011/05/06/2038703.html

与Android联动

  • brew cask install android-file-transfer可以管理小米手机上的文件

自制iPhone铃声

iTunes 簡單自製 iPhone 鈴聲不求人

Mackup配置备份

1
2
3
4
5
6
7
8
9
10
brew install mackup

vim ~/.mackup.cfg进行配置
[storage]
engine = file_system # 表示用文件系统进行存储
path = /Users/haofly/OneDrive # 指定路径

mackup backup # 备份命令
mackup restore # 数据恢复
mackup uninstall# 将配置文件拷回原来的系统目录

ios safari移动端真机调试

https://channaly.medium.com/how-debug-cordova-based-application-with-chrome-dev-tool-43e095a735b4

  • 可用于调试Cordova/Inoic/Phonegap等hybrid项目
  1. ios移动端配置: Settings -> Safari -> Advanced , 打开JavaScriptWeb Inspector
  2. mac上safari浏览器配置: Preferences -> Advanced -> Show Develop menu in menu bar
  3. 当连接上设备后就可以点击Safari->Develop->iPhone选择你的设备即可

android通过蓝牙向Mac/macbook传输文件失败

  • 需要在电脑左上角apple logo -> System Preferences -> Sharing -> Bluetooth Sharing打开并设置读写权限

iPad或者iPhone投屏到Mac

  1. iPad数据线连接Mac
  2. Mac上打开QuickTime Player,然后选择File -> New Movie Recording,在中间录像按钮边上点开的下拉菜单选择你的设备

安装python2或者python3

不要期待brew,最好直接从官网下载对应版本的dmg文件安装,都可以直接安装的

Mac OS降级

  • 降级最简单的是直接从timemachine恢复,但是大多数情况下我们并没有timemachine,那么就需要U盘了

  • 首先需要从苹果官方下载老版本的系统

  • 然后执行以下命令制作系统盘,执行完成后会提示Done.,如果多次尝试仍然报错,那么可能需要换个更大的U盘,或者换一个U盘。(我最开始用的16G的USB2.0,后来换成32G的USB3.0就可以了)

    1
    2
    # 其中Catalina.app是下载的系统的名称,MyVolume是U盘名称
    sudo /Applications/Install\ macOS\ Catalina.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume
  • 开机时按住Option键,然后选择U盘进入,然后用磁盘工具格式化磁盘,重装系统即可

TroubleShooting

  • 磁盘空间爆了,重启后spotlight一直显示正在索引: 原因可能是误删了索引的文件(索引文件确实有哦几个G),修复需要执行以下几个命令:

    1
    2
    3
    sudo mdutil -i off /
    sudo mdutil -E /
    sudo mdutil -i on /
  • Library not loaded: /usr/local/opt/readline/lib/libreadline.6.2.dylib Referenced from: /usr/local/bin/gawk Reason: image not found: 执行下面这个命令更新所有brew安装的包可以修复

    1
    brew upgrade
  • 明明安装了xcode命令行工具却还是提示找不到,可以用这个命令重装一下:

    1
    2
    3
    xcode-select --print-path	# 一般会打印/Library/Developer/CommandLineTools
    sudo rm -r -f /Library/Developer/CommandLineTools
    xcode-select --install # 重新安装
  • Macos使用ssh登陆linux服务器无法显示中文,需要设置终端的字符集:

    1
    2
    3
    # vim ~/.zshrc,在底部输入如下内容,然后保存重启终端
    export LC_ALL=en_US.UTF-8
    export LANG=en_US.UTF-8
  • autoreconf: command not found: brew install autoconf && brew install automake

  • **xcrun: error: invalid active developer path, missing xcrun **: 重装xcode工具: xcode-select --install

  • macOS Big Sur无法使用VPN: 系统限制没办法,得修改VPN服务器的配置,参考苹果的官方说明

  • telnet: command not found: brew install telnet

  • Safari不能审查元素,没有审查元素按钮:得手动打开开发者菜单: Preferences -> Advanced -> Show Develop menu in menu bar

  • MacOs安装指定的java版本: https://www.azul.com/downloads/?package=jdk

  • zsh: bad CPU type in executable: 执行softwareupdate --install-rosetta