PHP

导出excel

进入项目根目录,composer 安装

cd /www/wwwroot/dgtapi/
php73 /usr/bin/composer require mk-j/PHP_XLSXWriter

composer报错

图片.png

降级

composer selfupdate --1
composer install

laravel验证参数

public function zhangyidebug()
    {
        //待验证的数据
        $data = [
            'a'=>123,
            'b'=>'',
            'c'=>null,
            'd'=>0,
            'e'=>false,
            'f'=>'hello',
            'g'=>'阿萨德,分为软',
            'h'=>999999999
        ];
        //验证规则 ,key(要验证的字段) => value(字段需要满足的规则)
        $rules = [
            'a'=>'required|numeric',
            'b'=>'required',
            'c'=>'required',
            'd'=>'required',
            'e'=>'required',
            'sort'=>'sometimes|numeric', //数组中该字段存在时就验证
            'ison'=>'nullable|numeric',//字段可为空, 不为空的时候必须是数字


        ];
        //验证失败的错误提示 , key(规则) => value(规则不满足时的提示)
        $messages = [
            'required' => '错误 :attribute 必填',
            'numeric' => '你输入的 :attribute 不是数字'
        ];
        //字段名 , key(字段) => value(字段的中文名)
        $customAttributes = [
            'a' => '第一个字段',
            'b' => '第二个字段',
            'c' => '第三个字段',
            'd' => '第四个字段',
        ];
        $validator = Validator::make($data, $rules,$messages,$customAttributes);
        if ($validator->fails()){
            $errorMessage = $validator->errors()->first();//拿到第一个错误
            dd($errorMessage);
        }
        //TODO 验证通过 正常业务流程

    }

laravel框架自带,可用验证规则列表

--end--

laravel中使用ide-helper为model生成字段注释

php artisan ide-helper:models - 为数据模型生成注释

导出csv

<?php


namespace App\Libs;


class CSVExport
{
    /** @var null 查询 MYSQL得到的生成器 */
    private $generator = null;
    /** @var array 表头 */
    private $tableHeader = array();
    /** 表头中的字段名 @var array */
    private $tableHeaderFiledName = array();
    /** 表头中的输出显示汉字 @var array */
    private $tableHeaderFiledNameDesc = array();
    /** 下载的文件名,不带后缀 @var string */
    private $fileName = '';
    /** 字段转换的.回调函数 @var null */
    private $convert = null;
    /** 直接下载@ var bool */
    private $directDownload = true;
    /** 脚本超时时间 @var int */
    private $timeout = 300;

    /**
     * CSVExport constructor.
     *
     * @param          $generator
     * @param array    $tableHeader 表头,一维数组['field_name'=>'要展示的文字']
     * @param string   $fileName    下载时的文件名, 不含后缀
     * @param callable $convert     回调函数, 用来处理某些字段
     */
    public function __construct ($generator, $tableHeader , $fileName = '' , $convert = null)
    {
        $this->generator                = $generator;
        $this->tableHeader              = $tableHeader;
        $this->tableHeaderFiledName     = array_keys($tableHeader);
        $this->tableHeaderFiledNameDesc = array_values($tableHeader);
        $this->fileName                 = $fileName ? $fileName : md5(time());
        $this->convert                  = $convert;
    }

    /**
     * @return float|int
     */
    public function getTimeout ()
    {
        return $this->timeout;
    }

    /**
     * @param float|int $timeout
     */
    public function setTimeout ($timeout)
    {
        $this->timeout = $timeout;
    }

