今天是10月24日,祝程序员们节快乐!

也许有人不懂 1024 为啥是程序员节,这里简单普及下吧。

1024 最初源自于一个论坛,他的回帖机制是,新用户发过帖之后,过 1024 秒之后才能再发一帖。

我们知道,程序员是跟计算机打交道的,而一般计算机多采用二进制,2 的 10 次方是 1024,1G = 1024 M,1 M = 1024 kb,1kb =1024 bit,所以在程序员眼里,1024 是一个整数,相当于普通人眼里的 1000,不是有个笑话么:

一个人问程序员借钱,借 1000 块,程序员说,给你凑个整,借 1024 元吧。现在看懂这个意思了吧?

而在某草 X 社区,多见到 1024 的留言,原因就是因为 1024 M = 1GB,即一级棒的意思。

现实中的那些纷纷扰扰,都无非是过眼云烟。
你在人生的战场上追名逐利,不得解脱。
我在我的草 X 社区中,宁静致远,深藏功与名。

就这样,逐渐的,1024 走入了人们的视野,而随着互联网的迅速发展,程序员这一群体也受到越来越多的人关注。

2015 年,每年 10 月 24 日被定义为程序员节。以一个节日的形式,向通过 Coding 改变世界,也以实际行动在浮躁的世界里,固执地坚持自己对于知识、技术和创新追求的程序员们表示致敬。

今天,是所有程序员们自己的节日,也许没有那么狂欢,没有被纳入法律规定,我们还是正常的上班,没有公司的特殊待遇,但是至少,我们这个群体被世界所关注,每个程序员都有过「改变世界」的梦想,虽然它并没有实现,但是我们至少努力过!

1024,所有程序员们节日快乐!

不同版本PHP之间cURL的区别

之前在做一个采集的工具,实现采集回来的文章,图片保存起来.文章内容是保存在数据库,图片是先需要上传到图片服务器,再返回图片地址,替换掉文章的图片地址.

问题来了:都能成功采集都东西,但是,本地测试是正常的,图片也可以上传成功,但是生产环境就是一直没有图片.然后自己就一步一步调试,,发现数据都有,但为什么偏偏生产上没有成功上传图片呢.

后来折腾了几天,经过一步步的看代码,调试,百度,终于找到答案了.真是一个大坑.

上传到图片服务器是用curl post过去的,

PHP的cURL支持通过给CURL_POSTFIELDS传递关联数组(而不是字符串)来生成multipart/form-data的POST请求。

传统上,PHP的cURL支持通过在数组数据中,使用“@+文件全路径”的语法附加文件,供cURL读取上传。这与命令行直接调用cURL程序的语法是一致的:

curl_setopt(ch, CURLOPT_POSTFIELDS, array(
    'file' => '@'.realpath('image.png'), 
)); 
equals
$ curl -F "file=@/absolute/path/to/image.png" <url>

但PHP从5.5开始引入了新的CURLFile类用来指向文件。CURLFile类也可以详细定义MIME类型、文件名等可能出现在multipart/form-data数据中的附加信息。PHP推荐使用CURLFile替代旧的@语法:

curl_setopt(ch, CURLOPT_POSTFIELDS, [
    'file' => new CURLFile(realpath('image.png')), 
]); 

PHP 5.5另外引入了CURL_SAFE_UPLOAD选项,可以强制PHP的cURL模块拒绝旧的@语法,仅接受CURLFile式的文件。5.5的默认值为false,5.6的默认值为true。

但是坑的一点在于:@语法在5.5就已经被打了deprecated,在5.6中就直接被删除了(会产生 ErorException: The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead)。

对于PHP 5.6+而言,手动设置CURL_SAFE_UPLOAD为false是毫无意义的。根本不是字面意义理解的“设置成false,就能开启旧的unsafe的方式”——旧的方式已经作为废弃语法彻底不存在了。PHP 5.6+ == CURLFile only,不要有任何的幻想。

我的部署环境是5.4(仅@语法),但开发环境是5.6(仅CURLFile)。都没有压在5.5这个两者都支持过渡版本上,结果就是必须写出带有环境判断的两套代码。

