搜索

📄 文章 📚 合集
热门搜索
🐘 PHP ⚡ Laravel 🎨 Vue.js ⚛️ React 📦 Yii 📘 JavaScript 🗄️ MySQL 🐳 Docker
返回合集

[板块5:静态页面生成器] - 02- 创建页面渲染服务

代码示例
## 创建页面渲染服务

### 新建文件夹 Services
### 新建文件:`app/Services/PageRenderService.php`

**文件路径**:`app/Services/PageRenderService.php`

**完整代码**:

```php
<?php

namespace App\Services;

use App\Models\Page;
use App\Models\PageComponent;

class PageRenderService
{
    /**
     * 渲染整个页面为 HTML
     */
    public function render(Page $page): string
    {
        $components = $page->components()->orderBy('sort_order')->get();
        
        $html = '';
        foreach ($components as $component) {
            $html .= $this->renderComponent($component);
        }
        
        return $this->wrapWithLayout($page, $html);
    }
    
    /**
     * 渲染单个组件
     */
    protected function renderComponent(PageComponent $component): string
    {
        $content = $component->content ?? [];
        $settings = $component->settings ?? [];
        
        $method = 'render' . ucfirst($component->component_type);
        if (method_exists($this, $method)) {
            return $this->$method($content, $settings);
        }
        
        return $this->renderDefault($content, $settings);
    }
    
    /**
     * 渲染横幅组件
     */
    protected function renderBanner(array $content, array $settings): string
    {
        $title = $content['title'] ?? '';
        $subtitle = $content['subtitle'] ?? '';
        $imageUrl = $content['image_url'] ?? '';
        $linkUrl = $content['link_url'] ?? '';
        
        $style = $imageUrl ? 'background-image: url(' . e($imageUrl) . '); background-size: cover; background-position: center;' : '';
        
        $html = '<div class="banner" style="' . $style . '">';
        $html .= '<div class="banner-content">';
        $html .= '<h1>' . e($title) . '</h1>';
        if ($subtitle) {
            $html .= '<p>' . e($subtitle) . '</p>';
        }
        if ($linkUrl) {
            $html .= '<a href="' . e($linkUrl) . '" class="banner-btn">了解更多</a>';
        }
        $html .= '</div></div>';
        
        return $html;
    }
    
    /**
     * 渲染文本组件
     */
    protected function renderText(array $content, array $settings): string
    {
        $title = $content['title'] ?? '';
        $text = $content['text'] ?? '';
        
        $html = '<div class="text-block">';
        if ($title) {
            $html .= '<h2>' . e($title) . '</h2>';
        }
        if ($text) {
            $html .= '<p>' . nl2br(e($text)) . '</p>';
        }
        $html .= '</div>';
        
        return $html;
    }
    
    /**
     * 渲染图片组件
     */
    protected function renderImage(array $content, array $settings): string
    {
        $imageUrl = $content['image_url'] ?? '';
        $linkUrl = $content['link_url'] ?? '';
        $alt = $content['title'] ?? '';
        
        $img = '<img src="' . e($imageUrl) . '" alt="' . e($alt) . '">';
        
        if ($linkUrl) {
            return '<div class="image-block"><a href="' . e($linkUrl) . '">' . $img . '</a></div>';
        }
        
        return '<div class="image-block">' . $img . '</div>';
    }
    
    /**
     * 默认渲染(未实现的组件类型)
     */
    protected function renderDefault(array $content, array $settings): string
    {
        return '<div class="component">组件开发中</div>';
    }
    
    /**
     * 包裹页面布局
     */
    protected function wrapWithLayout(Page $page, string $content): string
    {
        $site = \App\Models\Site::first();
        
        return view('frontend.layouts.app', [
            'title' => $page->title,
            'siteName' => $site->site_name ?? '好站站',
            'siteKeywords' => $site->site_keywords ?? '',
            'siteDescription' => $site->site_description ?? '',
            'content' => $content,
        ])->render();
    }
}
```

**修改原因**:
- `render()`:遍历页面所有组件,按 sort_order 顺序渲染
- `renderComponent()`:根据组件类型(banner、text、image 等)动态调用对应的渲染方法
- `renderBanner()`:渲染横幅组件,支持背景图、标题、副标题、按钮
- `renderText()`:渲染文本组件,支持标题和段落内容
- `renderImage()`:渲染图片组件,支持图片和链接跳转
- `renderDefault()`:未实现组件的占位渲染
- `wrapWithLayout()`:将渲染的内容嵌入到前台布局模板中

---

🧸 adorable code

专注 PHP、JavaScript、Laravel、Vue.js、React、Yii 全栈开发。记录技术探索过程中的灵感与经验,分享工程实践洞见。

hello@adorablecode.com