0%

人总是喜欢自己没有的
### 介绍 querySelector()是用于接收一个CSS选择符,返回与该模式匹配的第一个元素; querySelectorAll()用于选择匹配到的所有元素。 query选择符选出来的元素及元素数组是静态的,而getElement这种方法选出的元素是动态的。 ### 说明 querySelector list 是一个静态的 Node List,是一个 li 集合的快照,对文档的任何操作都不会对其产生影响。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
<script>

var ul=document.querySelector('ul');
var list=ul.querySelectorAll('li');
for(var i=0;i<list.length;i++){
ul.appendChild(document.createElement('li'));
}
//这个时候就创建了3个新的li,添加在ul列表上。
console.log(list.length);
// 输出的结果仍然是3,不是此时li的数量6
</script>

getElementById
list 是一个动态的 Node List, 每一次调用 lis 都会重新对文档进行查询,导致无限循环的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
<script>
var ul=document.getElementsByTagName('ul')[0];
var list=ul.getElementsByTagName('li');
for(var i=0;i<5;i++){
ul.appendChild(document.createElement('li'));
}
console.log(list.length)//此时输出的结果就是3+5=8
</script>

你我之间本无缘分,全靠我死撑
### sleep()与usleep()的区别 sleep()是暂停多少秒 usleep()是暂停多少微秒 注意:usleep()单位是微秒,1秒 = 1000毫秒 ,1毫秒 = 1000微秒,即1微秒等于百万分之一秒。 ### microtime
1
2
3
4
$start = microtime(true);
sleep(2);
$end = microtime(true);
$execution_time = number_format($end-$start, 2); // 单位秒
### 文件修改时间
1
2
3
4
5
6
$updateTime = filemtime($tokenPath);
$nowTime = microtime(true);
$diffTime = round($nowTime - $updateTime);
if ($diffTime < 7000) {
return file_get_contents($tokenPath);
}

如果不走出去,你就会认为你看到的就是你的全部。

bigint

最大数: 18446744073709551615, 也就是2的64次方减去1, 也就是unsigned(无符号)
有符号范围:-2的63次方—2的63次方-1
默认长度:20
在mysql建表中的length,只是用于显示的位数,不影响所能存储的最大数

int

最大数: 4294967295, 也就是2的32次方减去1,也就是unsigned(无符号)
有符号范围:-2的31次方—2的31次方-1
默认长度:10
在mysql建表中的length,只是用于显示的位数,不影响所能存储的最大数

smallint

最大数: 65535, 也就是2的16次方减去1, 也就是unsigned(无符号)
有符号范围:-2的15次方—2的15次方-1
默认长度:5
在mysql建表中的length,只是用于显示的位数,不影响所能存储的最大数

tinyint

最大数: 255, 也就是2的8次方减去1, 也就是unsigned(无符号)
有符号范围:-2的7次方—2的7次方-1
默认长度:3
在mysql建表中的length,只是用于显示的位数,不影响所能存储的最大数

注意

插入像bigint这样非常大的数字请注意检查mysql的严格模式
laravel默认mysql是开启严格模式的

这段情,曾夏了夏天,后来却也冬了冬天

悲观锁

操作前假设一切操作都可能发现并发冲突,所以采取悲观态度。通过加锁,屏蔽一切可能违反数据完整性的操作
比方

1
2
select * from table for update;  --就是表锁
select * from table where x = 1 for update; --就是行锁

当使用for update后,其它会话还是可以执行select操作,但无法执行select xx for update操作,只有当前会话commit后,其它for update操作才会被执行。

for update仅适用于InnoDB,且必须在事务块(BEGIN/COMMIT)中才能生效

1
2
3
4
BEGIN;
SELECT * FROM test FOR UPDATE;
SLEEP(20);
COMMIT;

乐观锁