现在问题来了……

 

环境判断:小心魔法数字!

我见过这种环境判断的代码:

if (version_compare(phpversion(), '5.4.0') >= 0)

我对这种代码的评价只有一个字:

这个判断掉入了典型的魔法数字陷阱。版本号莫名其妙的出现在代码之中,不查半天PHP手册和更新历史,很难明白作者被卡在了哪个功能的变更上。

代码应该回归本源。我们的实际需求其实是:有CURLFile就优先采用,没有再退化到传统@语法。那么代码就来了:

if (class_exists('\CURLFile')) {
    $field = array('fieldname' => new \CURLFile(realpath($filepath)));
} else {
    $field = array('fieldname' => '@' . realpath($filepath));
}

建议明确指定的退化选项

从可靠的角度,推荐指定CURL_SAFE_UPLOAD的值,明确告知php是容忍还是禁止旧的@语法。注意在低版本PHP中CURLOPT_SAFE_UPLOAD常量本身可能不存在,需要判断:

if (class_exists('\CURLFile')) {
    curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
} else {
    if (defined('CURLOPT_SAFE_UPLOAD')) {
        curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
    }
}

cURL选项设置的顺序

不管是curl_setopt()单发还是curl_setopt_array()批量,cURL的选项总是设置一个生效一个,而设置好的选项立刻就会影响cURL在设置后续选项时的行为。

例如CURLOPT_SAFE_UPLOAD就和CURLOPT_POSTFIELDS的行为有关。如果先设置CURLOPT_POSTFIELDS再设置CURLOPT_SAFE_UPLOAD,那么后者的约束作用就不会生效。因为设置前者时cURL就已经把数据实际的识读处理完毕了!

cURL有那么几个选项存在这种坑,务必小心。还好这种存在“依赖关系”的选项不多,机制也不复杂,简单处理即可。我的方法是先批量设置所有的选项,然后直到curl_exec()的前一刻才用curl_setopt()单发设置CURLOPT_POSTFIELDS

实际上在curl_setopt_array()用的数组中,保证CURLOPT_POSTFIELDS的位置在后边也是可靠的。PHP的关联数组是有顺序保障的,我们也可以假设curl_setopt_array()内部的执行顺序一定是从头到尾按顺序[注A],所以尽可放心。

我的做法只是在代码表现上加个多余的保险,突出强调顺序的重要性防以后手贱。

命名空间

PHP 5.2或以下的版本没有命名空间。代码中用到了空间分隔符\就会引发解析器错误。要照顾PHP 5.2其实容易想,放弃命名空间即可。

要注意的反倒是有命名空间的PHP 5.3+。无论是调用CURLFile还是用class_exists()判断CURLFile的存在性,都推荐写成\CURLFile明确指定顶层空间,防止代码包裹在命名空间内的时候崩掉。

好了,这坑挖得好深,跳出来就分享下.

(以上解决方法是转载网站的,感谢让我找到了你这篇东西!)

美国康奈尔大学:研究发现性格随和的员工的薪酬比“带刺儿的”员工低18%

中国有句俗话:老实人吃亏多,会哭的孩子有奶吃。这话听上去像句牢骚,不过最近居然被证实了。

美国康奈尔大学劳资关系学院的一项调查中,分析了职场人员的“随和度”特征后发现:性格随和的员工的薪酬比“带刺儿的”员工低18%。

这个调查结果真让人心寒,这个社会怎么了?

心理学说上的“随和性”,又叫“宜人性”(Agreeableness),通常是指与他人和睦相处、相互协作,包括了和善友好、协作性、值得依赖的性格特征。

我在《职场“中等收入陷阱”:你的薪水为什么不再增加?》中提出一个观点:你的薪水取决于你解决问题的层次,而不是做了多少工作。

从这个角度理解,“随和性”影响了你的薪水,很可能是你工作做了很多,但都不是那些能提升你解决问题层次的工作。

有一些工作,职责并不明确,别人让你做,你想想也不难,就做了;

有一些工作要求本身就不合理,为了避免争执,你硬着头皮,最后效果不好,别人反而怨你能力不够。

