Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Ahondev/portfolio-v2/llms.txt

Use this file to discover all available pages before exploring further.

The PostType builder provides a fluent, declarative API for registering WordPress custom post types together with their ACF Extended field groups, taxonomies, and Eloquent model bindings — all in one place. Every call to PostType::create() immediately registers the post type with WordPress and adds it to the EloquentManager model registry. Calling ->make() at the end of the chain finalises the ACF field group.

PostType::create()

The static factory that starts the builder chain. It calls register_post_type() internally and throws wp_die() if the slug is already taken.
public static function create(
    string $slug,
    string $title,
    string $title_plural,
    string $url_rewrite,
    string $icon,
    bool   $has_seo,
    string $class_name = 'undefined'
): PostType
slug
string
required
The WordPress post type slug, e.g. 'article'. Must be unique; calling create() with an existing slug triggers wp_die().
title
string
required
Singular label for the post type, displayed in the WordPress admin.
title_plural
string
required
Plural label used as the admin menu item name.
url_rewrite
string
required
The URL slug for the post type’s rewrite rule, e.g. 'blog' produces /blog/{slug} permalinks.
icon
string
required
A Dashicons identifier without the dashicons- prefix, e.g. 'hammer' renders the dashicons-hammer icon in the admin sidebar.
has_seo
bool
required
When true, the SEOServiceProvider automatically attaches the shared ACF SEO field group (title, description, keywords, OG image, author) to this post type and includes it in the SEO dashboard score calculation.
class_name
string
The EloquentCPT subclass name that will be generated in app/PostTypes/. Defaults to 'undefined', which causes the slug to be used as the class name. Pass an explicit PascalCase name when you want a custom file name, e.g. 'Article'.

Chainable Methods

->taxonomy()

Register a WordPress taxonomy attached to this post type. Optionally include ACF Extended fields scoped to the taxonomy.
public function taxonomy(
    string  $slug,
    string  $title,
    string  $title_plural,
    string  $url_rewrite,
    bool    $show_in_rest,
    ?array  $fields = null
): PostType
slug
string
required
The taxonomy slug, e.g. 'category'.
title
string
required
Singular label.
title_plural
string
required
Plural label shown in the admin.
url_rewrite
string
required
URL slug for taxonomy archive pages.
show_in_rest
bool
required
Whether to expose this taxonomy through the WordPress REST API.
fields
array
An optional array of ACF Extended field objects. When provided, a field group scoped to this taxonomy is registered automatically.

->fields()

Append ACF Extended field objects to this post type’s field group. You can call ->fields() multiple times — fields are merged.
public function fields(array $fields): PostType
fields
array
required
An array of ACF Extended field objects such as Text::make(), Repeater::make(), WYSIWYGEditor::make(), etc.

->make()

Finalises the configuration by calling register_extended_field_group(). Must be the last call in the chain. Omitting ->make() means no ACF field group is created.
public function make(): void

Static Methods

PostType::all()

Returns an associative array of all PostType instances registered during the current request, keyed by slug. Used by SEOServiceProvider and RoutingServiceProvider to iterate over registered types.
public static function all(): array // [slug => PostType]

PostType::init()

Loaded by the Kernel at init priority 20. Requires configuration/posts.php, which in turn requires each individual post-type definition file.
public static function init(): void

Example: Article Post Type

A minimal post type with a taxonomy, a WYSIWYG body field, and SEO enabled.
<?php
// configuration/posts/article.php

use Ahon\WPCMS\PostType\PostType;
use Extended\ACF\Fields\Text;
use Extended\ACF\Fields\WYSIWYGEditor;

PostType::create('article', 'Article', 'Articles', 'blog', 'welcome-write-blog', true)
    ->taxonomy('category', 'Category', 'Categories', 'blog', true)
    ->fields([
        WYSIWYGEditor::make('Contenu', 'content'),
        Text::make('Temps de lecture', 'readTime'),
        Text::make('Extrait', 'excerpt'),
    ])
    ->make();

Example: Service Post Type

A complex post type showing every available field type — Text, Textarea, WYSIWYGEditor, Image, URL, Select, and Repeater.
<?php
// configuration/posts/service.php