假定操作很少发生冲突,一般对于读多写少的情况。只在提交操作时检查是否违反数据完整性, 乐观锁不能解决脏读的问题。
可以通过版本号是否比上个版本号或者时间戳来实现, 也或者检查通过检查某个字段来实现;
对于冲突检测后的处理,需要业务逻辑去处理。

排它锁

当数据对象被加上排它锁时,其他的事务不能对它读取和修改。

1
2
3
BEGIN;
SELECT * FROM test FOR UPDATE;
COMMIT;

共享锁

加了共享锁的数据对象可以被其他事务读取,但不能修改。

1
SELECT * from city where id = "1"  lock in share mode; 

吃了就睡或长成猪的
### 错误
1
mySQL auto increment problem: Duplicate entry '4294967295' for key 1

解决

I had the same problem with the exact same number. My problem was that I had the field on int(10) when I changed it to bigint(20) it solved my problem.

你没有变强是因为你一直很舒服。
### 安装
1
composer require symfony/dom-crawler
### 代码片段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// october cms
$crawler = new Crawler($content);
$crawler->filter('img')->each(function (Crawler $node) use($pid) {
$sourceSrc = explode('?',$node->attr('src'))[0];
$sourceSrc = str_replace('https', 'http', $sourceSrc);
if (!starts_with($sourceSrc, 'http')) {
$sourceSrc = "http:".$sourceSrc;
}
$imageManager = new ImageManager(['driver' => 'gd']);
$temPath = storage_path() . '/temp/' .time().basename($sourceSrc);
$imageManager->make($sourceSrc)->save($temPath);
$attachment_type = 'Jason\Ccmall\Models\Product';
$productImage = new File();
$productImage->data = $temPath;
$productImage->field = 'content';
$productImage->attachment_id = $pid;
$productImage->attachment_type = $attachment_type;
$productImage->save();
$node->getNode(0)->setAttribute('src', $productImage->path);
@unlink($temPath);
});
$html = $crawler->html();
Product::query()->where('id', $pid)->update([
'content' => $html
]);
### 实例一
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use Symfony\Component\DomCrawler\Crawler;

$html = <<<'HTML'
<!DOCTYPE html>
<html>
<body>
<p class="message">Hello World!</p>
<p>Hello Crawler!</p>
</body>
</html>
HTML;

$crawler = new Crawler($html);

foreach ($crawler as $domElement) {
var_dump($domElement->nodeName);
}

实例二

1
2
3
4
5
6
7
8
9
10
$crawler = new Crawler('<html><body /></html>');

$crawler->addHtmlContent('<html><body /></html>');
$crawler->addXmlContent('<root><node /></root>');

$crawler->addContent('<html><body /></html>');
$crawler->addContent('<root><node /></root>', 'text/xml');

$crawler->add('<html><body /></html>');
$crawler->add('<root><node /></root>');

实例三

1
2
3
4
5
$imagesCrawler = $crawler->selectImage('Kitten');
$image = $imagesCrawler->image();

// or do this all at once
$image = $crawler->selectImage('Kitten')->image();

https://symfony.com/doc/current/components/dom_crawler.html

为了看起来毫不费力
### 批量插入
1
2
3
4
5
6
7
8
9
10
11
POST /shop/product/_bulk
{ "index" : {"_id" : "1" } }
{ "name" : "apple", "price":15.15 }
{ "index" : {"_id" : "2" } }
{ "name" : "pear", "price":16.00 }
{ "index" : {"_id" : "3" } }
{ "name" : "orange", "price":15.09 }
{ "index" : {"_id" : "4" } }
{ "name" : "bnanan", "price":3.00 }
{ "index" : {"_id" : "5" } }
{ "name" : "pototo", "price":9.15 }

批量修改

