分类 Webman 下的文章

/**
 * 下划线转驼峰
 * @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;
}

目前我用phpspeadsheet导出excel文件,是存为文件然后再respon的。 有没有方法直接输出而不用输出实体文件?
$writer = new Xlsx($spreadsheet);
$response = response();
ob_start();
$writer->save('php://output');
$c = ob_get_contents();
ob_flush();
flush();
$response->withHeaders([
    'Content-Type' => 'application/vnd.ms-excel',
    'Content-Disposition' => 'attachment;filename="xxx.xlsx"',
    'Cache-Control' => 'max-age=0',
])->withBody($c);
return $response;

转自:https://www.workerman.net/q/9070

方案一

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

直接上代码

<?php
namespace app\controller;

use support\Request;
use support\Response;
use Yansongda\Pay\Pay;

class Payment
{
    protected $config = [
        'alipay' => [
            'default' => [
                // 必填-支付宝分配的 app_id
                'app_id' => 'wx4926de289f70b113',
                // 必填-应用私钥 字符串或路径
                'app_secret_cert' => 'MIIEvLoLc1s/VdBHku+JEd0YmEY+p4sjmcRnlu4AlzLxkWUTTg==',
                // 必填-应用公钥证书 路径
                'app_public_cert_path' => '/Users/yansongda/pay/cert/appCertPublicKey_2016082000295641.crt',
                // 必填-支付宝公钥证书 路径
                'alipay_public_cert_path' => '/Users/yansongda/pay/cert/alipayCertPublicKey_RSA2.crt',
                // 必填-支付宝根证书 路径
                'alipay_root_cert_path' => '/Users/yansongda/pay/cert/alipayRootCert.crt',
                'return_url' => 'https://yansongda.cn/alipay/return',
                'notify_url' => 'https://yansongda.cn/alipay/notify',
                // 选填-第三方应用授权token
                'app_auth_token' => '',
                // 选填-服务商模式下的服务商 id,当 mode 为 Pay::MODE_SERVICE 时使用该参数
                'service_provider_id' => '',
                // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
                'mode' => Pay::MODE_NORMAL,
            ]
        ],
        'wechat' => [
            'default' => [
                // 必填-商户号,服务商模式下为服务商商户号
                'mch_id' => '123xxxx02',
                // 必填-商户秘钥
                'mch_secret_key' => 'xxxxx',  //api安全中心里的V3密码32位的那个
                // 必填-商户私钥 字符串或路径
                'mch_secret_cert' => '/xxxxx/apiclient_key.pem',  //api安全中心里下载的的密钥,绝对路径
                // 必填-商户公钥证书路径
                'mch_public_cert_path' => '/xxxx/apiclient_cert.pem', //api安全中心里下载的公钥,绝对路径
                // 必填
                'notify_url' => 'https://www.xxx.com/member/wx_native_notify', //支付回调地址必须https
                // 选填-公众号 的 app_id
                'mp_app_id' => 'wx4926de289f70b113',
                // 选填-小程序 的 app_id
                'mini_app_id' => '',
                // 选填-app 的 app_id
                'app_id' => '',
                // 选填-合单 app_id
                'combine_app_id' => '',
                // 选填-合单商户号
                'combine_mch_id' => '',
                // 选填-服务商模式下,子公众号 的 app_id
                'sub_mp_app_id' => '',
                // 选填-服务商模式下,子 app 的 app_id
                'sub_app_id' => '',
                // 选填-服务商模式下,子小程序 的 app_id
                'sub_mini_app_id' => '',
                // 选填-服务商模式下,子商户id
                'sub_mch_id' => '',
                // 选填-微信公钥证书路径, optional,强烈建议 php-fpm 模式下配置此参数
                'wechat_public_cert_path' => [
                    '4248DC46520F9EAC26C7FET4464ADBE5ADDA3A' => '/xxxx/wechatpay_public.pem', //通过算法生成的,具体生成方式往下面看。
                ],
                // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
                'mode' => Pay::MODE_NORMAL,
            ]
        ],
        'logger' => [
            'enable' => false,
            'file' => './logs/alipay.log',
            'level' => 'info', // 建议生产环境等级调整为 info,开发环境为 debug
            'type' => 'single', // optional, 可选 daily.
            'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
        ],
        'http' => [ // optional
            'timeout' => 5.0,
            'connect_timeout' => 5.0,
            // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
        ],
    ];

    //二维码生成展示页
    public function index(Request $request)
    {
        Pay::config($this->config);

        $order = [
            'out_trade_no' => time().'',
            'description' => 'subject-测试',
            'amount' => [
                'total' => 1,
            ],
        ];

        $result = Pay::wechat()->scan($order);
        // 二维码内容: $qr = $result->code_url;
        //var_export($result->code_url);

        return view('payment/index', ['code_url' => $result->code_url]);
    }

    //支付成功回调
    public function verify(Request $request)
    {
        Pay::config($this->config);

        // 是的,你没有看错,就是这么简单!
        $result = Pay::wechat()->callback($request->post());
        file_put_contents(__DIR__ . '/notify_result_ysd.txt',
            date('Y-m-d H:i:s') . ':' . var_export($result, true));
        

        //这里很关键,需要注意。
        return new Response(200, [], json_encode(['code' => 'SUCCESS', 'message' => '成功']));
    }
}

微信支付平台证书下载:

http://www.liziyu.com/archives/309/

话不多说直接上代码:

// app\member\controller\pay.php

<?php

namespace app\controller;

use EasyWeChat\Kernel\Exceptions\Exception;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use support\Request;
use EasyWeChat\Pay\Application;
use Symfony\Component\HttpFoundation\HeaderBag;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;

class Index
{
    private $config = [
        'mch_id' => 'xxxx', //根据自已实际的填写
        // 商户证书
        'private_key' => '/xxx/apiclient_key.pem',//根据自已实际的填写,绝对路径
        'certificate' => '/xxx/apiclient_cert.pem', //根据自已实际的填写,绝对路径
        // v3 API 秘钥
        'secret_key' => 'xxxx', //根据自已实际的填写
        // v2 API 秘钥
        'v2_secret_key' => 'xxx', //根据自已实际的填写
        'platform_certs' => [
            '/xxx/wechatpay_public.pem', //根据自已实际的填写,获取办法见下面。
        ],
        'http' => [
            'throw' => true, // 状态码非 200、300 时是否抛出异常,默认为开启
            'timeout' => 5.0,
            // 'base_uri' => 'https://api.mch.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用,根据不同的模块配置不同的 uri
        ],
    ];

    //二维码生成展示页
    public function index(Request $request)
    {
        try {
            $app = new Application($this->config);
            $response = $app->getClient()->post('/v3/pay/transactions/native', [
                'json' => [
                    'mchid' => (string)$app->getMerchant()->getMerchantId(),
                    'out_trade_no' => 'SN_'.time(),
                    'appid' => 'xxxx', //根据自已实际的填写
                    'description' => '测试内容',
                    'notify_url' => 'https://www.xxxx.com/member/wx_native_notify', //注意是ssl协议
                    'amount' => [
                        'total' => 2,
                        'currency' => 'CNY',
                    ]
                ]
            ]);
        } catch (InvalidArgumentException $e) {
            //
        }
        return view('index/index', ['code_url' => $response->toArray()]);
    }


    //回调
    public function verify(Request $request)
    {
        try {
           //下面四行很关键
            $symfony_request = new SymfonyRequest($request->get(), $request->post(), [], $request->cookie(), [], [], $request->rawBody());
            $symfony_request->headers = new HeaderBag($request->header());
            $app = new Application($this->config);
            $app->setRequestFromSymfonyRequest($symfony_request);

            // $app 为你实例化的支付对象,此处省略实例化步骤
            $server = $app->getServer();
            
            // 处理支付结果事件
            $server->handlePaid(function ($message) {
                // $message 为微信推送的通知结果,详看微信官方文档
                file_put_contents(__DIR__ . '/notify_result.txt',
                    date('Y-m-d H:i:s') . ':' . var_export($message, true));
                
                // 微信支付订单号 $message['transaction_id']
                // 商户订单号 $message['out_trade_no']
                // 商户号 $message['mchid']
                // 具体看微信官方文档...
                // 进行业务处理,如存数据库等...

            });
            //这一步特别要注意,必须这么写。
            return $server->serve()->getBody()->getContents();

        } catch (Exception $e) {
            echo $e->getMessage();
        }
    }

}

“平台证书”申请办法:http://www.liziyu.com/archives/309/