为什么不能勇于拒绝那些工作要求呢?别拿“面子薄”一类的话来宽慰自己,随和不是错,错在你忘记了对自己真正重要的东西是什么。

1479387567-8677-ouxeinejgpg1baj61200

第一类不合理的要求往往出自客户、领导。

客户说:“这次广告设计的要求是,时尚大气上档次,低调奢华有内涵。”面对面有难色的你,他们会拍拍你的肩:“年轻人,挑战一下嘛。”

领导说:“XXX手头比较忙,这件事你就处理一下吧,也不难。”

于是,你出于“帮助别人,提高自己”的美好愿望,跳进了这些万劫不复的火坑。

我们做每一项工作,总是期望得到正面的评价,但评价本身很主观,总是与客户或领导的期待有关。

以前广告界的前辈跟我说过一句话:“如果客户完全知道自己想要什么?那你的价值何在呢?”

所以有一个叫“客户期待管理”的说法,在接触客户之初,就必须帮客户把工作目标建立在一个合理的基础上。

这次的广告推广,你要解决的最重要的问题是什么?是形象提升问题?是客群转换?是配合销售旺季?它对应的广告预算能达到什么地步?你掌握的渠道是否符合要求?时间是否充足?……

面对客户的“无理要求”,把这些问题和客户一起讨论清楚,相信客户会对工作目标有更清晰的认识。

对领导的“期待管理”同样重要,不是让你去拒绝领导的任务,领导这样安排,往往有他自己不得已的苦衷,但你一定要“用自己的方式完成”。

什么叫“用自己的方式完成工作”?就是用你最擅长的能力去工作,在领导心中树立你的“能力边界”——你核心能力是什么?辅助能力是什么?适合做什么?不适合做什么?引导领导去评估你的“核心工作能力”,建立你的核心价值,而不是试图证明自己是个“万金油”,这就是“领导期待管理”。

这样做,你做好了,那是扩展了你的“能力边界”;没做好,那是界定了你的“能力边界”。

1479387567-2447-py37kootthnhflbn1200

为什么你不能拒绝别人的求助?第二个常见的原因是你误解了人际关系。你的口头禅是“赠人玫瑰,手有余香”,但人性并不一定支持这一点。

一位美国作家讲了这样一段经历:每天早晨,他在上班的路上都会经过一个卖白吉饼的老妇人,出于同情,他每次都会丢下25美分的硬币,但从来不要白吉饼。一直坚持了15年,终于有一天,老妇人拦住他,并问了他一句话。

可惜这句话并不是他想像中的“为什么只丢钱不拿东西”,而是“你难道不知道,白吉饼的价格已经涨到50美分一个了吗?”

当你长期不懈地关心、帮助一个人超过一定程度后,他的想法就会从“他是个不错的人”变成“他有多久没帮助我了?”

为了分析受帮助的人的这种奇怪的心态,他在文章中又引用了一位政客的回忆录里的一个故事。

这位政客年轻时曾发起过一个法案,建议把工人的最低工资和当地居民平均收入自动联系起来,这样做就不用每年去审核最低工资标准。这位政客原指望这项法案会得到那些亲劳工的民主党议员的支持,但到最后的投票,支持者寥寥。

很多年后,那位年轻政客成了老司机,才明白其中的奥妙。

一方面,本来每隔几年,那些议员就会利用提高最低工资标准的机会,争取那些底层选民的支持。如果最低工资标准自动提升,他们就失去了这些拉选票的机会。

但更重要的原因在于,工资是一种市场行为,而“最低工资标准”则是一项“不劳而获”的社会福利。如果每年自动提升,久而久之,就会在底层劳工中形成一个印象——这是他们应得的,这在很多高福利国家都成了“养懒汉”政策。

职场也是如此,无私地帮助别人,反而让别人曲解了帮助的意义,只会让自己的付出变成“懒汉福利”,并不能让我们获得良好的人际关系。

帮助同事的前提,是让他们理解你付出的努力,这绝不是为了卖个人情,而是提高他们求助的成本,迫使每一个人首先寻找自己的“能力边界”。

1479387567-2879-nbruw85hpeoiczdj1200

