<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FrankenPHP 扩展开发指南</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-gradient: linear-gradient(160deg, #0f172a 0%, #020617 100%);
--card-bg: rgba(30, 41, 59, 0.7);
--card-border: rgba(56, 189, 248, 0.15);
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
--accent-blue: #38bdf8;
--accent-green: #34d399;
--accent-purple: #a78bfa;
--accent-pink: #f472b6;
--code-bg: #0f172a;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', sans-serif;
background: var(--bg-gradient);
color: var(--text-primary);
min-height: 960px;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.poster-container {
width: 720px;
min-height: 960px;
background: transparent;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
}
/* Decorative Background Elements */
.orb {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.4;
z-index: 0;
}
.orb-1 { width: 300px; height: 300px; background: var(--accent-blue); top: -100px; left: -100px; }
.orb-2 { width: 400px; height: 400px; background: var(--accent-purple); bottom: -150px; right: -150px; }
.content-wrapper {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
gap: 24px;
height: 100%;
padding: 10px;
}
/* Header */
.header {
text-align: left;
padding-bottom: 10px;
border-bottom: 1px solid rgba(255,255,255,0.1);
}
.badge {
display: inline-flex;
align-items: center;
background: rgba(56, 189, 248, 0.1);
color: var(--accent-blue);
padding: 6px 12px;
border-radius: 20px;
font-size: 14px;
font-weight: 600;
margin-bottom: 16px;
border: 1px solid rgba(56, 189, 248, 0.2);
}
.title {
font-size: 52px;
font-weight: 800;
line-height: 1.1;
background: linear-gradient(90deg, #fff, #94a3b8);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 8px;
}
.subtitle {
font-size: 22px;
color: var(--text-secondary);
font-weight: 300;
}
/* Grid Layout for Features */
.feature-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.card {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 20px;
padding: 24px;
backdrop-filter: blur(10px);
display: flex;
flex-direction: column;
transition: transform 0.3s ease;
}
.card-full {
grid-column: span 2;
}
.card-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 16px;
}
.card-icon {
color: var(--accent-green);
font-size: 28px;
}
.card-title {
font-size: 20px;
font-weight: 700;
color: var(--text-primary);
}
.card-text {
font-size: 16px;
color: var(--text-secondary);
line-height: 1.6;
}
/* Code Block */
.code-block {
background: var(--code-bg);
border-radius: 12px;
padding: 20px;
font-family: 'JetBrains Mono', monospace;
font-size: 14px;
border: 1px solid rgba(255,255,255,0.05);
overflow-x: auto;
white-space: pre;
color: #e2e8f0;
line-height: 1.5;
flex-grow: 1;
}
.keyword { color: var(--accent-pink); }
.func { color: var(--accent-blue); }
.string { color: var(--accent-green); }
.comment { color: #64748b; font-style: italic; }
.type { color: var(--accent-purple); }
/* List Styles */
.check-list {
list-style: none;
display: flex;
flex-direction: column;
gap: 12px;
}
.check-item {
display: flex;
align-items: flex-start;
gap: 10px;
font-size: 15px;
color: var(--text-secondary);
}
.check-item i {
color: var(--accent-green);
font-size: 20px;
margin-top: 2px;
}
/* Process Steps */
.steps-container {
display: flex;
justify-content: space-between;
position: relative;
margin-top: 10px;
}
.step {
text-align: center;
flex: 1;
position: relative;
}
.step-num {
width: 36px;
height: 36px;
background: rgba(56, 189, 248, 0.1);
border: 1px solid var(--accent-blue);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: var(--accent-blue);
font-weight: bold;
margin: 0 auto 10px;
}
.step-title {
font-weight: 600;
font-size: 15px;
color: var(--text-primary);
margin-bottom: 4px;
}
.step-desc {
font-size: 12px;
color: var(--text-secondary);
}
.divider-line {
position: absolute;
top: 18px;
left: 15%;
right: 15%;
height: 1px;
background: linear-gradient(90deg, transparent, var(--card-border), transparent);
z-index: 0;
}
.footer {
margin-top: auto;
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 20px;
border-top: 1px solid rgba(255,255,255,0.05);
font-size: 14px;
color: var(--text-secondary);
}
.tag-group {
display: flex;
gap: 8px;
}
.tag {
background: rgba(255,255,255,0.05);
padding: 4px 10px;
border-radius: 6px;
font-size: 12px;
color: #cbd5e1;
}
</style>
</head>
<body>
<div class="poster-container">
<!-- Background Orbs -->
<div class="orb orb-1"></div>
<div class="orb orb-2"></div>
<div class="content-wrapper">
<!-- Header -->
<header class="header">
<div class="badge">
<i class="material-icons" style="font-size: 16px; margin-right: 6px;">bolt</i>
高性能原生扩展
</div>
<h1 class="title">FrankenPHP<br>扩展开发指南</h1>
<p class="subtitle">使用 Go 语言编写 PHP 扩展,释放协程并发潜力</p>
</header>
<!-- Main Content Grid -->
<div class="feature-grid">
<!-- Concept Card -->
<div class="card">
<div class="card-header">
<i class="material-icons card-icon">rocket_launch</i>
<h3 class="card-title">核心优势</h3>
</div>
<ul class="check-list">
<li class="check-item">
<i class="material-icons">check_circle</i>
<span><strong>无需 C 代码</strong>:纯 Go 开发,避开复杂的 C/CGO</span>
</li>
<li class="check-item">
<i class="material-icons">check_circle</i>
<span><strong>高性能并发</strong>:直接利用 Goroutines 协程模型</span>
</li>
<li class="check-item">
<i class="material-icons">check_circle</i>
<span><strong>生态复用</strong>:无缝使用现有 Go 库生态</span>
</li>
</ul>
</div>
<!-- Type System Card -->
<div class="card">
<div class="card-header">
<i class="material-icons card-icon">schema</i>
<h3 class="card-title">类型系统</h3>
</div>
<p class="card-text" style="margin-bottom: 12px;">提供公共类型 API,自动处理 PHP 与 Go 间的类型转换。</p>
<ul class="check-list">
<li class="check-item"><i class="material-icons">data_object</i><span>支持 Int, Float, Bool</span></li>
<li class="check-item"><i class="material-icons">text_fields</i><span>String: frankenphp.GoString</span></li>
<li class="check-item"><i class="material-icons">view_list</i><span>Array: frankenphp.Array</span></li>
</ul>
</div>
<!-- Code Example Card (Full Width) -->
<div class="card card-full">
<div class="card-header">
<i class="material-icons card-icon" style="color: var(--accent-blue);">code</i>
<h3 class="card-title">定义 PHP 函数</h3>
</div>
<div class="code-block">
<span class="comment">// 使用指令注释定义 PHP 函数签名</span>
<span class="comment">//export_php:function repeat_this(string $str, int $n): string</span>
<span class="keyword">func</span> <span class="func">repeat_this</span>(s *<span class="type">C.zend_string</span>, n <span class="type">int64</span>) <span class="type">unsafe.Pointer</span> {
<span class="comment">// Go 转换辅助函数</span>
str := frankenphp.<span class="func">GoString</span>(<span class="type">unsafe</span>.<span class="func">Pointer</span>(s))
result := strings.<span class="func">Repeat</span>(str, <span class="type">int</span>(n))
<span class="comment">// 返回 PHP 兼容类型</span>
<span class="keyword">return</span> frankenphp.<span class="func">PHPString</span>(result, <span class="keyword">false</span>)
}</div>
</div>
<!-- Development Process -->
<div class="card card-full">
<div class="card-header">
<i class="material-icons card-icon">timeline</i>
<h3 class="card-title">开发流程</h3>
</div>
<div class="steps-container">
<div class="divider-line"></div>
<div class="step">
<div class="step-num">1</div>
<div class="step-title">创建模块</div>
<div class="step-desc">go mod init ...</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-title">编写扩展</div>
<div class="step-desc">定义函数与类</div>
</div>
<div class="step">
<div class="step-num">3</div>
<div class="step-title">生成存根</div>
<div class="step-desc">extension-init</div>
</div>
<div class="step">
<div class="step-num">4</div>
<div class="step-title">编译集成</div>
<div class="step-desc">嵌入 FrankenPHP</div>
</div>
</div>
</div>
<!-- Advanced Features -->
<div class="card card-full">
<div class="card-header">
<i class="material-icons card-icon">extension</i>
<h3 class="card-title">高级特性</h3>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px;">
<div style="background: rgba(255,255,255,0.03); padding: 15px; border-radius: 12px;">
<strong style="color: var(--accent-purple); font-size: 16px;">不透明类</strong>
<p style="font-size: 13px; color: var(--text-secondary); margin-top: 6px;">
使用 <code style="color: var(--accent-blue);">//export_php:class</code> 封装 Go 结构体
</p>
</div>
<div style="background: rgba(255,255,255,0.03); padding: 15px; border-radius: 12px;">
<strong style="color: var(--accent-purple); font-size: 16px;">类方法</strong>
<p style="font-size: 13px; color: var(--text-secondary); margin-top: 6px;">
通过方法暴露行为,保障内部状态安全
</p>
</div>
<div style="background: rgba(255,255,255,0.03); padding: 15px; border-radius: 12px;">
<strong style="color: var(--accent-purple); font-size: 16px;">常量导出</strong>
<p style="font-size: 13px; color: var(--text-secondary); margin-top: 6px;">
支持全局常量与类常量的跨语言共享
</p>
</div>
</div>
</div>
</div>
<!-- Footer -->
<footer class="footer">
<div class="tag-group">
<span class="tag">GoLang</span>
<span class="tag">PHP 8.2+</span>
<span class="tag">Worker Mode</span>
</div>
<div style="display: flex; align-items: center; gap: 6px;">
<i class="material-icons" style="font-size: 16px;">auto_awesome</i>
<span>frankenphp.dev</span>
</div>
</footer>
</div>
</div>
</body>
</html>
登录后可参与表态
讨论回复
1 条回复
✨步子哥 (steper)
#1
03-13 16:08
登录后可参与表态