分类目录归档:随笔

我写下这篇随笔,并刻印在了心上。
I wrote down this essay and put it in my mind.

ThinkPHP 6 中的morphTo 和 laravel 不一样

在 Laravel 中,使用 Eloquent 的 morphTo 关联时,你可以根据某个字段的值(通常是 type 字段)来动态地关联到不同的模型。这种机制被称为多态关联(polymorphic relationships)。

而在 ThinkPHP 6 中,并没有直接的 morphTo 关联方法。但你可以通过自定义关联逻辑来实现类似的功能。

要实现根据字段值关联到不同表的功能,你可以考虑以下步骤:

  1. 创建基础模型:首先,创建一个基础模型,这个模型将包含你想要关联到的所有模型共有的属性和方法。
  2. 自定义关联方法:在需要使用多态关联的模型中,定义一个自定义的关联方法。在这个方法中,你可以根据字段的值来决定关联到哪个模型。
  3. 动态查询构建:在自定义关联方法中,使用 ThinkPHP 的查询构建器来根据字段值动态构建查询。你可以使用 case 语句或 if 条件来判断字段值,并据此选择正确的表进行关联。
  4. 返回关联结果:最后,返回构建好的关联结果。这可以是一个模型实例、模型集合或其他适当的数据结构。

需要注意的是,由于 ThinkPHP 6 没有内置的 morphTo 方法,因此你需要自行处理关联逻辑和数据映射。这可能需要更多的代码和逻辑判断,但你可以根据自己的需求灵活实现所需的功能。

如果你发现手动实现多态关联较为复杂或繁琐,你也可以考虑使用第三方扩展或包来增强 ThinkPHP 的功能。有时候,社区中可能会有开发者提供了类似的解决方案或工具,可以帮助你更轻松地实现所需的功能。

总之,虽然 ThinkPHP 6 没有直接的 morphTo 方法,但你可以通过自定义关联逻辑来实现类似的多态关联功能。

以太坊( Ethereum ) 和 波场(Tron)的数学计算函数类

以太坊( Ethereum ) 和 波场(Tron)的数学计算函数类,当然也可用用在阿里蚂蚁区块链上,可以帮助减少gas消耗和防止溢出错误

/**
  * @dev包装了Solidity的算术运算,并添加了溢出检查。
  *
  * Solidity中的算术运算会在溢出时自动换行。 这很容易导致在运算中使用错误的值,尤其是在一些资金运算。
  * `SafeMath`通过在操作溢出时回滚事务来处理溢出回滚。
  *
  * 使用这个库会自动帮你检查类型溢出的情况,所以建议一直使用这个库。
  */