为什么你不拒绝别人?还有一个原因是你被“道德绑架”了。

最近郎平与国家队的执教合同要到期了,突然杀出了个意大利女排,抛出了500万美元年薪再加3个月陪伴家人的假期。

国家队是怎么表态的呢?“郎平续约女排国家队是众望所归,我们会以最大的诚意挽留郎平,我有信心能够签下郎平。”

人家500万美刀,你200万软妹币,请问你的信心是从哪里来的呢?无非就是那两个人人都会说的字嘛,这就多多少少有点道德绑架的味道了。

职场上的道德绑架也不少,想要say no?你对得起朋友吗,对得起领导吗,对得起公司吗,都是常见的理由。

大凡你会被别人进行道德绑架,说明你已经被抬到了一个更高层次上。就像有人说,到了郎平这个层次,500万美刀和200万软妹币的区别已经不大了。

“道德绑架”是个无解的问题,因为选择无关利弊,纯属个人价值观。只不过,自己心甘情愿去做一件事,和被别人“抬举”着做一件事,那心里的滋味是大大不同。

1479387567-6660-vm4mc457gdnjj2y41200

大部分关于“拒绝”的文章都在教你如何体面地“say no”,这当然很重要,不过,更重要的是,哪些该拒绝?哪些能做则做?

我假设了两个最常见的场景,给出了一些我的建议:

第一个场景,领导交给你一项不属于你工作范围的工作,是否需要拒绝,你可以考虑以下问题:

  1. 这是与我核心能力相关的工作吗?是,接受;否,进入下一条:
  2. 它能帮助我拓展我核心能力的边界,或是我感兴趣的吗?是,接受;否,下一条:
  3. 如果我没有达到要求,领导可以理解我吗?是,接受;否,下一条:
  4. 我可以直接而清晰地表达我的能力不足以处理此项工作,或我的特点不符合这项工作的要求吗?是,拒绝;否,下一条:
  5. 如果我直接拒绝,我可以承受相应的代价,或者我早有离职的意思?是:拒绝;否:接受。

第二个场景,同事请你帮忙完成一项工作,是否需要拒绝,你可以考虑以下问题:

  1. 这是与我核心能力相关的工作吗?是,接受;否,进入下一条:
  2. 它能帮助我拓展我核心能力的边界,或是我感兴趣的吗?是,接受;否,下一条:
  3. 我有时间,或者愿意牺牲其他时间吗?是,下一条;否,拒绝:
  4. 如果我不帮助他,他就无法完成工作吗?或者,我在帮助他的过程,他也能得到提高?是,下一条,否,拒绝:
  5. 这是他第一次求助我,或者我希望和他多多接触吗?是,接受,否,拒绝。

这些考虑因素中,最核心的还是自己到底想成为什么样的人。

而尊重自己的付出,更不是自私。《国富论》中有一句名言:“我们不能借着向肉贩、啤酒商、或面包师傅诉诸兄弟之情而获得免费的晚餐,我们填饱肚子的方式,是源于他们对自身利益的看重。” 

一款基于Bootstrap扁平化的后台框架Ace

最近一段时间在做一个管理系统,在网上找了很久的前端展示框架,终于找到一款基于Bootstrap的后台管理系统模版:Ace。Bootstrap是Twitter 于2010年开发出来的前端框架,用过的同学应该知道,这款前端框架不仅界面很美观,而且兼容了很多的浏览器,大大加速了我们开发网站的速度!这篇文章讲到的Ace是基于Bootstrap的,所以界面自然也非常美观,这款后台管理系统组合了好多插件以及组件,可以满足很大一部分的后台管理系统模版.

ace.jpg

下载资源:ace

防止网站被刷票的一些思路与方法

在Web开发中,投票模块会经常出现。这样就使得防止刷票,成了至关重要的技术。以下是试验过或者网上找到的防止刷票方法:

1. IP限制