1
2
3
4
5
6
7
8
9
10
11
POST /shop/product/_bulk
{ "update" : {"_id" : "1"} }
{ "doc" : {"name" : "apple iphone"} }
{ "update" : {"_id" : "2"} }
{ "doc" : {"name" : "pear yoyo"} }
{ "update" : {"_id" : "3"} }
{ "doc" : {"name" : "orange milk"} }
{ "update" : {"_id" : "4"} }
{ "doc" : {"name" : "bnanan egg"} }
{ "update" : {"_id" : "5"} }
{ "doc" : {"name" : "pototo chips"} }

批量添加新的字段

1
2
3
4
5
6
7
8
9
10
11
POST /shop/product/_bulk
{ "update" : {"_id" : "1"} }
{ "doc" : {"desc" : "this is a apple iphone"} }
{ "update" : {"_id" : "2"} }
{ "doc" : {"desc" : "the price is low"} }
{ "update" : {"_id" : "3"} }
{ "doc" : {"desc" : "the frieight is free"} }
{ "update" : {"_id" : "4"} }
{ "doc" : {"desc" : "buy one and a free one"} }
{ "update" : {"_id" : "5"} }
{ "doc" : {"desc" : "you lost it"} }

批量删除

1
2
3
POST /shop/product/_bulk
{ "delete" : {"_id" : "2" } }
{ "delete" : {"_id" : "3" } }

弱国无外交,人弱亦如此
### call_user_func_array
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
function foobar($arg, $arg2) {
echo __FUNCTION__, " got $arg and $arg2\n";
}
class foo {
function bar($arg, $arg2) {
echo __METHOD__, " got $arg and $arg2\n";
}
}


// Call the foobar() function with 2 arguments
call_user_func_array("foobar", array("one", "two"));

// Call the $foo->bar() method with 2 arguments
$foo = new foo;
call_user_func_array(array($foo, "bar"), array("three", "four"));
?>

call_user_func

1
2
3
4
5
6
7
8
function increment($var)
{
$var++;
}

$a = 0;
call_user_func('increment', $a);
echo $a."\n";

其他

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

$class= new \Jason\Ccshop\Models\Product();

//返回对象的类名 命名空间
dump(get_class($class));

// 返回由类的方法名组成的数组
dump(get_class_methods($class));

// 返回由类的默认属性组成的数组
dump(get_object_vars($class));
dump(get_class_vars($class));

// 返回对象或类的父类名
dump(get_parent_class($class));

//检查类的方法是否存在
dump(method_exists($class, 'getMainThumb'));

//以参数列表的数组,调用用户方法, 在php7 中被废弃
call_user_method_array
//call_user_func_array 代替
//对特定对象调用用户方法 call_user_method 在php7 中被废弃
// call_user_func 代替

“我先起,你再睡一会儿。”

文章核心:

甲先算出原文的类似于MD5的校验值(数字”指纹”,也称”信息摘要”),接下来甲用自己的私钥K对MD5进行变形,得到变形C就是甲对合同A的签名。乙拿到源文件后也先算出MD5值,用甲的公钥K2再对签名C进行反运算,变回MD5,看是否与源文件的MD5一样,如果一样 ,则签名是真的,反之签名则为假冒的。 MD5/数字”指纹”是一种单向散列函数,它是完全不可逆的。 加密用公钥,解密是用私钥进行反运算得到原文。 签名用私钥,验证签名是用公钥进行反运算得到原指纹。 不必担心伪造MD5,因为只有用私钥才能进行签名

一、加密 加密用来保护敏感信息的传输,保证信息的安全性。在一个加密系统中,信息使用加密密钥加密后,得到的密文传送给接收方,接收方使用解密密钥对密文解密得到原文。FF有两种加密体系:秘密密钥加密和公开密钥加密。

1、秘密密钥加密 秘密密钥加密也称为对称密钥加密,加密和解密使用同一个密钥,即:原文经过密钥K加工(为避免歧意,本文将所有的对信息的变换均称为“加工”,而不区分加密和解密;加工前的信息称“原文”,加工后所得到的信息称为“变形”)后得到变形,而变形经过密钥K加工后又恢复为明文。因此信息的发送方和接收方必须共享一个密钥。 这种加密类型快速牢固,只要密钥足够长(目前128位被认为是“不可破解的”),密文就不可被破解。对称密钥加密的缺陷是密钥本身必须单独进行交换以便接收看能解密数据,如果密钥没有以安全方式传送,它就很可能被他人截获并用于信息解密。