use Ahon\WPCMS\PostType\PostType;
use Extended\ACF\Fields\Repeater;
use Extended\ACF\Fields\Select;
use Extended\ACF\Fields\Text;
use Extended\ACF\Fields\Textarea;
use Extended\ACF\Fields\WYSIWYGEditor;

PostType::create('service', 'Service', 'Services', 'services', 'hammer', true)
    ->fields([

        // General info
        Text::make('Description', 'desc')->required(),
        Text::make('Label court', 'shortLabel')->required(),
        Text::make('Tag', 'tag')->required(),

        // Hero section
        Text::make('Titre hero', 'hero.title')->required(),
        Text::make('Sous-titre hero', 'hero.subtitle')->required(),
        Select::make('Couleur d\'accent hero', 'hero.accent')
            ->choices([
                'bg-gradient-to-br from-purple-500/20 to-pink-500/20' => 'Pourpre → Rose',
                'bg-gradient-to-br from-blue-500/20 to-cyan-500/20'   => 'Bleu → Cyan',
                'bg-gradient-to-br from-emerald-500/20 to-teal-500/20' => 'Émeraude → Teal',
                'bg-gradient-to-br from-amber-500/20 to-orange-500/20' => 'Ambre → Orange',
            ])->required(),

        // Highlight badges (Repeater)
        Repeater::make('Points forts', 'highlights')
            ->fields([
                Text::make('Valeur', 'value')->required(),
            ])
            ->maxRows(5),

        // Rich text
        WYSIWYGEditor::make('Problème rencontré', 'problem')->required(),
        WYSIWYGEditor::make('Solution proposée', 'solution')->required(),

        // Features (Repeater)
        Repeater::make('Prestations incluses', 'features')
            ->fields([
                Text::make('Titre', 'title')->required(),
                Textarea::make('Description', 'desc')->required(),
            ]),

        // Use cases (Repeater)
        Repeater::make("Cas d'usage", 'useCases')
            ->fields([
                Text::make('Cas', 'value')->required(),
            ]),

        // Technologies (Repeater)
        Repeater::make('Technologies utilisées', 'technologies')
            ->fields([
                Text::make('Techno', 'value')->required(),
            ]),

        // Why us (Repeater with min/max)
        Repeater::make('Pourquoi ahon', 'whyAhon')
            ->fields([
                Text::make('Titre', 'title')->required(),
                Textarea::make('Description', 'desc')->required(),
            ])
            ->minRows(4)
            ->maxRows(6),

        // Process steps (Repeater with min/max)
        Repeater::make('Processus', 'process')
            ->fields([
                Text::make('Titre', 'title')->required(),
                Textarea::make('Description', 'desc')->required(),
            ])
            ->minRows(4)
            ->maxRows(5),

        // FAQ (Repeater)
        Repeater::make('FAQ', 'faq')
            ->fields([
                Text::make('Question', 'q')->required(),
                Textarea::make('Réponse', 'a')->required(),
            ]),

        // Lucide icon (Select)
        Select::make('Icône', 'icon')
            ->choices([
                'Globe'     => 'Globe',
                'Code2'     => 'Code2',
                'Search'    => 'Search',
                'BarChart'  => 'BarChart',
                'Megaphone' => 'Megaphone',
                'PenTool'   => 'PenTool',
                'Rocket'    => 'Rocket',
                'Shield'    => 'Shield',
                'Zap'       => 'Zap',
            ])
            ->required(),
    ])
    ->make();

Registration File

The configuration/posts.php file acts as the manifest that requires individual post-type definition files.
<?php
// configuration/posts.php

require_once __DIR__ . '/posts/article.php';
require_once __DIR__ . '/posts/service.php';
require_once __DIR__ . '/posts/realisations.php';
Keep one file per post type and require them all from configuration/posts.php. This mirrors the routes file pattern and makes it easy to add, disable, or reorder post types without touching framework code.

WordPress Post Type Options

The createPostType() method registers all post types with the following fixed WordPress options:
OptionValue
publictrue
show_in_restfalse (REST access goes through ApiRouter, not WP REST)
show_uitrue
capability_type'post'
supports['title']
rewrite.with_frontfalse

Build docs developers (and LLMs) love