这是使用的最多,也是最广泛,不可少的刷票限制。而且由于专题都没有用户模块,使得这个方法,几乎成了唯一可行的手段。该方式,通过获取访问游客的IP地址,来限制其在一段时间内所能使用的票数。当然,正常访问页面投票的游客,肯定都能很好的被这个手段所限制,但是,各种投票的活动和专题,以及丰厚的奖品,使得一些人想方设法的想要进行刷票。

  • ADSL用户,可以通过断线重拨来更换IP地址。
  • 使用代理访问的用户,我们也无法获得其真实的IP地址。
  • 还有我们未知的刷票工具。

以上都是我们没有办法克服的难题,而且对于网吧/内网用户来说,这样的设置也会显得不够公平。

2. Cookies 验证

这也是网上所用到较多的手段,不过,所有来自于客户端的信息和内容都是不可靠的。熟知cookies原理的人,就可以很容易的绕过限制。

  • cookies 可以禁用。
  • 使用代理访问的用户,我们也无法获得其真实的IP地址。
  • Cookies可以随意清除、修改。

3. Session 验证

session会给所有访问的游客,指定一个唯一的sessionID。这样,似乎对于防止刷票有一些作用。可惜session有致命的缺点。

  • 关闭浏览器,session就会被销毁。
  • 客户端禁用cookies,session也会失效。

4. 验证码

注册,登陆,回复,发帖……验证码使用的范围很广,很多。可惜,至于具体效果呢,长久下来,只发现这样的方式,其实只是加大了普通游客的投票难度,而且刷票频繁的访问验证码,也大大加大了服务器负担。

有一种验证码是可行的,google推出的图形验证码,旨在让用户将图片翻转至正确的方向,方可完成验证。想必很少有软件或者电脑操作可以很好的绕过这样的验证码。不过,缺点呢,实现难度很高。

5. MAC地址限制

作为web程序,很难获取真实的Mac地址(我用php/js实验过,并没有成功的获取到Mac地址)。当我们读取客户端Mac地址时,读取的也是存储于注册表的一个信息,它也是可以进行修改的。

6. 用户模块

这应该算很有用的方式。每个游客,必须注册了账户才能进行投票,通过限制账户ID来限制投票,并且可以限制初始注册用户,一段时间内不能参与投票。而且,真有大量的注册用户涌入,也可以增加网站的流量。可是,对于小地区网站来说,这样会让网友觉得很麻烦,可能放弃投票,从而可能流失网站的用户。

7. 行为记录

其实,很多刷票行为我们是没办法进行限制的。可是有时候,我们却可以很好的记录下来。而且当检测到非正常投票的时候,自动提出票数,要么返回投票成功的假象,也可以很好的限制刷票。

缺点就是,记录过多的数据,会让服务器压力很大。而且,如果记录行为的记录点不够多,不够复杂,也可能被刷票的专业户所参透。

8. 回答问题

第一次使用这个方式限制刷票的时候,我们很欣慰的看到了不错的效果。可惜,如果没有足够海量的题库,很快问题的内容和答案就会被收集。反而让正常投票的用户,觉得投票很恶心、麻烦,产生厌恶心理。渐渐的也被我们抛弃了。

9. 随机投票地址

该方法, 让每一个访问页面的用户得到一个随机唯一的KEY,通过这个KEY,生成一个投票地址,该地址只能访问一次,使用过后便作废。

可惜,指定的KEY的内容,我目前是采用的sessionid+ip+随机数 生成的MD5码,而sessionid和ip在上面的内容都提到,是可以销毁和篡改的。这样的方式,也不过是在ip限制和session限制无效时候的垂死挣扎。

10. 填写信息

投票时,让游客填写身份证,姓名,手机号码等可以表示一个人身份的信息,来进行唯一性验证。不过,身份证你知道格式,姓名随便填,手机号码随便填写,也是没办法限制的。反而让正常投票的人觉得麻烦。

11. 投票码/排号系统

投票前,用户都需要在其他页面/邮箱先获取到一个唯一投票的编码/卷,使用一次作废。不过,如何验证‘人’的唯一呢,如果有用户,他的邮箱足够多,是不是就可以无限获取投票码呢。

对!所以,这也只是治标不治本的方法了。不过,至少,这个方式也会让刷票的人觉得很麻烦。但是同时,也会让正常投票的人觉得不方便。不过,能够让刷票党,刷得不是那么痛快,也算是有用了。

