Laravel将$fillable应用于update()

因为所有的 Eloquent 模型都默认不可进行批量赋值,而 $fillable 属性可以看作是批量赋值的“白名单”,定义了它就可以批量赋值了,但也只能应用于 create() 方法,如想要在 update() 方法中同样有效,须结合$request->only()与Eloquent模型的getFillable()一起使用:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $primaryKey = 'id';
    /**
     * 可以被批量赋值的属性。
     *
     * @var array
     */
    protected $fillable = ['name', 'avatar', 'job'];
}

用法举例:

$result = App\User::where('id', $id)->update($request->only((new App\User)->getFillable()));

svn使用post-commit实现自动部署,自动checkout,自动update(生产环境与svn服务处于同一服务器)

以admin.01h.net项目为例,仓库地址为:svn://01h.net/admin,生产环境目录为:/home/wwwroot/admin.01h.net,svn版本库目录为:/var/svn/admin。先进入svn版本库的hooks目录:

cd /var/svn/admin/hooks
cp post-commit.tmpl post-commit  //复制post-commit.tmpl 改名为post-commit
> post-commit  //清空内容
vi post-commit  //编辑文件

写入以下内容:

#!/bin/sh
export LANG=zh_CN.UTF-8
/usr/bin/svn update --username **** --password **** /home/wwwroot/admin.01h.net

其中第一行意思是用sh来解析这个脚本,因为各种shell的语法有细微的差别。
第二行是编码格式,这里使用的是UTF-8。
最后一行/usr/bin/svn 是svn可执行文件的路径,后半句分别是用户名、密码、和项目路径。

修改post-commit的可执行权限:

chmod 755 post-commit

进入项目目录/home/wwwroot/admin.01h.net,checkout整个项目。

cd /home/wwwroot/admin.01h.net
svn co svn://01h.net/admin .

Linux最常用操作:vim全选,全部复制,全部删除

全选(高亮显示):按esc后,然后ggvG或者ggVG
全部复制 :按esc后,然后ggyG
全部删除 :按esc后,然后dG

解析:
gg :是让光标移到首行,在vim才有效,vi中无效。
v :是进入Visual(可视)模式。
G :光标移到最后一行。

选中内容以后就可以其他的操作了,比如:
d :删除选中内容。
y :复制选中内容到0号寄存器。
“+y :复制选中内容到+寄存器,也就是系统的剪贴板,供其他程序用。

微信小程序客服消息AES解密问题

微信官方的demo下载地址:https://res.wx.qq.com/op_res/-serEQ6xSDVIjfoOHcX78T1JAYX-pM_fghzfiNYoD8uHVd3fOeC0PC_pvlg4-kmP

DEMO里面有php版本的加解密示例代码, 我们把文件名为 pkcs7Encoder.php 里面的解密代码列出来看看:

	/**
	 * 对密文进行解密
	 * @param string $encrypted 需要解密的密文
	 * @return string 解密得到的明文
	 */
	public function decrypt($encrypted, $appid)
	{

		try {
			//使用BASE64对需要解密的字符串进行解码
			$ciphertext_dec = base64_decode($encrypted);
			$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
			$iv = substr($this->key, 0, 16);
			mcrypt_generic_init($module, $this->key, $iv);

			//解密
			$decrypted = mdecrypt_generic($module, $ciphertext_dec);
			mcrypt_generic_deinit($module);
			mcrypt_module_close($module);
		} catch (Exception $e) {
			return array(ErrorCode::$DecryptAESError, null);
		}


		try {
			//去除补位字符
			$pkc_encoder = new PKCS7Encoder;
			$result = $pkc_encoder->decode($decrypted);
			//去除16位随机字符串,网络字节序和AppId
			if (strlen($result) < 16)
				return "";
			$content = substr($result, 16, strlen($result));
			$len_list = unpack("N", substr($content, 0, 4));
			$xml_len = $len_list[1];
			$xml_content = substr($content, 4, $xml_len);
			$from_appid = substr($content, $xml_len + 4);
		} catch (Exception $e) {
			//print $e;
			return array(ErrorCode::$IllegalBuffer, null);
		}
		if ($from_appid != $appid)
			return array(ErrorCode::$ValidateAppidError, null);
		return array(0, $xml_content);

	}

