Write the Code. Change the World.

分类目录
2月 13

安装 laravel mix

Laravel Mix 一款前端任务自动化管理工具,使用了工作流的模式对制定好的任务依次执行。Mix 提供了简洁流畅的 API,让你能够为你的 Laravel 应用定义 Webpack 编译任务。Mix 支持许多常见的 CSS 与 JavaScript 预处理器,通过简单的调用,你可以轻松地管理前端资源。

使用 Mix 很简单,首先你需要使用以下命令安装 npm 依赖即可。我们将使用 Yarn 来安装依赖,在这之前,因为国内的网络原因,我们还需为 Yarn 配置安装加速:

继续阅读

1月 08

MVP 是 Minimum Viable Prodcut (最小化可行性产品)的简称

1月 05

快捷键

常用快捷键,记住几个就好很多了。在 mac 中, cmd 对应 command,alt 对应 option。

cmd + p 快速打开文件或查找打开文件

control + ‘ (同~) 打开关闭控制台

shift+cmd+k 删除一行

shift+alt+down 向下复制一行

shift+alt+up 向上复制一行

cmd + d 显示选中的内容

alt + up 向上移动一行

alt + down 向下移动一行

cmd + b 侧边栏的隐藏与显示

插件的快捷键

cmd + alt + n 创建文件

mac 下,使用命令启动当前项目

打开 vscode,打开控制面板(⇧⌘P),输入 shell command,在提示里看到 Shell Command: Install ‘code’ command in PATH,运行它就可以了。

然后就可以了。

code . # 打开当前文件夹项目
code readme.md # 打开当前文件

安装插件

Auto Rename Tag
  自动重命名配对的HTML / XML标签

Auto Close Tag
  自动添加 HTML/XML 的闭合标签

Color-Highlight
  在编辑器中高亮显示颜色。

Color Picker
  代码的颜色选择器。

Guides
  代码的标签对齐线。

Bracket Pair Colorizer
  让括号拥有独立的颜色,易于区分。可以配合任意主题使用。

vetur
  vue项目语法高亮、智能感知、Emmet等。

Laravel Blade Snippets
  Laravel blade 代码片段和语法高亮支持 Visual Studio。

PHP Intellisense Crane
  Crane 是 Visual Studio Code 的生产力增强扩展,提供了 PHP 代码的自动完成。它具有零依赖性,并可以极大程度地工作于任何规模的项目里。它仍在开发中,可能存在 Bug 或缺失某些功能。。

Laravel goto view
  从controller进入view。

php intelephense
  php 语法提示工具。

advanced-new-file
  快捷创建文件、文件夹。

Bootstrap 4 & Font awesome snippets
  bootstrap4和font awesome 快速引用和代码生成。。

12月 10

虽然,mariadb 可以替代 mysql,但某些函数,mariadb 是没有的。比如,ST_Distance_Sphere 。当然,mariadb 拥有的函数 mysql 也不一定有。

请参考:
https://mariadb.com/kb/en/library/function-differences-between-mariadb-102-and-mysql-57/

https://mariadb.com/kb/en/library/mysqlmariadb-spatial-support-matrix/

看着 ST_Distance_Sphere 很好用,却不能用。那也没办法,可以试试 ST_DISTANCE 函数。

eg:

select ST_Distance_Sphere(ST_GeomFromText(‘Point(115.452081 30.486021)’), position) as distance from ball_invitations

select (ST_Distance(GeomFromText(‘Point(115.452081 30.486021)’), position) / 0.0111195) as distance from ball_invitations

参考

https://mariadb.com/kb/en/library/st_distance/

https://dev.mysql.com/doc/refman/5.7/en/spatial-convenience-functions.html

http://www.innomysql.com/mysql_gis_lbs/

https://blog.csdn.net/zhouzhiwengang/article/details/53612481

10月 11

  1. 去除镜像
composer config -g --unset repos.packagist
  1. 添加全局镜像(两个选一个)
composer config -g repo.packagist composer https://packagist.laravel-china.org

composer config -g repo.packagist composer https://packagist.phpcomposer.com
  1. 当前项目添加镜像
composer config repo.packagist composer https://packagist.laravel-china.org
  1. 查看镜像
composer config -l -g

娃哈哈

https://packagist.laravel-china.org/

https://pkg.phpcomposer.com/#how-to-use-packagist-mirror

10月 09

Laravel有非常强大的ORM,但是对于刚接触ORM的我来说,在理解上还是有点障碍的,开启打印SQL的功能能帮助更好的理解。

打印SQL默认是关闭的,需要在 /vendor/illuminate/database/Connection.php中打开。

protected $loggingQueries = true;

之后可在代码中使用了:


$res = User::where('id', 100)->first(); $log = DB::getQueryLog(); var_dump($log);

如果不想开启但需要临时查看,可以这样操作:

DB::connection()->enableQueryLog();

$res = User::where('id', 100)->first();

$log = DB::getQueryLog();
var_dump($log);

这样就这样。但是得到的语句与参数是分开的,不方便去观看以及使用。所以额外加了一个函数来处理这种情况。通常,我们会用到辅助函数类,可以放到这里。

function transSql($queries)
{
    if(!$queries)
        return FALSE;

    $sqls = [];
    foreach($queries as $query)
    {
        $sql = [
            'sql' => vsprintf(str_replace('?', '%s', $query['query']), $query['bindings']),
            'time' => $query['time']
        ];
        $sqls[] = $sql;
    }
    return $sqls;
}

使用:

DB::connection()->enableQueryLog();

$res = User::where('id', 100)->first();

$log = DB::getQueryLog();

$log = transSql($log);
var_dump($log);

这里的sql语句可能不止一条,通过查看sql的条数,可以看到查询的详细情况。

相关

https://laravel-china.org/articles/5166/quick-print-laravel-database-query-sql-statement

9月 27

场景

有一个海报,里边有美丽的画面,还有一些需要填充的地府。比如,往海报中添加一个二维码,或加一段文字。

但是,这些二维码和文字是动态的。方便推广宣传,合成图片就很有必要了。

就拿关注微信公众号这件是吧。微信公众号,可以生成带场景值的二维码。推广的时候,合成成一张海报就方便使用了。

图片处理用 imagick 库

imagick 功能比较强大,方便各种图片的操作。

php 使用 image intervention

http://image.intervention.io/api/destroy

使用 composer 安装

composer require intervention/image

实现细节

<?php

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use Image;

class ImageBuilderController extends Controller
{
    public function poster(Request $request)
    {
        $bg = 'static/image/group/groupbg.png';
        $description = '给你一个美丽的意外';
        $fonts = 'static/image/group/pingfang.ttf';

        $scene = $request->scene ? $request->scene : urlencode('xxxx');
        $avatar = $request->avatar ? $request->avatar : 'static/image/group/avatar.png';
        $nickname = $request->nickname ? $request->nickname : '神奇动物在哪里';
        $page = $request->page;

        $qrcode = $this->qrcode($scene, $page);
        $qrcodeImg = Image::make($qrcode)->resize(300, 300);
        $avatarImg = Image::make($avatar)->resize(100, 100);

        $image = Image::make($bg)->insert($qrcodeImg, 'bottom-left', 225, 196)
                                ->insert($avatarImg, 'bottom-left', 171, 511, function ($constraint) {
                                     $constraint->aspectRatio();
                                });

        $image->text($nickname, 288, 645, function($font) use ($fonts) {
            $font->file($fonts);
            $font->size(34);
            $font->color('#222');
        });

        $image->text($description, 288, 685, function($font) use ($fonts){
            $font->file($fonts);
            $font->size(24);
            $font->color('#888');
        });

        $folder = '/upload/image/wxapp/' . date('Ym', time()) . '/';
        $upload_path = public_path() . $folder;
        // 创建文件夹
        if (!file_exists($upload_path))
        {
            mkdir($upload_path, 0777, true);
        }
        $name = time() . '_' . str_random(10) . '.jpg';
        $image->save($upload_path . $name, 80);
        $image->destroy();

        return $this->response->array(['url' => url($folder . $name)])->setStatusCode(201);
    }

    private function qrcode($scene, $page)
    {
        $access_token = getAccessToken(env('WECHAT_MINI_PROGRAM_APPID'), env('WECHAT_MINI_PROGRAM_SECRET'));

        $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=$access_token";

        $params = ['scene' => $scene];
        if($page)
            $params['page'] = $page;

        $data = curl($url, json_encode($params), TRUE, TRUE);

        $check = json_decode($data);

        if($check && $check->errcode)
            return $this->response->errorUnauthorized($check->errmsg);

        return $data;
    }
}

9月 27

场景

要求用户给公众平台发一个消息 (特殊定义好的关键词语)时,公众号同时给用户返回多条消息。

然而,如果用公众号自己的回复能力,却只能回复一条,是不能实现的。那么,想要一次发几条消息怎么实现的呢。其实用客服消息功能就行

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547

先说说客服消息

公众平台官方文档已经有说明。

http请求方式: POST
https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN

利用客服接口,可以发送多条消息。一样可以发送文本,图片,语音,视频等消息。

接用户信息

接用户消息。

$postStr = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
if (!empty($postStr)) {
    libxml_disable_entity_loader(true);
    $msg = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
    if ($msg['Content'] === 'xxx') {
       // 如果关键字刚好是需要的 这个时候就可以用客服消息了。
       // 1. 获取accessToken
       // 2. 组织消息内容
       // 3. 发客服消息 1
       // 4. 发客服消息 2
       // 5. 发客服消息 3
       // ……
    }   
}



如果向上边这样操作,腾讯那边迟迟接不到回音,就会重复请求,这样就会重复发三次客服消息。下边就是解决方法。

在 获取 accessToken 之前,加入下边的代码。

    ignore_user_abort(true);
    ob_start();
    echo '';
    header('Connection: close');
    header('Content-Length: ' . ob_get_length());
    ob_end_flush();
    ob_flush();
    flush();

这样还不能解决问题的。

很傻很直接的办法

1, 消息进来,对消息数据进行观察。发现超时请求的数据格式一样。这样,我们可以知道该条消息的特征(FromUserName 和 CreateTime 组合成唯一识别key)。
2,对特殊关键字的消息做消息过滤。以 FromUserName 和 CreateTime 组合的值为key 作为 redis 的 key,先判断该 key 对应值是否存在,如果存在,表示是 超时过来的请求,请 echo ”; exit; 相应。如果不存在,建立一个 15 秒的 redis缓存即可。

    if($this->msg['Content'] == '领红包')
    {
    $key = $this->msg['FromUserName'] . $this->msg['CreateTime'];

    if(\Illuminate\Support\Facades\Redis::exists($key))
    {
    echo '';
    exit;
    }

    \Illuminate\Support\Facades\Redis::setex($key, 15, $this->msg['Content']);
    }

很傻很直接但有效。