首页
关于
友链
推荐
肥啾解析
百度一下
肥啾GPT
Search
1
宝塔面板登录 phpMyAdmin 提示服务器和客户端上指示的HTTPS之间不匹配
269 阅读
2
Customer complaints evolve with in-car tech
188 阅读
3
JavaScript解析
153 阅读
4
内连接,左连接,右连接作用及区别
111 阅读
5
所谓关系
109 阅读
默认分类
网游架设
手机游戏
python
PHP
Mysql
VBA
C++
JAVASCRIPT
javascript基础
Oracle
生产管理
计划控制
ERP系统开发
APS排产
MES研究
考勤系统
CPA
财管
实务
经济法
战略
审计
税法
藏书架
古典名著
世界名著
编程秘籍
攻防渗透
经管书籍
大佬传经
风雅读物
考试相关
心情格言
拾玉良言
外文报刊
外刊随选
Facebook
Twitter
China Daily
软考
登录
Search
标签搜索
期刊读物
古文
何瑜明
累计撰写
160
篇文章
累计收到
154
条评论
首页
栏目
默认分类
网游架设
手机游戏
python
PHP
Mysql
VBA
C++
JAVASCRIPT
javascript基础
Oracle
生产管理
计划控制
ERP系统开发
APS排产
MES研究
考勤系统
CPA
财管
实务
经济法
战略
审计
税法
藏书架
古典名著
世界名著
编程秘籍
攻防渗透
经管书籍
大佬传经
风雅读物
考试相关
心情格言
拾玉良言
外文报刊
外刊随选
Facebook
Twitter
China Daily
软考
页面
关于
友链
推荐
肥啾解析
百度一下
肥啾GPT
搜索到
160
篇与
的结果
2025-12-25
学习路径
你说得非常对。如果不知道“为什么学”,再好的知识也是死知识。抽象的知识必须落地到具体的“用处”上,才能产生价值。让我彻底换个角度回答你:我们就从你熟悉的“用网页建立功能”出发,看看当你试图把功能做得更好、更大、更专业时,那些“其它知识”是如何一个个跳出来,成为你绕不过去的坎的。它们不是“要学的一堆东西”,而是“你在成长路上不得不解决的问题的答案”。故事:从个人博客到下一个“微博”假设你现在已经能用 PHP + SQL + JavaScript 建一个不错的个人博客了。用户能注册、登录、发表文章、评论。接下来,你想把它做大。你会遇到什么?这些“其它知识”的用处就来了。第一阶段:你的博客开始卡顿、出Bug问题1:网站越来越慢。 一篇文章有几千条评论时,你的 SELECT * FROM comments WHERE post_id=... 查询要好几秒。SQL底层知识(索引、执行计划) 的用处:你会知道,在 post_id 字段上加一个索引,可以让这个查询从几秒变成几毫秒。这就叫“优化”。问题2:你改了段PHP代码,结果整个网站白屏,还搞乱了之前的正常功能。Git 的用处:有了Git,你可以在改代码前“存个档”。改坏了?一键回滚到昨天正常的状态。这是你代码的“时光机”和“保险箱”。问题3:你想在服务器上找出为什么慢,或者批量修改一万个用户的后缀名。Linux命令行 的用处:你需要登录到那台远程的Linux服务器。看日志用 tail -f error.log,找慢查询用 grep 'slow',批量修改数据可以写个Shell脚本,一分钟搞定。没有命令行,你就像被关在机房玻璃门外,干着急。👉 第一阶段小结: 为了让你已有的功能更稳定、更快、更可控,你需要数据库优化、版本控制和服务器操作知识。这不是“额外学的”,而是维护和优化你的作品所必需的技能。第二阶段:你想吸引更多用户,功能变复杂问题4:用户数破万,搜索功能变得奇慢无比。算法与数据结构 的用处:你会理解,为什么简单的循环匹配不行,而用“倒排索引”(想想书的目录)这种数据结构能瞬间找到结果。你就能理解为什么要用Elasticsearch这样的专业搜索引擎,而不是自己瞎写SQL LIKE。问题5:图片上传功能被坏人利用,上传了木马,或者有人用脚本疯狂注册垃圾账号。网络与安全基础 的用处:你会理解文件类型校验、SQL注入、XSS攻击的原理。你知道怎么给PHP配置防火墙,怎么设计安全的API。你的功能不再只是一个玩具,而是一个需要负责的产品。问题6:你和朋友一起开发,代码合并冲突,分工混乱。Git高级用法(分支管理) 的用处:你们可以各开一个“分支”开发新功能,互不干扰,开发完再优雅地合并。这就是团队协作的基石。👉 第二阶段小结: 为了让你能开发更高级、更安全、需要协作的功能,你需要理解程序效率的根本(算法)、安全的基础和团队工作的流程。第三阶段:你的网站火了,需要面对海量用户问题7:每天百万人访问,你的单台服务器瞬间宕机。系统设计 的用处:这时你会思考:数据库读写分离(一台负责写,多台负责读)、加缓存(用Redis把热门文章存起来,不用每次都查数据库)、把图片扔到对象存储(比如阿里云OSS)、用负载均衡把流量分给十台服务器。这时,你不再是一个写PHP页面的程序员,而是一个系统架构师。你画的系统架构图,决定了网站能承载的极限。问题8:你需要管理几十台服务器,手动操作已不可能。Linux命令行 + Shell脚本 + 自动化工具 的用处:你会写脚本自动部署代码、监控服务器健康、批量处理日志。你从手动劳动中解放出来,让机器为你工作。问题9:你需要向投资人解释你的技术优势,或者给新同事讲解系统。清晰的写作与沟通 的用处:你能画出一张清晰的架构图,写一份易懂的技术文档。这是让你的技术和想法产生更大影响力的“乘数技能”。👉 第三阶段小结: 为了让你亲手构建的功能能承载百万、千万级的用户,并高效地管理它,你需要有设计复杂系统的思维和自动化一切的效率工具。这时,你的天花板被无限拔高。所以,它们到底能做什么?—— 一句话总结SQL底层原理:让你手里的数据库这把枪,从“烧火棍”变成“狙击步枪”,指哪打哪,又快又准。Linux命令行:让你获得操作服务器的“超能力”,从门外汉变成机房的主人。算法与数据结构:让你在遇到性能瓶颈时,知道问题的本质,并知道用什么“武器”去解决,而不是永远只会蛮力循环。Git:让你写代码时有胆量创新、有后悔药可吃、能与人合作。网络与系统设计:让你能从 “盖一个狗窝” 进阶到 “设计一座摩天大楼” ,并且知道如何防震、防火、防拥堵。清晰的沟通:让你所有的技术和努力能被别人看见、理解并认可,将你的价值放大10倍。最终结论:你学 PHP + SQL + JS,是在学习 “如何制造零件和组装一辆自行车”。而学习那些底层知识,是在学习 “内燃机原理、道路规划、交通法规、车队管理”。当你想造一辆汽车,甚至管理一个物流网络时,后者是决定性因素。给你的行动建议:继续用你喜欢的网页技术做项目,这是你的动力源泉和试验田。当项目遇到实际问题时(比如慢了、崩了、难合作了),把这当作学习那些“底层知识”的绝佳入口。带着问题去学习:比如今天网站慢了,你就去研究“SQL索引优化”;明天要团队开发,就去学“Git分支模型”。这样学来的知识,立刻就能用上,你立刻就能感受到它的“用处”。你不是在学一堆无用的理论,你是在为你亲手创造的世界,打下越来越坚实的地基,并获得建造更高大厦的蓝图与工具。
2025年12月25日
2 阅读
0 评论
0 点赞
2025-12-25
调用API重新加载数据知识点
try-catch错误捕获机制try-catch-finally结构 try { // 尝试执行的代码,可能会抛出错误 const result = await riskyOperation(); } catch (error) { // 捕获错误,进行错误处理 console.error('操作失败:', error); } finally { // 无论成功或失败都会执行的代码 cleanup(); }错误类型分类try { await fetch('https://api.example.com/data'); } catch (error) { if (error instanceof TypeError) { // 网络错误或URL错误 console.error('网络错误:', error.message); } else if (error instanceof SyntaxError) { // JSON解析错误 console.error('数据格式错误'); } else if (error.name === 'AbortError') { // 请求被取消 console.error('请求超时'); } else { // 其他未知错误 console.error('未知错误:', error); } }异步操作:使用async/await处理异步API调用async/await基本概念// 传统Promise方式(回调地狱) function oldWay() { fetch(url) .then(response => response.json()) .then(data => { return processData(data); }) .then(result => { console.log(result); }) .catch(error => { console.error(error); }); } // async/await方式(同步写法) async function newWay() { try { const response = await fetch(url); const data = await response.json(); const processed = await processData(data); console.log(processed); } catch (error) { console.error(error); } }await的工作机制async function example() { console.log('1. 开始执行'); // await会暂停函数执行,等待Promise完成 const result = await someAsyncFunction(); // ⬆️ 这里会"等待",但不会阻塞主线程 console.log('3. 异步操作完成:', result); } console.log('0. 函数调用前'); example(); console.log('2. 函数已调用(不会等待)'); // 输出顺序: 0 → 1 → 2 → 3并行与串行执行// 1. 串行执行(一个接一个) async function serialExecution() { console.time('串行'); const result1 = await fetchData1(); // 等待2秒 const result2 = await fetchData2(); // 等待3秒(等第一个完成后才开始) console.timeEnd('串行'); // 总耗时≈5秒 } // 2. 并行执行(同时进行) async function parallelExecution() { console.time('并行'); const promise1 = fetchData1(); // 立即开始,不等待 const promise2 = fetchData2(); // 立即开始,不等待 // 使用Promise.all同时等待多个Promise const [result1, result2] = await Promise.all([promise1, promise2]); console.timeEnd('并行'); // 总耗时≈3秒(取最长的) } // 3. 竞赛模式(谁先完成用谁) async function raceExecution() { const result = await Promise.race([ fetchWithTimeout('api1', 2000), fetchWithTimeout('api2', 2000) ]); // 第一个完成的(无论成功或失败)会被返回 }错误处理模式对比// 模式1:每个await单独try-catch async function individualCatch() { let data; try { data = await fetchData(); } catch (error) { console.error('获取数据失败:', error); return; } try { await processData(data); } catch (error) { console.error('处理数据失败:', error); } } // 模式2:统一错误处理 async function unifiedCatch() { try { const data = await fetchData(); await processData(data); await saveData(data); } catch (error) { // 任何一个步骤失败都会跳到这里 handleError(error); } } // 模式3:使用高阶函数包装 function withErrorHandling(asyncFunc) { return async function(...args) { try { return await asyncFunc(...args); } catch (error) { console.error('函数执行失败:', error); return { error: true, message: error.message }; } }; } const safeFetch = withErrorHandling(fetchData); const result = await safeFetch(url);实际案例<script> // 当DOM内容完全加载后执行(确保所有HTML元素已存在) document.addEventListener('DOMContentLoaded', function() { // 获取页面中的按钮元素 const reloadBtn = document.getElementById('reload-btn'); // 获取显示结果的div元素 const resultDiv = document.getElementById('result'); // 获取显示服务器URL的span元素(虽然代码中未使用,但已定义) const serverUrlSpan = document.getElementById('server-url'); // 获取当前页面的主机名和端口号,用于构建API URL(备用) const currentHost = window.location.hostname; const currentPort = window.location.port; // 为"更新数据"按钮添加点击事件监听器 reloadBtn.addEventListener('click', async function() { // 禁用按钮,防止用户重复点击 reloadBtn.disabled = true; // 更改按钮文字提示用户正在更新 reloadBtn.textContent = '更新中...'; // 清空之前显示的结果 resultDiv.className = 'hidden'; // 添加隐藏类 resultDiv.innerHTML = ''; // 清空内容 try { // 显示加载状态 resultDiv.className = 'loading'; // 添加加载样式类 resultDiv.textContent = '正在重新加载数据...'; resultDiv.classList.remove('hidden'); // 移除隐藏类,显示div // 调用API发送POST请求到指定端点 const response = await fetch(`https://api.demo.top/api/reload`, { method: 'POST', // 使用POST方法 headers: { 'Content-Type': 'application/json' // 设置请求头为JSON格式 } }); // 将响应解析为JSON格式 const result = await response.json(); // 根据API返回的成功状态设置结果显示样式 resultDiv.className = result.success ? 'success' : 'error'; // 构建要显示的结果HTML内容 let html = ''; if (result.success) { // 成功情况的显示内容 html += '<div class="status-line"><strong>✅ 数据重载成功</strong></div>'; html += `<div class="status-line">${result.message}</div>`; // 如果有详细数据,显示详细信息 if (result.data) { html += '<hr style="margin: 15px 0;">'; // 添加分隔线 html += '<div class="status-line"><strong>详细信息:</strong></div>'; html += `<div class="status-line">重载前: ${result.data.before} 条记录</div>`; html += `<div class="status-line">重载后: ${result.data.after} 条记录</div>`; html += `<div class="status-line">变化: ${result.data.difference > 0 ? '+' : ''}${result.data.difference} 条记录</div>`; html += `<div class="status-line">时间: ${result.data.timestamp}</div>`; } } else { // 失败情况的显示内容 html += '<div class="status-line"><strong>❌ 数据重载失败</strong></div>'; html += `<div class="status-line">${result.message}</div>`; // 如果有错误详情,显示错误信息 if (result.error) { html += `<div class="status-line">错误: ${result.error}</div>`; } } // 将构建的HTML插入结果div resultDiv.innerHTML = html; } catch (error) { // 捕获网络错误或其他异常 resultDiv.className = 'error'; resultDiv.innerHTML = ` <div class="status-line"><strong>❌ 请求失败</strong></div> <div class="status-line">无法连接到服务器</div> <div class="status-line">错误: ${error.message}</div> <div class="status-line">请确保服务器正在运行</div> `; } finally { // 无论成功或失败,最后都会执行这里 // 恢复按钮的可用状态 reloadBtn.disabled = false; // 恢复按钮文字 reloadBtn.textContent = '更新数据'; } }); }); </script>
2025年12月25日
1 阅读
0 评论
0 点赞
2025-12-16
正则表达式核心用法
三、常见模式示例(直接拿来用) 现在我们把上面的规则组合起来,看看实际应用。 匹配手机号(中国大陆):1[3-9]\d{9} 1:以1开头 [3-9]:第二位是3-9 \d{9}:后面跟着9个数字 示例匹配:13800138000 匹配电子邮箱:\w+@\w+\.\w+ \w+:一个或多个单词字符(用户名) @:字面量@ \w+:一个或多个单词字符(域名) \.:转义的点号(.是元字符,需要\转义) \w+:一个或多个单词字符(顶级域名,如com) 简单示例匹配:test@example.com(实际邮箱更复杂,这是简化版) 提取日期(YYYY-MM-DD格式):(\d{4})-(\d{2})-(\d{2}) 这里引入了 () 分组 的概念。括号内的内容会被单独“捕获”,方便你提取。 匹配 2023-10-27 后,可以分别获得 2023、10、27 三个部分。 匹配空白行:^\s*$ ^:行首 \s*:0个或多个空白字符 $:行尾 这行除了空白什么都没有,所以是空白行。
2025年12月16日
1 阅读
0 评论
0 点赞
2025-12-05
JavaScript DOM 相关知识整理
1. DOM 简介 DOM (Document Object Model) 是一种以树形结构表示 HTML 或 XML 文档的编程接口。它将文档解析为一个由节点和对象组成的结构,使编程语言能够连接和操作文档。 1.1 DOM 树结构 - Document - Element (html) - Element (head) - Element (title) - Text - Element (body) - Element (div) - Element (p) - Text 2. 节点类型 DOM 树中的每个节点都是一个对象,主要有以下几种类型: 节点类型 Node常量 nodeType 值 元素节点 Node.ELEMENT_NODE 1 属性节点 Node.ATTRIBUTE_NODE 2 文本节点 Node.TEXT_NODE 3 注释节点 Node.COMMENT_NODE 8 文档节点 Node.DOCUMENT_NODE 9 3. 获取 DOM 元素 3.1 基本获取方法 // 通过 ID 获取单个元素 document.getElementById('myId'); // 通过类名获取元素集合 (HTMLCollection) document.getElementsByClassName('myClass'); // 通过标签名获取元素集合 (HTMLCollection) document.getElementsByTagName('div'); // 通过 CSS 选择器获取单个元素 document.querySelector('#myId .myClass'); // 通过 CSS 选择器获取所有匹配元素 (NodeList) document.querySelectorAll('div.className'); 3.2 新增获取方法 (HTML5) // 通过元素 name 属性获取 document.getElementsByName('username'); // 获取第一个匹配的表单元素 document.forms['myForm']; document.images; document.links; 4. DOM 操作 4.1 元素创建 // 创建元素节点 const newDiv = document.createElement('div'); // 创建文本节点 const textNode = document.createTextNode('Hello World'); // 创建完整元素 (设置文本内容) const div = document.createElement('div'); div.textContent = 'Hello World'; // 或者 div.innerHTML = '<span>Hello</span> World'; 4.2 元素添加 // 添加子元素 (作为最后一个子元素) parentElement.appendChild(newElement); // 在指定位置插入元素 parentElement.insertBefore(newElement, referenceElement); // 在特定位置插入 HTML (不推荐用于用户内容,有 XSS 风险) parentElement.insertAdjacentHTML('beforebegin', htmlString); insertAdjacentHTML 位置参数: beforebegin: 元素前面 afterbegin: 元素内部第一个子元素前面 beforeend: 元素内部最后一个子元素后面 afterend: 元素后面 4.3 元素移除 // 移除子元素 parentElement.removeChild(childElement); // 直接移除自身 (现代浏览器) element.remove(); // 移除所有子元素 element.innerHTML = ''; // 或者 while (element.firstChild) { element.removeChild(element.firstChild); } 4.4 元素替换 parentElement.replaceChild(newElement, oldElement); 4.5 克隆元素 // 浅克隆 (只克隆元素,不克隆子元素) const shallowClone = element.cloneNode(false); // 深克隆 (克隆元素及其所有子元素) const deepClone = element.cloneNode(true); 5. 元素属性与特性 5.1 属性访问 // 获取属性 element.getAttribute('class'); // 设置属性 element.setAttribute('class', 'myClass'); // 移除属性 element.removeAttribute('class'); // 属性存在性检查 element.hasAttribute('class'); 5.2 DOM 属性与 HTML 特性 // DOM 属性 (直接访问) element.id = 'newId'; element.className = 'newClass'; element.value = 'newValue'; // HTML 特性 (通过 attribute 方法) element.setAttribute('data-value', '123'); const dataValue = element.getAttribute('data-value'); 5.3 类名操作 // 检查类名 element.classList.contains('myClass'); // 添加类名 element.classList.add('newClass'); // 移除类名 element.classList.remove('oldClass'); // 切换类名 element.classList.toggle('active'); // 替换类名 element.classList.replace('old', 'new'); 6. 元素样式操作 // 直接修改样式 (行内样式) element.style.color = 'red'; element.style.backgroundColor = '#f0f0f0'; element.style.cssText = 'color: red; background: #f0f0f0;'; // 获取计算样式 (所有最终样式) const computedStyle = window.getComputedStyle(element); console.log(computedStyle.color); 7. 元素尺寸与位置 7.1 尺寸 // 内容区域尺寸 (不包括边框和内边距) element.clientWidth; element.clientHeight; // 总尺寸 (包括边框和内边距) element.offsetWidth; element.offsetHeight; // 尺寸 (精确到浮点数) element.getBoundingClientRect().width; element.getBoundingClientRect().height; 7.2 位置 // 元素相对于文档的位置 (包括滚动偏移) element.offsetTop; element.offsetLeft; // 元素相对于最近的已定位祖先元素的位置 element.getBoundingClientRect().top; element.getBoundingClientRect().left; // 元素相对于视口的位置 const rect = element.getBoundingClientRect(); console.log(rect.top, rect.left, rect.width, rect.height); 8. 事件处理 8.1 事件绑定 // 方式1: 事件属性 element.onclick = function() { /* 处理函数 */ }; // 方式2: addEventListener (推荐) element.addEventListener('click', function() { /* 处理函数 */ }); // 多个事件监听器 element.addEventListener('click', handler1); element.addEventListener('click', handler2); // 一次性事件 element.addEventListener('click', function handler() { // 执行后自动移除 }, { once: true }); 8.2 事件对象 element.addEventListener('click', function(e) { console.log(e.type); // 事件类型 (click) console.log(e.target); // 事件目标元素 console.log(e.currentTarget); // 当前处理事件的元素 console.log(e.eventPhase); // 事件阶段 (1: 捕获, 2: 目标, 3: 冒泡) // 鼠标事件 e.clientX; e.clientY; // 相对于视口的坐标 e.pageX; e.pageY; // 相对于文档的坐标 // 阻止默认行为 e.preventDefault(); // 阻止事件冒泡 e.stopPropagation(); }); 8.3 事件委托 // 在父元素上监听子元素的事件 document.querySelector('ul').addEventListener('click', function(e) { if (e.target.tagName === 'LI') { // 处理 li 的点击 } }); 8.4 常见事件类型 鼠标事件: click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave 键盘事件: keydown, keyup, keypress 表单事件: submit, reset, change, focus, blur, input 窗口事件: load, resize, scroll, unload
2025年12月05日
5 阅读
0 评论
0 点赞
2025-12-04
oracle查询语句在内部可以运行,但套入变量就不行问题
$sql = " SELECT i.SPECIFICATION, i.MD_ID, i.MD_NAME, i.REVISIONID FROM PLM2024.ITEM_0 i INNER JOIN ( SELECT MD_ID, MAX(REVISIONID) AS latest_revision FROM PLM2024.ITEM_0 WHERE REGEXP_LIKE(MD_ID, '^(XC|XQ|QD|QB|QE|QF|QG|QH|QM|QN|QR|QY)') GROUP BY MD_ID ) latest ON i.MD_ID = latest.MD_ID AND i.REVISIONID = latest.latest_revision WHERE REGEXP_LIKE(i.MD_ID, '^(XC|XQ|QD|QB|QE|QF|QG|QH|QM|QN|QR|QY)'); "; 里面的语句能在oracle里正常运行,但是套入$sql里就查不了了解决办法$sql = <<<SQL SELECT i.SPECIFICATION, i.MD_ID, i.MD_NAME, i.REVISIONID FROM PLM2024.ITEM_0 i INNER JOIN ( SELECT MD_ID, MAX(REVISIONID) AS latest_revision FROM PLM2024.ITEM_0 WHERE REGEXP_LIKE(MD_ID, '^(XC|XQ|QD|QB|QE|QF|QG|QH|QM|QN|QR|QY)') GROUP BY MD_ID ) latest ON i.MD_ID = latest.MD_ID AND i.REVISIONID = latest.latest_revision WHERE REGEXP_LIKE(i.MD_ID, '^(XC|XQ|QD|QB|QE|QF|QG|QH|QM|QN|QR|QY)') SQL;这个问题通常是由于 SQL语句中的换行符和引号处理 导致的。在PHP中直接将多行SQL字符串赋值给变量时,需要注意以下几点:问题分析换行符问题:PHP中的多行字符串会包含实际换行符引号转义:SQL语句中的引号可能需要转义SQLPlus与PHP环境差异:在SQLPlus中能运行不代表在PHP中也能直接运行HEREDOC语法详解 什么是HEREDOC? HEREDOC(Here Document)是PHP中一种定义多行字符串的语法结构,特别适合处理包含大量文本、HTML或SQL代码的情况。 $string = <<<标识符 多行文本内容 标识符; HEREDOC的特点 1. 保留所有格式 $sql = <<<SQL SELECT * FROM users WHERE status = 'active' AND created_at > '2024-01-01' ORDER BY id DESC SQL; // SQL字符串会完全保留换行和缩进 2. 变量解析 HEREDOC中会解析变量(类似于双引号字符串): $name = "张三"; $age = 25; $text = <<<TEXT 姓名:$name 年龄:$age 职业:程序员 TEXT; echo $text; /* 输出: 姓名:张三 年龄:25 职业:程序员 */ 3. 支持复杂表达式 $user = ['name' => '李四', 'age' => 30]; $text = <<<TEXT 用户信息: 姓名:{$user['name']} 年龄:{$user['age']} TEXT; 使用规则和注意事项 重要规则: 标识符命名:自定义,通常使用大写字母(如SQL、EOD、HTML等) 结束标识符: 必须单独一行 必须顶格写(不能有缩进) 后面只能有分号,不能有其他字符 在PHP中,HEREDOC语法中的标识符(如SQL、EOD、HTML)是自定义的,没有预定义的标准格式。你可以使用任何有效的标签名称,但通常使用大写字母以增强可读性,并且要与内容有所区分。重要规则:标识符由字母、数字和下划线组成,且必须以字母或下划线开头。开始标识符(<<<之后)和结束标识符必须相同,结束标识符必须顶格写,且后面只能有分号(不能有任何其他字符,包括空格)。开始标识符可以用双引号括起来,也可以不用(但通常不用)。如果用双引号,则与不用一样,都是HEREDOC;如果用单引号,则变成Nowdoc,不解析变量。示例:$str = <<<EOD示例文本EOD;$str = <<<'EOD'示例文本(不解析变量)EOD;注意:在PHP 7.3.0之前,结束标识符必须从行的第一列开始,并且后面只能有一个分号(或没有分号,但必须是行结束)。从PHP 7.3.0开始,结束标识符可以缩进,但缩进部分会被从每行文本中去除(称为“缩进终止”)。因此,在编写HEREDOC时,选择标识符要避免与内容中的字符串冲突。例如,如果你在写SQL,使用“SQL”作为标识符很直观,但要确保在内容中不会出现“SQL”这个词单独在一行且顶格。
2025年12月04日
6 阅读
0 评论
0 点赞
1
2
3
4
...
32
0:00