You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在本地localhost用核心PHP实现Facebook Instant Article SDK及HTML自动转换

Step-by-Step Guide to Convert HTML to Facebook Instant Articles with Core PHP (Localhost)

Got it, let's walk through how to turn regular HTML into Facebook Instant Articles (IA) format using plain PHP—no frameworks needed. Since you already know how to submit articles via the Graph API, we’ll focus on the conversion logic first, then tie it to your existing workflow.


1. First, Understand the Instant Articles Structure

Facebook requires a specific HTML structure for Instant Articles. Here’s the bare minimum you need to hit:

<!doctype html>
<html lang="en" prefix="op:http://media.facebook.com/op#">
<head>
  <meta charset="utf-8">
  <link rel="canonical" href="YOUR_ARTICLE_CANONICAL_URL">
  <meta property="op:markup_version" content="v1.0">
</head>
<body>
  <article>
    <header>
      <h1>Article Title</h1>
      <time class="op-published" datetime="2024-05-20T12:00:00+00:00">May 20, 2024</time>
      <address>
        <a rel="author" href="AUTHOR_PROFILE_URL">Author Name</a>
      </address>
      <figure>
        <img src="HEADER_IMAGE_URL" />
        <figcaption>Header Image Caption</figcaption>
      </figure>
    </header>
    
    <!-- Your converted article content goes here -->
    <p>...</p>
    <figure>
      <img src="INLINE_IMAGE_URL" />
      <figcaption>Inline Image Caption</figcaption>
    </figure>
    
    <footer>
      <p>© 2024 Your Site. All rights reserved.</p>
    </footer>
  </article>
</body>
</html>

Key notes:

  • The prefix attribute on the <html> tag is mandatory.
  • The canonical URL must match your original article’s public URL.
  • Images need to be wrapped in <figure> tags with optional captions.

2. Prep Your Local PHP Environment

Before writing code, make sure your localhost setup is ready:

  • Use PHP 7.0 or newer (DOMDocument works more reliably here).
  • Enable the DOMDocument extension:
    1. Open your php.ini file (found in XAMPP/WAMP/MAMP config folders).
    2. Find ;extension=dom and remove the leading semicolon.
    3. Restart your local server.
  • Test the extension: Create a test-dom.php file with <?php var_dump(class_exists('DOMDocument')); ?>—it should return bool(true) when you access it via localhost.

3. Build the Core Conversion Function

We’ll use DOMDocument to parse your regular HTML and rebuild it into IA-compliant markup. Create a file named ia-converter.php with this code:

<?php
function convertToInstantArticle(string $regularHtml, array $metadata): string {
    // Initialize DOM parser for regular HTML (suppress malformed HTML warnings)
    libxml_use_internal_errors(true);
    $sourceDom = new DOMDocument();
    $sourceDom->loadHTML($regularHtml);
    libxml_clear_errors();

    // Create a new DOM for the Instant Article
    $iaDom = new DOMDocument('1.0', 'UTF-8');
    $iaDom->formatOutput = true;

    // Build the root HTML element with required prefix
    $html = $iaDom->createElement('html');
    $html->setAttribute('lang', 'en');
    $html->setAttribute('prefix', 'op:http://media.facebook.com/op#');
    $iaDom->appendChild($html);

    // Build the HEAD section
    $head = $iaDom->createElement('head');
    // Charset meta tag
    $charset = $iaDom->createElement('meta');
    $charset->setAttribute('charset', 'utf-8');
    $head->appendChild($charset);
    // Canonical link
    $canonical = $iaDom->createElement('link');
    $canonical->setAttribute('rel', 'canonical');
    $canonical->setAttribute('href', $metadata['canonical_url']);
    $head->appendChild($canonical);
    // IA markup version
    $markupVersion = $iaDom->createElement('meta');
    $markupVersion->setAttribute('property', 'op:markup_version');
    $markupVersion->setAttribute('content', 'v1.0');
    $head->appendChild($markupVersion);
    $html->appendChild($head);

    // Build BODY and ARTICLE elements
    $body = $iaDom->createElement('body');
    $article = $iaDom->createElement('article');
    $body->appendChild($article);
    $html->appendChild($body);

    // Build the HEADER with metadata
    $header = $iaDom->createElement('header');
    // Title
    $title = $iaDom->createElement('h1', $metadata['title']);
    $header->appendChild($title);
    // Published time
    $published = $iaDom->createElement('time', $metadata['published_date']);
    $published->setAttribute('class', 'op-published');
    $published->setAttribute('datetime', $metadata['published_datetime']);
    $header->appendChild($published);
    // Author
    $address = $iaDom->createElement('address');
    $authorLink = $iaDom->createElement('a', $metadata['author_name']);
    $authorLink->setAttribute('rel', 'author');
    $authorLink->setAttribute('href', $metadata['author_url']);
    $address->appendChild($authorLink);
    $header->appendChild($address);
    // Header image (if provided)
    if (!empty($metadata['header_image_url'])) {
        $figure = $iaDom->createElement('figure');
        $img = $iaDom->createElement('img');
        $img->setAttribute('src', $metadata['header_image_url']);
        $figure->appendChild($img);
        if (!empty($metadata['header_image_caption'])) {
            $figcaption = $iaDom->createElement('figcaption', $metadata['header_image_caption']);
            $figure->appendChild($figcaption);
        }
        $header->appendChild($figure);
    }
    $article->appendChild($header);

    // Convert regular content to IA format
    $contentNodes = $sourceDom->getElementsByTagName('body')->item(0)->childNodes;
    foreach ($contentNodes as $node) {
        $convertedNode = convertNodeToIA($iaDom, $node);
        if ($convertedNode) {
            $article->appendChild($convertedNode);
        }
    }

    // Add footer (optional but recommended)
    if (!empty($metadata['footer'])) {
        $footer = $iaDom->createElement('footer', $metadata['footer']);
        $article->appendChild($footer);
    }

    return $iaDom->saveHTML();
}

