laradock 中 php5.6 连接 mysql 报错解决
发表于|更新于|码不能停
|总字数:199|阅读时长:1分钟|浏览量:
laradock 中 php 5.6 连接 mysql 报错的解决方法。

之前弄的是默认版本的 php 7.2 和 mysql 8,配置好以后一直都能正常使用。
最近因为需要切换 php 版本,突然发现切换后连接 mysql 时无法识别 host。
emmmm……,最开始还以为是 php 的锅,各种重新 build,无果,最后在 github 上找到别人发出来的解决办法:
rm -rf ~/.laradock/data/mysql
删除老版本的数据docker-compose build mysql
重新构建 mysql进入 mysql 容器
mysql -uroot -p
root
ALTER USER root IDENTIFIED WITH mysql_native_password BY ‘root’;
exit;
到这里也就可以了。
有这个问题是因为 8 和 5.7 的配置不一样,不清掉老数据的话会引起报错,一有请求去连接 mysql 马上就宕机。
文章作者: m-finder
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 M-finder!
相关推荐

2019-04-09
laravel 队列学习
学习下 laravel 的队列系统。 队列的目的是将耗时的任务延时处理,比如发送邮件,从而大幅度缩短 Web 请求和相应的时间。 常用的队列后台有: Beanstalk,Amazon SQS,Redis 等。 配置laravel 为多种队列服务做了统一的API,在配置文件 config/queue.php 中可以找到每种队列驱动的配置。 其中每种驱动都有一个默认的 queue 属性,用来存放使用时没有显示定义队列的任务。 12345// 分发到默认队列Job::dispatch();// 分发到 emails 队列Job::dispatch()->onQueue('emails'); 在项目的配置文件中,可以指定驱动,老版本中为 QUEUE_DRIVER,新版本中为QUEUE_CONNECTION , 驱动默认为 sync,这是一个本地的同步驱动,方便调试队列里的任务。 先以 redis 为例做一个邮件发送队列。 因为 laravel 的 redis 默认使用了 predis,所以先装下扩展: 1composer require 'predis/predis' 邮件配置,最后两项是手动添加的,否则会报错: 12345678MAIL_DRIVER=smtpMAIL_HOST=smtp.mxhichina.comMAIL_PORT=25MAIL_USERNAME=m@m-finder.comMAIL_PASSWORD=xxxxxxMAIL_ENCRYPTION=nullMAIL_FROM_NAME=M-finderMAIL_FROM_ADDRESS=m@m-finder.com 生成任务类命令行执行:php artisan make:job EmailJob,该命令会在 app/jobs 下自动创建文件。 在任务类中发送邮件: 12345678public function handle() { $email = $this->email; $content = '这是一封来自Laravel的队列测试邮件.'; Mail::raw($content, function ($message) use ($email) { $message->subject('[ 测试 ] 测试邮件SendMail - ' . date('Y-m-d H:i:s')); $message->to($email); });} 任务调度之前弄了登录事件和监听,就在监听里去触发吧。 1EmailJob::dispatch($guard->user)->onQueue('emails'); 开启队列1php artisan queue:work --tries=3 --timeout=30 --queue=emails 然后重新登录触发任务。可以看到邮箱已经有了提示: 邮件已经成功发出,接下来就可以在实际的需求中使用了。