    /**
     * 执行查询导出操作
     */
    function doExport(){
        set_time_limit($this->timeout);//超时限制
        // 向浏览器发送 http 下载头
        $this->sendHTTPHeader($this->fileName);
        echo $this->tableHeaderDescImplode(); //表头

        //遍历生成器, 发送数据
        foreach ($this->generator as $data) {
            $data = get_object_vars($data);
            if ($this->convert){
                $data = call_user_func($this->convert,$data);
            }
            echo $this->dataFieldImplode($data);
        }
    }
    /**
     * 拼接表头
     * @return string 逗号分割的表头字符串
     */
    private function tableHeaderDescImplode(){
        $str = implode("\t,", $this->tableHeaderFiledNameDesc);
        return $str.PHP_EOL;
    }
    /**
     * 按照表头字段,从结果集取出对应的字段,拼接
     * @param array $data 数据库结果集, 一维数组
     *
     * @return string 拼接后的字符传
     */
    private function dataFieldImplode($data){
        $str = '';
        foreach ($this->tableHeaderFiledName as $field){
            $str .= $data[$field]."\t,";
        }
        return rtrim($str,',').PHP_EOL;
    }
    /**
     * 发送http下载header
     *
     * @param $fileName
     */
    private function sendHTTPHeader($fileName){
        header("Cache-control: private");
        header("Pragma: public");
        header('Content-type: application/x-csv');
        header("Content-Disposition:attachment;filename=" . $fileName. ".csv");
    }
}

调用

$query = "select * from skyshop_member limit 10000 ";
        $generator = DB::connection()->cursor($query);

        $tableHeader = [
            'id'=>'序号',
            'full_name'=>'全名'
        ];
        $fileName = 'csv导出测试';
        $callable = function($data){
            if($data['id'] == 1){
                $data['id'] = 'yi';
            }
            return $data;
        };
        $CSVExport = new CSVExport($generator, $tableHeader, $fileName,$callable);
        $CSVExport->doExport();

图片上传oss

前端通过form表单enctype="multipart/form-data"直接上传文件,PHP可以在$_FILES中接收.直接传到阿里OSS服务器
现在前端把图片转成base64(字符串)上传,没法用$_FILES接收

解决方案

步骤1. 输出到本地
步骤2. 上传到OSS服务器,得到url
步骤3. 删除本地文件

/**
     * 上传base64图片到OSS服务器
     * @param string $imageBase64 从前端接收到的图片资源
     * @param string $serviceDir 想要保存在OSS服务器上的目录
     *
     * @return string 图片在OSS服务器上的地址
     */
    public function uploadImageBase64($imageBase64,$serviceDir){
        $URL = '';
        /** 得到文件后缀 */
        //data:image/png;base64,iVBORw0KGgoA..
        list($head,$image_data) = explode(',',$imageBase64); // head = data:image/png;base64 image_data = iVBORw0KGgoA..
        list($type,) = explode(';',$head);// type = data:image/png
        list(,$suffix) = explode('/',$type);// suffix = png

        /** 步骤1. 输出到本地 */
        $localDir = $_SERVER['DOCUMENT_ROOT'].'/Temp';
        $localFilename = $this->makeUUID().'.'.$suffix;
        file_put_contents($localDir.'/'.$localFilename,base64_decode($image_data));

        /** 步骤2. 上传到OSS服务器,得到url */
        try{
            //$this->oss_client->uploadFile 是阿里提供的PHP-SDK中的方法
            $response = $this->oss_client->uploadFile($this->bucket,$serviceDir.'/'.$localFilename,$localDir.'/'.$localFilename);
            $URL = $response['info']['url'];
        }catch (\Exception $e){
            Log::write('文件上传错误:'.$e->getMessage());
            $URL = '';
        } finally {
            /** 步骤3. 删除本地文件 */
            unlink($localDir.'/'.$localFilename);
            return $URL;
        }
    }

生成uuid方法

/**
     * 生成uuid (8-4-4-4-12)
     * @return string
     */
    private function makeUUID(){
        $chars = md5(uniqid(mt_rand(), true));
        return substr ( $chars, 0, 8 ) . '-'
            . substr ( $chars, 8, 4 ) . '-'
            . substr ( $chars, 12, 4 ) . '-'
            . substr ( $chars, 16, 4 ) . '-'
            . substr ( $chars, 20, 12 );
    }

调用时只需要

$serviceDir = 'Uploads/driver_report';//OSS服务器上保存的位置
$obj = new myClass();
$url = $obj->uploadImageBase64($post['img1'],$serviceDir)

laravel 发送邮件

  1. env中配置发送方的账号密码