12. 人民币投票

虎,这样最好,不管是发短信,打电话,还是支付宝,一票一元人民币,你如果是足够舍得,当然,随便你投,随便你刷,咱也乐意不是。通过支付接口的结合,作弊是相当难的了。

不过,公平性有待考究,毕竟不是所有人的支持者都有钱,都舍得花钱,可能让好的作品因为‘穷’而得不到票数,这是在咱公平、民主的社会中,是不提倡的!

好了,差不多就以上这些方式。引用一个网友的原文:“要想完全杜绝刷票,基本只能靠人”。

抛砖引玉:

  • flash投票,不过不是很清楚原理,有空的时候会投入测试。
  • 插件。 web插件,可能需要用户下载安装,普通用户会觉得很麻烦,可行性有待考究。
  • 一些有趣的设置 例如,短时间内的多次投票,可能导致投票数下降;可以给作品投负票数,不过有一定几率无效或者反射到其他作品;类似农场的‘偷菜’,我们可以投票等。也许可以增加一点可玩性,可是公平性就无法保证了。

总结:个人觉得目前最有效的只能是人民币投票了,可以很好的限制刷票行为。

PHP快速读取大文件方法比较

在PHP中,对于文件的读取时,最快捷的方式莫过于使用一些诸如file、file_get_contents之类的函数,简简单单的几行代码就能 很漂亮的完成我们所需要的功能。但当所操作的文件是一个比较大的文件时,这些函数可能就显的力不从心, 下面将从一个需求入手来说明对于读取大文件时,常用的操作方法。

需求需求

有一个800M的日志文件,大约有500多万行, 用PHP返回最后几行的内容。

实现方法

1. 直接采用file函数来操作

由于 file函数是一次性将所有内容读入内存,而PHP为了防止一些写的比较糟糕的程序占用太多的内存而导致系统内存不足,使服务器出现宕机,所以默认情况下限制只能最大使用内存16M,这是通过php.ini里的 memory_limit = 16M 来进行设置,这个值如果设置-1,则内存使用量不受限制。

下面是一段用file来取出这具文件最后一行的代码:

view sourceprint?

1.<?php

2.ini_set('memory_limit''-1');

3.$file 'access.log';

4.$data = file($file);

5.$line $data[count($data) - 1];

6.echo $line;

7.?>

整个代码执行完成耗时 116.9613 (s)。

我机器是2个G的内存,当按下F5运行时,系统直接变灰,差不多20分钟后才恢复过来,可见将这么大的文件全部直接读入内存,后果是多少严重,所以不在万 不得以,memory_limit这东西不能调得太高,否则只有打电话给机房,让reset机器了。

2.直接调用Linux的 tail 命令来显示最 后几行

在Linux命令行下,可以直接使用 tail -n 10 access.log 很轻易的显示日志文件最后几行,可以直接用PHP来调用tail命令,执行PHP代码如下:

view sourceprint?

1.<?php

2.$file 'access.log';

3.$file escapeshellarg($file); // 对命令行参数进行安全转义

4.$line = `tail -n 1 $file`;

5.echo $line;

6.?>

整个代码执行完成耗时 0.0034 (s)

3. 直接使用PHP的 fseek 来进行文件操作

这种方式是最为普遍的方式,它不需要将文件的内容全部读入内容,而是直接通过指针来操作,所以效率是相当高效的。在使用fseek来对文件进行操作时,也有多种不同的方法,效率可能也是略有差别的,下面是常用的两种方法:

方法一

首先通过fseek找到文件的最后一位EOF,然后找最后一行的起始位置,取这一行的数据,再找次一行的起始位置, 再取这一行的位置,依次类推,直到找到了$num行。

#实现代码如下

view sourceprint?

01.<?php

02.$fp fopen($file"r");

03.$line = 10;

04.$pos = -2;

05.$t " ";

06.$data "";

07.while ($line > 0)

08.{

09.while ($t != "n")

10.{

11.fseek($fp$pos, SEEK_END);

12.$t fgetc($fp);

13.$pos--;

14.}

15.$t " ";

16.$data .= fgets($fp);

17.$line--;

18.}

19.fclose($fp);

