找到
171
篇与
技术教程
相关的结果
- 第 17 页
-
JavaScript Cookie插件 JavaScript Cookie介绍 一个简单、轻量级的JavaScript API,用于处理Cookie 安装 <script src="https://cdn.bootcdn.net/ajax/libs/js-cookie/3.0.1/js.cookie.min.js"></script>基本用法 创建一个在整个网站上有效的cookie: Cookies.set('name', 'value')创建一个7天后过期的cookie,在整个站点上有效: Cookies.set('name', 'value', { expires: 7 })创建对当前页面路径有效的过期cookie: Cookies.set('name', 'value', { expires: 7, path: '' })读取cookie: Cookies.get('name') // => 'value' Cookies.get('nothing') // => undefined读取所有可见cookie: Cookies.get() // => { name: 'value' }*注意:通过传递一个cookie属性(可能是也可能不是)来读取特定的cookie是不可能的 在编写所述cookie时使用):* Cookies.get('foo', { domain: 'sub.example.com' }) // `domain` won't have any effect...!名为的 foo cookie将仅在以下日期提供 .get() 如果从调用代码的地方可见;读取时,域和/或路径属性不会产生影响。 删除cookie: Cookies.remove('name')删除对当前页面路径有效的cookie: Cookies.set('name', 'value', { path: '' }) Cookies.remove('name') // fail! Cookies.remove('name', { path: '' }) // removed!这很重要!删除cookie时,如果您不依赖默认属性,则必须传递与设置cookie完全相同的路径和域属性: Cookies.remove('name', { path: '', domain: '.yourdomain.com' })注意:删除不存在的cookie既不会引发任何异常,也不会返回任何值。 命名空间冲突 如果存在与名称空间 Cookies 冲突的危险,noConflict 方法将允许您定义新名称空间并保留原始名称空间。当在第三方站点上运行脚本时,这尤其有用,例如作为小部件或SDK的一部分。 // 将js cookie api分配给不同的变量,并恢复原始的“window.Cookies” var Cookies2 = Cookies.noConflict() Cookies2.set('name', 'value')注意:在 .noConflict 方法在使用AMD或CommonJS时不是必需的,因此它不会在这些环境中公开。 Cookie属性 Cookie属性默认值可以通过 withAttributes() 创建api实例来全局设置,也可以通过传递一个普通对象作为最后一个参数来单独设置对`Cookie.set(…) 的每次调用。每次调用属性覆盖默认属性。 过期 定义何时删除cookie。值必须是 Number这将被解释为从创建时算起的天数或 日期例如。如果省略,cookie将成为会话cookie。 要创建一个在一天内过期的cookie,您可以查看 Wiki上的常见问题。 默认值:当用户关闭浏览器时,将删除Cookie。 例如: Cookies.set('name', 'value', { expires: 365 }) Cookies.get('name') // => 'value' Cookies.remove('name')路径 在 String 指示cookie可见的路径。 默认值: / 例如: Cookies.set('name', 'value', { path: '' }) Cookies.get('name') // => 'value' Cookies.remove('name', { path: '' })关于Internet Explorer的说明: 由于基础WinINET InternetGetCookie实现中的一个模糊错误,IE的文档。如果设置了包含文件名的路径属性,cookie将不会返回cookie。(From Internet Explorer Cookie Internals (FAQ)) 这意味着不能使用 window.location.pathname 设置路径,如果这样的路径名包含这样的文件名: /check.html (或者至少,这样的cookie无法正确读取)。 事实上,您不应该允许不受信任的输入设置cookie属性,否则您可能会受到XSS攻击。 域名 A String 指示cookie应可见的有效域。cookie也将对所有子域可见。 默认值: Cookie仅对创建Cookie的页面的域或子域可见,Internet Explorer除外(见下文)。 示例: 假设正在 site.com 上创建cookie: Cookies.set('name', 'value', { domain: 'subdomain.site.com' }) Cookies.get('name') // => undefined (need to read at 'subdomain.site.com')关于Internet Explorer默认行为的注意事项: Q3: 如果我没有为cookie指定域属性,IE会将其发送到所有嵌套的子域吗? A: 是的,cookie上的example.com集将被发送到sub2.sub1.example.com。 Internet Explorer在这方面与其他浏览器不同。这意味着如果您省略了 domain 属性,它将在IE的子域中可见。 安全的 可以是 true 或 false ,指示cookie传输是否需要安全协议(https)。 默认值: 没有安全协议要求。 示例: Cookies.set('name', 'value', { secure: true }) Cookies.get('name') // => 'value' Cookies.remove('name')相同站点 A String, 允许控制浏览器是否随跨站点请求一起发送cookie。 默认值:未定义。 请注意,最近的浏览器将“Lax”设置为默认值,即使没有在此处指定任何内容。 示例: Cookies.set('name', 'value', { sameSite: 'strict' }) Cookies.get('name') // => 'value' Cookies.remove('name')设置默认值 const api = Cookies.withAttributes({ path: '/', domain: '.example.com' })转换器 查看 创建api的新实例,以覆盖默认解码实现。所有依赖于正确解码的get方法,如 Cookies.get() 和 Cookies.get('name') ,都将为每个cookie运行给定的转换器。返回的值将用作cookie值。 读取只能使用 escape 功能解码的其中一个cookie的示例: document.cookie = 'escaped=%u5317' document.cookie = 'default=%E5%8C%97' var cookies = Cookies.withConverter({ read: function (value, name) { if (name === 'escaped') { return unescape(value) } // 对于所有其他cookie,返回默认值 return Cookies.converter.read(value, name) } }) cookies.get('escaped') // 北 cookies.get('default') // 北 cookies.get() // { escaped: '北', default: '北' }写入 创建重写默认编码实现的api的新实例: Cookies.withConverter({ write: function (value, name) { return value.toUpperCase() } })
-
JavaScript 正则常用校验大全 手机号(mobile phone)中国(严谨), 根据工信部 2019 年最新公布的手机号段 const reg = /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/; const str = "19119255642"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);Email(邮箱) const reg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; const str = "90203918@qq.com"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);座机(Tel Phone)电话(国内) 如: 0341-86091234 const reg = /^(?:(?:\d{3}-)?\d{8}|^(?:\d{4}-)?\d{7,8})(?:-\d+)?$/; const str = "0936-4211235"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);身份证号(2 代,18 位数字),最后一位是校验位,可能为数字或字符 X const reg = /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/; const str = "12345619991205131x"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文姓名 const reg = /^(?:[\u4e00-\u9fa5·]{2,16})$/; const str = "韩小韩"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);英文姓名 const reg = /(^[a-zA-Z][a-zA-Z\s]{0,20}[a-zA-Z]$)/; const str = "James Han"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);网址(URL) const reg = /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/; const str = "https://www.vvhan.com"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);必须带端口号的网址(或 IP) const reg = /^((ht|f)tps?:\/\/)?[\w-]+(\.[\w-]+)+:\d{1,5}\/?$/; const str = "https://www.vvhan.com:80"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);银行卡号(10 到 30 位, 覆盖对公/私账户) const reg = /^[1-9]\d{9,29}$/; const str = "6222026006705354000"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);帐号是否合法(字母开头,允许 5-16 字节,允许字母数字下划线组合) const reg = /^[a-zA-Z]\w{4,15}$/; const str = "han_666666"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文/汉字 const reg = /^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/; const str = "易航博客"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);密码强度校验,最少 6 位,包括至少 1 个大写字母,1 个小写字母,1 个数字,1 个特殊字符 const reg = /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/; const str = "han@666vvx,"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);微信号(wx),6 至 20 位,以字母开头,字母,数字,减号,下划线 const reg = /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/; const str = "kd_-666"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);邮政编码(中国) const reg = /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/; const str = "734500"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文和数字 const reg = /^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$/; const str = "易航好6啊"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);匹配连续重复的字符 const reg = /(.)\1+/; const str = "112233"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);统一社会信用代码 const reg = /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/; const str = "91110108772551611J"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);子网掩码(不包含 0.0.0.0) const reg = /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(255|254|252|248|240|224|192|128|0)$/; const str = "255.255.255.0"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(新能源) const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z](?:((\d{5}[A-HJK])|([A-HJK][A-HJ-NP-Z0-9][0-9]{4}))|[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳])$/; const str = "京AD92035"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(非新能源) const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]$/; const str = "京A00599"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(新能源+非新能源) const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/; const str = "京A12345D"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);护照(包含香港、澳门) const reg = /(^[EeKkGgDdSsPpHh]\d{8}$)|(^(([Ee][a-fA-F])|([DdSsPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))\d{7}$)/; const str = "s28233515"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);图片
-
一文搞懂HTTP和HTTPS的通信过程及区别 一、两者的区别 端口: http 端口号是80, https 端口号是443 传输协议: http 是超文本传输协议,属于明文传输;https 是安全的超-文本传输协议,是经过 SSL 加密后的传输协议 安全性: https 使用了 TLS/SSL 加密,比 http 更加的安全 证书: https 需要申请 ca 证书 二、HTTP的通信过程 理解: 作为标准的 C/S 模型, http 协议总是由客户端发起,服务端进行响应。 DNS 解析,域名系统 DNS 将域名解析成IP地址 建立 TCP 连接,进行 TCP 的三次握手 客户端发送请求 服务端响应客户端,向客户端发送数据 通信完成, TCP 连接关闭 三、HTTPS的通信过程 理解: https 通信是建立在 ssl 连接层之上的请求和响应,客户端将加密组件发送到服务端,服务端进行匹配后将数字证书等信息发送到客户端,客户端进行证书验证,验证通过后使用非对称加密对数据的密钥进行协商,协商后得到对称的加密密钥,然后使用对称算法进行 TCP 链接,然后与客户端进行三次握手后,进行数据传输,传输完成后,四次挥手,断开链接,通信结束。 客户端和服务端通过 TCP 建立连接,并发送 https 请求。 服务端响应请求,并将数字证书发送给客户端,数字证书包括 公共秘钥、域名、申请证书的公司 。 客户端收到服务端的数字证书之后,会验证数字证书的合法性。 如果公钥合格,那么客户端会生成 client key ,一个用于进行对称加密的密钥,并用服务端的公钥对客户端密钥进行非对称加密。 客户端会再次发起请求,将加密之后的客户端密钥发送给服务端。 服务端接收密文后,会用私钥对其进行非对称解密,得到客户端秘钥。并使用客户端秘钥进行对称加密,生成密文并发送。 客户端收到密文,并使用客户端秘钥进行解密,获取数据。 四、HTTPS通信过程介绍图 HTTPS通信过程介绍图图片
-
-
Typecho 1.2.0 提示版本更新Bug解决方法 Typecho以一向高雅的动作宣布了自己的回归: “这不是玩笑,我们回来了” Typecho 1.2.0 我也按照更新的方法将我的typecho更新到了1.2.0版,但是在后台却还是看到提示升级,当前版本1.2.0,最新版本1.2.0的字样。 图片 可以确定这是typecho的一个Bug,官方也给出了修复的办法,在代码的判断中修改一处就可以解决了。 if ( isset($json['release']) && preg_match("/^[0-9\.]+$/", $json['release']) && version_compare($json['release'], $version, '>=') && version_compare($json['release'], $version, '>') )在 var/Widget/Ajax.php 这个文件中,将 >= 改为 > 即可。 图片
-
PHP各种常用函数方法封装 当前日期和时间 /** * 当前日期和时间 * @return string */ function date_time(): string { return date('Y-m-d H:i:s'); }动态创建Element元素 /** * 动态创建Element元素 * * @param string $element * @return ElementBuilder */ function element($element) { return new ElementBuilder($element); } /** * @package ElementBuilder * @description 动态创建HTML的Element标签 * @author 易航 * @version 1.0 * @link http://blog.yihang.info */ class ElementBuilder { private $options = [ 'element' => 'div', 'inner' => null, 'attributes' => [] ]; private function attributes($attributes) { return FormBuilder::attributes($attributes); } public function __construct($element) { $this->options['element'] = $element; } /** * 设置标签内部的HTML内容 * @param $innerHTML 要设置的标签HTML内容 * @return $this */ public function innerHTML($innerHTML) { $this->options['inner'] = $innerHTML; return $this; } /** * 设置标签内部的文本内容 * @param $innerText 要设置的标签文本内容 * @return $this */ public function innerText($innerText) { $this->options['inner'] = empty($innerText) ? $innerText : htmlentities($innerText); return $this; } /** * 批量设置标签的属性 * @param $attributes * @return $this */ public function attr($attributes, $content = null) { if (is_array($attributes)) { foreach ($attributes as $key => $value) { $this->options['attributes'][$key] = $value; } } if (is_string($attributes)) { $this->options['attributes'][$attributes] = $content; } return $this; } /** * 获取生成的HTML内容 * @return string */ public function get($html = null) { $this->innerHTML($html); $element = $this->options['element']; $content = $this->options['inner']; $attributes = $this->attributes($this->options['attributes']); if ($content === false) { $html = "<$element$attributes />"; } else { $html = "<$element$attributes>$content</$element>"; } return $html; } public function __toString() { return $this->get($this->options['inner']); } }解压ZIP文件 function zipExtract($src, $dest) { // 通过ZipArchive的对象处理zip文件 $zip = new ZipArchive(); //新建一个ZipArchive的对象 /* $zip->open这个方法的参数表示处理的zip文件名。 如果对zip文件对象操作成功,$zip->open这个方法会返回TRUE */ if ($zip->open($src) === true) { $zip->extractTo($dest); //假设解压缩到$dest路径文件夹的子文件夹php $zip->close(); //关闭处理的zip文件 return true; } return false; }获取指定目录下的文件和目录列表 /** * 获取指定目录下的文件和目录列表 * * @param string $directory 要扫描的目录 * @return DirScanner */ function scan_dir(string $directory) { return new DirScanner($directory); } /** * 获取指定目录下的文件和目录列表 */ class DirScanner { private array $list; private string $directory; /** * @param string $directory 要扫描的目录 */ public function __construct(string $directory) { $this->directory = str_replace(['//', '\\\\'], ['/', '\\'], $directory); $this->directory = preg_match('/^\/|\\\$/', $this->directory) ? $this->directory : $this->directory . DIRECTORY_SEPARATOR; $this->list = array_values(array_diff(scandir($directory), ['.', '..'])); } /** * 只获取文件 */ public function files(array $suffixes = []): array { return $this->filter($suffixes, 'is_file'); } /** * 只获取目录 */ public function dirs(): array { return $this->filter([], 'is_dir'); } /** * 获取所有文件和目录 */ public function all(): array { return $this->list; } /** * 过滤列表 */ private function filter(array $suffixes, callable $callback): array { $directory = $this->directory; return array_filter($this->list, function ($item) use ($directory, $suffixes, $callback) { $path = $directory . $item; if (!empty($suffixes) && is_file($path)) { $extension = pathinfo($item, PATHINFO_EXTENSION); if (!in_array($extension, $suffixes)) return false; } return $callback($path); }); } }删除文件或文件夹 /** * 删除文件或文件夹 * * @param string $directory 目录的路径。 * @param resource $context 上下文流(context stream) resource * @return bool */ function delete_directory(string $directory, $context = null) { if (is_dir($directory)) { $objects = scandir($directory); foreach ($objects as $object) { if ($object != "." && $object != "..") { if (is_dir($directory . DIR_SEP . $object)) { delete_directory($directory . DIR_SEP . $object); } else { unlink($directory . DIR_SEP . $object); } } } rmdir($directory, $context); } elseif (is_file($directory)) { unlink($directory, $context); } }多维数组转对象 /** * 多维数组转对象 * @param array $d * @return object */ function array_to_object(array $d): object { if (is_array($d)) { $json = json_encode($d); return json_decode($json); } else { return $d; } }多维对象转数组 /** * 多维对象转数组 * @param object|array $d * @return array */ function object_to_array($d) { if (is_object($d)) { $d = get_object_vars($d); // 获取给定对象的属性 } if (is_array($d)) { $function = __FUNCTION__; return array_map("self::$function", $d); } else { return $d; } }发送电子邮件 /** * 发送电子邮件 * @access public * @param string $title 邮件标题 * @param string $subtitle 邮件副标题 * @param string $content 邮件内容 * @param string $email 不填写则默认发送系统配置中的邮箱,优先程度:配置收件人>发信邮箱 * @return bool|object */ function send_mail($title, $subtitle, $content, $email = null) { $site = options('site'); $mail = options('mail'); if (empty($email)) { $email = empty($mail['recv']) ? $mail['account'] : $mail['recv']; } $PHPMailer = new \PHPMailer\PHPMailer\PHPMailer(); $language = $PHPMailer->setLanguage('zh_cn'); if (!$language) { return 'PHPMailer语言文件zh_cn加载失败'; } $PHPMailer->isSMTP(); $PHPMailer->SMTPAuth = true; $PHPMailer->CharSet = 'UTF-8'; $PHPMailer->SMTPSecure = $mail['secure']; // 允许 TLS 或者ssl协议 $PHPMailer->Host = $mail['smtp']; // SMTP服务器 $PHPMailer->Port = $mail['port']; // 服务器端口 25 或者465 $PHPMailer->FromName = $site['title']; //发件人昵称 $PHPMailer->Username = $mail['account']; //邮箱账号 $PHPMailer->From = $mail['account']; //邮箱账号 $PHPMailer->Password = $mail['pwd']; //邮箱密码 $PHPMailer->isHTML(true); $html = '<!DOCTYPE html><html lang="zh-cn"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, initial-scale=1.0"></head><body><style>.container{width:95%;margin:0 auto;border-radius:8px;font-family:"Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;box-shadow:0 2px 12px 0 rgba(0,0,0,0.1);word-break:break-all}.title{color:#fff;background:linear-gradient(-45deg,rgba(9,69,138,0.2),rgba(68,155,255,0.7),rgba(117,113,251,0.7),rgba(68,155,255,0.7),rgba(9,69,138,0.2));background-size:400%400%;background-position:50%100%;padding:15px;font-size:15px;line-height:1.5}</style><div class="container"><div class="title">{title}</div><div style="background: #fff;padding: 20px;font-size: 13px;color: #666;"><div style="margin-bottom: 20px;line-height: 1.5;">{subtitle}</div><div style="padding: 15px;margin-bottom: 20px;line-height: 1.5;background: repeating-linear-gradient(145deg, #f2f6fc, #f2f6fc 15px, #fff 0, #fff 25px);">{content}</div><div style="line-height: 2">请注意:此邮件由系统自动发送,请勿直接回复。<br>若此邮件不是您请求的,请忽略并删除!</div></div></div></body></html>'; $PHPMailer->Body = strtr( $html, [ "{title}" => $title . ' - ' . $site['title'], "{subtitle}" => $subtitle, "{content}" => $content, ] ); $PHPMailer->addAddress($email); $PHPMailer->Subject = $title . ' - ' . $site['title']; if ($PHPMailer->send()) { return true; } else { return $PHPMailer->ErrorInfo; } }获取配置信息 function options($name = false, $value = false) { if ($name === false && $value == false) { return Options::all(); } if (func_num_args() == 1) { returnOptions::get($name); } return Options::save($name, $value); } class Options { private static $options = null; public static function initialize() { if (is_null(self::$options)) { $select = Db::name('options')->select(); self::$options = []; foreach ($select as $value) { self::$options[$value['name']] = $value['value']; } } } public static function get($name) { $name_list = explode('.', $name); // 将路径分解成键名数组 $value = self::$options; // 初始化$value为数组的根 // 遍历键名数组,逐级深入到数组中 foreach ($name_list as $name_value) { if (isset($value[$name_value])) { $value = $value[$name_value]; // 如果键存在,更新$value } else { return null; // 如果键不存在,返回null或者你可以选择抛出异常 } } return $value; // 返回最终找到的值 } public static function all() { return self::$options; } public static function save(string $name, $value) { if (array_key_exists($name, self::$options)) { $save = self::update($name, $value); } else { $save = self::insert($name, $value); } // 保存虚拟模型数据 self::model($name, $value); return $save; } public static function insert(string $name, $value) { // 插入虚拟模型数据 self::model($name, $value); // 插入数据库数据 return Db::name('options')->insert(['name' => $name, 'value' => $value]); } /** * 设置虚拟模型数据 */ public static function model(string $name, $value) { self::$options[$name] = $value; return true; } public static function update(string $name, $value) { // 更新虚拟模型数据 self::model($name, $value); // 更新数据库数据 return Db::name('options')->where('name', $name)->update(['value' => $value]); } }以数组的形式返回关于文件路径的信息 pathinfo(path, options); /** 返回的数组元素如下: ['dirname']: 目录路径 ['basename']: 文件名 ['extension']: 文件后缀名 ['filename']: 不包含后缀的文件名 **/ // path:规定要检查的路径。 /** options: PATHINFO_DIRNAME - 只返回 dirname PATHINFO_BASENAME - 只返回 basename PATHINFO_EXTENSION - 只返回 extension PATHINFO_FILENAME - 只返回 filename **/获取PHP代码执行后的结果 <?php function run_code($code) { $file_name = rand() . 'txt'; $content = '<?php $text = ' . $code . ' ?>'; file_put_contents($file_name, $content); include($file_name); unlink($file_name); return $text; } ?>多维数组降维 function ArrMd2Ud($arr) { #将数值第一元素作为容器,作地址赋值。 $ar_room = &$arr[key($arr)]; #第一容器不是数组进去转呀 if (!is_array($ar_room)) { #转为成数组 $ar_room = array($ar_room); } #指针下移 next($arr); #遍历 while (list($k, $v) = each($arr)) { #是数组就递归深挖,不是就转成数组 $v = is_array($v) ? call_user_func(__FUNCTION__, $v) : array($v); #递归合并 $ar_room = array_merge_recursive($ar_room, $v); #释放当前下标的数组元素 unset($arr[$k]); } return $ar_room; }字符串加密解密 /** * $string:需要加解密的字符串; * $operation:E表示加密,D表示解密; * $key:自定义密匙 */ function string($string, $operation, $key = '') { $key = md5($key); $key_length = strlen($key); $string = $operation == 'D' ? base64_decode($string) : substr(md5($string . $key), 0, 8) . $string; $string_length = strlen($string); $rndkey = $box = array(); $result = ''; for ($i = 0; $i <= 255; $i++) { $rndkey[$i] = ord($key[$i % $key_length]); $box[$i] = $i; } for ($j = $i = 0; $i < 256; $i++) { $j = ($j + $box[$i] + $rndkey[$i]) % 256; $tmp = $box[$i]; $box[$i] = $box[$j]; $box[$j] = $tmp; } for ($a = $j = $i = 0; $i < $string_length; $i++) { $a = ($a + 1) % 256; $j = ($j + $box[$a]) % 256; $tmp = $box[$a]; $box[$a] = $box[$j]; $box[$j] = $tmp; $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); } if ($operation == 'D') { if (substr($result, 0, 8) == substr(md5(substr($result, 8) . $key), 0, 8)) { return substr($result, 8); } else { return ''; } } else { return str_replace('=', '', base64_encode($result)); } }图片
-
如何利用个人博客赚钱 个人博客如何赚钱盈利图片 最近在研究个人博客赚钱,看了很多关于技术人员如何赚钱的文章,但都很肤浅,没有提供具体的方法和策略,也就是赚钱的“技巧”和“途径”。本文将与你分享基于个人博客的赚钱方法和途径。乔布斯和比尔·盖茨 1981年,在苹果公司总部,召开了个人电脑领域的21世纪会议。乔布斯与比尔·盖茨讨论了合作事宜,并向比尔·盖茨展示了新设计的麦金塔电脑。图形界面的操作震惊了比尔·盖茨,但也为乔布斯制造了一个强大的对手。 这个故事想说明两点:第一,分享这些干货会不会给自己培养对手,因为你也是做个人博客的;二、解释“艺”与“道”的区别。乔布斯更多用艺术来创新,比尔盖茨更多用道来整合利润。 本文阐述如何通过个人博客赚钱,也是基于“术”与“道”的融合。 不听也不问 你可能听说过,个人博客已经不赚钱了。那个时代已经过去了。你可能也在搜索“做个人博客还能赚钱吗”?对于这种问题,不要听也不要问,直接去做。 所谓“后那个时代”,只是过了那个暴利时代,但不代表不赚钱。通过搜索引擎,你可以找到数以千计的网站,这些网站每天产生数以亿计的新内容。 如果不赚钱,为什么会这样?不赚钱的可能只是其中的一部分方式。 思维的改变 如果你想通过写博客赚钱,请先丢弃那些千篇一律的“专家”建议,比如:如何保持激情,如何坚持写作,如何养成良好的写作习惯,如何创新内容。都是基于“艺术”的层面,都是一样正确的废话。 现在告诉你,如果你想通过博客变得正确,你首先要改变你的角色:你现在不是一个博主,而是一个创业公司的CEO。你需要像CEO一样经营你的公司,像CEO一样思考,而不仅仅是一种爱好。 让个人博客从爱好变成一个企业的产品,让个人博客从“术”的层面变成“道”的层面进行思考和规划。如果你说写博客纯粹是爱好,不想赚钱,那就没必要读下去了。 根据市场选择 根据市场需求选择博客内容,而不仅仅是热情。说起博客失败的原因,95%的人认为是因为不够热情。如果通过写博客可以每天获得大量收入,你会热情吗? 个人博客失败的原因和经营企业一样:无利可图。 现在看看你的个人博客,你是在玩你的爱好吗?今天的爱好,明天的兴趣,后天的感受... 如果一个企业管理一个产品,会这么随便吗?会不会包罗万象?这样,你只会变得精疲力尽,无利可图。 现在从博主变成企业经营者。 作为一个商业运营者,你应该考虑的不是带着激情写作,而是分析你所选择的细分市场的商业因素:受众预算潜力、专业影响力和市场需求。 受众预算潜力 一个产品成功的核心因素是什么?当然可以解决用户的痛点,给用户提供价值。同时考虑用户愿意为此付出多少。 首先,你是博客的受众。推而广之,想想你提供的内容能给受众带来什么。然后,结合自己的专业知识,提供专业的内容和解决方案。 如果你说,我只是想写篇文章发泄一下情绪。这个时候,虽然你天然是观众,但对大部分用户来说是没用的。 像技术圈比较知名的个人博客:廖雪峰的个人博客,阮一峰的个人博客。他们都是为入门级技术人员提供有价值的内容,然后通过广告和销售在线课程来盈利。 广告是“羊毛出在猪身上”的模式,在线课程的定位也不错。新程序员愿意支付一定的学习费用,也有支付能力。 这些都是比较传统的做法,但是如果你作为一个公司来运营,你考虑做一些事情来增加几十倍甚至上百倍的收益吗?这个想法很简单。选择更丰富的受众,能够为他们提供核心服务。 举个简单的例子,如果你的专业技能能让你设计出很多好的方案。如果只是把这些方案发布在个人博客上,然后通过流量赚取广告费,收入可能少得可怜。但是如果你把这个包装成一个产品,从B2C走向B2B,为企业提供解决方案,你的收入会翻倍。 这个过程的时间成本和运营成本几乎相同,但收益却翻倍。 提炼:在选择细分市场的时候,优先考虑受众能给你带来多少收益,思考是否能通过ToC转化为ToB。靠近最有利可图的地区。 专业影响力 选好受众,给他们提供核心价值观之后,接下来就是发掘比别人更好的战略优势。 问问你自己: 我目前的创业能力如何?到什么程度? 我在这个行业有什么资源? 我能利用我的专业经验建立一个盈利的博客吗? 谁会从一开始就看重我做的事情? 要建立一个成功的博客,最重要的是建立影响力,树立权威。这些都需要你走出自己的舒适区,充分利用自己的人脉资源、专业知识以及一切相关的东西。 有人会问,写个人博客就行了。有必要这么受欢迎吗?别忘了,你现在是在做生意。举两个知识付费圈的例子:罗辑思维和樊登读书。 罗辑思维一开始只是在优酷上分享一个每周一次的知识视频脱口秀,然后在微信官方账号上每天更新一个语音,建立自己的个人影响力,然后就有了Get这个产品。 在这个过程中,罗胖动用了几乎所有的个人资源,专业知识,突破舒适区的学习能力,毅力等等。(打个广告,我是微信微信官方账号:节目新视界,一直在持续更新干货) 樊登读书会也是如此,采用线下和线下两种方式。这些对于个人博客(甚至其他内容平台)的运营都是可以借鉴的。 知乎V成功回答问题,获得粉丝,并将其引导到个人产品或平台的例子不胜枚举。至于个人博客,涉及到SEO中的反向链接,也是建立影响力的形式之一。 另一方面,如果你有很强的背景(来自BAT或ATM),也可以放在个人博客上作为信用背书。 提炼:打造品牌,建立影响力,利用一切可以利用的资源来经营你的“产品”,而不仅仅是凭激情,三天打鱼两天晒网。 市场需求 考虑了受众,建立了品牌之后,就该考察如何盈利了。搜索一下,看看有没有人在搜索你的话题,并为解决方案付费。 在你的小众市场选择5到10个关键词,然后使用关键词分析工具(Google关键词策划大使、百度指数)或者更好的SEO工具(比如Ahrefs)进行分析。 如果你的前5个关键词的搜索量达到一定程度(比如每个月至少5000次),说明有人对这样的话题感兴趣。 此时需要注意关键词的难度评分(从易到难0-100)。如果你的关键词难度分在80以上,可能竞争太激烈了,没什么影响。搜索一个月5000次以上,难度系数低于40的目标关键词,这样可以在竞争较少的情况下获得更多的流量。 另一种竞争方式是使用类似Ahrefs的SEO工具来查看搜索引擎结果页面(SERP)数据。具体来说,寻找域名当局(DA)和首页结果的SERP位置历史。 如果前10个结果的DA都超过65,阿达值为0的新博客就不会进入第一页,所以得不到访客。但是如果你在首页看到DA在30以下的网站,你可以通过他们提供更好的内容。如果SERP的持仓历史在过去6个月没有变化,那么竞争可能太激烈了。 回顾研究市场需求的几个要点: 每月超过5000次搜索。 关键词难度分值在0.4以下。 谷歌首页至少有一个网站的阿达低于30。 最近改变的SERP头寸的历史。 “专家”告诉你继续写,但你要把经验集中在受众预算潜力、专业影响力、市场需求等领域。 试想一下,如果你是一家公司的CEO,你应该更关注什么?是市场,是用户,是盈利模式,而不是每一行具体的代码。 归根结底:激情不创造金钱,金钱创造激情。如果你想赚钱,先停止“激情”创作。 运行并扩展您的博客 停止大量写作,开始扩展你的博客。写作必不可少,但“酒香也怕巷子深”。很多好的产品不能被更多的人使用。关键在于操作。 大多数个人博客更侧重于写作,而不是运营。为什么公司愿意高薪聘请优秀的销售人员?因为这个环节太重要了。而技术人员的个人博客更容易忽略运营和推广的重要性。 操作的主要组件: 建立和扩大关系 访客留言 外向 反向链接 无限重复上述步骤。 为什么会有商会和联盟?即众人拾柴火焰高。通过筛选高权重的博客,然后和他们建立关系,你就可以通过转发、留言、友情链接等方式,把你在高权重的网站上创作的内容传播出去。 关系的基础是什么?就是你能给别人提供价值,这就提供了筛选的标准。比如你想在一个网站上发表文章,保留这个网站的链接,那么你提供的文章首先必须是有价值的,至少可以弥补他们博客内容的不足。 内容匹配和受众匹配可以弥补自己博客内容的不足,是通过同行拓展自己博客的最好标准。 当这样的关系建立之后,剩下的事情就由搜索引擎替你处理了,可以快速获得流量和权重。 核心:链接建设是最难掌握的SEO策略,也是最有价值的。想办法扩展,让你的网站建立更多的链接。 如何正确盈利 有了内容,有了访客,有了流量,其实盈利是自然而然的。通过博客赚钱的方式有很多:营销联盟、广告、一对一辅导、咨询、实体销售、电子书销售、在线课程、知识付费等。 在挣钱的过程中,你还需要有一个时间表来进行不同的操作来对抗。 在新建立的网站上贴满广告是没有意义的,因为没有流量,而且会阻碍流量的发展。联盟营销也是如此。只有达到一定的用户基数,一次性销售才能达到效果。 能产生“被动收入”的网络营销、网络课程、广告收入、数码产品,可能需要几年时间,但毕竟是“睡后”收入。 如果你想在短时间内赚钱?那么可以考虑以下几种方式:高端咨询和会员制产品。然后就是在线课程、广告、会员产品等。 高端咨询主要靠你长期的专业知识积累,而会员产品也需要专业的输出。高端咨询可以为个人提供一对一辅导,为企业提供内训。会员制产品类似于Get、知识星球等服务类产品,购买一年。 在整个盈利过程中,请参考以下规则: 低流量x高价格=高流量x低价格流量低时提供高价服务产品,流量高时选择低价产品。 你的博客能赚多少钱? 如果通过激情创作来博客,可能根本没有收入。但是如果你像做生意一样经营你的博客,那么一个成功的博客每年可以赚到七位数。 现在,是时候开始你的博客之旅了。当然,如果你有更有效的方案,也可以分享给大家。
-
-
PHP使用PDO连接数据库 一、什么是PDO? PDO是PHP Date Object(PHP数据对象)的简称,它是与PHP 5.1版本一起发行的。 目前支持的数据库包括Firebird、FreeTDS、Interbase、MySQL、MS SQL Server、ODBC、Oracle、Postgre SQL、SQLite和Sybase。 PHP开发图片 有了PDO,您不必再使用mysql_函数、oci_函数或者mssql_*函数,也不必再为它们封装数据库操作类,只需要使用PDO接口中的方法就可以对数据库进行操作。在选择不同的数据库时,只需修改PDO的DSN(数据源名称)。 在PHP 6中将默认使用PDO连接数据库,所有非PDO扩展将会在PHP 6中被移除。该扩展提供PHP内置类PDO来对数据库进行访问,不同数据库使用相同的方法名,以解决数据库连接不统一的问题。 二、PDO的作用与特点 统一各种数据库的访问接口 PDO是一个“数据库访问抽象层”,作用是统一各种数据库的访问接口,与mysql和mssql函数库相比,PDO让跨数据库的使用更具有亲和力;与ADODB和MDB2相比,PDO更高效。 图片 三、PDO的启用 PDO是与PHP 5.1一起发行的,默认包含在PHP 5.1中。 由于PDO需要PHP 5.0核心面向对象特性的支持,因此其无法在PHP 5.0之前的版本中使用。 默认情况下,PDO在PHP 5.2中为开启状态,但是要启用对某个数据库驱动程序的支持,仍需要进行相应的配置操作。 在Windows环境下,PDO在php.ini文件中进行配置,如果想支持某个特定数据库,只需要把php.ini 文件里边所对应的 ;号 去掉即可。 我们先找到php.ini 配置文件,然后进入 搜索 pdo_ 可以看到我们这里只打开了 mysql和sqlite。注意:开启过后需要重启Apache 图片 我们可以使用输出 phpinfo() 函数来查看是否开启。 四、通过PDO连接数据库 PDO的构造函数 在PDO中,要建立与数据库的连接需要实例化PDO的构造函数,PDO构造函数的语法如下: __construct(string $dsn[,string $username[,string $password[,array $driver_options]]]) dsn:数据源名,包括主机名、端口号和数据库名称。 username:连接数据库的用户名。 password:连接数据库的密码。 driver_options:连接数据库的其他选项。 格式:mysql,db_databvase17,127.0.0.1,root,123456 实例: $dbms='mysql';//数据库类型 $host='127.0.0.1';//数据库主机名 也可以是127.0.0.1 $dbName='db_database17';//使用的数据库名称 $user='root';//用户名 $pass='123456';//对应的密码 $dsn="$dbms:dbname=$dbName;host=$host"; $conn= new PDO($dsn,$user,$pass); //初始化一个PDO对象,就是创建了连接数据库的对象 $conn构造函数用于构造PDO对象,有了这个对象,我们我就可以使用里边的方法来访问数据库。 1. exec() 方法 exec() 方法返回执行后受影响的行数,: 通常用于 INSERT 、 DELETE 和 UPDATE 语句中。 实例: <?php try { $conn = new PDO($dsn, $user, $pass); //初始化一个PDO对象,就是创建了连接数据库的对象 $conn $query = "insert into tb_pdo_mysql(pdo_type,database_name,dates)values('" . $_POST['pdo'] . "','" . $_POST['databases'] . "','" . $_POST['dates'] . "')"; $result = $conn->exec($query); echo "数据添加成功,受影响的行数为:" . $result; } catch (PDOException $e) { die("Error!:" . $e->getMessage() . '<br/>'); } ?>2. query() 方法 用于返回执行查询后的结果集 query() 方法用于返回执行查询后的结果集: 实例: <?php try { $pdo = new PDO($dsn, $user, $pass); $sql = 'select * from tb_pdo_mysql'; $result = $pdo->query($sql); foreach ($result as $row) { echo "<tr align='center'>" . "<td>" . $row['id'] . "</td>"; echo "<td>" . $row['pdo_type'] . "</td>"; echo "<td>" . $row['database_name'] . "</td>"; echo "<td>" . $row['dates'] . "</td>" . "</tr>"; } } catch (PDOException $e) { die("Error!:" . $e->getMessage() . '<br/>'); } ?>