2、公开密钥加密 公开密钥加密也称为非对称密钥加密。公开密钥加密体系使用两个不同的密钥:一个用主人秘密保存和专用的,主要用于解密和签名,称为私钥;另一个对外公开,主要用于验证签名和加密,称为公钥(公钥体系即因此而得名)。这两个密钥是数学相关的,但仅凭借公钥,人们无法推算出其对应的私钥。原文经过公钥加工后得到变形,该变形经过私钥加工后又复原为原文;反之亦然,原文经过私钥加工后得到变形,该变形经过公钥加工后又复原为原文。下面将要讲到,“先公后私”和“先私后公”这两者看起来差不多,但应用是完全不同的。用某用户的公钥加工后所得的数据只能用该用户的私钥才能复原为原文。因而要求用户的私钥不能透露给自己不信任的任何人。 公钥加密与对称密钥加密相比,其优势在于不需要一把共享的通用密钥,私钥不发往任何地方,由主人秘密保存,而公钥是公开的,不存在管理和保密的问题。但其缺点是计算复杂,不适应于对大量的数据进行加工处理。 FF在具体的应用时,先将秘密密钥用收件人的公钥进行加工,将变形用公开通道(实际上是附加在加密文件当中)传递给收件人,收件人用其私钥对变形进行加工,恢复出秘密密钥,然后再用秘密密钥对密文进行解密。 公钥加密的另一个用处是身份验证。私钥主人用私钥加工了一条信息后,拥有公钥拷贝的任何人都能对其复原,接收者由此可以知道这条信息确实来自于拥有私钥的人,因为除了私钥的主人外,其他人没有私钥,是无法进行“原文经过私钥加工后得到变形”这一操作的,故“先私后公”的操作方式可以进行身份验证,或者称为“数字签名”、“电子签名”。 二、安全的单向散列函数 (Secure Hash) 单向散列函数(简称“H函数”或“Hash函数”)用于对要传输的数据作运算生成信息摘要,它并不是一种加密机制,但却能产生信息的数字”指纹”,它的目的是为了确保数据没有被修改或变化,保证信息的完整性不被破坏。

单向散列函数有三个主要特点:

1.它能处理任意大小的信息,并将其技信息摘要(message digest)方法生成固定大小的数据块(FF是128位,即16字节),对同一个源数据反复执行Hash函数将总是得到同样的结果。
2.它是不可预见的。产生的数据块的大小与原始信息的大小没有任何联系,同时源数据和产生的数据块的数据看起来也没有明显关系,源信息的一个微小变化都会对数据块产生很大的影响。
3.它是完全不可逆的,没有办法通过生成的数据块直接恢复源数据。

H函数最主要的用途是数字签名。具体过程为: 甲先用H函数对某个信息(如合同的电子文件)A进行计算,得到128位的结果B,再用私钥K对B进行变形,得到C,该变形C就是甲对合同A的签名。 他人(乙)的验证过程为:乙用H函数对A进行计算,得到结果B1,对签名C用甲的公钥K1进行加工,得到变形B2,如果B1=B2,则签名是真的,反之签名则为假冒的。 原理:只有持有私钥K的人可以完成从A到C的操作。因为 甲虽然可以指责乙捏造了合同A(任何人都可以在计算机上打出一份他想要的合同),乙也的确可以从A计算出B,但从B到C的过程要用到甲的私钥K,该过程只有甲可以完成; 甲也可以指责乙先捏造了签名C,乙也的确可以用甲的公钥从C计算出B,但乙无法从B推算出A,从A到B的H函数是单向的,无法反向计算。