20.echo $data

21.?>

整个代码执行完成耗时 0.0095 (s)

方法二

还是采用fseek的方式从文件最后开始读,但这时不是一位一位的读,而是一块一块的读,每读一块数据时,就将读取后的数据放在一个buf里,然后通过换 行符(n)的个数来判断是否已经读完最后$num行数据。

#实现代码如下

view sourceprint?

01.<?php

02.$fp fopen($file"r");

03.$num = 10;

04.$chunk = 4096;

05.$fs = sprintf("%u"filesize($file));

06.$max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : filesize($file);

07.for ($len = 0; $len $max$len += $chunk)

08.{

09.$seekSize = ($max $len $chunk) ? $chunk $max $len;

10.fseek($fp, ($len $seekSize) * -1, SEEK_END);

11.$readData fread($fp$seekSize) . $readData;

12.if (substr_count($readData"n") >= $num + 1)

13.{

14.preg_match("!(.*?n){" . ($num) . "}$!"$readData$match);

15.$data $match[0];

16.break;

17.}

18.}

19.fclose($fp);

20.echo $data;

21.?>

整个代码执行完成耗时 0.0009(s)。

方法三

view sourceprint?

01.<?php

02.function tail($fp$n$base = 5)

03.{

04.assert($n > 0);

05.$pos $n + 1;

06.$lines array();

07.while (count($lines) <= $n)

08.{

09.try

10.{

11.fseek($fp, -$pos, SEEK_END);

12.}

13.catch (Exception $e)

14.{

15.fseek(0);

16.break;

17.}

18.$pos *= $base;

19.while (!feof($fp))

20.{

21.array_unshift($linesfgets($fp));

22.}

23.}

24. 

25.return array_slice($lines, 0, $n);

26.}

27. 

28.var_dump(tail(fopen("access.log""r+"), 10));

29.?>

整个代码执行完成耗时 0.0003(s)

微信开发中emoji表情的处理方法

57fb1242a4197.gif

背景

做微信开发的时候就会发现,存储微信昵称必不可少。

可这万恶的微信支持emoji表情做昵称,这就有点蛋疼了

一般Mysql表设计时,都是用UTF8字符集的。把带有emoji的昵称字段往里面insert一下就没了,整个字段变成了空字符串。这是怎么回事呢?

原来是因为Mysql的utf8字符集是3字节的,而emoji是4字节,这样整个昵称就无法存储了。这要怎么办呢?我来介绍几种方法

解决方案

1、使用utf8mb4字符集

如果你的mysql版本>=5.5.3,你大可直接将utf8直接升级为utf8mb4字符集
这种4字节的utf8编码可完美兼容旧的3字节utf8字符集,并且可以直接存储emoji表情,是最好的解决方案
至于字节增大带来的性能损耗,我看过一些评测,几乎是可以忽略不计的

2、使用base64编码

如果你因为某些原因无法使用utf8mb4的话,你还可以使用base64来曲线救国
使用例如base64_encode之类的函数编码过后的emoji可以直接存储在utf8字节集的数据表中,取出时decode一下即可

3、干掉emoji表情

emoji表情是个麻烦的东西,即使你能存储,也不一定能完美显示。在iOS以外的平台上,例如PC或者android。如果你需要显示emoji,就得准备一大堆emoji图片并使用第三方前端类库才行。即便如此,还是可能因为emoji图片不够全而出现无法显示的情况在大多数业务场景下,emoji也不是非要不可的。我们可以适当地考虑干掉它,节约各种成本

经过一番苦苦的google,终于找到靠谱能用的代码:

// 过滤掉emoji表情function filterEmoji($str){
 $str = preg_replace_callback(
   '/./u',
   function (array $match) {
    return strlen($match[0]) >= 4 ? '' : $match[0];
   },
   $str);
 
  return $str;
 }

以上就是为大家总结的PHP微信开发中涉及到emoji表情的几种处理方法,基本思想就是遍历字符串中的每个字符,如果该字符的长度为4个字节,就将其删除。

图片叠加并增加文字DEMO

<?php
/**
 * 图片叠加并增加文字demo
 * @author caozhong
 * @version 2016-11-03
 */