// Helper function to convert individual HTML nodes to IA format
function convertNodeToIA(DOMDocument $iaDom, DOMNode $node): ?DOMNode {
    switch ($node->nodeType) {
        case XML_TEXT_NODE:
            // Skip empty text nodes
            return trim($node->nodeValue) === '' ? null : $iaDom->createTextNode($node->nodeValue);
        
        case XML_ELEMENT_NODE:
            switch ($node->tagName) {
                case 'p':
                    // Keep paragraphs as-is
                    $p = $iaDom->createElement('p');
                    foreach ($node->childNodes as $child) {
                        $childConverted = convertNodeToIA($iaDom, $child);
                        if ($childConverted) $p->appendChild($childConverted);
                    }
                    return $p;
                
                case 'img':
                    // Wrap images in <figure> tags
                    $figure = $iaDom->createElement('figure');
                    $img = $iaDom->createElement('img');
                    $img->setAttribute('src', $node->getAttribute('src'));
                    if ($node->hasAttribute('alt')) $img->setAttribute('alt', $node->getAttribute('alt'));
                    $figure->appendChild($img);
                    // Check for adjacent figcaption
                    $nextSibling = $node->nextSibling;
                    if ($nextSibling && $nextSibling->tagName === 'figcaption') {
                        $figcaption = $iaDom->createElement('figcaption', $nextSibling->nodeValue);
                        $figure->appendChild($figcaption);
                    }
                    return $figure;
                
                case 'h2':
                case 'h3':
                    // Keep subheadings as-is
                    $heading = $iaDom->createElement($node->tagName);
                    foreach ($node->childNodes as $child) {
                        $childConverted = convertNodeToIA($iaDom, $child);
                        if ($childConverted) $heading->appendChild($childConverted);
                    }
                    return $heading;
                
                case 'blockquote':
                    // Convert to IA pullquote
                    $quote = $iaDom->createElement('blockquote', $node->nodeValue);
                    $quote->setAttribute('class', 'op-pullquote');
                    return $quote;
                
                default:
                    // Fallback: Convert unsupported tags to paragraphs
                    $p = $iaDom->createElement('p');
                    foreach ($node->childNodes as $child) {
                        $childConverted = convertNodeToIA($iaDom, $child);
                        if ($childConverted) $p->appendChild($childConverted);
                    }
                    return $p;
            }
        
        default:
            return null;
    }
}
?>

4. Test the Conversion

Create a test-conversion.php file to try out the function:

<?php
include 'ia-converter.php';

// Sample regular HTML content
$regularHtml = '
<body>
    <p>Hey there! This is a sample article that we’ll convert to Instant Articles format.</p>
    <img src="https://example.com/mountain.jpg" alt="Snowy mountain peak" />
    <figcaption>A beautiful winter mountain scene</figcaption>
    <h2>Why Instant Articles Matter</h2>
    <p>They load 10x faster than regular web pages, keeping readers engaged longer.</p>
    <blockquote>Speed is everything for mobile users.</blockquote>
</body>
';

// Metadata for your Instant Article
$metadata = [
    'title' => 'My First Instant Article',
    'canonical_url' => 'https://example.com/my-first-article',
    'published_date' => 'May 20, 2024',
    'published_datetime' => '2024-05-20T12:00:00+00:00',
    'author_name' => 'Jane Smith',
    'author_url' => 'https://example.com/jane-smith',
    'header_image_url' => 'https://example.com/main-header.jpg',
    'header_image_caption' => 'Main article header',
    'footer' => '© 2024 Example Blog. All rights reserved.'
];

// Run conversion
$iaHtml = convertToInstantArticle($regularHtml, $metadata);

// Output the result (formatted for readability)
echo '<pre>' . htmlspecialchars($iaHtml) . '</pre>';
?>

Access localhost/test-conversion.php in your browser—you’ll see a perfectly formatted Instant Article HTML string.


5. Integrate with Your Graph API Workflow

Since you already know how to submit articles via the Graph API, just pass the converted HTML as the html parameter. Here’s a quick snippet to tie it all together:

<?php
// After converting to IA HTML
$iaHtml = convertToInstantArticle($regularHtml, $metadata);

// Your existing Graph API credentials
$accessToken = 'YOUR_FACEBOOK_ACCESS_TOKEN';
$pageId = 'YOUR_PAGE_ID';
$apiEndpoint = "https://graph.facebook.com/v19.0/{$pageId}/instant_articles";

// Prepare post data
$postData = [
    'html' => $iaHtml,
    'published' => false, // Set to true to publish immediately, false for draft
    'access_token' => $accessToken
];

// Send request via cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiEndpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

// Handle response
$responseData = json_decode($response, true);
if (isset($responseData['id'])) {
    echo "Success! Instant Article ID: {$responseData['id']}";
} else {
    echo "Error: {$responseData['error']['message']}";
}
?>

6. Troubleshooting Tips

  • Malformed HTML Warnings: We suppressed these with libxml_use_internal_errors(true) because most real-world HTML isn’t perfectly valid—don’t worry about it unless the conversion breaks.
  • Rejected Articles: Facebook will reject articles missing required fields like the canonical URL or op:markup_version meta tag. Double-check your header section.
  • Image Issues: Ensure all images are publicly accessible (Facebook’s crawler needs to fetch them). Use absolute URLs instead of relative paths.

内容的提问来源于stack exchange,提问作者Prabal Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:10:06