contentpulseio/laravel 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

contentpulseio/laravel

Composer 安装命令:

composer require contentpulseio/laravel

包简介

Laravel integration for ContentPulse.io — webhook ingestion, local content storage, and rendering.

README 文档

README

Laravel integration for ContentPulse.io. Receives content webhooks, stores a local copy of the published content, and renders it through your own layout. Once content is delivered, your app serves it from its own database with no runtime dependency on ContentPulse.

Requirements

  • PHP ^8.2
  • Laravel ^10 | ^11 | ^12

Installation

composer require contentpulseio/laravel
php artisan contentpulse:install
php artisan migrate

The package is published on Packagist, so the command above works out of the box. contentpulse:install publishes the config and migration; the service provider is auto-discovered.

If you install from a private fork instead of Packagist, add the repository to your composer.json before requiring:

"repositories": [
    { "type": "vcs", "url": "https://github.com/contentpulseio/laravel" }
]

Set your credentials in .env:

CONTENTPULSE_API_KEY=your-api-key
CONTENTPULSE_WEBHOOK_SECRET=your-webhook-secret
# optional
CONTENTPULSE_BASE_URL=https://contentpulse.io
CONTENTPULSE_TIMEOUT=30

How it works

  1. Register the webhook endpoint (webhooks/contentpulse) in your ContentPulse dashboard. Incoming requests are verified against CONTENTPULSE_WEBHOOK_SECRET.
  2. On content.* events the package fetches the item and upserts it into the contentpulse_contents table.
  3. Published content is served from the local store via the bundled routes:
    • GET /resources — index
    • GET /resources/{slug} — single item

Set your layout so rendered content slots into your site chrome:

CONTENTPULSE_LAYOUT=layouts.app

Webhooks

The package ships a ready-to-use webhook receiver — no controller or middleware to write in your app.

  • Endpoint: POST /webhooks/contentpulse (override with CONTENTPULSE_WEBHOOK_PATH).
  • Signature: every request is verified by the VerifyContentPulseSignature middleware. It computes hash_hmac('sha256', <raw request body>, CONTENTPULSE_WEBHOOK_SECRET) and compares it (constant-time) to the X-Webhook-Signature header.
    • Secret not set → 503
    • Missing/invalid signature → 401
    • Valid → 200 {"status":"ok"}
  • Handled events (from the event field or X-Webhook-Event header, with data.content_id as the ContentPulse ULID):
    • content.created, content.updated, content.published → fetch the item from the API and upsert it into contentpulse_contents
    • content.deleted → remove the local row

Register the endpoint in your ContentPulse dashboard (Webhooks) pointing at https://your-app.test/webhooks/contentpulse, subscribe to the content.* events, and set the signing secret to match CONTENTPULSE_WEBHOOK_SECRET. Published content then syncs automatically; contentpulse:sync is only needed for the initial backfill.

Using your own design (decoupled read model)

Already have a blog with your own Post model, controller, views, and SEO? Keep all of it. The package Content model is a plain, queryable Eloquent model that exposes a post-like surface, so it drops into your existing views with no trait, no base class, and no changes to your Post model.

Scopes

use ContentPulse\Laravel\Models\Content;

Content::published()->get();          // status = published, newest first
Content::whereCategory('laravel')->get();
Content::whereTag('seo')->get();

Post-like accessors (built in)

Accessor Returns
title, excerpt, slug, featured_image columns
content pre-rendered HTML (rendered_html)
read_time minutes (from word_count)
categories, tags Collection of {name, slug} objects
meta_title, meta_description, meta_keywords SEO fields
views, user 0 / null (override in your view if needed)
published_at Carbon

Merge with your existing posts

Because the field surface matches a typical Post, you can render both sources through the same Blade views:

use App\Models\Post;
use ContentPulse\Laravel\Models\Content;

public function index()
{
    $feed = Post::published()->get()
        ->concat(Content::published()->get())
        ->sortByDesc('published_at')
        ->values();

    return view('blog.index', ['posts' => $feed]);
}

public function show(string $slug)
{
    $post = Post::published()->where('slug', $slug)->first()
        ?? Content::published()->where('slug', $slug)->firstOrFail();

    return view('blog.show', ['post' => $post]);
}

Your views, your routes, your SEO tags — the package only supplies the data.

Or just echo the HTML

$content = Content::published()->where('slug', $slug)->firstOrFail();

echo $content->rendered_html;

Customizing the design

The bundled Blade views are fully overridable. Publish them into your app to own the markup and styling:

php artisan vendor:publish --tag=contentpulse-views

This copies the views to resources/views/vendor/contentpulse/:

  • index.blade.php — list page
  • show.blade.php — single item
  • partials/head.blade.php — SEO meta tags / JSON-LD
  • partials/styles.blade.php — base CSS

Laravel automatically loads the published copies instead of the package defaults, so edit them freely. Delete a file to fall back to the package version. Package updates never overwrite your published views.

Artisan

php artisan contentpulse:sync --locale=en

Backfills the local store from the API (useful for the initial import).

License

MIT

统计信息

  • 总下载量: 37
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 7
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-06

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固