$dst_path 'bg.jpg';//底图
$src_path '2.jpg';//合成图片
$dst = imagecreatefromstring(file_get_contents($dst_path));
$src = imagecreatefromstring(file_get_contents($src_path));
list($src_w$src_h) = getimagesize($src_path);
imagecopymerge($dst$src, 120, 120, 0, 0, $src_w$src_h, 50);
/*imagecreatefromstring()--从字符串中的图像流新建一个图像,返回一个图像标示符,其表达了从给定字符串得来的图像
图像格式将自动监测,只要php支持jpeg,png,gif,wbmp,gd2.*/
$font 'heiti.ttf';
$black = imagecolorallocate($dst, 0, 0, 0);
//增加文字,如果多条,请增加多条
imagefttext($dst, 14, 0, 330, 125, $black$font'姓名:白猫');
imagefttext($dst, 14, 0, 330, 155, $black$font'性别:雄');
/*imagefttext($img,$size,$angle,$x,$y,$color,$fontfile,$text)
$img由图像创建函数返回的图像资源
size要使用的水印的字体大小
angle(角度)文字的倾斜角度,如果是0度代表文字从左往右,如果是90度代表从上往下
x,y水印文字的第一个文字的起始位置
color是水印文字的颜色
fontfile,你希望使用truetype字体的路径*/
list($dst_w,$dst_h,$dst_type) = getimagesize($dst_path);
/*list(mixed $varname[,mixed $......])--把数组中的值赋给一些变量
像array()一样,这不是真正的函数,而是语言结构,List()用一步操作给一组变量进行赋值*/
/*getimagesize()能获取到什么信息?
getimagesize函数会返回图像的所有信息,包括大小,类型等等*/
//header("Content-Disposition: attachment; filename='1.jpg'");
switch($dst_type){
    case 1://GIF
        header("content-type:image/gif");
        imagegif($dst);
        break;
    case 2://JPG
        header("content-type:image/jpeg");
        imagejpeg($dst);
        break;
    case 3://PNG
        header("content-type:image/png");
        imagepng($dst);
        break;
    default:
        break;
}
imagedestroy($dst);

Http请求方法和响应状态码整理

一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成,格式如下:
Http请求方法和响应状态吗整理
可见请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。
HTTP请求方法:

  • GET: 请求指定的页面信息,并返回实体主体。
  • HEAD: 只请求页面的首部。
  • POST: 请求服务器接受所指定的文档作为对所标识的URI的新的从属实体。
  • PUT: 从客户端向服务器传送的数据取代指定的文档的内容。
  • DELETE: 请求服务器删除指定的页面。
  • OPTIONS: 允许客户端查看服务器的性能。
  • TRACE: 请求服务器在响应中的实体主体部分返回所得到的内容。
  • PATCH: 实体中包含一个表,表中说明与该URI所表示的原内容的区别。
  • MOVE: 请求服务器将指定的页面移至另一个网络地址。
  • COPY: 请求服务器将指定的页面拷贝至另一个网络地址。
  • LINK: 请求服务器建立链接关系。
  • UNLINK: 断开链接关系。
  • WRAPPED: 允许客户端发送经过封装的请求。
  • Extension-mothed:在不改动协议的前提下,可增加另外的方法。

HTTP响应状态码:
① 客户方错误
100  继续
101  交换协议
② 成功
200  OK
201  已创建
202  接收
203  非认证信息
204  无内容
205  重置内容
206  部分内容
③ 重定向
300  多路选择
301  永久转移
302  暂时转移
303  参见其它
304  未修改(Not Modified)
305  使用代理
④ 客户方错误
400  错误请求(Bad Request)
401  未认证
402  需要付费
403  禁止(Forbidden)
404  未找到(Not Found)
405  方法不允许
406  不接受
407  需要代理认证
408  请求超时
409  冲突
410  失败
411  需要长度
412  条件失败
413  请求实体太大
414  请求URI太长
415  不支持媒体类型
⑤ 服务器错误
500  服务器内部错误
501  未实现(Not Implemented)
502  网关失败
504  网关超时
505 HTTP版本不支持