SegmentFault 王道中强流最新的文章
2023-09-24T17:07:34+08:00
https://segmentfault.com/feeds/blogs
https://creativecommons.org/licenses/by-nc-nd/4.0/
macos homebrew 安装 php 8.2 swoole
https://segmentfault.com/a/1190000044255103
2023-09-24T17:07:34+08:00
2023-09-24T17:07:34+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<h4>安装php</h4><p>安装<code>php</code>部分详见:<a href="https://link.segmentfault.com/?enc=SR2JShdjAWrmH78vL43Orw%3D%3D.HAGNzeZHI1dTaTTpnHDoUfKM0THLha%2Fn2cNsHi4BmOjp9sGM97PVKn0lcnrOcR5g" rel="nofollow">https://github.com/shivammathur/homebrew-php</a></p><p>切换版本:</p><pre><code>brew link --overwrite --force shivammathur/php/php@8.2</code></pre><h4>安装swoole</h4><p><code>swoole</code>直接用<code>pecl</code>安装,命令:<code>pecl install swoole</code></p><p>但由于网络问题,经常会下载失败,可以直接用浏览器下载,然后用<code>pecl</code>安装。</p><p>下载地址:<a href="https://link.segmentfault.com/?enc=4KWJ0nTmOQuOWqojvf1lZA%3D%3D.0t46ttJjS9pgyInlNKwoXCFdfgwxBRxCeX0%2FdHp%2B89ScSCMSFqRoq6z20ZZseTIE" rel="nofollow">https://pecl.php.net/package/swoole</a><br>下载后运行:</p><pre><code>pecl install /Users/cos800/Downloads/swoole-5.0.3.tgz</code></pre><p>安装时候如果出现:<code>fatal error: 'pcre2.h' file not found</code><br>需要创建一个<code>pcre2.h</code>文件软链接:</p><pre><code>ln -s /opt/homebrew/opt/pcre2/include/pcre2.h /opt/homebrew/opt/php@8.2/include/php/ext/pcre </code></pre><p>安装时候会询问是否启用各种支持,我目前是全默认。</p><h4>启用swoole</h4><p>安装完还要需要在<code>php.ini</code>中添加<code>extension=swoole.so</code></p><p>1,查看<code>php.ini</code>文件所在位置:<code>brew info php@8.2</code> 会看到这一句:</p><pre><code>The php.ini and php-fpm.ini file can be found in:
/opt/homebrew/etc/php/8.2/</code></pre><p>或者执行:<code>php --ini</code>也可以看到。<br>2,直接用vscode打开目录:<code>code /opt/homebrew/etc/php/8.2/</code><br>3,修改php.ini,找个喜欢的位置加上两行:</p><pre><code>extension=swoole.so
swoole.use_shortname = 'Off'</code></pre><p>4,运行<code>php -m|grep swoole</code>,看到<code>swoole</code>就安装成功了。</p><h4>管理php-fpm服务</h4><p>详见<code>brew services -h</code><br>常见命令</p><pre><code># 启动
brew services start php@8.2
# 停止
brew services stop php@8.2
# 重启
brew services restart php@8.2
# 服务状态
brew services info --all
# 所有服务
brew services list</code></pre>
Linux自动备份MySQL
https://segmentfault.com/a/1190000014565290
2018-04-24T15:55:56+08:00
2018-04-24T15:55:56+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<h2>首先找到你的MySQL配置文件<code>my.cnf</code>
</h2>
<pre><code>$ locate my.cnf
> /etc/my.cnf</code></pre>
<h3>然后修改它,</h3>
<pre><code>$ nano /etc/my.cnf</code></pre>
<h3>在<code>[client]</code>里增加三行:</h3>
<pre><code>host = localhost
user = root
password = yourpassword</code></pre>
<blockquote>本来不需要这些操作,直接把用户名密码写到备份脚本里就可以,<br>但是 MySQL 5.6 之后在命令行里写密码会出现警告。</blockquote>
<h2>然后创建脚本文件<code>mybak.sh</code>
</h2>
<pre><code>$ nano ~/mybak.sh</code></pre>
<h3>文件内容如下:</h3>
<pre><code>#!/bin/bash
root="/data/backup/"
dir=`date "+%y%m%d/"`
mkdir -p $root$dir
cd $root$dir
/usr/local/mysql/bin/mysqldump db1 > db1.sql
/usr/local/mysql/bin/mysqldump db2 > db2.sql
/usr/local/mysql/bin/mysqldump db3 > db3.sql</code></pre>
<h3>记得给它执行的权限:</h3>
<pre><code>$ chmod +x ~/mybak.sh</code></pre>
<h2>然后再修改<code>crontab</code>
</h2>
<pre><code>$ export EDITOR=nano
$ crontab -e</code></pre>
<p><code>export EDITOR=nano</code> 将nano设置为默认编辑器</p>
<h3>添加一行</h3>
<pre><code>0 1 * * * ~/mybak.sh >> ~/mybak.log 2>&1 &</code></pre>
<p>意思是每天1:00的时候执行<code>~/mybak.sh</code>,并且将所有输出记录到<code>~/mybak.log</code>。</p>
php nginx 实时输出
https://segmentfault.com/a/1190000012860030
2018-01-16T15:45:13+08:00
2018-01-16T15:45:13+08:00
王道中强流
https://segmentfault.com/u/tmdphp
1
<p>PHP 里开启实时输出方法是<code>ob_implicit_flush()</code>,<br>但它大部分情况下都不管用,</p>
<p>因为<code>php.ini</code>配置里<code>output_buffering</code>输出缓冲大部分是<code>On</code>开启的,<br>还有<code>zlib.output_compression</code>也经常会被开启,</p>
<p>除了 PHP 这一层,还有 Nginx 的缓冲设置<code>proxy_buffering</code>,和压缩<code>gzip</code>也大都是开启的。<br>为了一两个页面的需求,修改整个服务器的网站配置,恐怕没有人会做这种选择。</p>
<p>这里推荐一下简单的方法:</p>
<pre><code class="php">set_time_limit(0);
ob_end_clean();
ob_implicit_flush();
header('X-Accel-Buffering: no'); // 关键是加了这一行。
echo '现在是:'.date('H:i:s').'<br>';
sleep(5);
echo '五秒后:'.date('H:i:s');</code></pre>
PHP导出Excel电子表格
https://segmentfault.com/a/1190000011296047
2017-09-21T16:19:35+08:00
2017-09-21T16:19:35+08:00
王道中强流
https://segmentfault.com/u/tmdphp
13
<p>这方法我一直在用,根本用不着类库框架什么的,</p>
<p>直接输出<code>html</code>格式的<code><table></code>就好了,并且指定为Excel的Mime。</p>
<pre><code class="php">$table = "<table>
<thead>
<tr>
<th>姓名</th>
<th>电话</th>
<th>身份证</th>
<th>购买产品</th>
<th>消费金额</th>
<th>奖品</th>
<th>时间</th>
</tr>
</thead>
<tbody>";
foreach ($all as $r) {
$table .= "<tr>
<td>{$r->name}</td>
<td>{$r->mobile}</td>
<td>{$r->idcard}&nbsp;</td>
<td>{$r->product}</td>
<td>{$r->price}</td>
<td>{$r->prize_level}:{$r->prize_name}</td>
<td>{$r->create_time}</td>
</tr>";
}
$table .= "</tbody></table>";
header('Content-type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="export.xls"');
echo $table;</code></pre>
<p>对了,这里有个小技巧:<br>像身份证号码这么长的线数字,Excel显示的时候最后几位会变成00000。<br>解决办法就是在单元格里面加个<code>&nbsp;</code><br>像这样:<code><td>{$r->idcard}&nbsp;</td></code></p>
微信小程序五星级评分效果
https://segmentfault.com/a/1190000010449124
2017-08-01T16:22:16+08:00
2017-08-01T16:22:16+08:00
王道中强流
https://segmentfault.com/u/tmdphp
1
<pre><code class="html"><view>
<view class="zan-font-16 my-ib" bindtap="myStarChoose">
<block wx:for="{{starMap}}">
<text wx:if="{{star>=index+1}}" style="padding-right: .5em" class="zan-c-red" data-star="{{index+1}}">★</text>
<text wx:if="{{star<index+1}}" style="padding-right: .5em" class="zan-c-gray-dark" data-star="{{index+1}}">☆</text>
</block>
</view>
<!--★-->
<text class="zan-c-gray-dark">{{starMap[star-1]}}</text>
</view></code></pre>
<p>这里的<code>zan-font-16</code>,<code>zan-c-red</code>,<code>zan-c-gray-dark</code>是<code>ZanUI-WeApp</code>的样式。<br>这里的<code>my-ib</code>只是将设置<code>display</code>为<code>inline-block</code>。</p>
<pre><code class="js">Page({
data: {
star: 0,
starMap: [
'非常差',
'差',
'一般',
'好',
'非常好',
],
},
myStarChoose(e) {
let star = parseInt(e.target.dataset.star) || 0;
this.setData({
star: star,
});
}
});</code></pre>
<p>效果如图:</p>
<p><img src="/img/bVR0rw?w=380&h=61" alt="clipboard.png" title="clipboard.png"></p>
关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
https://segmentfault.com/a/1190000007660159
2016-12-01T13:47:16+08:00
2016-12-01T13:47:16+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p>你可能有所不知,我最近喜欢上钓鱼,并决定为此开发一个钓鱼网站, <br>这个钓鱼网站,不是那个“钓鱼”,我说的是真的钓鱼,也就是垂钓……</p>
<p>做个网站一点都不难,但如果是用心做,那么任何事都简单不起来, <br>你知道,网站要能被搜索到,就得做SEO,而SEO的第一步就是:标题、描述和关键词。</p>
<p>而其中重中之重,就是关键词了,因为标题和描述都是围绕关键词展开的, <br>那么如何更有效的列出相关关键词呢?网络上倒也不缺这方面的工具,<br>比如 <a href="https://link.segmentfault.com/?enc=ESTv1Cp4igJ%2BxPm2XnAy%2Fw%3D%3D.TcDwG5vY8oDTZR9tzQd0gZYHBkAVfEsO%2FY6WLqdaqEI%3D" rel="nofollow">爱站</a> 和 <a href="https://link.segmentfault.com/?enc=GrPtJF8wtwBwanIOIcVdtw%3D%3D.Kgyi9W19kMKMG2w2nP5wcI7EiyOes%2FBFQa3xIMbS3x83naFgukVHLVfRb%2Bur%2BrWg" rel="nofollow">站长站</a>:</p>
<p><img src="/img/bVGiRZ?w=819&h=630" alt="clipboard.png" title="clipboard.png"></p>
<p>这个结果不知道你怎么看,反正在我看来根本不能满足需求, <br>这结果里只包含了“XX钓鱼”和“钓鱼XX”,还有就是“XX钓鱼XX”。 <br>难道不是应该包含:垂钓,海钓,路亚,野钓,夜钓……等关键词吗?</p>
<p>所以,我决定自己开发一个,并且开源! <br>至于怎么实现呢?大概流程,已经在我脑海里运行起来了。</p>
<p>下一篇写这个程序的大概流程,敬请期待。 <br>另外我的钓鱼主题网站名叫:<a href="https://link.segmentfault.com/?enc=1yOob0W0tQWaxGYNIlQY2Q%3D%3D.HQa%2FSzd%2Feov1mRxzYYJaqjRN4DJdLZic1g65A8PchxU%3D" rel="nofollow">钓鱼家</a> - www.diaoyujia.cn <br>和下一篇文章一样,敬请期待。</p>
将数组按照值出现的次数排序
https://segmentfault.com/a/1190000007640992
2016-11-29T23:55:38+08:00
2016-11-29T23:55:38+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<pre><code class="js">// 将数组按照值出现的次数排序
let sortByCount = function (arr) {
let arrUni = [];
let arrCnt = [];
arr.forEach((val)=>{
let idx = arrUni.indexOf(val);
if (idx<0) {
arrUni.push(val);
arrCnt.push(1);
}else{
arrCnt[idx]++;
}
});
let arrTmp = arrUni.slice();
arrUni.sort((a, b)=>{
let idxa = arrTmp.indexOf(a);
let idxb = arrTmp.indexOf(b);
return arrCnt[idxb] - arrCnt[idxa];
});
return arrUni;
};</code></pre>
windows 10 共享给 win7 出错,登录失败。
https://segmentfault.com/a/1190000005072878
2016-05-06T15:42:27+08:00
2016-05-06T15:42:27+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p>错误提示:</p>
<pre><code>打开文件夹
\\PC201406031034 无法访问。您可能没有权限使用网络资源。请与这台服务器的管理员联系以查明您是否有访问权限。
登录失败: 未授予用户在此计算机上的请求登录类型。</code></pre>
<p>解决办法:<br>进入:本地安全策略》本地策略》用户权限分配》拒绝从网络访问这台计算机<br>把 Guest 删除,就可以了。</p>
<p>打开<code>本地安全策略</code>的办法:<br><code>Win + R</code> 运行 <code>secpol.msc</code></p>
ThinkPHP 3.2.3 的一个 Bug 和一个错误的设计
https://segmentfault.com/a/1190000005024988
2016-04-28T13:44:31+08:00
2016-04-28T13:44:31+08:00
王道中强流
https://segmentfault.com/u/tmdphp
1
<p>ThinkPHP 3.2.3 的 <code>ajax_rerurn</code> 这个 <code>Hook</code> 是有逻辑错误的……<br>源代码在这里:</p>
<pre><code> protected function ajaxReturn($data,$type='',$json_option=0) {
if(empty($type)) $type = C('DEFAULT_AJAX_RETURN');
switch (strtoupper($type)){
case 'JSON' :
// 返回JSON数据格式到客户端 包含状态信息
header('Content-Type:application/json; charset=utf-8');
exit(json_encode($data,$json_option));
case 'XML' :
// 返回xml格式数据
header('Content-Type:text/xml; charset=utf-8');
exit(xml_encode($data));
case 'JSONP':
// 返回JSON数据格式到客户端 包含状态信息
header('Content-Type:application/json; charset=utf-8');
$handler = isset($_GET[C('VAR_JSONP_HANDLER')]) ? $_GET[C('VAR_JSONP_HANDLER')] : C('DEFAULT_JSONP_HANDLER');
exit($handler.'('.json_encode($data,$json_option).');');
case 'EVAL' :
// 返回可执行的js脚本
header('Content-Type:text/html; charset=utf-8');
exit($data);
default :
// 用于扩展其他返回格式数据
Hook::listen('ajax_return',$data);
}
}</code></pre>
<p>其中 <code>C('DEFAULT_AJAX_RETURN')</code> 获取到的配置默认是 <code>json</code>。<br>很明显 <code>Hook::listen('ajax_return',$data)</code> 所在的位置,决定了它正常情况都不会被调用。<br>不管你将它改成 <code>xml</code>、<code>jsonp</code>、还是 <code>eval</code>。</p>
<p>于是为了使这个 <code>Hook</code> 生效,只能将 <code>DEFAULT_AJAX_RETURN</code> 这个配置改成 <code>json</code>、<code>xml</code>、<code>jsonp</code>、<code>eval</code> 之外的任意字符串。。。比如我将它改成 <code>'DEFAULT_AJAX_RETURN' => 'hook'</code>。</p>
<p>然后在创建文件:<code>/Application/Admin/Conf/tags.php</code></p>
<pre><code><?php
return array(
'ajax_return' => array('Admin\\Behaviors\\ajaxBehavior'),
);</code></pre>
<p>再创建文件:<code>/Application/Admin/Behaviors/ajaxBehavior.class.php</code></p>
<pre><code><?php
namespace Admin\Behaviors;
use Think\Behavior;
class ajaxBehavior extends Behavior
{
function run(&$data)
{
if ($data['status']===0) {
http_response_code(500);
}
header('Content-Type:application/json; charset=utf-8');
exit(json_encode($data, JSON_UNESCAPED_UNICODE));
}
}</code></pre>
<p>我的目的是:<code>Controller</code> 内调用 <code>$this->error('tmdphp')</code> 的时候,响应的 HTTP 状态码变成 500。<br>这样客户端才会正确的执行 <code>jQuery.ajax</code> 的 <code>error</code> 回调。</p>
<p>其实这也算另一个 Bug 吧,<code>Think\Controller::error</code> 然道不应该响应一个错误的 HTTP 状态码?</p>
<p>但是没办法,鉴于团队的平均水平,用 <code>ThinkPHP</code> 开发仍然是最佳选择。</p>
<p>等会去 Github 提交个 PR 看看会不会被采纳。。。</p>
富客户端后台界面框架,企业级UI框架 控件库,类Ext JS前端框架收录
https://segmentfault.com/a/1190000004729596
2016-03-30T11:39:27+08:00
2016-03-30T11:39:27+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p>今天有朋友问起这个问题,顺便记录一下。</p>
<hr>
<p>鼻祖 Ext JS:<a href="https://link.segmentfault.com/?enc=UCGC3fWI9qnOI5mXOdIZDQ%3D%3D.TgwxWFtexEb%2FZHwrLbKKhCIgWm%2FT%2BxiVL5TB6IPzIwGDh8N1x1WNcsWcXPX03qif" rel="nofollow">https://www.sencha.com/products/extjs/</a><br>但不是开源的,而且学习曲线陡峭。</p>
<p>jQuery EasyUI:<a href="https://link.segmentfault.com/?enc=KSjpHfNs9WJrNyfLkQ30Ng%3D%3D.dty0QZN3jB8mF9Uhkigi6VhzBrQJGBd5BmPi1Rw3uOM%3D" rel="nofollow">http://www.jeasyui.com/</a><br>这个我用过,记得也是一个华人弄的,出道较早,当年除了 Extjs 就只有这个选择了。</p>
<p>kendo-ui:<a href="https://link.segmentfault.com/?enc=ogds59MPRN15WN67UjwWFQ%3D%3D.mvr4t67iIH4uCVMUuCI9gG%2Bvj%2BqupdL4rsKcHZRO7BbXOsrKSaMRLAN1zhKixGzk" rel="nofollow">http://demos.telerik.com/kendo-ui/</a><br>全英文,但是好像很强大。</p>
<p><strong>接下来的几个是国人作品</strong></p>
<p>JUI:<a href="https://link.segmentfault.com/?enc=%2BDysF64jroHwZxqzvd3mdA%3D%3D.IZgx3zvwkqDrrznJPr18lg%3D%3D" rel="nofollow">http://jui.org/</a><br>原名 DWZ。团队项目。</p>
<p>Liger UI:<a href="https://link.segmentfault.com/?enc=Jr7JD3GylPuQgKDMWAaM8w%3D%3D.7pAbB5Kpp%2FKX%2FPHP3qyiftT2zXh4NpKu6mWs6f%2FYevI%3D" rel="nofollow">http://www.ligerui.com/</a><br>与 DWZ 同时期。个人项目。</p>
<p>MiniUI:<a href="https://link.segmentfault.com/?enc=wF%2BdPlN9mqI3EaXt0sJPfg%3D%3D.bmrx0F4p8ePplOmWyP%2FZqUmlVTnQEqbAEYYWGI1O4QA%3D" rel="nofollow">http://www.miniui.com/</a><br>公司产品。</p>
<p>BUI:<a href="https://link.segmentfault.com/?enc=6HR1usXEPvq%2BC%2F66jPFwIA%3D%3D.s3wMQ8Hyg7CO71U5a3zm7dn8Q2XEqg1Rxwz01hZU2FM%3D" rel="nofollow">http://www.builive.com/</a><br>阿里系开源项目,年久失修。</p>
<p>B-JUI:<a href="https://link.segmentfault.com/?enc=Dj3XlFT4vbqD7%2F5wbNteHQ%3D%3D.826rScXGhCS1Ahxy9Am%2BxVrWRhUgRh4ftasqKWaQZtQ%3D" rel="nofollow">http://b-jui.com/</a><br>刚知道的,公司产品。</p>
<p>OperaMasks-UI:<a href="https://link.segmentfault.com/?enc=A5EeBvlwpX1IYu9ekPZlKA%3D%3D.mxEQhGPBS17O4BS4Y%2FqWF31WQ%2FyBvXXvI%2BgdKUHqvtg%3D" rel="nofollow">http://ui.operamasks.org/</a><br>金碟软件的开源项目。</p>
<hr>
<p>记得还有一些,但是想不起来的,<br>有知道的其它同类型产品,欢迎留言评论。</p>
Promise化,Promisify,将函数改成 既支持Callback回调,又支持Promise
https://segmentfault.com/a/1190000004716793
2016-03-30T01:27:08+08:00
2016-03-30T01:27:08+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p>初学 <code>Node.js</code>,用 <code>Express</code> 开发 <code>Web</code> 项目。<br>而且还是个不小的项目,说起来挺冒险的。</p>
<p>一开始比较简单,并没有使用 <code>Promise</code> 也能顺利进行,<br>随着开发的深入,到了不用 <code>Promise</code> 不行的地步了。</p>
<p>于是产生了一个问题,一些之前写的方法并不支持 <code>Promise</code>,<br>如果直接改成 <code>Promise</code>,那之前调用过的地方也都得改,工作量有点大。<br>如果加一个 <code>Promise</code> 版,那就有点啰嗦有点丑陋,如下所示:</p>
<pre><code>// 也就是同一个功能,写两个版本
function getInfo(uid, callback) { ... };
function getInfoPromise(uid) { ... };
</code></pre>
<p>听说 <code>Bluebird</code> 有个 <code>promisify</code> 方法,可以将方法 <code>Promise</code> 化,<br>但是又感觉为了这一个方法,多加载一个库,有点浪费内存,<br>毕竟 <code>Node.js</code> 现在原生的支持 <code>Promise</code> 了,<br>能不能“人工手动”将函数改成,既支持 <code>Callback</code> 回调,又支持 <code>Promise</code> 呢?<br>于是有了以下修改:</p>
<pre><code>// 原先只支持 callback 回调版:
var getInfo = function(uid, callback) {
var sql = "select * from v_user where uid=? limit 1";
Mysql.query(sql, [uid], function(err, row) {
if(err) return callback(err);
if(row.length===0) return callback();
var info = row[0];
callback(null, info);
});
};
</code></pre>
<pre><code>// 修改后 既支持 callback 回调,又支持 Promise
var getInfo = function(uid, callback) {
return new Promise(function(resolve, reject) {
if (callback) {
resolve = function (ret) {
callback(null, ret);
};
reject = callback;
}
var sql = "select * from v_user where uid=? limit 1";
Mysql.query(sql, [uid], function(err, row) {
if(err) return reject(err);
if(row.length===0) return resolve();
var info = row[0];
resolve(info);
});
});
};
</code></pre>
<p>但不知道这种写法 是否足够聪明,欢迎指教。</p>
超优雅!node.js 无限级分类,无递归获取所有下级分类ID。
https://segmentfault.com/a/1190000004588206
2016-03-11T20:03:39+08:00
2016-03-11T20:03:39+08:00
王道中强流
https://segmentfault.com/u/tmdphp
1
<p>昨天帮同事解决问题,于是诞生了“<a href="https://segmentfault.com/a/1190000004579532">超优雅!两行代码搞定 php 无限级分类 获取顶级分类ID</a>”这篇文章。</p>
<p>晚上回家做自己的<code>node.js</code>项目的时候,又遇到关于<code>无限级分类</code>的问题了。<br>其实也不是“遇到”,而是强迫症发作 不睡觉 干脆起床,把之前用<code>递归</code>现实的版本,改成用<code>循环</code>实现了。</p>
<p>这次要解决的问题是:根据<code>分类ID</code>,获取<code>所有下级分类的ID</code>,<br>这里说的“所有下级分类”,是包含下级、下下级、下下下级……</p>
<p>另外刚好在学习<code>ES6</code>,于是用上了<code>Set</code>对象。<br>首先还是要将数据处理成<code>{ id:pid, ... }</code>这种格式,以下是我的数据。</p>
<pre><code>var idPidArr = {
'1': 2,
'2': 0,
'3': 2,
'4': 43,
'5': 2,
'6': 2,
'7': 0,
'8': 0,
'9': 1,
'10': 1,
'11': 1,
'12': 1,
'13': 1,
'14': 1,
'15': 0,
'16': 1,
'17': 102,
'18': 43,
'19': 43,
'20': 3,
'21': 3,
'22': 43,
'23': 43,
'24': 5,
'25': 43,
'26': 43,
'27': 43,
'28': 4,
'29': 4,
'30': 4,
'31': 43,
'32': 111,
'33': 5,
'34': 43,
'35': 5,
'36': 88,
'37': 43,
'38': 43,
'39': 43,
'40': 6,
'41': 70,
'42': 6,
'43': 0,
'44': 43,
'45': 43,
'46': 8,
'47': 8,
'48': 43,
'49': 8,
'50': 43,
'51': 67,
'52': 125,
'53': 43,
'54': 43,
'55': 124,
'56': 0,
'57': 6,
'58': 6,
'59': 111,
'60': 43,
'61': 43,
'62': 56,
'63': 43,
'64': 4,
'65': 43,
'66': 43,
'67': 102,
'68': 43,
'69': 4,
'70': 102,
'71': 56,
'72': 124,
'73': 43,
'74': 43,
'75': 8,
'76': 17,
'77': 43,
'78': 0,
'79': 43,
'80': 43,
'81': 103,
'82': 15,
'83': 17,
'84': 3,
'85': 15,
'86': 3,
'87': 43,
'88': 43,
'89': 111,
'90': 43,
'91': 15,
'92': 6,
'93': 6,
'94': 43,
'95': 53,
'96': 103,
'97': 111,
'98': 6,
'99': 70,
'100': 15,
'101': 6,
'102': 0,
'103': 43,
'104': 103,
'105': 103,
'106': 103,
'107': 7,
'108': 7,
'109': 7,
'110': 7,
'111': 102,
'112': 8,
'113': 1,
'114': 103,
'115': 103,
'116': 43,
'117': 43,
'118': 43,
'119': 125,
'120': 111,
'121': 70,
'122': 111,
'123': 70,
'124': 8,
'125': 8,
'126': 124,
'127': 125,
'128': 88,
'129': 43,
'130': 3,
'131': 43,
'132': 43,
'133': 86,
'134': 21,
'135': 21,
'136': 86,
'137': 20,
'138': 20 };
</code></pre>
<p>然后 假设要获取分类 ID: 8 的所有下级分类的 ID。</p>
<pre><code>var bmid = 8;
var pids = new Set([bmid]);
do {
var len = pids.size;
for(var id in idPidArr) {
if (pids.has(idPidArr[id])) {
pids.add(Number(id));
delete idPidArr[id]; // 感谢 @zhoutk 提醒
}
}
} while (pids.size>len);
console.log(Array.from(pids));
</code></pre>
<p>输出所有下级分类 ID 数组是 <code>[ 8, 46, 47, 49, 75, 112, 124, 125, 126, 127, 52, 55, 72, 119 ]</code></p>
<p>然后……没有了,<br>为什么有一种虎头蛇尾的感觉呢?<br>代码已经够简洁了,应该不必逐行解释了吧……</p>
<hr>
<p>哎~ 为什么我可以写出如此精妙的代码,<br>却永远猜不透“<a href="https://link.segmentfault.com/?enc=4kqsHDi3AvgqRzMflJNr1w%3D%3D.luwhqS1NwuWd3oaL13nsRthsCeIGqEssDvb1VBG8P7i%2B%2Ba1aMu9qyd3Y2nPEFGNThb%2Fd%2F3JlfXJED3KnvkdE4g%3D%3D" rel="nofollow">石化油服</a>”的走势!!!<br>来一首<a href="https://link.segmentfault.com/?enc=gXVDXbBk3GZ3o9ndmXDIig%3D%3D.%2BkleTI%2FLGh5q42zoLlUeFDSzl29%2FK9OoOR%2BRaPrM1p%2BuCEtJlI%2FuAnIfuCCp4zDH" rel="nofollow">五月天的《超人》</a>体会一下我此刻的心情。</p>
超优雅!两行代码搞定 php 无限级分类 获取顶级分类ID
https://segmentfault.com/a/1190000004579532
2016-03-10T17:06:55+08:00
2016-03-10T17:06:55+08:00
王道中强流
https://segmentfault.com/u/tmdphp
8
<p>有这样一个表,<code>id</code>是分类的ID,<code>name</code>是分类名称,<code>pid</code>是上级分类的ID。<br><img src="/img/bVtnrg" alt="图片描述" title="图片描述"></p>
<p>现在有个分类ID,程序要找到它上级的上级的上级……分类的ID,简单说就是找出顶级分类的ID。<br>比如“新鲜水果”的ID是13,对应父类ID是5,而5的父ID是1,1没有父类,也就是顶级分类了。</p>
<p>以前年轻气盛不懂事,总想着用递归来查找,然后再将结果缓存来解决性能问题。<br>后来又试过将整个表缓存起来,再递归查找。<br>再后来……似乎比较少有机会遇到无限级分类……</p>
<p>最近有个同事问我怎么“优雅”的解决这个问题。<br>于是我灵机一动,就有了如下解决方案:</p>
<pre><code><?php
$sql = "select id, pid from tablename ";
// 查询后 将结果处理成 如下数组格式
$arr = [
// id => pid
1 => 0,
// 省略...
5 => 1,
// 省略...
13 => 5
];
// 建议将这数组缓存起来
$id = 13;
while($arr[$id]) {
$id = $arr[$id];
}
echo $id; // 1
</code></pre>
<p>不得不说:真是太优雅了!连我都佩服我自己了,同事更是五体投地,痛哭流涕。<br>因为他写了几十行循环再判断再递归的代码,被我用两行代码替换了……</p>
各型号手机微信浏览器可见区域尺寸比例
https://segmentfault.com/a/1190000004408561
2016-02-03T10:50:23+08:00
2016-02-03T10:50:23+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p>在国内做移动 web 开发,恐怕适应微信浏览器才是最重要的事情吧?<br>于是我开始收集各种型号的手机上微信浏览器的可见区域的尺寸。</p>
<table>
<thead><tr>
<th>#</th>
<th>手机型号</th>
<th>宽</th>
<th>高</th>
</tr></thead>
<tbody>
<tr>
<td>1</td>
<td>iPhone 5</td>
<td>320</td>
<td>504</td>
</tr>
<tr>
<td>2</td>
<td>iPhone 6 Plus</td>
<td>414</td>
<td>672</td>
</tr>
<tr>
<td>3</td>
<td>小米 米3</td>
<td>360</td>
<td>572</td>
</tr>
<tr>
<td>4</td>
<td>锤子 坚果</td>
<td>360</td>
<td>566</td>
</tr>
<tr>
<td>5</td>
<td>魅族 MX4 Pro</td>
<td>384</td>
<td>567</td>
</tr>
</tbody>
</table>
<p>。。。</p>
<p>未完待续,欢迎补充。</p>
<h2>贡献方式</h2>
<p>用微信扫描这个二维码,<br><img src="/img/bVsGyd" alt="二维码" title="二维码"><br>或者打开这个链接:<br><a href="https://link.segmentfault.com/?enc=09%2FWLzZoZcnIprJC%2BvHxEA%3D%3D.UefdGT7m5lqznlXTJObqIW6qZS4gAcd5JPdGd9noHEqRv7b7DjLFwAc7%2BrXEUuRS" rel="nofollow">http://mdwx.sinaapp.com/forum.php</a></p>
<p>获取到微信浏览器可见区域尺寸后,<br>回到这篇文章评论,<br>留下你的手机型号和可视区域尺寸。</p>
Selectize.js Option Groups optgroup optgroups 参数的使用方法
https://segmentfault.com/a/1190000004353497
2016-01-23T00:19:30+08:00
2016-01-23T00:19:30+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p><code>selectize</code>是什么东西?它是用来代替原生<code>html</code>标签<code>select</code>一个<code>jQuery</code>插件。众所周知,原生的<code>select</code>既不好看又不好用,所以我们一般选择用一些插件来模拟生成,比如<code>Chosen</code>,<code>select2</code>等等。而<code>selectize</code>是我认为最好用的一个。</p>
<p>看<code>selectize</code>的<a href="https://link.segmentfault.com/?enc=%2BpIFrrODuEnxy3MfiMjCAQ%3D%3D.CZkpSwdWiD8xXRif0YzkZfRlRaPuSJs2m8dig2x2%2FAswsCqUOUlaRmHyvoxh9pzM" rel="nofollow">演示</a>,它是支持 Option Groups 的,<br><img src="/img/bVsqFC" alt="图片描述" title="图片描述"></p>
<p>但它演示的是<code>selectize</code>会将原生<code>html</code>的<code>optgroup</code>模拟成<code>selectize</code>样式的<code>optgroup</code>。</p>
<p>而我需要的是根据我的数据由<code>selectize</code>生成<code>optgroup</code>,<br>没关系我再看<a href="https://link.segmentfault.com/?enc=xuuFyXaNvnzZhDpsDH3dVA%3D%3D.fjOtzIgSSWY%2FQenVyyWKmoq8fuboVzM0jYqSmS9NVzJw1aeir0I6Ae0%2Brra0Sme5YVvrBOcIguN9m98Oswi559fFACVoCh1FPlsQvr3Wk2I%3D" rel="nofollow">文档</a>,按下<code>Ctrl+F</code>搜索<code>optgroup</code>,果然有相关参数,<br><img src="/img/bVsqFD" alt="图片描述" title="图片描述"></p>
<p>但或许是我英文水平太烂,或许是它确实没写清楚怎么使用(估计前者的可能性更大一点),反正是没有很直观的知道怎么用。</p>
<p>没关系,还有谷歌嘛…… 可是还真就搜不到相关解答,<br>算了,作为一名优秀的程序员,没有点分析能力,怎么行走江湖……<br>这个<code>optgroups</code>要么是接受一个树状数组,要么就是和<code>options</code>分别代表两个表,然后用一个字段关联,还能有啥第三种可能吗?<br>估计关联的可能性更大一些,于是就这么一试:</p>
<pre><code>$('#distSub').selectize({
options: [
{text: 'aaa', value:'AAA', optgroup:'a'},
{text: 'abb', value:'ABB', optgroup:'a'},
{text: 'acc', value:'ACC', optgroup:'a'},
{text: 'caa', value:'CAA', optgroup:'c'},
{text: 'cbb', value:'CBB', optgroup:'c'},
{text: 'ccc', value:'CCC', optgroup:'c'},
],
optgroups: [
{label: 'CC', value:'c'},
{label: 'AA', value:'a'}
]
});</code></pre>
<p>还真就可以了……<br><img src="/img/bVsqGw" alt="图片描述" title="图片描述"></p>
<p>代码一出,还看啥文档……<br><code>optgroups</code>, <code>optgroupValueField</code>, <code>optgroupLabelField</code>, <code>optgroupField</code> 分别代表什么,你我心知肚明……</p>
node.js express jquery ajax post options 跨域问题 解决办法
https://segmentfault.com/a/1190000004351980
2016-01-22T16:57:18+08:00
2016-01-22T16:57:18+08:00
王道中强流
https://segmentfault.com/u/tmdphp
1
<p>就不啰嗦了,直接给正确答案。</p>
<p>一 服务器端 也就是 <code>node.js</code> & <code>express</code>:<br>最简单的就是使用 <a href="https://link.segmentfault.com/?enc=AYg7FY7badnN5u7YKWwtaw%3D%3D.WhoqWX5bw8AYI9ydTKE4e%2BR1AjbXoEv2fQ5Bo9ZlmRzwtfSc4vW5wo%2BGpwQ2%2F3w%2B" rel="nofollow">expressjs/cors</a><br>安装 <code>npm install cors --save</code><br>引入 <code>var cors = require('cors');</code><br>使用 <code>app.use(cors());</code><br>这就搞定了服务器端。</p>
<p>二 客户端 也就是 <code>js</code> & <code>jQuery</code>:<br>首先不能用快捷方法 <code>$.post()</code> 了,得用 <code>$.ajax()</code></p>
<pre><code class="js">$.ajax({
type: 'POST',
url: '...',
data: JSON.stringify(params),
processData: false,
contentType: 'application/json',
dataType: 'json'
}).then(function(ret){
alert(ret);
});</code></pre>
<p>除了 <code>{type: 'POST', url: '...', dataType: 'json'}</code> 这几个参数没有变化之外,<br>不同之处在于:<br><code>data</code> 得先用 <code>JSON.stringify()</code> 手动转换成 <code>json</code> 字符串,<br><code>processData</code> 指定为 <code>false</code> 告诉 <code>jQuery</code> 不要再对 <code>data</code> 进行处理,<br><code>contentType</code> 指定为 <code>application/json</code> 告诉服务器,我发送的数据是 <code>json</code> 格式。</p>
<p>我自己解决这问题的时候,搜索到的答案都少指定了 <code>processData</code>,<br>于是服务器收到的数据变成这样子:<code>{ '{id:123, name:"asd"}' }</code>,<br>可能是 <code>jQuery</code> 不同版本之间的差别吧,<br>反正手动指定一下 <code>processData: false</code> 就不会错。</p>
<p>但为什么服务器端收到的会是一个 <code>OPTIONS</code> 和一个 <code>POST</code> 请求?<br><img src="/img/bVsqk5" alt="图片" title="图片"><br>大概是浏览器安全机制方面的问题吧……</p>
一如既往的年终总结,我的2015
https://segmentfault.com/a/1190000004341791
2016-01-21T01:21:15+08:00
2016-01-21T01:21:15+08:00
王道中强流
https://segmentfault.com/u/tmdphp
1
<p>看完《康熙来了》最后一集,突然想写一下2015年的总结,也不知道是一种什么样的逻辑,反正感觉就这么来了,那就这么写了吧。</p>
<p>朋友说我今年又是买车又是买房,总结起来应该很拉风,但说真的并没有…… 反而是有一种很忧郁的心情,不然也不会在看完康熙最后一集的时候突然想写…… 毕竟有意无意的看了那么多年的康熙,突然就停播了真的挺感伤的……</p>
<p>我已经很久没有写那些自认为很煽情或者很有趣的文字的了,这也算是今年一个改变,甚至变得不那么爱看朋友圈了,变得有点厌世的情绪,但不知道从何而来…… 曾以为“有故事,有意思”就是我追求的人生,却不知不觉的成为了自己的反面教材…… 甚至,不想做任何改变,就这么忧郁着吧。</p>
<p>不管怎样 我是想写一篇年终总结来着……</p>
<p>看了一下去年的总结,里面有一句“但行好事,去他妈的前程”,倒是挺有感触,因为最近凑巧又将QQ签名改成“但行好事,莫问前程”…… 初心未变,挺好,只是情绪没那么饱满了。</p>
<p>去年的计划也有实现了一些,拿了驾照,买了车,还顺便把房子也买了,但也没什么可骄傲的,花的是银行的钱,和家里的钱…… 得感谢我父亲,以前很幼稚的认为搞建筑那么多年,没成为开发商就是不够厉害,现在看我自己,写程序这么多年,也还是个码农…… 只希望等我儿子长大,有一天他任性的要买房子的时候,我也有能力像我父亲一样帮他实现……</p>
<p>还有每年都计划的早睡早起,少抽烟多运动…… 恐怕这一生都只是计划。跑步倒是跑了……八次,手机里写好了的八条便签,跑一次发一条到朋友圈,然后……就没有然后了…… 抽烟、晚睡、迟到仍然是常态,也不想改变了,这么多年了,改得了早就改了,顺其自然吧…… 今年听音乐的口味却不知不觉的发生了很大的改变,已经很少听那么热血沸腾的摇滚乐了,转而听电子乐,这是我没想到的,我以为我可以听摇滚到80岁……</p>
<p>技术方面今年算是有一些进步,已经开始在用 node.js 做项目了,尽管 PHP 是世界上最好的语言,但它也是程序员鄙视链中的最低层…… 而 JS 终将统治这个世界…… JS 的世界比 PHP 精彩很多,我用过 Express, mongoose, FIS, coolie, Webpack, Vue, SPA, REST…… 不过比起一些比我年轻,从 PHP 转到 IOS 开发的朋友,还是逼格低人一等,哎……</p>
<p>今年又开始弄我那个五月天中文网…… 现在转做微信公众号了,不管还有没有意义,却是我认为最有成就感的事情…… 本来说好年底要发布 APP,但是突然接了个单,又没时间弄了……</p>
<p>今年朋友圈里最后两个未婚的朋友也结婚了,一个是鸡哥,一个是小庄,鸡哥结婚的时候我开着自己的车载着朋友去了趟宁德,感觉挺好…… 小庄结婚的日期跟我表妹结婚的日期撞在一起了,没去,挺遗憾的。表妹结完婚,表弟去美国了,还有个表弟从阿根廷回来了一趟,组织了几次户外烧烤,平潭,自驾游之类的。还有华哥从澳洲回国了,却还没有机会聚一聚……<br>可能年龄越大对这些聚散离别越是有感触,也可能是基因里与生俱来,因为我发现儿子也有点怕人离开,不管是谁出个门,甚至是出房间,他都会哭…… 也可能是我想太多吧……</p>
<p>儿子现在会跑、会下床铺、甚至会爬到桌子上,每天头上都有撞伤起的包,果然男孩子更顽皮一些,他很爱笑,一逗他就笑,我原以为我会更爱女儿一些,但其实都一样爱。<br>女儿今年上幼儿园了,有点不忍心,不想要她这么快长大,上学意味着有可能被同学欺负,有可能被老师批评,要早起,要做作业…… 还有她常抱怨的在学校吃不饱这种事情…… 好吧,她平常在家吃得确实有点多……<br>今年最开心的时光是跟儿子女儿在一起的那些时间……</p>
<p>有了车以后,大部分周末我都选择回家,少了很多跟朋友相聚的时间,补上了一些跟孩子相处的时间,即便如此还是没有时间挺高一下生活品质,比如携家带口旅个游什么的,这可能也跟儿子还小、老妈身体不好有关系吧,希望明年有机会实现。去个远一点地方,有阳光有风,辽阔而平静的地方……</p>
<p>以前觉得旅行就是一种逃避,逃避现实生活…… 现在我却只想逃避……<br>三十一岁以后可能会习惯这种状态吧…… 不挣扎就不痛了…… 今年我30岁!</p>
<p>30岁了还是没学会怎么排版,就这么乱乱的发布了吧。也不期待有人会认真的看完了……</p>
express express-generator node-dev 自动重新加载 重启
https://segmentfault.com/a/1190000004262297
2016-01-07T00:02:59+08:00
2016-01-07T00:02:59+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p>如果是<code>express-generator</code>创建的项目,创建完成时会提示:</p>
<pre><code>run the app:
$ DEBUG=myapp:* npm start</code></pre>
<p>也就是建议你以<code>npm start</code>方式来启动应用。</p>
<p>其实<code>npm start</code>对应的是<code>package.json</code>中的:</p>
<pre><code> "scripts": {
"start": "node ./bin/www"
},</code></pre>
<p>所以呢,如果你用<code>node-dev</code>来实现自动重启,<br>一种方式是<code>DEBUG=myapp:* node-dev ./bin/www</code><br>另一种方式是修改<code>package.json</code></p>
<pre><code> "scripts": {
"start": "node-dev ./bin/www"
},</code></pre>
<p>然后还是运行<code>DEBUG=myapp:* npm start</code>来启动应用。</p>
<p>而不是其它文章里写的<code>node-dev app.js</code>,<br>因为你的应用是最新版<code>express-generator</code>创建的。</p>
<p>(注意:请将<code>myapp</code>改成你的项目名称)</p>
<p>另外收录几个常用的重启或者说进程管理的包:<br>生产环境用:<code>pm2</code>,<code>forever</code><br>开发环境用:<code>node-dev</code>,<code>nodemon</code>,<code>supervisor</code><br>这些都只是听说,我也只是刚开始用<code>node.js</code>做网站开发。</p>
BootStrap之外 我喜欢的几个Web前端CSS UI框架
https://segmentfault.com/a/1190000004260089
2016-01-06T17:08:42+08:00
2016-01-06T17:08:42+08:00
王道中强流
https://segmentfault.com/u/tmdphp
5
<h3>国内</h3>
<p>Plane UI<br><a href="https://link.segmentfault.com/?enc=kjAJ0LBfkAoUbJ%2FrkASiJg%3D%3D.uBLr%2BnQsxV8QP%2FHbJ8feh9SQ8%2F%2BYB60vkkaZym7re5VjzN%2BeBuEKFGYpe0dhJhAv" rel="nofollow">https://pandao.github.io/plan...</a><br>160726收录,感觉挺好的,但是github最后一次提交时间2015-06-28</p>
<p>ZUI<br><a href="https://link.segmentfault.com/?enc=2aUW7a4MsigcjTXszSwJnQ%3D%3D.O0M2ZXcz65gLrwHR%2BIuHKij4FwRUpPIqWVOYnAJWDNA%3D" rel="nofollow">http://zui.sexy/</a><br><a href="https://link.segmentfault.com/?enc=SLR2Ov2hlMVHMR68Di3cxg%3D%3D.lUoMRwHiTy32Yx8XcmkxRngC4pj6MC%2B%2BUKa91NmsgAo%3D" rel="nofollow">https://github.com/easysoft/zui</a></p>
<p>拼图(用过)<br><a href="https://link.segmentfault.com/?enc=Et%2BUeOmhCAEMOE8hTQlM%2Bw%3D%3D.acbXYAvW6bU4wnZ9Irg5o%2FnK1OGtiX4Sd3XUZJpl8a8%3D" rel="nofollow">http://www.pintuer.com/</a></p>
<p>AmazeUI(用过)<br><a href="https://link.segmentfault.com/?enc=DTlN1tjem8MUvyikSFchSQ%3D%3D.RVEM5ikZ2xGLtZPGqkiG%2BoMCaAIUZpEuHwfVco%2BmdXE%3D" rel="nofollow">http://amazeui.org/</a></p>
<p><del>AliceUI</del><br><del><a href="https://link.segmentfault.com/?enc=Psh8uOS1GhD5r6lBp87x9w%3D%3D.vW%2BJ9epX2SpSSj3tfJZuhZ7LEgc0Kig5M3TFZTa5OD8UCNapYN1%2FR0CfPqxWBDXl" rel="nofollow">http://aliceui.org/docs/widge...</a></del></p>
<p>SUI<br><a href="https://link.segmentfault.com/?enc=Wt8Jrj4AfnKS7PgrGm0DeQ%3D%3D.tWU18yarH%2B2vYQi931Yc9EKfV5Ro0PaDhuUoeS1Ta8E%3D" rel="nofollow">http://sui.taobao.org/</a></p>
<p>BUI(好久都没更新了)<br><a href="https://link.segmentfault.com/?enc=ar6BK4UBOwvU1F8SnuX0wA%3D%3D.H15wrj0Y%2BNHWd762KQto7HC%2Fd%2B4ef0CW9XTfkLPCUl0%3D" rel="nofollow">http://www.builive.com/</a></p>
<p>Layui(未发布)<br><a href="https://link.segmentfault.com/?enc=YidfMj2M2EDl7wD70i2qfg%3D%3D.XF0PwaEG79cJwTzhR0VzwtO3Lvz9BZ0Dznss%2Ftsyo6Q%3D" rel="nofollow">http://www.layui.com/</a></p>
<p>ESUI(百度)<br><a href="https://link.segmentfault.com/?enc=EFloqNzJi7BuOnN3Q6DjbA%3D%3D.lugeiZx6ajU3oYYAw%2BQq0ij5%2FgunBqfYWfOhXr4dM%2BLTlgCxWfRDmL2FIvhamPYH" rel="nofollow">http://ecomfe.github.io/esui-...</a></p>
<h3>国外</h3>
<p>uikit(用过)<br><a href="https://link.segmentfault.com/?enc=HidaUG59PdLlmaAm1S2Cng%3D%3D.mkKe4O9mEkfcdrY0AqKRjqbI3mW4rXFxasEGH%2F%2FewEA%3D" rel="nofollow">http://getuikit.com/</a></p>
<p>Semantic UI<br><a href="https://link.segmentfault.com/?enc=XVHyqfAEz%2BKY920%2Fdp7xdg%3D%3D.Y2YhzSp7o7q4hYUfQ7K%2BO8GNnvNpmgYrZQP%2F2YKbo3I%3D" rel="nofollow">http://semantic-ui.com/</a></p>
<h3>类ext</h3>
<p>EasyUI(用过)<br><a href="https://link.segmentfault.com/?enc=F8iBZCZIV0iar9rJQZd8Rw%3D%3D.0wu8QbeEnEfDwm6QMkufSt8aU8GnfvM%2Fcgao6CpIshY%3D" rel="nofollow">http://www.jeasyui.com/</a></p>
<p>JUI(原名DWZ)<br><a href="https://link.segmentfault.com/?enc=P4fsjgUH%2FlhmRvhqK2hong%3D%3D.EpAJJpMISdYHbBfzkBimtg%3D%3D" rel="nofollow">http://jui.org/</a></p>
<p>LigerUI<br><a href="https://link.segmentfault.com/?enc=zNdN0H9yZKWuWhQ0beVlnw%3D%3D.dMqDpMU0M0ZjjnO9I4NiBeRDWduLEwQGB2Biy5MA3nY%3D" rel="nofollow">http://ligerui.com/</a></p>
单页应用 WebApp SPA 骨架 框架 路由 页面切换 转场
https://segmentfault.com/a/1190000004186135
2015-12-23T10:20:31+08:00
2015-12-23T10:20:31+08:00
王道中强流
https://segmentfault.com/u/tmdphp
5
<p>所能想到的关键词 都写到标题上了,<br>为了让你不管搜索什么都能找到这篇文章,<br>有没有被我的智商所折服? ^o^</p>
<p>这里收录三个同类产品,找到他们花了我不少时间呢。</p>
<ol>
<li><p>张鑫旭写的<code>mobilebone</code><br> 自述:mobile移动端,PC桌面端页面无刷新过场JS骨架,简单、专注!<br><a href="https://link.segmentfault.com/?enc=uPkgQvv9l1C7FgrTnPNEKA%3D%3D.tglNeMS0ckGdytOf4XpSSL8DilHsUwjfvi7pEufHisY3R4N0iKyDv6t4IutFWGP2qChP3RS505QphT7x5qQeFwBZmHsICBNnAjVyJ5YDBiQ%3D" rel="nofollow">http://www.zhangxinxu.com/wordpress/2014/10/mobilebone-js-mobile-web-app-core/</a><br><a href="https://link.segmentfault.com/?enc=iUV5nfzkSOmWR%2BiuJgluAw%3D%3D.JKJ%2Fa7yatYC3D88MTWt9Bq3iICwkO0wJKpdTemHjC8TPfHtcWWMmiYD7jYvecGPT" rel="nofollow">https://github.com/zhangxinxu/mobilebone/</a></p></li>
<li><p>赵达写的<code>spa</code><br> 自述:SPA是为构建WebApp设计的路由控制和视图转换框架<br><a href="https://link.segmentfault.com/?enc=t8o5LjP9YimY535Cj3XGcw%3D%3D.E5ZKRbI1QmCB1nunsv57gSIe57M%2FmY%2FfHze%2B%2FaZxqrk%3D" rel="nofollow">http://zhaoda.net/spa/docs/</a><br><a href="https://link.segmentfault.com/?enc=u1F3jXvKbpMWWEsQKDNLWA%3D%3D.3zA5%2Baq8kfSxa79ggYNBJp8xFg4jr3XqnaTaCm5hKt8%3D" rel="nofollow">https://github.com/zhaoda/spa/</a></p></li>
<li><p>dolymood的<code>mobile-router</code><br> 自述:轻量级web端单页面骨架<br><a href="https://link.segmentfault.com/?enc=TqIFL4TSk5nJ%2Far9cBPslQ%3D%3D.XjggYyjwNwVws99Pj218AtcolbEO7YAOkBrXizJ4HjE%3D" rel="nofollow">http://mrdocs.aijc.net/</a><br><a href="https://link.segmentfault.com/?enc=Ek9VaSRy%2BKpZ0vOM81R5TA%3D%3D.PPB8IZDLDPZm%2BRoStpoM6GjsyOBI4kgyrLRtN2Vxtp6OG5fLltJ6i5IP2z%2F%2BqONCZUjr2KvdVwCVmWB%2BqdaaXg%3D%3D" rel="nofollow">https://github.com/mobile-router/mobile-router.js</a></p></li>
</ol>
<p>但是我还没决定用哪个,我再比较比较,或者看看还有没有别的。</p>
微擎中使用微信之门接口,让订阅号也能直接以网页的方式获取OpenID
https://segmentfault.com/a/1190000003900818
2015-10-24T11:48:36+08:00
2015-10-24T11:48:36+08:00
王道中强流
https://segmentfault.com/u/tmdphp
1
<p>开发微擎模块的时候 常会遇到一个问题:<br>只有服务号才能直接在网页上获取<code>OpenID</code>,<br>如果是订阅号就只能从对话消息中获取<code>OpenID</code>然后传到网页,<br>虽然微擎有个功能叫做“借用<code>oAuth</code>权限”,<br>但是有时候连借都没地方借,怎么办呢?<br>还好这是个互联网时代,有需求,就会有服务。<br>“<a href="https://link.segmentfault.com/?enc=LxrTydGIsNRYQyHqhteCqw%3D%3D.2F%2FievWFhQRuV2BnvEKuUlefkb6y3%2Bnb9kg786wxjl4%3D" rel="nofollow">微信之门</a>”就是为此而生的,转发一下他们的简介:</p>
<blockquote><p>微信打开的网页,是无法持久存贮 <code>cookies</code> 的,你知道吗? 那么如何辨识唯一用户呢?<br>是的,使用微信服务号!服务号拥有高级接口,可以给让网站通过微信的<code>OAuth2</code>授权, 获得用户的 <code>OpenID</code>, 从而辨别一个唯一用户。<br>那么,没有微信服务号呢? 这就是微信之门诞生的原因。</p></blockquote>
<p>其它使用说明可以到<a href="https://link.segmentfault.com/?enc=ABd8dSTuo4J1e5cPguwHEQ%3D%3D.ziWKO5Ws8IUGqiX07MtYL3PIz%2FWaqeqSpu40xItgZ5Y%3D" rel="nofollow">微信之门官网</a>查看。</p>
<p>我要写的是怎么在微擎模块中使用微信之门的接口,<br>在你的<code>xxxModuleSite</code>类(也就是<code>addons/xxx/site.php</code>文件)添加一个构造函数 代码如下:</p>
<pre><code class="php">function __construct()
{
global $_W, $_GPC;
if (empty($_W['openid'])) {
if (empty($_SESSION['openid'])) {
if ($_GPC['wgateid']) {
$_W['openid'] = $_SESSION['openid'] = $_GPC['wgateid'];
} else {
$thisUrl = urlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
$gateUrl = "http://www.weixingate.com/gate.php?back=$thisUrl&force=1&info=none";
header('Location: ' . $gateUrl);
exit;
}
} else {
$_W['openid'] = $_SESSION['openid'];
}
}
}</code></pre>
<p>好吧,代码一出 说什么都显得多余,<br>这逻辑简单到小朋友都看得懂,就不多做解释了,<br>事实上还可以调用一下验证接口,检查一下传回来的的<code>wgateid</code>,如何有需要的话……</p>
另辟蹊径 搞定PHP读取XML大文件 数据导入
https://segmentfault.com/a/1190000003699340
2015-09-02T14:02:26+08:00
2015-09-02T14:02:26+08:00
王道中强流
https://segmentfault.com/u/tmdphp
3
<p>由于工作原因,不得不与一个二逼团队合作,<br>我说直接导出SQL文件给我就好了,而他们坚持要导出XML文件。<br>或者他们有他们的原因吧,但我还是要叫他们二逼团队,懒得了解他们有什么苦衷。</p>
<p>我想MySQL应该是支持导入XML的话,搜索的结果是什么我忘了。<br>反正我最后决定还是自己写一段PHP来生成SQL语句。</p>
<p>XML数据结构大概是这样子的:<br><img src="/img/bVpGlj" alt="图片描述" title="图片描述"></p>
<p>文件很大,有很多<code><object></code>,也就是很多记录,但是单个记录里的数据并不大。</p>
<p>PHP里关于XML的操作有很多类和函数。<br>详见:<a href="https://link.segmentfault.com/?enc=IISO99ZQCSIgK39xbhx1Wg%3D%3D.6ZOu5emVN1niJakFyBaKefIYI1xW4aAyLrm9twkY39Pc6PW88TMsOvN%2F%2FAWCr78n" rel="nofollow">http://php.net/manual/zh/refs.xml.php</a><br>其中常用的应该是<code>XMLReader</code>、<code>SimpleXML</code>(纯属个人感觉,并没有数据支持)<br><code>XMLReader</code>是以文件流的方式 一句一句读取,主要用来处理体积很大的XML文件,但用起来比较麻烦。<br><code>SimpleXML</code>用起来则便捷了许多,但它没办法处理很大的XML数据。</p>
<p>刚开始我只用<code>XMLReader</code>来导入,当然也是可以导入的,但是嵌套了好几层循环和判断。<br>要不是后来又要导入一批数据,我几乎以为只能这样写了。</p>
<p>第二次导入的时候,我采用的方法是结合<code>XMLReader</code>和<code>SimpleXML</code>,<br>因为不管你XML文件再怎么大,单条记录的数据能大到哪里去?(我说的是一般情况)</p>
<p>想到这个方法之后,于是代码就简洁到 我都不好意思发出来的程度了。<br>但是为了让这篇文章的读者 对这种简洁有个更直观的感受,我还是厚着脸皮发一下吧:</p>
<pre><code><?php
$xml = new XMLReader();
$xml->open(__DIR__ . '/company.xml');
while($xml->read()) {
if($xml->name=='object' and $xml->nodeType==XMLReader::ELEMENT) { // 进入 object
$inXml = $xml->readOuterXML(); // 获取当前整个 object 内容(字符串)
$inXml = simplexml_load_string($inXml); // 转换成 SimpleXMLElement 对象
// 然后没有了 就这么简单 具体怎么保存到数据库 dump 一下 $inXml 你就懂了
var_dump($inXml);
}
// 继续读取 直到进入下一个 object
}</code></pre>
<p>就是这样了,如果你还在为<code>XMLReader</code>太难用,<code>SimpleXML</code>搞不定大文件,而苦苦搜寻“php xml 操作类 大文件”,这篇文章的思路应该就是你需要的。</p>
MySQL 无缘无故忽然连不上了 有可能是你硬盘满了
https://segmentfault.com/a/1190000003502167
2015-08-27T19:04:46+08:00
2015-08-27T19:04:46+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p>今天服务器突然连不上MySQL数据库,提示连接数太多。<br>作为一名老油条程序员,也懒得想那么多,</p>
<p>一、尝试重启MySQL,咦~ 居然失败。<br>二、尝试查看日志,咦~ 怎么没有记录。<br>三、我去,干脆重启服务器,反正网站也没什么人访问。</p>
<p>好吧,看来不得不动一下脑子了,<br>直觉告诉我,应该不是被黑,感觉可能是硬盘满了,<br>于是搜了一下命令。<br>一、查看各分区空间使用情况:<code>df -h</code><br>果然不出我所料,其中一个盘满掉了。</p>
<p>二、看看哪个文件占用这么多空间:<code>du -sh /*</code><br>看到<code>/root</code>目录占了几十G,再进去看:<code>du -sh /root/*</code><br>其中<code>/root/mysql_backup</code>占了几十G,</p>
<p>三、于是删掉太久了的数据库备份,然后重启MySQL。<br>搞定收工……</p>
<p>写了一堆费话,主要记录一下这几个命令。<br>查看各分区空间使用情况:<code>df -h</code><br>看看哪个文件占用这么多空间:<code>du -sh /*</code></p>
<hr>
<p>2015/12/17 更新</p>
<p>今天又遇到<code>Lost connection to MySQL server at 'reading initial communication packet'</code>这个错误提示。</p>
<p>仍然是:硬!盘!满!了!</p>
文件上传前压缩图片尺寸大小,支持安卓微信APP浏览器
https://segmentfault.com/a/1190000002769740
2015-05-15T18:14:52+08:00
2015-05-15T18:14:52+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<pre><code> function ImageFileResize(file, maxWidth, maxHeight, callback) {
var Img = new Image;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
Img.onload = function() {
if (Img.width>maxWidth || Img.height>maxHeight) {
var bili = Math.max(Img.width/maxWidth, Img.height/maxHeight);
canvas.width = Img.width/bili;
canvas.height = Img.height/bili;
}else{
canvas.width = Img.width;
canvas.height = Img.height;
}
ctx.drawImage(Img, 0, 0, Img.width, Img.height, 0, 0, canvas.width, canvas.height);
// $('body').append(canvas);
callback(canvas.toDataURL());
};
try{
Img.src = window.URL.createObjectURL(file);
}catch(err){
try{
Img.src = window.webkitURL.createObjectURL(file);
}catch(err){
alert(err.message);
}
}
}
$('.js-uploader').on('click', function () {
var $clickObj = $(this);
var $fileInput = $('<input type="file"/>');
$fileInput.on('change',function () {
$clickObj.text('正在上传...');
ImageFileResize($fileInput[0].files[0], 800, 800, function (dataUrl) {
$.ajax({
type: "POST",
url: "<?=$this->createMobileUrl('Upload')?>",
data: {imgDatUrl:dataUrl},
success : function (ret) {
$clickObj.prev().remove();
$clickObj.before("<img src=\"" + dataUrl + "\"/> ");
$clickObj.next().val(ret.path);
$clickObj.text('重新上传');
},
dataType : "json"
});
});
});
$fileInput.click();
});
</code></pre>
PHP加密和解密函数
https://segmentfault.com/a/1190000002558209
2015-02-15T16:21:19+08:00
2015-02-15T16:21:19+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<pre><code>php</code><code>/**
* Returns an encrypted string
*/
function encrypt($pure_string, $encryption_key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, $pure_string, MCRYPT_MODE_ECB, $iv);
return rawurlencode($encrypted_string);
}
/**
* Returns decrypted original string
*/
function decrypt($encrypted_string, $encryption_key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, rawurldecode($encrypted_string), MCRYPT_MODE_ECB, $iv);
return $decrypted_string;
}
</code></pre>
禁用 BootStrap Modal 点击空白时自动关闭
https://segmentfault.com/a/1190000000953850
2014-11-13T17:27:27+08:00
2014-11-13T17:27:27+08:00
王道中强流
https://segmentfault.com/u/tmdphp
1
<pre><code>$('#myModal').modal({backdrop: 'static', keyboard: false});
</code></pre>
<p>这样就可以了,<br><code>backdrop</code> 为 <code>static</code> 时,点击模态对话框的外部区域不会将其关闭。<br><code>keyboard</code> 为 <code>false</code> 时,按下 <code>Esc</code> 键不会关闭 Modal。</p>
国内开源html5游戏引擎全收录
https://segmentfault.com/a/1190000000749890
2014-10-30T21:10:39+08:00
2014-10-30T21:10:39+08:00
王道中强流
https://segmentfault.com/u/tmdphp
4
<p>游戏开发这潭水太深,英文水平太差,不敢看国外的,<br>而且这几年国内技术水平也挺高了不少,特别是JS方面。(我个人感觉)</p>
<p>最近看了几个国产的js游戏引擎,有点想开发个游戏玩玩,<br>毕竟搞编程这么多年,开发过各种类型的程序,就是没搞过游戏,<br>人生是不完整的。。。</p>
<p>就先收录一下我所知道的国产开源h5游戏引擎吧。</p>
<p>cocos2d-js<br><a href="https://link.segmentfault.com/?enc=NlHju%2FPbG9WSRkP%2FgZH35g%3D%3D.%2FpWsMwylNpFmKLgSR5jD149NCTnC3gm%2F2PGfCuC%2FpKQ%3D" rel="nofollow">http://cn.cocos2d-x.org/</a></p>
<p>egret<br><a href="https://link.segmentfault.com/?enc=yUwIMJMXBw3HA0vg7C4Nsg%3D%3D.74YJCiV%2F20C9Eu1JRCyqZm1GwlxdKopinYxAENTkdJ4%3D" rel="nofollow">http://www.egret-labs.org/</a></p>
<p><del>Sirius2D</del><br><del><a href="https://link.segmentfault.com/?enc=oMxn%2FubHVwJVo8u3EwgCuA%3D%3D.hvTHiV%2FbcPZPnE3FsJTWd0AM7hO79VfeP8JWn9qIMJU%3D" rel="nofollow">http://www.sirius2d.com/</a></del></p>
<p>lufylegend.js<br><a href="https://link.segmentfault.com/?enc=I8%2FC%2FNB3Ej6y5V0HmoVDWA%3D%3D.YoMCLCDynFVaW1goPVjdXUouOwvUbFEMFT8SmomqpFY%3D" rel="nofollow">http://www.lufylegend.com/</a></p>
<p>鉴于我对游戏行业的无知,其实很纠结要不要每个引擎写点评论,<br>想想可能会有更无知的人来看我的文章,要不就随便写写吧。</p>
<p><strong>cocos2d</strong> 应该是IOS平台最火的游戏引擎之一,保险起见加个『之一』总是没有错了哈。<br>而cocos2d-js则是官方新推出不久的JS版本,之前还有个cocos2d-html5,也不知道为什么又推出cocos2d-js,有什么区别呢?<br>还有c++版本之类的,万一你以后要改其它编程语言,还可以继续使用cocos2d。<br>大公司,好像要上市,团队作品,文档很全。<br>开发完可以转换成原生应用,打包之后你的游戏也就和html5没什么关系了,调用的都是高级接口,牛逼闪闪。</p>
<p><strong>egret</strong> 最近也火到不行,自从出了那个围住神经猫之后……<br>虽是新团队,但也是企业级产品,据说团队都是来自各界精英,大部分是从Flash阵营转过来的。<br>用的是typescript作为开发语言,而且和cocos2d-js一样 也可以转换成原生应用。<br>生命力很旺盛,假以时日必成大器。还有跟腾讯X5浏览器合作,恐怕会是微信游戏开发不二之选。<br>不过看过一些用egret开发的案例,感觉有点Low,也许是围住神经猫给人留下的第一印象吧。</p>
<p>比起egret,<strong>Sirius2D</strong> 展示的一些案例,效果都杠杠的,<br>但是对于他们团队的了解并不是很多,也没有像egret那样搞在线培训,<br>我个人对这引擎还是挺有好感的,但就是不知道它明天会不会死,<br>今天还一度打不开官网…… 拜托也努力一点好吗?</p>
<p><strong>lufylegend</strong> 应该是《HTML5 Canvas游戏开发实战》作者开发的,<br>这个感觉倒是挺努力的,但是Canvas怎么拼得过WebGL。。。</p>
<p>另外:<br>cocos2d egret 都是同时支持WebGL和Canvas的,<br>Sirius2D只支持WebGL,</p>
<hr>
<p>写完感觉没什么信心发表啊,对于以上言论的准确性并不是很有把握,<br>完全凭印象写的,懒得去核实。</p>
<hr>
<p>2015.8.20 收录:<br><a href="https://link.segmentfault.com/?enc=IZ3FfGYhwKwNBd%2FiBDHh0A%3D%3D.855DNBPKBcpvOP1yydN13fRxkeLBFd3x%2FwlolU88wnI%3D" rel="nofollow">http://soya2d.com/</a></p>
<p>2016.6.29 收录:<br><a href="https://link.segmentfault.com/?enc=t4Ptri%2FpbLhpB%2BhHPpbpnw%3D%3D.GMdGNpzS%2BkTqw5B%2B5YJy0G4pmabSjwBCQxhB8gmXZTw%3D" rel="nofollow">http://ldc.layabox.com/</a></p>
windows mongodb 安装
https://segmentfault.com/a/1190000000731782
2014-10-20T17:11:30+08:00
2014-10-20T17:11:30+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p>解压后,将 E:\mongodb\bin 加入 PATH 中,会方便很多。</p>
<p>然后创建 data 和 log 目录,</p>
<p>然后命令行运行:<br>
mongod --dbpath E:\mongodb\data --logpath E:\mongodb\log\mongod.log --install</p>
<p>就安装成服务了,</p>
<p>然后到服务中启动就好了~</p>
<p>so easy~</p>
用一段非常难懂的语句,但是很简洁的实现了一个很实用的函数。
https://segmentfault.com/a/1190000000647252
2014-08-24T23:19:52+08:00
2014-08-24T23:19:52+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<p>我又来写博客了~ 原因是用一段非常难懂的语句,但是很简洁的实现了一个很实用的函数。</p>
<p><strong>这个函数的作用:</strong><br>
比如论坛的帖子列表吧,比如<code>Discuz</code> <a rel="nofollow" href="http://www.discuz.net/forum-21-1.html">http://www.discuz.net/forum-21-1.html</a><br>
就有帖子的作者和最后回复的人,<br><img src="http://segmentfault.com/img/bVcSw0" alt="请输入图片描述"></p>
<p>如果表里只存两个<code>user_id</code>,列表页要显示两个用户名 就必须去关联<code>user</code>表,而且要关联两次。<br>
不过Discuz的方法是把两个用户名也存到表里。<br>
但这是个极low的办法,至少我个人是这么认为的。</p>
<p>比如 列表页要显示用户性别的时候怎么办?<br>
为此你得修改至少三个地方,1.数据库;2.发贴的代码;3:回复的代码<br>
然后用户要修改用户名怎么办?那工作量简直不敢想像了……</p>
<p>那么关联用户呢?理论上最应该采用的应该是关联的办法,但现实是帖子表和用户表是论坛最重要的两个数据,也是最大的表,用join的话那性能可想而知。</p>
<p>所以最好的方法应该是:查询帖子表,再用帖子表的用户ID,去查询用户表。<br>
虽然用了两次SQL查询,但这是介于追求灵活性和追求性能之间的最佳实践。</p>
<p>像论坛这种程序,它就这么一个列表页,也许不一定要独立出一个函数,<br>
而我的工作是做那种类似OA,ERP之类的东西,就是有无数的列表,<br>
于是有了以下几个函数:</p>
<pre><code>// 将类似“1, 3, , 5”这种字符串分割成数组
function tmdExplode($str) {
if (!$str) return array();
return array_filter(array_map('trim', explode(',', $str)));
}
// 在一个数组集中取出一个或多个字段,组成的数组,多个字段以逗号分隔
// 比如:arrayColumn($all, 'post_uid, reply_uid')
// 返回数组如:array(1, 3, 5, 7, 9)
function arrayColumn(&$dat, $cols) {
$arr = array();
$cols = tmdExplode($cols);
foreach ($cols as $col) {
foreach($dat as $r) {
if ($r[$col] and !in_array($r[$col], $arr)) {
$arr[] = $r[$col];
}
}
}
return $arr;
}
</code></pre>
<p>以上两个是全局函数,以下是用户类里的一个方法,并不通用,你拿去用的话恐怕要改改:</p>
<pre><code>function dataSetUser(&$data, $fields='uid', $appends='_user') {
$uidArr = arrayColumn($data, $fields);
$userArr = M('user')->where("id in (%s)", implode(',', $uidArr))
->getField("id, sex, username");
$appends = tmdExplode($appends);
foreach (tmdExplode($fields) as $i=>$field) {
foreach($data as &$r) {
$userTmp = $userArr[ $r[$field] ];
$r[ $appends[$i] ] = $userTmp['username'].' '.$userTmp['sex'];
}
}
}
</code></pre>
<p>但这是一个牛逼的方法,也是本文最核心的代码,<br>
没有注释是因为我实在无法用语言来形容它……<br>
就让它自生自灭去吧~ Sorry~</p>
为什么mysql字段要设置为not null?
https://segmentfault.com/a/1190000000646755
2014-08-24T12:03:33+08:00
2014-08-24T12:03:33+08:00
王道中强流
https://segmentfault.com/u/tmdphp
2
<p>为什么mysql字段要设置为<code>not null</code>?<br>
现在 大师来跟大家解释解释</p>
<p>首先 我们创建一个表 <code>asd</code>字段为<code>null</code>,<code>qwe</code>字段为<code>not null</code>,都无默认值</p>
<pre><code>CREATE TABLE `tb` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`asd` VARCHAR(45) NULL,
`qwe` VARCHAR(45) NOT NULL,
PRIMARY KEY (`idtb`)
)
</code></pre>
<p>然后</p>
<pre><code>insert tb(asd) values('123123123');
insert tb(qwe) values('123123123');
</code></pre>
<p>现在 我们来查看这个表<br><img src="http://segmentfault.com/img/bVcSpy" alt="请输入图片描述"><br>
可以看出<br><code>not null</code> 的<code>qwe</code>字段 未设置的时候是个空字符串<br><code>null</code> 的<code>asd</code>字段 未设置的时候是个<code>NULL</code></p>
<p>以上结果 大家应该都可以想像到的。<br>
那么为什么要设置<code>NOT NULL</code>呢<br><strong>因为 MYSQL不是PHP,NULL不等于空字符串</strong><br>
比如我们查询<code>qwe</code>为空的</p>
<pre><code>select * from tb where qwe=''
</code></pre>
<p>可以找到<br><img src="http://segmentfault.com/img/bVcSpz" alt="请输入图片描述"><br>
但是</p>
<pre><code>select * from tb where asd=''
</code></pre>
<p>则什么都找不到</p>
<p>而我们WEB开发的时候,果然有的地方插入记录 是指定空字符串,有的地方插入记录没有指定值,如果字段没设置<code>NOT NULL</code>,那就是出现:<br><img src="http://segmentfault.com/img/bVcSpB" alt="请输入图片描述"></p>
<p>而你查找的时候,只会出现<br><img src="http://segmentfault.com/img/bVcSpE" alt="请输入图片描述"></p>
<p>所以 要设置 <code>NOT NULL</code><br>
这个 就不会有<code>NULL</code>出现了。</p>
<hr>
<p>后记:好久以前写的一篇文章,忘记了有没有发表,今天整理网盘刚好看到,就发上来了。</p>
玩了一把nodejs 批量下载保存远程图片文件 并更新数据库
https://segmentfault.com/a/1190000000645290
2014-08-22T16:24:47+08:00
2014-08-22T16:24:47+08:00
王道中强流
https://segmentfault.com/u/tmdphp
0
<pre><code>var request = require('request');
var fs = require('fs');
var mysql = require('mysql');
var mydb = mysql.createConnection({
host: 'localhost',
// port: 3306,
user: 'root',
password: 'root',
//charset: 'UTF8_GENERAL_CI',
debug: false
});
mydb.connect(function(err){
if (err) {
console.error(err);
throw err;
}
});
mydb.query('USE `dbname`', function(err){
if (err) {
console.error(err);
throw err;
}
});
mydb.query("SELECT `id`,`image` FROM `fy_scenic` WHERE INSTR(`image`, 'http://') ORDER BY `image` ", function(err, rst) {
if (err) {
console.error(err);
throw err;
}
rst.forEach(function(row) {
console.log(row);
var filepath = 'old/'+row.image.substr(36);
var filedir = filepath.substr(0,7);
if (!fs.existsSync(filedir)) {
fs.mkdirSync(filedir);
}
request(row.image).pipe(fs.createWriteStream(filepath));
var sql = "UPDATE `fy_scenic` SET `image`=? WHERE `id`=? ";
sql = mydb.format(sql, [filepath, row.id]);
console.log(sql);
mydb.query(sql, function(err, rst) {
if (err) {
console.error(err);
throw err;
}
});
});
});
</code></pre>
php允许被跨域ajax请求
https://segmentfault.com/a/1190000000620437
2014-07-28T18:33:20+08:00
2014-07-28T18:33:20+08:00
王道中强流
https://segmentfault.com/u/tmdphp
6
<p>一个没那么难的历史难题,其实只要在被请求端,加一句:</p>
<pre><code>header('Access-Control-Allow-Origin: *');
</code></pre>
<p>然后……然后没有了。</p>
禁止360浏览器登录管家记住用户名密码
https://segmentfault.com/a/1190000000613683
2014-07-22T14:43:57+08:00
2014-07-22T14:43:57+08:00
王道中强流
https://segmentfault.com/u/tmdphp
1
<p>很简单<br>
把原本为<code>password</code>的<code>input</code>改为<code>text</code>,<br>
再加上<code>onfocus="this.type='password'"</code></p>
<pre><code><li><em>设置密码</em><input type="text" name="passwd" onfocus="this.type='password'" /></li>
</code></pre>
<p>这样就可以了~</p>