MAIL_DRIVER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=465
MAIL_USERNAME=171913904@qq.com
MAIL_PASSWORD=授权码在qq邮箱个人中心获取
MAIL_ENCRYPTION=ssl
  1. 生成一个mail类
    命令php73 artisan make:mail MailA
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class MailA extends Mailable
{
    use Queueable, SerializesModels;

    public $code;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($code)
    {
        //
        $this->code = $code;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->subject('邮件标题')->from('171913904@qq.com')->view('emails.mail_a');
    }
}

3 写一个blade模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Email Verification Code</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            margin: 0;
            padding: 0;
            font-size: 16px;
            line-height: 1.6;
        }
        .container {
            max-width: 600px;
            margin: 20px auto;
            padding: 20px;
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
        h1 {
            font-size: 24px;
            color: #333;
        }
        p {
            margin-bottom: 20px;
            color: #666;
        }
        strong {
            font-weight: bold;
        }
    </style>
</head>
<body>
<div class="container">
    <h1>您正在找回密码</h1>
    <p>Dear 用户</p>
    <p>您的验证码是: <strong>{{ $code }}</strong></p>
    <p>如果非您本人操作可忽略。(请勿回复本邮件)</p>
</div>
</body>
</html>

4 发送

Mail::to('接受者的邮箱')->send(new MailA(666666));

php中的索引不连续的关联数组 返给前端变成了对象

php中定义

    const typeList =
         [
            10 => '首页视频',
            20 => '教学视频',
            30 => '介绍视频',
        ];
浏览器接收到的.png

可以在js中处理 把对象转成数组

state.typeList = Object.entries(data.typeList).map(([key, value]) => ({
      key: parseInt(key, 10),
      value,
    }))
js处理完的结果.png

GPT对js代码的解释

详细解释

    Object.entries:
        Object.entries(typeListObject) 将对象的键值对转换为一个二维数组,其中每个元素是一个包含键和值的数组。
        例如,如果 typeListObject 是 { 1: '首页视频', 2: '教学视频', 3: '介绍视频' }
        则 Object.entries(typeListObject) 生成 [[1, '首页视频'], [2, '教学视频'], [3, '介绍视频']]。

    map:
        map 方法用于遍历数组中的每一个元素,并对每一个元素执行给定的函数,然后返回一个新数组。
        在这个例子中,map 函数接收一个回调函数作为参数。

    箭头函数:
        箭头函数的语法是 ([key, value]) => ({ key: parseInt(key, 10), value })。
        ([key, value]) 是解构赋值语法,表示将数组的第一个元素解构为 key,第二个元素解构为 value。
        parseInt(key, 10) 将字符串形式的键转换为整数。parseInt 函数的第二个参数 10 表示使用十进制进行解析。
        ({ key: parseInt(key, 10), value }) 返回一个新的对象,其键为 key 的整数形式,值为原始值。

为什么箭头函数 => 后要用括号 ()?

当你需要返回一个对象字面量时,必须用括号将对象括起来。
这是因为在箭头函数的语法中,大括号 {} 通常被解析为函数体的开始,而不是对象字面量的开始。
通过使用括号 (),可以明确告诉 JavaScript 引擎这里返回的是一个对象字面量,而不是一个函数体。

示例
需要括号的情况

如果你直接写对象字面量而不使用括号,JavaScript 会误解你的意图:

javascript

const getObject = () => { key: 'value' }; // 这样写是错误的

上面的代码会抛出一个错误,因为 JavaScript 会将大括号 {} 视为函数体的开始,而不是对象字面量。

正确的做法是使用括号将对象字面量括起来:

javascript

const getObject = () => ({ key: 'value' });

这样,JavaScript 就能正确地解析并返回一个对象字面量。

获取本年的12个月

<?php
// 获取当前年份
$currentYear = date("Y");

// 初始化一个数组来存储12个月的时间范围
$monthRanges = array();

// 循环12个月
for ($i = 1; $i <= 12; $i++) {
    // 获取当前月份的第一天
    $startDate = date("Y-m-01", strtotime("$currentYear-$i-01"));
    
    // 获取当前月份的最后一天
    $endDate = date("Y-m-t", strtotime("$currentYear-$i-01"));

    // 将时间范围添加到数组中
    $monthRanges[] = array(
        "start_date" => $startDate,
        "end_date" => $endDate
    );
}
dd($monthRanges);
图片.png

php 安装扩展

php有两个配置文件 , 以当前docker环境为例 ,安装的php版本是7.3.32

php pecl安装扩展

去网站搜索想要的扩展 https://pecl.php.net/
找到合适的版本 下载下来

linux 系统下载扩展 
cd ~
wget https://pecl.php.net/get/gmagick-2.0.5RC1.tgz

不用解压,直接使用pecl命令安装

pecl install gmagick-2.0.5RC1.tgz

出现
lease provide the prefix of GraphicsMagick installation [autodetect] :
直接回车
后续报错自行百度

php7.3 zip扩展

composer安装三方包时报错phpoffice/phpspreadsheet 1.10.1 requires ext-zip *

图片.png

zip扩展可以通过编译 ,php7.3为例 zip的扩展源码位置在/www/server/php/73/src/ext/zip目录
编译完成后得到文件
/www/server/php/73/lib/php/extensions/no-debug-non-zts-20180731/zip.so
在php.ini和php-cli.ini中分别加入

extension = /www/server/php/73/lib/php/extensions/no-debug-non-zts-20180731/zip.so

注意:
用composer安装三方扩展时 ,使用的是php-cli.ini ,

php-cli使用的配置文件.png

处理http请求的php-fpm的work进程使用的是php.ini

替换/删除 mysql某字段中的指定字符

图片.png
update 表名 set 字段名 = replace(字段名,'被替换的字符','替换为')

update member set headpic = REPLACE(headpic,':33380','')

替换为空字符 ,则删除了字段中的被替换的字符


图片.png

model时间格式化
解决laravel数据库取出的数据,created_at,updated_at字段,时间格式问题

    /**
     * 格式化时间
     * @param \DateTimeInterface $date
     * zhangyi [2022-12-12]
     * @return string
     */
    protected function serializeDate(\DateTimeInterface $date)
    {
        return $date->format('Y-m-d H:i:s');
    }

生成迁移文件

php artisan make:migration create_table_demo

执行单个迁移

php artisan migrate --path=database\migrations\2021_10_13_153021_create_jobs_table.php

回滚一步迁移

php artisan migrate:rollback --step=1

生成repository

php artisan core:model --table=users --name=User
php artisan core:model --table=

清除视图缓存

php artisan view:clear

创建命令行脚本

php artisan make:command 自定义名称(生成的文件名)

在app->console->commands目录内找到脚本文件 ,修改属性 $signature = '自定义名称'(脚本启动名称) ,在handle方法内写逻辑
启动脚本

php artisan 自定义名称($signature)

composer

更新指定的包composer u 包名

composer autoload使用

自己写的vendor包 ,应用到项目后 如何自动加载

  1. 类文件需要声明命名空间,并且根据规范 ,目录结构与命名控件对应
包的项目目录.png
  1. 在项目的composer.json中加入autoload相关内容 ,此处使用的psr-4规范
    composer.json.png

    "autoload": { "psr-4": { "utils\\": "./" } }
    解释:
    "psr-4"规范,具体百度
    "utils\\"自定义的顶级命名空间
    "./"对应的类文件路径
  2. 命令行执行composer dumpautoload -o 更新自动加载文件
    4.测试 可以正常执行
    图片.png

    说明:
    此处测试需要手动require_once __DIR__."/vendor/autoload.php";
    一般框架的index.php文件已经引入了autoload.php,所以框架项目中只需通过composer安装三方包 ,就能直接用.

重新生成autoload

composer dumpautoload

三方包网站

http://packagist.p2hp.com/

composer更换镜像

查看镜像

全局
composer config -l -g
当前项目
composer config -l

更换当前项目镜像

全局
composer config -g repo.packagist composer ${镜像地址}
当前项目
composer config repo.packagist composer ${镜像地址}

| 阿里云 Composer 镜像 | https://mirrors.aliyun.com/composer/ | 阿里云 | 96 秒 | 推荐 |
| 腾讯云 Composer 镜像 | https://mirrors.cloud.tencent.com/composer/ | 腾讯云 | 24 小时 | - |
| PHP 国内 Composer 镜像 | https://packagist.phpcomposer.com | 仁润股份 | 24 小时 | 不稳定 |
| 华为云 Composer 镜像 | https://repo.huaweicloud.com/repository/php/ | 华为云 | 未知 | 未知 |
| php.cnpkg.org Composer 镜像 | https://php.cnpkg.org | 安畅网络 | 60 秒 | - |

composer三方包的搜索网站

packagist

卡死

安装三方包时卡在Updating dependencies (including require-dev)
一般都是镜像问题 ,composer官网给的镜像不能用 ,换成阿里云的镜像

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

切换镜像无效

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/不一定能切换成功

在项目根目录下找到composer.json文件 ,切换成功应该是

图片.png

或者直接把下边代码粘贴到composer.json文件

    "repositories": {
        "packagist": {
            "type": "composer",
            "url": "https://mirrors.aliyun.com/composer/"
        }
    }

内存溢出

Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 67108872 bytes) in phar://C:/ProgramData/ComposerSetup/bin/composer.phar/src/Composer/DependencyResolver/RuleSet.php on line 84
官方有解决方案

