分类 Laravel 下的文章

条件聚合

实际上有一种非常简单的方法可以查询计算这些总数。诀窍是将条件放在聚合函数中。下面是一个 SQL 示例:

select
  count(*) as total,
  count(case when status = 'confirmed' then 1 end) as confirmed,
  count(case when status = 'unconfirmed' then 1 end) as unconfirmed,
  count(case when status = 'cancelled' then 1 end) as cancelled,
  count(case when status = 'bounced' then 1 end) as bounced
from subscribers

 total | confirmed | unconfirmed | cancelled | bounced
-------+-----------+-------------+-----------+---------
   200 |       150 |          50 |        30 |      25

以下是在 Model 中使用查询构建器编写此查询:

$totals = DB::table('subscribers')
    ->selectRaw('count(*) as total')
    ->selectRaw("count(case when status = 'confirmed' then 1 end) as confirmed")
    ->selectRaw("count(case when status = 'unconfirmed' then 1 end) as unconfirmed")
    ->selectRaw("count(case when status = 'cancelled' then 1 end) as cancelled")
    ->selectRaw("count(case when status = 'bounced' then 1 end) as bounced")
    ->first();

<div>Total: {{ $totals->total }}</div>
<div>Confirmed: {{ $totals->confirmed }}</div>
<div>Unconfirmed: {{ $totals->unconfirmed }}</div>
<div>Cancelled: {{ $totals->cancelled }}</div>
<div>Bounced: {{ $totals->bounced }}</div>


与G银行对接时用到的

<?php
/**
 * Describe:
 * Author: liziyu
 * Date: 2022/10/31 11:10 AM
 */

namespace App\encrypt;

class MD5WithRSA
{
    /**
     * 利用约定数据和私钥生成数字签名
     * @param $data 待签数据
     * @return String 返回签名
     */
    public function sign($data='')
    {
        if (empty($data))
        {
            return false;
        }
        $private_key="MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgE==";
        $private_key = chunk_split($private_key, 64, "\n");
        $private_key = "-----BEGIN PRIVATE KEY-----\n$private_key-----END PRIVATE KEY-----";

        if (empty($private_key))
        {
            echo "私钥为空";
            return false;
        }
        // 生成密钥资源id
        $private_key_resource_id = openssl_get_privatekey($private_key);
        if (empty($private_key_resource_id))
        {
            echo "私钥资源id为空";
            return false;
        }

        $verify = openssl_sign($data, $signature, $private_key_resource_id, OPENSSL_ALGO_MD5);
        openssl_free_key($private_key_resource_id);
        // 二次Base64编码
        return base64_encode(base64_encode($signature));
    }

    /**
     * 利用公钥和数字签名以及约定数据验证合法性
     * @param string $data 待验证数据
     * @param string $signature 数字签名
     * @return  -1 验证错误;0 验证失败;1 验证成功
     */
    public function isValid($data='', $signature='')
    {
        if (empty($data) || empty($signature))
        {
            return false;
        }

        $public_key ="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB";
        $public_key = chunk_split($public_key, 64, "\n");
        $public_key = "-----BEGIN PUBLIC KEY-----\n$public_key-----END PUBLIC KEY-----";

        if (empty($public_key))
        {
            echo "公钥为空";
            return false;
        }
        // 生成密钥资源id
        $public_key_resource_id = openssl_get_publickey($public_key);
        if (empty($public_key_resource_id))
        {
            echo "公钥资源id为空";
            return false;
        }

        // 对签名进行二次Base64解码
        $signature=base64_decode(base64_decode($signature));
        $ret = openssl_verify($data, $signature, $public_key_resource_id, OPENSSL_ALGO_MD5);
        openssl_pkey_free($public_key_resource_id);
        return $ret;
    }
}

微信小程序获取客户端手机号码,踩的坑。如下提示:

{"errcode":47001,"errmsg":"data format error hint: [6kMDxSDNRa-hAwqia] rid: 6308d1b5-69935bc9-1d99d19f"}

protected function getPhoneNo($code): string
    {
        try {
            $accessToken = $this->getAccessToken();
            if($accessToken) {
                //POST https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN
                $client = new Client();
                $url = config('mini.get_phone_number');
                $req = $client->post("$url?access_token={$accessToken}", [
                    'json' => [
                        'code' => $code
                    ]
                ]);
                var_export($req->getBody()->getContents());
            }
        } catch (\Throwable | \Exception $e) {
            return $e->getMessage();
        }
    }

这里需要注意的是,post请求时,格式需要用json格式,不能用body格式,即:

正确:

'json' => [
    'code' => $code
]

错误:

'form_params' => [
    'code' => $code
]


先理解几个概念:

1.StdClass 对象 => 基础的对象
2.Eloquent 模型对象 (Model 对象) => 和模型相关的类对象
3.Eloquent 集合 => 可以简单理解为对象数组,里面的每一个元素都是一个 Model 对象

DB Facades

1.$users = DB::table('users')->get(); 返回值:数组结果,其中每一个结果都是 StdClass
2.$user = DB::table('users')->first();返回值:单个 StdClass 实例