可以看出,解密代码使用了 mcrypt_module_open() 、 mcrypt_generic_init() 、 mdecrypt_generic() 这些mcrypt扩展函数,PHP7.1以后的版本已不再支持,要用openssl扩展中的 openssl_decrypt() 代替,可修改如下:

	/**
	 * 对密文进行解密
	 * @param string $encrypted 需要解密的密文
	 * @return string 解密得到的明文
	 */
	public function decrypt($encrypted, $appid)
	{

		try {
			//使用BASE64对需要解密的字符串进行解码
			$iv = substr($this->key, 0, 16);
            $decrypted = openssl_decrypt(base64_decode($encrypted), 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
        } catch (\Exception $e) {
			return array(ErrorCode::$DecryptAESError, null);
		}

		try {
			//去除补位字符
			$pkc_encoder = new PKCS7Encoder;
			$result = $pkc_encoder->decode($decrypted);
			//去除16位随机字符串,网络字节序和AppId
			if (strlen($result) < 16)
				return "";
			$content = substr($result, 16, strlen($result));
			$len_list = unpack("N", substr($content, 0, 4));
			$xml_len = $len_list[1];
			$xml_content = substr($content, 4, $xml_len);
			$from_appid = substr($content, $xml_len + 4);
		} catch (\Exception $e) {
			return array(ErrorCode::$IllegalBuffer, null);
		}
		if ($from_appid != $appid)
			return array(ErrorCode::$ValidateAppidError, null);
		return array(0, $xml_content);
	}

值得注意的是 openssl_decrypt() 的第四个参数使用了“OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING”,网上的其他教程大多使用“OPENSSL_RAW_DATA”参数,实测发现,使用“OPENSSL_RAW_DATA”参数会导致无法解密小程序卡片类型(即msg_type=miniprogrampage)的客服消息。

php将图片文件转成base64编码

/**
 * 获取图片的Base64编码(不支持url)
 * @date 2020-03-28
 * @param $img_file 传入本地图片地址
 * @param $type 是否带前缀, 1:带, 0:不带
 * @return array 0编码结果  1图片类型
 */
function imgToBase64($img_file, $type=1) {
    $img_base64 = '';
    if (file_exists($img_file)) {
        $app_img_file = $img_file; // 图片路径
        $img_info = getimagesize($app_img_file); // 取得图片的大小,类型等
        $fp = fopen($app_img_file, "r"); // 图片是否可读权限
        if ($fp) {
            $filesize = filesize($app_img_file);
            $content = fread($fp, $filesize);
            $file_content = chunk_split(base64_encode($content)); // base64编码
            switch ($img_info[2]) {           //判读图片类型
                case 1: $img_type = "gif";
                    break;
                case 2: $img_type = "jpg";
                    break;
                case 3: $img_type = "png";
                    break;
            }
			//合成图片的base64编码
            if($type){
				$img_base64 = 'data:image/' . $img_type . ';base64,' . $file_content;
			}else{
				$img_base64 = $file_content;
			}
        }
        fclose($fp);
    }
    return array($img_base64, $img_type);  //返回图片的base64及图片类型
}
//用法
$result = imgToBase64('/www/html/ken.01h.net/xxx.png');
//解码
$base64_string = explode(',', $result[0]); //截取data:image/png;base64, 这个逗号后的字符
$data = base64_decode($base64_string[1]);  //对截取后的字符使用base64_decode进行解码
file_put_contents('/www/html/ken.01h.net/yyy.'.$result[1], $data); //写入文件并保存