注意 即使配置了composer全局环境变量也不行 必须用composer.phar文件绝对路径

php -d memory_limit=-1 ${composer.phar 绝对路径} require ${包名}

如:

php -d memory_limit=-1 C:\ProgramData\ComposerSetup\bin\composer.phar require phpoffice/phpspreadsheet

laravel创建命令行脚本

php artisan make:command 自定义名称(生成的文件名)

在app->console->commands目录内找到脚本文件 ,修改属性 $signature = '自定义名称'(脚本启动名称) ,在handle方法内写逻辑
启动脚本

php artisan 自定义名称($signature)

phpstorm多行变成一行

有时候拿到一部分数据ID ,需要在数据库进行批量处理 .
比如对下边的用户ID进行封号


图片.png

解决

在phpstorm中新建一个普通文本文件 , 把excel中的一列粘贴进去


图片.png

1. Ctrl + a 全选

2. Ctrl + Shift + j 多行变成一行,空格分割

3. Ctrl + r 替换 空格为想要的字符

图片.png

完成

图片.png

phpspreadsheet 导出微信昵称数据丢失

遇到昵称带表情的用户数据后 ,接下来的很多表格都变成了空白 .实际上数据是存在的


图片.png

解决方法 ,生成的excel文件后缀 ,由xsl 改为更高版本的 xslx ,便可恢复正常

判断数组值是否存在

经常需要判断前端传过来的筛选参数, 如果存在有效值 sql中 就增加筛选条件
判断前端是否传了有效参数 ,当参数是数字 0 时 筛选状态为0的数据 经常出现问题

$arr['status'] = 0;  

判断数组$arr中是否有某个参数

返回false
$arr['key'] = null
$arr['key'] = false
$arr['key'] = ''
$arr['未定义索引']
返回true
$arr['key'] = 0
$arr['key'] = '0'
$arr['key'] = 'null'
$arr['key'] = 'false'

    /**
     * 判断数组中是否存在某个有效参数
     * @param array $arr 数组
     * @param string $key 索引
     * @return bool
     */
    function hasVal($arr,$key){
        if (!is_array($arr)) return false;
        
        if (array_key_exists($key , $arr)){
            if (
                $arr[$key] !== '' &&
                $arr[$key] !== false &&
                $arr[$key] !== null
            ){
                return true;
            }
        }
        return false;
    }

找出一维数组中重复的值
通过in_array()判断

        $temp = [];
        foreach ( $list as $val ) {
            if ( !in_array($val , $temp) ) {
                $temp[] = $val;
                continue;
            }
            throw new \Exception("值:{$val}重复");
        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容