Category: 编程、软件、技术

  • Microsoft Power BI初尝试

    最近测试了一下Microsoft Power BI Desktop。用的是我的藏书数据库。

    注意事项一:BID访问MySQL数据库需要安装MySQL .NET Connector,官方下载地址:http://dev.mysql.com/downloads/connector/net/

    注意事项二:BID不能单独Export图片,而只能用服务器端控件的方式显示。如下图。所以你还需要去官网下载Desktop并注册一个账号(特别注意:注册中的国家列表没有“中国”,但是你选择随便一个地方也无所谓;另外,不能用任何类型的免费邮箱)。

    还有很多要学习的地方。慢慢来。

    5.14补充:

    • 发现一个问题:我修改了图表,也已经publish,但是在本页面上还是显示老的图表。重新贴上BI里给出的链接还是老的图表。解决方法是克隆这个修改后的表格,再导出Web链接即可。
  • 微信订阅号的开发

    最近看了一下微信订阅号的开发。

    我要做一个个人订阅号,用户订阅之后,可以通过输入命令获得交互,得到英文单词的解释,大概就是这样。

    微信开发权限获得就不讲了,需要帮助的同学可以去访问相应的站点。

    首先,我开了一个域名(http://weixin.rsywx.com) 作为和微信通讯的接口。

    按照微信的说法,用户输入命令后,该接口将“被动”地回复信息。而这也是我这个订阅号和用户交互的主要渠道。

    在weixin.rsywx.com中,我用Silex框架构建了我的应用。这是因为我需要在这个框架中进行一些控制。当然你也可以用一个plain PHP文件来完成这个接口的工作。 该应用的入口文件很简单:

    require_once __DIR__ . '/../vendor/autoload.php';
    require_once __DIR__ . '/./WechatCallbackAPI.php';
    $app = new Silex\Application();
    $app['debug'] = true;
    // Twig registration
    $app->register(new Silex\Provider\TwigServiceProvider(), ['twig.path' => __DIR__ . '/../views']);
    $app->post('/', function () use ($app)
    {
        $obj=new WechatCallbackAPI();
        echo $res=$obj->response($app);
    });
    $app->run();

    其中的Twig注册不是必要的,因为微信要求的回应是一个XML字符串。不过放进去也没有关系。 对于“/”这个路径,我们在响应微信的请求时必须使用POST方式。同时我们创建了一个对象,并调用response方法来返回消息。 在WechatCallbackAPI中,我们抄袭微信的实例代码并作一些改进:

    public function response($app)
        {
            $post=$GLOBALS['HTTP_RAW_POST_DATA'];
            //$post=file_get_contents('php://input');
            if(!empty($post))
            {
                libxml_disable_entity_loader(true);
                $obj=simplexml_load_string($post, 'SimpleXMLElement', LIBXML_NOCDATA);
                $from=$obj->FromUserName;
                $to=$obj->ToUserName;
                $key=strtolower(trim($obj->Content));
                if($key==?||$key==?||$key=='help')
                {
                    $wpme=new WPME($from, $to);
                    $res=$wpme->help();
            return $res;
                }
                else if (substr($key, 0,4)=='wpme')
                {
                    $wpme=new WPME($from, $to);
                    $wpme->setKey($key);
                    $res=$wpme->invoke();
                    return $res;
                }
                else if(substr($key, 0,4)=='wotd')
                {
                }
                else
                {
                    $wpme=new WPME($from, $to);
                    $res=$wpme->unknown();
                    return $res;
                }
            }

    注意,这里还用到了一个在PHP 5.6中被标记为deprecated,而在PHP 7将是obsolete的功能:

    $post=$GLOBALS['HTTP_RAW_POST_DATA'];

    PHP手册中建议用

    <pre lang="php">$post=file_get_contents('php://input');

    但是经过测试似乎不行。微信就是这么任性。

    在该response函数中,我们根据不同的用户输入来调用不同的功能。上述代码中列出了WPME(Word Power Made Easy)模块中的判断。WPME模块中最重要的方法是invoke,它将根据不同的命令($key)去进一步调用不同的资源并构造返回值。而另外一些命令在WPME中直接处理,比如最简单的help方法:

    public function help()
        {
            $content = Available commands:\nwpme1: Latest WPME\nwpme7: Last 7 WPMEs\nwpme????: Search WPME for ????;
            $res = sprintf(WPME::$txtTemplate, $this->from, $this->to, time(), $content);
            return $res;
        }

    help将列出可以使用的命令,比如wpme1,然后渲染一个静态文本模板并返回。文本模块的格式可以参考微信文档。

    而invoke方法如下:

    public function invoke()
        {
            $uri = https://rsywx.net/wechat/ . htmlentities($this->key);
            $content = file_get_contents($uri);
            preg_match_all('/(.*?)<\/title>/i', $content, $matches);
            $res = sprintf(WPME::$newsTemplate, $this->from, $this->to, time(), $matches[1][0], date('Y-m-d'), $uri);
            return $res;
        }

    我们可以看到,我们的一般命令将返回图文信息。而图文信息的模板格式也请参考微信文档。这里我们并不进行任何实质性的处理,真正的内容渲染我们在另外一个站点:https://rsywx.net 中进行。

    rsywx.net是一个之前我单独开发的站点,考虑到微信使用的一些功能可以在该站点中复用,所以我将微信需要的返回信息的功能(控制、数据、呈现)放在这里实现。这个站点用Symfony完成。其实,我这个微信号最本质的内容呈现逻辑都是在rsywx.net中完成的。

    我们看一个indexAction方法。这个方法接受来自weixin.rsywx.com的调用,并根据不同的关键字进行处理:

    public function indexAction($key)
        {
            $entity = substr($key, 0, 4);
            if ($entity == 'wpme')
            {
                if ($key == 'wpme1' || $key == 'wpme7')
                {
                    $uri = http://api/$entity/$key;
                    $res = json_decode(file_get_contents($uri))->out;
                    $theme = $this->container->getParameter('theme');
                    return $this->render(AppBundle:$theme/wechat:$key.html.twig, ['res' => $res->res]);
                }
                else //The key is like wpme????, where ???? is the search term
                {
                    $search = substr($key, 4);
                    $uri = http://api/$entity/s/$search;
                    $res = json_decode(file_get_contents($uri))->out;
                    $theme = $this->container->getParameter('theme');
                    return $this->render(AppBundle:$theme/wechat:wpme7.html.twig, ['res' => $res->res]);
                }
            }
        }

    如果从weixin传来的命令是wpme1(列出最新的单词)或者wpme7(列出7个最新的单词),那么rsywx.net将进一步调用http://api.rsywx.com 中相应的RESTful API接口获得数据并渲染;如果是类似wpme????这样的命令,那么将进行搜索,并将结果返回。

    最后我们来看http://api.rsywx.com ,如果我们直接访问这个站点,将会呈现该站点所提供的所有接口的API文档:

    Ashampoo_Snap_2016.02.01_20h46m03s_002_Chrome

    而在这个站点中,我同样用Silex框架实现了对应的方法来返回数据(实际上,rsywx.net的所有数据也都是由该站点提供的)。

    好了,如果你现在在公众号中输入这样的一个命令:wpme1,你将看到如下的界面:

    Screenshot_20160201-205011

    Screenshot_20160201-205018

    怎么样?是不是很酷?

    本文收录于[go4pro.org]

  • 学习了JavaScript中的reduce

    之前一直没有认认真真地学习JavaScript(https://en.wikipedia.org/wiki/ECMAScript),因为一直只是将它作为在Web中进行编程,进行动态效果呈现的一个辅助脚本(我用jQuery比较多,还用过一段时间的Dart)。

    这两天因为脚扭了在家里休息了几天,随手拿起《Eloquent JavaScript》就看几段,就顺手学习了一下JavaScript中的reduce。

    完整的说明在这里

    按照定义,reduce对一个数组中的每个元素进行一个类似于“累加”的操作,将其规整到一个单一值。 它的完整语法如下:

    arr.reduce(callback[, initialValue])

    而其中的callback函数,又可以最多有四个参数:

    • previousValue
    • currentValue
    • index
    • array

    我们先看一个对数组中所有元素求和的例子:

    var total = [0, 1, 2, 3].reduce(
        function(sum, current) {
            return sum+current;
        });
    // total == 6

    这是一个非常直观的例子。 计算机程序求和总是用一个循环的方式。所以,“和”会保存在一个变量中,然后顺序一个元素一个元素的相加。

    注意,由于我们没有给出initialValue,所以在第一次运行时,sum(作为previousValue)就会取数组的第一个数值0,而此时的currentValue就会是数组的第二个元素1。在这个程序中,这么做当然是没有问题的。 我们可以将这个程序等价地写作:

    var total = [0, 1, 2, 3].reduce(
        function(sum, current) {
            return sum+current;
        }, 0);
    // total == 6

    此时我们显式地给予初始值为0(求和当然是如此),得到的结果是一致的。

    第二个例子是将多维数组“压扁”成一维数组。这也可以用reduce来完成。

    var arr=[[1,2,3],[4,5],[6,1]];
    var x=arr.reduce(
      function(flat, current)
      {
        return flat.concat(current);
      }, [])
    );

    这里必须给定initialValue。

    本文收录于[go4pro.org]

  • PHP 7已经来临(一)

    PHP界最近最热门的消息就是:PHP 7已经来临!Sitepoint的Bruno适时地写了一篇文章,列出了一些资源和回顾。 我用百度搜索了一下国内的相关内容,发现相关的讨论还是非常非常少。所以觉得有必要结合我的实践,写点东西,以求推动国内的PHP7的落地。

    (more…)

  • Vagrant虚拟机中apt-get的翻墙

    用Vagrant安装虚拟机不是什么麻烦的事。这次我装了一个虚拟机后,准备用这台虚拟机学习一下HHVM。

    按照HHVM官方的文档,其实是很简单的。但是只有一个问题:HHVM的仓库地址(http://dl.hhvm.com)被墙。所以……我们只能用翻墙的方式。

    (more…)

  • BitTorrent Sync 2.0正式发布

    2013年4月份的时候,我推荐过BitTorrent Sync这个同步软件大杀器(文章链接)。当时这个软件还在很初期的阶段。

    今天,它已经正式发布了2.0。下载地址:http://www.getsync.com/platforms/desktop。还有移动版本和特殊硬件版本。

    (more…)

  • Elevate使用心得

    Elevate真的是一个很强大的英语训练软件。我已经连续每天受训达43天了。想想为了保持脑子清爽,延缓得老年痴呆的节奏,我也是蛮拼的。

    ks_93365

    (more…)

  • 解决git push时出现的https错误

    (本文收录于[go4pro.org])

    这两天更新了一点我的“任氏有无轩“站点,结果发现无论是使用命令行的git还是SourceTree,都无法push到远程repo,出现错误如下:

    Ashampoo_Snap_2014.07.26_09h38m21s_001_

    在网上查了一下,基本上都指向Windows搜索一个DLL——本例中是libcurl.dll——的路径优先问题。

    (more…)

  • PHP开发者经常会犯的另外7个错误

    本文原始链接:7 More Mistakes Commonly Made by PHP Developers。作者:Bruno Skvorc

    Thanks for Sitepoint.com authorization for translation and publication in my blog.

    本文翻译力求忠实原始文档。

    (more…)

  • Dart 1.5.3的一些变化

    Ashampoo_Snap_2014.07.15_22h13m10s_003_

    Dart是一个发展非常快速的语言。如今最新的版本是1.5.3。自从今年1月份我写了两篇关于Dart的文章()以来,Dart语言本身,尤其是我用到的Polymer部分,有了很大的变化。

    为了准备8月9日(暂定)于苏州举行的,由G4P.ccGDG Suzhou联合举办的活动,我对之前编写的Dart小程序进行了调试。本文就在这次调试中发现的变化进行一些总结。

    (more…)