2023-05-11
php 国密 sm2 sm3 sm4 完整测试类
应用范围及描述 算法类型 国密算法 应用范围及描述 对称加密 SM1 128位数据加密,算法不公开,仅以IP核的形式存在于芯片中。智能IC卡、智能密码钥匙、加密卡、加密机。 非对称加密 SM2 被用来替换RSA算法。常用于身份认证,数据签名,密码交换,256位椭圆曲线。 完整性运算 SM3 256位数据摘要计算,相当于SHA256,数字签名及验证、消息认证码生成及验证、随机数生成 对称加密 SM4 128位数据加密,相当于AES(128) 相关代码php sm2 sm3 sm4 完整测试类,可拖入 laravel unit test 模块运行。基于扩展包 [ lpilp/guomi ] , sm2 与兴业银行有部分区别,sm4 已互通,未做招行验证。 sm2 密钥长度一般为 128 或 130 位,部分使用压缩密钥长度为 66,也就是将密钥分成 x、y,y是偶数就是02,y是奇数就是03,通过 x 可以算出 y。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290<?phpnamespace Tests\Unit;use FG\ASN1\ASNObject;use FG\ASN1\Exception\ParserException;use Mdanter\Ecc\Crypto\Signature\Signature;use Mdanter\Ecc\Serializer\Signature\DerSignatureSerializer;use PHPUnit\Framework\TestCase;use Rtgm\sm\RtSm2;use Rtgm\sm\RtSm3;use Rtgm\sm\RtSm4;/** * 国密加密测试 * sm4 已与兴业银行调通 */class GmTest extends TestCase{ /** * 获取 sm2 * @return RtSm2 */ private function getSm2(): RtSm2 { return new RtSm2('base64'); } /** * 获取 sm3 * @return RtSm3 */ private function getSm3(): RtSm3 { return new RtSm3(); } /** * 获取 sm4 * @return RtSm4 */ private function getSm4(): RtSm4 { $privateKey = $this->getSm4PrivateKey(); return new RtSm4($privateKey); } /** * 获取 16进制 sm2 密钥 * 生成于工具站 https://www.lzltool.com/SM2 base64格式 * @return string */ private function getSm2PrivateKey(): string { return bin2hex(base64_decode('L8TbMByc+rQmKECWMBjnDQHrXrExqZKdl5S6sBbP07M=')); } /** * 获取 16进制 sm2 公钥 * 生成于工具站 https://www.lzltool.com/SM2 base64格式 * @return string */ private function getSm2PublicKey(): string { return bin2hex(base64_decode('BCxc4cDX1OQEpCD8O7wzPhTOljYg0uzfsMAEanCvYgBIj966+i5pgjwyIOtFSNWLWjoDzLmMJP9nf2cVmiH+aYI=')); } /** * sm2 数据格式化 * @param $dec * @return string */ private function sm2FormatHex($dec): string { $hex = gmp_strval(gmp_init($dec, 10), 16); $len = strlen($hex); if ($len == 64) { return $hex; } return $len < 64 ? str_pad($hex, 64, "0", STR_PAD_LEFT) : substr($hex, $len - 64, 64); } /** * 获取 16位 密钥 * @return bool|string */ private function getSm4PrivateKey(): bool|string { return base64_decode('NmQzZDQ2YTcxMmRjNGE0NQ=='); } /** * 获取待加密字符串 * @return string */ private function getDataStr(): string { return '{"bankCardNo":"6212028190240439021","certNo":"41052619700925136X","userName":"南瓜"}'; } /** * 拼接 sm2 待加密字符串 * @return bool|string */ private function getSm2SignStr(): bool|string { $params = json_decode($this->getDataStr(), true); $signStr = ''; if ($params != null) { ksort($params); foreach ($params as $k => $v) { $signStr .= "{$k}={$v}&"; } } return substr($signStr, 0, strlen($signStr) - 1); } public function test_sm2_sign() { $sm2 = $this->getSm2(); $signStr = $this->getSm2SignStr(); // 加密 $sign = $sm2->doSign($signStr, $this->getSm2PrivateKey()); $encryptStr = base64_decode($sign); try { $a = ASNObject::fromBinary($encryptStr)->getChildren(); } catch (ParserException $e) { $this->fail('加密失败: ' . $e->getMessage()); } $aa = $this->sm2FormatHex($a[0]->getContent()); $bb = $this->sm2FormatHex($a[1]->getContent()); $encryptStr = base64_encode(hex2bin($aa . $bb)); $this->assertNotEmpty($encryptStr); return $encryptStr; } public function test_sm2_verify_sign() { $sm2 = $this->getSm2(); $encryptSignStr = bin2hex(base64_decode($this->test_sm2_sign())); echo 'sm2 sign str: ', $encryptSignStr, PHP_EOL; $r = substr($encryptSignStr, 0, 64); $s = substr($encryptSignStr, 64, 64); $r = gmp_init($r, 16); $s = gmp_init($s, 16); $signature = new Signature($r, $s); $serializer = new DerSignatureSerializer(); $sign = base64_encode($serializer->serialize($signature)); $boolean = $sm2->verifySign($this->getSm2SignStr(), $sign, $this->getSm2PublicKey()) ?? false; echo $boolean ? 'sm2 验签通过' : 'sm2 验签失败', PHP_EOL; $this->assertTrue($boolean); } public function test_sm2_encrypt() { $sm2 = $this->getSm2(); // 压缩公钥 $key = $this->decompressPublicKey('0315edd9126410e9b94b83ee2bcdfeebe9166e84d7aad1b9d16fa923995d28e81f'); $encrypt = $sm2->doEncrypt($this->getDataStr(), $key); $this->assertNotEmpty($encrypt); return $encrypt; } public function test_sm2_decrypt() { $sm2 = $this->getSm2(); $encrypt = $this->test_sm2_encrypt(); $privateKey = 'bf5e3e47e5392a8cdba8e3f854db2d3f5e2c536235303a02898b58d085a8246a'; echo 'sm2 encrypt str: ', $encrypt, PHP_EOL; $decryptStr = $sm2->doDecrypt($encrypt, $privateKey); echo 'sm2 decrypt str: ', $decryptStr, PHP_EOL; $this->assertNotEmpty($decryptStr); $this->assertTrue($decryptStr === $this->getDataStr()); } /** * 获取未压缩公钥 * @param $compressedKey * @return string|null */ function decompressPublicKey($compressedKey): ?string { // 获取压缩标志和X坐标 $flag = substr($compressedKey, 0, 2); $x = substr($compressedKey, 2); // 将16进制字符串转换为大整数 $p = gmp_init('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16); $a = gmp_init('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16); $b = gmp_init('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16); $gx = gmp_init('32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1711D7AFB1B8B4E16', 16); $gy = gmp_init('BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0', 16); $n = gmp_init('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16); // 计算Y坐标 $x = gmp_init($x, 16); $alpha = gmp_powm($x, 3, $p); $beta = gmp_add(gmp_mod(gmp_mul($a, $x), $p), $b); $y2 = gmp_mod(gmp_add($alpha, $beta), $p); $y = gmp_powm($y2, gmp_div_q(gmp_add($p, 1), 4), $p); if ($flag == "02") { // 如果压缩标志为 02,则Y坐标为偶数 if (gmp_strval(gmp_mod($y, 2)) != "0") { $y = gmp_sub($p, $y); } return "04" . gmp_strval($x, 16) . str_pad(gmp_strval($y, 16), 64, "0", STR_PAD_LEFT); } if ($flag == "03") { // 如果压缩标志为 03,则Y坐标为奇数 if (gmp_strval(gmp_mod($y, 2)) != "1") { $y = gmp_sub($p, $y); } return "04" . gmp_strval($x, 16) . str_pad(gmp_strval($y, 16), 64, "0", STR_PAD_LEFT); } return null; } public function test_sm3() { $sm3 = $this->getSm3(); $signStr = $sm3->digest($this->getDataStr()); echo 'sm3 sign str: ', $signStr, PHP_EOL; $this->assertNotEmpty($signStr); } /** * 测试 byteArr to string * @return string */ public function test_sm4_iv() { $byteArr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; $iv = call_user_func_array('pack', array_merge(['C*'], $byteArr)); $this->assertTrue(base64_encode($iv) === 'AAAAAAAAAAAAAAAAAAAAAA=='); return base64_encode($iv); } public function test_sm4_encrypt() { try { $iv = $this->test_sm4_iv(); $sm4 = $this->getSm4(); $encryptJsonStr = $sm4->encrypt($this->getDataStr(), 'sm4', base64_decode($iv)); } catch (\Exception $e) { $this->fail('加密异常:' . $e->getMessage()); } $encryptJsonStr = base64_encode(hex2bin($encryptJsonStr)); $this->assertNotEmpty($encryptJsonStr); return $encryptJsonStr; } public function test_sm4_decrypt() { try { $sm4 = $this->getSm4(); $encryptJsonStr = $this->test_sm4_encrypt(); echo "sm4 encrypt str: " . $encryptJsonStr, PHP_EOL; $decryptJsonStr = $sm4->decrypt(bin2hex(base64_decode($encryptJsonStr)), 'sm4', base64_decode($this->test_sm4_iv())); } catch (\Exception $e) { $this->fail('解密异常:' . $e->getMessage()); } echo "sm4 decrypt str: " . $decryptJsonStr, PHP_EOL; echo $decryptJsonStr === $this->getDataStr() ? 'sm4 数据一致' : 'sm4 数据不一致', PHP_EOL; $this->assertNotEmpty($decryptJsonStr); }}

2018-03-28
Docker使用教程-入门
docker已经装好了,但是完全不知道怎么用,先来点官网的例子看看吧。 docker自带的终端不太好用,所以先用xshell连接上终端,ip为终端启动时显示的:192.1168.99.100,默认应该都是这个。账号密码是:docker / tcuser 1234567891011121314 ## . ## ## ## == ## ## ## ## ## === /"""""""""""""""""\___/ === ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~ \______ o __/ \ \ __/ \____\_______/ _ _ ____ _ _| |__ ___ ___ | |_|___ \ __| | ___ ___| | _____ _ __| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__| < __/ ||_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_| 安装centos镜像拉取一个centos的映像并在衍生容器内运行交互式终端: 1docker run --interactive --tty centos bash 官网的例子是ubuntu,没玩过,所以换成了更熟悉点的centos 安装完成后会自动进入centos的控制台,输入exit可以退出。 安装nginx1docker run --detach --publish 80:80 --name webserver nginx 装完以后,在你的宿主机,也就是装docker的电脑上打开浏览器,输入docker启动时输出的ip就能够看到nginx的欢迎页面了。 删除镜像1.停止所有的container,这样才能够删除其中的images: docker stop $(docker ps -a -q) 如果想要删除所有container的话再加一个指令: docker rm $(docker ps -a -q) 2.查看当前有些什么images docker images 3.删除images,通过image的id来指定删除谁 docker rmi 想要删除untagged images,也就是那些id为的image的话可以用 docker rmi $(docker images | grep “^“ | awk “{print $3}”) 要删除全部image的话 docker rmi $(docker images -q)

2019-03-15
Laravel 服务容器
在 Laravel 生命周期中,我们了解到框架运行过程中,会通过创建应用实例来完成很多事情,这个应用实例,也就是我们今天的主角,服务容器。 Laravel 的服务容器,是用于管理类的依赖和执行依赖注入的工具。 依赖注入 DI开始之前,需要我们先了解一下,什么是依赖注入。 简单来说,就是将类的依赖通过参数或其他方式注入。 比如: 12345678910111213141516171819202122232425262728293031323334interface Storage{ public function set($key, $value); public function get($key);}class SessionStorage implements Storage{ function __construct($cookieName='PHPSESSID'){ session_name($cookieName); session_start(); } function set($key, $value){ $_SESSION[$key] = $value; } function get($key){ return $_SESSION[$key]; }}class User{ private $storage; function __construct(Storage $storage){ $this->storage = $storage; } function setLanguage($language){ $this->storage->set('language', $language); }}$storage = new SessionStorage('SESSION_ID');$user = new User($storage); 依赖注入 并不局限于构造函数,也可以通过设值方法注入,或者类成员变量方式,通过构造函数注入适用于必要的依赖,设值注入适用于可选依赖,比如项目需要一个缓存功能的实现。在上面的例子中,我们如果需要改用 Redis 或者 MongoDB 来存储数据,只需要继承并实现 Storage 接口,然后在外部就可以很轻松的切换服务了。 依赖注入容器 IOC在实际的开发中,用上边的依赖注入方式还是很累的,所以,我们还需要了解一个新的概念,依赖注入容器,也可以叫控制反转。 简单来说,依赖注入容器就是将组件间的依赖关系由程序内部提到外部容器来管理,也就是将依赖的配置和使用分开,原本是程序控制执行流程,现在程序反倒成了被控制的对象,也就形成了控制反转。 通常用于管理大量依赖组件的实例。比如一个框架。 首先,我们可以定义一个容器: 123456789101112131415class Container{ public function getStorage() { return new SessionStorage(); } public function getUser() { return new User($this->getStorage()); }}// 更改实例化方式$container = new Container();$user = $container->getUser(); 在这个容器中,我们只需要调用容器 getUser 方法,既可以获取到 User 实例,并不需要关心它是怎么创建出来的。 但是,这个容器还存在一些问题,Storage 的实例化还是硬编码,如果要切换其他服务,只能通过改代码的方式。 对此,我们可以再次升级容器: 1234567891011121314151617181920212223242526272829303132333435363738394041class Container{ protected $binds; protected $instances; // 绑定 public function bind($abstract, $concrete) { // 判断是否为匿名函数 if ($concrete instanceof Closure) { $this->binds[$abstract] = $concrete; } else { $this->instances[$abstract] = $concrete; } } // 实例化 public function make($abstract, $parameters = []) { if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } array_unshift($parameters, $this); return call_user_func_array($this->binds[$abstract], $parameters); }}$container = new Container;$container->bind('Storage', function($container){ return new SessionStorage;});$container->bind('User',function($container,$module){ return new User($container->make($module));});$user = $container->make('User',['Storage']); 一个类似于 laravel 的服务容器就好了,当然 larave 的服务容器比这个要复杂的多。 总的来说,laravel 的服务容器有两大功能: 注册基础服务 管理需要实例化的类及其依赖 Laravel 服务容器的使用方法laravel 服务容器在使用时一般分为两个阶段:使用之前进行绑定(bind)完成将实现绑定到接口;使用时对通过接口解析(make)出服务。 laravel 内置多种不同的绑定方法以用于不同的使用场景: bind 简单绑定 singleton 单例绑定 instance 实例绑定 contextual-binding 上下文绑定 还有好几种,看文档吧 它们的最终目标是一致的:绑定接口到实现。 这样的好处是在项目的编码阶段建立起接口和实现的映射关系,到使用阶段通过抽象类(接口)解析出它的具体实现,这样就实现了项目中的解耦。 bindbind 方法的功能是将实现与接口进行绑定,然后在每次执行服务解析操作时,Laravel 容器都会重新创建实例对象。 例如: 123456789101112131415161718$this->app->bind( UserRepositoryInterface::class, UserRepository::class);class UserController extends Controller{ private $repository; function __construct(UserRepositoryInterface $userRepository) { $this->repository = $userRepository; } function users(){ return $this->repository->all(); }} 在服务提供者中,将 User 仓库的具体实现与接口进行绑定,使用时可以直接通过接口注入依赖。 singleton采用单例绑定时,仅在首次解析时创建实例,后续使用 make 进行解析服务操作都将直接获取这个已解析的对象,实现共享操作。 绑定处理类似 bind 绑定,只需将 bind 方法替换成 singleton 方法即可。 instance将已经创建的实例对象绑定到接口以供后续使用,这种使用场景类似于注册表。 比如用于存储用户模型: 12345678// 创建一个用户实例$artisan = new User();// 将实例绑定到服务容器App::instance('login-user', $artisan);// 获取用户实例$artisan = App::make('login-user'); contextual-binding主要用于一个接口多处实现,然后根据不同控制器去进行判断具体应该用哪个实现。 12345$this->app->when(PhotoController::class) ->needs(Filesystem::class) ->give(function () { return Storage::disk('local'); });

2024-09-19
Mac 用 Brew 安装旧版本 PHP
最近又用到 php7.4,奈何本地早就已经升到了 8,想搞回来,发现一个简单好用爽歪歪的三方库,需要的可以试一下,5.6 - 8.4 都有。[ homebrew-php ] 添加地址库1brew tap shivammathur/php 安装指定版本1brew install shivammathur/php/php@7.4 切换版本12345brew services stop php@7.4brew unlink php@xxbrew link php@7.4brew services start php@7.4 搞定收工。

2018-01-05
laravel5.4疑难杂症
公司项目最近翻新了页面,把 bootstrap 完全改成了 layui 。 按照惯例,上线之前先在测试环境跑几天,结果在搭建测试环境的时候,问题就出来了: laravel 版本是 5.4.63 ,服务器的 php 版本是 5.6 ,执行 composer install 时,提示我需要 php7.1 。 吓得我一阵懵逼,难道是什么时候装错扩展了? 把 composer.json 里没什么用的扩展完全去除后再试,结果还是一样。 反复折腾无果,想起还有 update 可以用,遂改为执行 composer update ,终于开始安装了。 小样,还治不了你了!容老夫抽根烟得瑟一下。 下一秒,一个新的报错又砸我个措手不及: class ‘’ not found ! 虽然不知道这个报错是咋回事,但是潜意识觉得应该是某个 Kernel 文件出错了。 找到一份之前的备份,一通对比,终于有所发现: 出错的代码比之前正常的代码多了个 “,”,丫的,太粗糙了! 去掉,再次执行 update ,果然一路畅通无阻。 但是那个该死的 install 是再也没回来。