Eloquent

1.$user = User::first(); 返回值:Eloquent 对象 `
2.$user = User::find(); 返回值:Eloquent 对象 `
3.$users = User::get(); 返回值:Eloquent 集合
4.$users = User::all(); 返回值:Eloquent 集合
5.$user = User::create($data); 返回值:Eloquent 对象
6.$user = new User(); $user->name = "admin" $user->save(); 返回值:Eloquent 对象
7.$result = User::insert($data); 返回值:bool
8.$result = $user->delete(); 返回值:bool
9.$count = User::destroy([1, 2]); 返回值:删除记录数
10.$count = User::where('id', '>', 1)->delete(); 返回值:删除记录数
11.$count = User::where('id', '>', 10)->update(['status' => 1]);返回值:更新记录数
12.$count = User::where('id', '>', 10)->increment('age', 1);返回值:更新记录数

纯粹为了查阅方便,作者辛苦了!本文转自:
https://learnku.com/articles/15654/laravel-return-value

/**
 * 下划线转驼峰
 * @param $str
 * @return null|string|string[]
 */
public static function lineToHump($str)
{
    $str = preg_replace_callback('/([-_]+([a-z]{1}))/i', function ($matches) {
        return strtoupper($matches[2]);
    }, $str);
    return $str;
}

/**
 * 驼峰转下划线
 * @param $str
 * @return null|string|string[]
 */
public static function humpToLine($str)
{
    $str = preg_replace_callback('/([A-Z]{1})/', function ($matches) {
        return '_' . strtolower($matches[0]);
    }, $str);
    return $str;
}

方案一

Casbin的核心-表.png

Casbin的核心.png

方案二

111.JPG
原理

222.JPG
规则

333.JPG
数据ER

444.PNG
管理UI

555.JPG
数据表实例

特别声明:其中方案二为某大佬线上生产环境系统设计,如果侵犯到此权限请通知我删除,同时采纳者一同承担相应责任。

评论表

idarticle_idparent_id(string)
130
231
331_2
432
531_2_3

模型操作

删除 id = 1 的1 级文章及下级所有文章
Article::where('id', 1)->delete();
Article::where('parent_id', 'like', '1%')->delete();
这样和 id = 1 的所有相关文章就删除了
删除这些文章下的评论就用观察者就行了



第一步:

习惯将CDN文件下载到本地,保存至静态目录中,注意保留版本号。

<!-- 引入 css -->
<link href="https://cdn.jsdelivr.net/npm/@wangeditor/editor@latest/dist/css/style.css" rel="stylesheet">
<!-- 引入 js -->
<script src="https://cdn.jsdelivr.net/npm/@wangeditor/editor@latest/dist/index.min.js"></script>

第二步:

直接上 HTML代码吧:

<div class="layui-row">
            <div class="layui-col-md12">
                <div class="layui-form-item">
                    <label class="layui-form-label">正文:</label>
                    <div class="layui-input-block">
                        <textarea name="content" id="content" style="display: none"></textarea>
                        <div id="toolbar-container"></div>
                        <div id="editor-container" style="height: 300px;border:1px solid #dddddd"></div>
                    </div>
                </div>
            </div>
        </div>


第三步:

注意从官方拷贝js代码时,要注意javascript与typescript的修改。
直接上 JS代码。

// 渲染富文本编辑器
const { createEditor, createToolbar } = window.wangEditor;
// 编辑器配置
const editorConfig = {MENU_CONF: {}};
// 图片上传
editorConfig.MENU_CONF['uploadImage'] = {
    // 表单字段名称
    fieldName: 'file',
    // 单个文件的最大体积限制,默认为 2M
    maxFileSize: 5 * 1024 * 1024, // 5M
    // 最多可上传几个文件,默认为 100
    maxNumberOfFiles: 5,
    // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
    allowedFileTypes: ['image/*'],
    // 小于该值就插入 base64 格式(而不上传),默认为 0
    base64LimitSize: 5 * 1024, // 5kb
    // 自定义参数
    meta: {
        from: 'editor', //标志是从编辑器上传
    },
    // 上传图片的配置
    server: '<?=route("upload.image")?>',
};
// 默认提示文字
editorConfig.placeholder = '请输入内容'
editorConfig.onChange = (editor) => {
    // 当编辑器选区、内容变化时,即触发
    //console.log('content', editor.children)
    //console.log('html', editor.getHtml())
    document.getElementById('content').value = editor.getHtml();
}


// 工具栏配置
const toolbarConfig = {}

// 创建编辑器
const editor = createEditor({
    html: document.getElementById('content').value,
    selector: '#editor-container',
    config: editorConfig,
    mode: 'simple' // 或 'simple' 参考下文
})
// 创建工具栏
const toolbar = createToolbar({
    editor,
    selector: '#toolbar-container',
    config: toolbarConfig,
    mode: 'simple' // 或 'simple' 参考下文
})

最后:

截图如下。

333333.png