library SafeMath {
    /**
     * @dev 返回两个无符号整数的相加,并在溢出时回滚事务。
     *
     * 与Solidity的+操作符相对应。
     *
     * 使用场景:
     * - 要求加法不能溢出的场景.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");  //报错并且回滚

        return c;
    }

    /**
     * @dev 返回两个无符号整数的减法,并在溢出时返回(结果为负数时)。
     *
     * 与Solidity的`-`运算符相对应。
     *
     * 使用场景:
     * - 要求减法不能溢出的场景.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");  //报错并且回滚
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev 返回两个无符号整数的乘法,并在溢出时恢复。
     *
     * 与Solidity的`*`运算符相对应。
     *
     * 使用场景:
     * - 要求乘法不能溢出的场景.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // gas优化:这里只检测'a'不为零,而是要求a更便宜
        // 如果还测试了“ b”,则将失去收益,因为检测也需要消耗gas。
        // 参见:https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");  //报错并且回滚

        return c;
    }

    /**
     * @dev返回两个无符号整数的整数除法。 恢复除以零。 结果四舍五入为零。
     *
     * 与Solidity的`/`运算符相对应。 注意:此功能使用
     * `revert`操作码(保留剩余gas不变),而Solidity使用无效的操作码进行还原(消耗所有剩余气体)。
     * 使用场景:
     * - 除数不能为零。
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity仅在除以0时自动断言
        require(b > 0, "SafeMath: division by zero");  //报错并且回滚
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev返回除以两个无符号整数的余数。 (无符号整数模),除以零时返回。
     *
     * 与Solidity的`%`运算符相对应。 此功能使用“还原”
     * 操作码(使剩余的气体保持不变),而Solidity使用
     * 无效的操作码还原(消耗了所有剩余的gas)。
     *
     * 使用场景:
     * - 除数不能为零。
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");  //报错并且回滚
        return a % b;
    }
}

Linux 大文件切割 命令

split -l 50000 -d –verbose 20210101-blog.thisnksoa.com.log split-line

split 是用来切割 大文件的工具,ubuntu 20 自带的,不需要安装

这是要被切割的日子文件

20210101-blog.thisnksoa.com.log

命令参数:

-l 多少行保存成一个文件 可以试试 5000 到 50000

-b 多大保存成一个文件 支持单位 K, M, G, T, P, E, Z 呵呵 ,后面几个单位是用来搞笑的 一般要切的话,肯定是因为太大了,才要切的,一般就k和m有点用吧
-d 参数以数字的方式显示 不设置的话生成的文件名后缀是字母的,有点不好看,最好还是设置上

–verbose 切割后自动加数字后缀

split-line 要保存的文件的名字

最简单生成证书的方法

第一步,切换到你要生成证书的目录

第二步:执行下面命令

openssl genrsa -out server.key 1024

openssl req -new -x509 -days 3650 -key server.key -out server.crt -subj “/C=CN/ST=mykey/L=mykey/O=mykey/OU=mykey/CN=blog.thinksoa.com”

第三步:完成

 

注意:生成的是自签证书,什么是自签证书自己百度.

php 中类 const可以被继承者覆盖

<?php
class a{
    const cc = “123”;
    public function aa(){
        echo self::cc;
        echo \n;
    }
}
class b extends a{
    const cc = “b123”;
    public function bb(){
        echo self::cc;
        echo \n;
    }
}
$a = new a();
$a->aa();
$b = new b();
$b->bb();
$b->aa();
 
 

代码!

Web App 之操作页面DOM操作优化

理由:

DOM操作主要分为页面渲染与资源清理(heap控制),两者之间又相辅相成,若是DOM操作一块处理不好,其产生的感觉就不再是慢,而是卡,所以DOM操作优化的主要目的就是消灭页面卡的问题,这个在移动端尤为重要。

关于页面渲染:

浏览器会解析三个东西:HTML、Javascript、CSS

浏览器首先会根据HTML生成DOM Tree,其次会根据CSS生成CSS Rule Tree,javascript可以通过DOM API与CSS API操作DOM Tree与CSS Rule Tree,从而引起页面变化。

浏览器解析结束会通过DOM Tree与CSS Rule Tree形成render tree,只有display不为none的元素才会形成render Tree,render Tree形成后浏览器会调用GUI绘制页面,在此之前做的一件事情便是layout或者说reflow。上面的描述简单而言可以分为以下流程:

l  生成DOM树

l  计算CSS样式

l  构建render tree

l  reflow,定位元素位置大小

l  绘制页面

在这个过程中,若是javascript动态改变DOM Tree便会引起reflow,页面中的元素改变,只要不影响尺寸,比如只是颜色改变只会引起repaint不会引起回流否则,reflow不可避免,这个时候便需要重新计算形成render Tree,reflow分为局部回流与全局回流,会影响下面的,不会影响上面的元素。reflow耗用的系统资源较大,DOM Tree中受到影响的节点皆会reflow,然后影响其子节点最坏的情况是所有节点reflow,该问题引发的现象便是低性能的电脑风扇不停的转,手机变得很热,并且非常耗电,以下操作可能引起reflow

l  操作dom结构

l  动画

l  DOM样式修改

l  获取元素尺寸的API

减少使用定位属性(fixed/absolute):

static元素处于文档流中,其渲染速度是最快的,我们做过一个测试:

100个absolute元素与100个static元素渲染时差在0.01-0.007ms

100000个元素渲染差距便增至30ms左右,这个微小的时差在移动端变得尤为明显,比如:

小米/三星手机(1000左右),便存在明显的渲染问题,具体表现为:

l  定位元素在手机上不能显示。

l  定位元素动画效果失效。

以上问题便是UI渲染失效多导致,最好的解决方案是减少使用定位元素,否则只能引起强烈reflow才能解决。

另外,产品经常会有fixed的相关需求,比如支付按钮一直出现在低端,这个需求会造成两个问题:

l  fixed元素遭遇文本框时失效,可能会飘到页面中间阻挡输入

l  影响效率

问题一原因与移动端的实现有关,暂时没有完美的解决方案,问题二便与渲染直接关联

滚屏时,页面上所有的像素会跟着滚动,显卡对全屏幕上下移动的处理很快,但是若是出现一个fixed元素或者有元素不跟着一起滚动,那么滚动对手机浏览器来说就是一个负担,这种滚动的性能甚至体现在了iphone 4s,因为滚动可能会造成reflow,这个现象体现在:

使用absolute配合javascript模拟fixed效果时,会有断片的效果,该问题在iphone5s便不会出现这个问题。

技巧:

当然,我们不能忽略产品的需求,fixed类需求应该在技术上得到解决,还用户一个良好的体验。

虚拟键盘导致fixed元素错位

fixed元素一定会伴随虚拟键盘的出现,但是虚拟键盘只是“贴”在了viewport上,表面上不会对dom产生“任何”影响,但是这个时候fixed元素表现却变得怪异起来,会错位。

应用层面解决问题方案是,虚拟键盘弹出时将fixed元素设置为static,虚拟键盘消失时候设置回来。

由于虚拟键盘出现并未抛出事件,而检测scroll或者resize事件,皆会有一定延迟,会出现闪烁现象,所以现有最好的方案是setinterval定时器监控当前获取焦点元素是否为文本元素,若是是的话便需要处理,如此便可解决fixed元素错误问题。

fixed元素滑动惯性平滑度

我们常常遇到这种产品需求,tab标签栏开始固定,当滚动向下超过该标签栏后便会变成fixed元素,一直出现在头部,这样的需求在电脑上没有问题,但是在iPhone5s以下的手机常常会出现小范围错位或者快速移动大范围错位的问题。

这个时候我们可以引起reflow迫使浏览器重绘以解决这个问题,这里推荐一个奇怪的hack写法:同时设置三个image元素的src属性,便可以全范围解决该难题,  该方案被团队证实并得到应用。

//三图片src,引发reflow,处理fixed方案惯性问题

var el = this.els.ctlc.find(‘img’);

$(el[0]).attr(“src”, ‘http://res.m.ctrip.com/html5/Content/images/144.png’);

$(el[1]).attr(“src”, ‘http://res.m.ctrip.com/html5/Content/images/144.png’);

$(el[2]).attr(“src”, ‘http://res.m.ctrip.com/html5/Content/images/144.png’);

另外,上图中的tab标签下面的蓝线具有动画,但是在小米或者三星手机上可能不会移动,这个时候也可以动态引起reflow解决这个BUG。

其它

l  CSS选择器尽量使用id与class,避免过度层叠

l  避免使用数值,比如:border: none不会引起渲染,而boder: 0会

l  动画时候让元素脱离文档流,以免导致大量reflow

l  避免逐条修改DOM样式,改以className实现同样功能

l  操作DOM时将display设置为none,因为这种元素不会影响渲染,或者操作fragment对象取代操作显示在页面上的DOM

l  避免将获取DOM样式属性的操作写在循环中,可能引起重复reflow

内存资源优化:

移动端的javascript

首先,移动端的性能与PC端的性能完全不在一个数量级上,比如,我哥做过一个测试,使用innerHTML绘制大段,之后想获取HTML的ID节点,事实上是获取不到的,这种问题在单页模拟多页,动态创建DOM会经常发生

var element   = $(‘<div id = “test”>…大量结构…</div>’);

$(root).html(element)

$(‘#test)  //为空

这类问题匪夷所思,因为页面UI渲染与DOM操作是互斥的,但是就算出现了这个问题,一个解决方案是使用settimeout,更好的方案是使用DOMNodeRemoved事件监控页面DOM改变,将我们的DOM操作回调放入以确保渲染结束。

以上问题只是为了说明移动端的性能问题,这类性能问题会导致很多莫名其妙的问题,而且很多与渲染有关。但是这也从侧面说明了移动端资源的紧缺,若是heap值过大,会导致操作出现卡的现象,更有甚者,会引起页面假死直接退出。

webapp的模式,完全依赖于浏览器的垃圾回收,基本就是作死,因为传统页面一旦刷新页面整个资源完全释放,而webapp没有刷新这类操作,只有一个状态到两一个状态,不相关的内存会保留,资源必须手动释放,或者说,框架必须提供垃圾释放的机制。

这个由图表heap值变化可以清晰看出。

而view切换过程中,不用的资源若是不手动设置为null会导致变量得不到回收便脱离框架控制而失控了。所以我们在webapp的过程中需要注意:

l  释放没有使用的闭包

l  观察者需要得到清理

l  释放定时器

l  view切换过程中,在destroy中释放view相关资源

——感谢艾伦友情支援

闭包陷阱

在我们工作过程中,滥用局部变量极有可能引起闭包陷阱,这个问题不止是性能问题,在逻辑上会引起错误,而且不易发现,比如,在AMD闭包中使用一个局部变量

var _attributes = {};

callback ($.extend(_attributes, opts));

如此操作,会改变_ attributes对象,若是一个实例还无问题,但是两个实例的话便会发生变量污染。

这只是一个例子,但是在代码中滥用局部变量可能会引起不必要的隐忧,戒之慎之。

webapp资源释放

根据前面的描述,我们可以得出一个结论:

无论是view还是UI组件我们得提供统一的destroy接口,以便让用户继承释放资源。

若是view的资源得不到释放导致heap值过高,webapp模式的网站其价值大减。这里有几点可以考虑:

l  webapp中view实例保存不超过5个,多了便释放dom结构以及内存引用(临界值自己判断最优)

l  view隐藏时释放内部资源,解除DOM事件句柄

l  UI组件与view相同,需要统一释放机制

但是单页应用由于页面不会刷新,总有一些资源得不到释放,此问题任重道远,平时编写过程可以做以下优化:

l  使用函数替换逻辑

让我们的函数产生一个返回值替换函数中的大段逻辑,这样的第一个好处便是逻辑清晰,第二个好处是这些函数在不同的函数中,这个函数被使用后便会自动得到释放。

l  清理闭包引用

当一个闭包函数或者什么使用结束后,若不会再使用,便需要手动清理该变量,以便解除闭包之间的引用关系,从而释放资源。

l  使用对象属性或者方法

一个对象可以引用其他对象的属性或者方法,比如obj.foo = thatObj;这种情况下,我们可以随时删除对象解除引用关系,然后便可以清理资源。

动画与假死

动画而言建议采用CSS3实现动画,CSS3中又推荐采用最新的接口,比如使用transform取代top/lelf操作,这样操作效率搞得多。

若是采用动画可以将对应元素设置为absolute以减少回流,另外最关键一点还是

避免移动DOM树过多的节点,这个时候需要驳回产品无理需求,比如:

产品要求日期滚屏组件,显示半年的数据,这半年的数据便是180个DOM树

这个级别的DOM一旦移动整个手机会直接卡死,甚至构建DOM树,渲染页面也会出现假死现象,该问题需要规避。

Application Cache

Application Cache是HTML5为webapp离线使用而增加的API,与localstorage、cookie等不同,Application Cache存储的是一系列请求资源允许浏览器在请求资源时不必通过网络,设计得当的话可以实现离线应用。

使用Application Cache主要是在网络性能上提升,有效降低了网络延迟,提升请求加速

但是也会有一些问题,比如新版本缓存不立刻生效;manifest中的请求路径相对于manifest文件,而非加载页面;更新/回滚等问题,所以使用与否还得论证。

Zxing 二维码识别库 横屏修改成竖屏

camera.setDisplayOrientation(90);

不知道为什么,Zxing用的是横屏,也许是因为外国人习惯横屏拍照的原因把,但是,在国内,很多人不习惯,呵呵,我用着也不习惯.所以还是该成竖屏,以适合国内人的习惯吧.

修改方法:

1.在DecodeHandler.java中,修改decode方法

PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(data, width, height);

byte[] rotatedData = new byte[data.length];

for (int y = 0; y < height; y++) {

 for (int x = 0; x < width; x++)
  rotatedData[x * height + height - y - 1] = data[x + y * width];

 }

int tmp = width; // Here we are swapping, that's the difference to #11
width = height;
height = tmp;
PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);

2.在CameraManager.java中,修改代码:

// 注释掉
// rect.left = rect.left * cameraResolution.x / screenResolution.x;
// rect.right = rect.right * cameraResolution.x / screenResolution.x;
// rect.top = rect.top * cameraResolution.y / screenResolution.y;
// rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;

//修改成这样的
rect.left = rect.left * cameraResolution.y / screenResolution.x;
rect.right = rect.right * cameraResolution.y / screenResolution.x;
rect.top = rect.top * cameraResolution.x / screenResolution.y;
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;

3.在CameraConfigurationManager.java中,在setDesiredCameraParameters方法中添加一句

camera.setDisplayOrientation(90);

4.在AndroidManifest.xml中,把Activity的属性android:screenOrientation="landscape" 改为

android:screenOrientation="portrait"

支付宝高级即时到帐的坑 千万别跳

呵呵,最近掉坑里了,换了支付宝高级支付之后,接口没有修改。回来,发现会员的充值,没有付款的,也给他充值了,原因是。支付宝修改了即时到帐的通知方式。

TRADE_FINISHED状态原本的通知方式,应该会员付款,之后,支付宝发来TRADE_FINISHED状态,现在,高级版的做了调整,发来TRADE_SUCCESS状态,因为,之前做担保交易的时候,处理了TRADE_SUCCESS状态。又处理了TRADE_FINISHED状态,导致给用户充值了2次!