PHPackages                             heikkivihersalo/custom-post-types - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. heikkivihersalo/custom-post-types

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

heikkivihersalo/custom-post-types
=================================

Flexible Laravel style custom post types for WordPress

00[1 PRs](https://github.com/heikkivihersalo/custom-post-types/pulls)PHPCI passing

Since Mar 16Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/heikkivihersalo/custom-post-types)[ Packagist](https://packagist.org/packages/heikkivihersalo/custom-post-types)[ RSS](/packages/heikkivihersalo-custom-post-types/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (2)Used By (0)

Custom Post Types
=================

[](#custom-post-types)

This is an Laravel style implementation of custom post types in WordPress. It is meant to offer file based custom post types and taxonomies, which can be easily added to a WordPress theme or plugin.

Note

Please not that this package is still in development and not yet ready for production use. There can be breaking changes as the wrapper and API develops further. If you want to use this package in production, please fork the repository and use your own version.

TODO
----

[](#todo)

- Add custom callback function for taxonomies
- Add basic tests for the package to ensure functionality
- Add more complex examples for the package
- Add rest of the WP methods to the `PostType` and `Taxonomy` classes

Installation
------------

[](#installation)

To install the package, run the following command:

```
composer require heikkivihersalo/custom-post-types
```

Usage
-----

[](#usage)

To use the API, you must first register the loader method somewhere in your theme or plugin. This will load all the custom post types and taxonomies dynamically from the `inc/post-types` and `inc/taxonomies` directories.

```
function run_custom_post_types() {
	$cpt = new CPTLoader( SITE_PATH, SITE_URI, __NAMESPACE__ );
	$cpt->run();
}

run_custom_post_types();
```

`SITE_PATH` is the path to the theme or plugin directory, `SITE_URI` is the URI to the theme or plugin directory and `__NAMESPACE__` is the namespace of the theme or plugin.

You can also create your own loader but please do note, that `image` -type metabox requires javascript to run. Basic styles are loaded from WP directly, but there are some extra styles required for `image` -type metaboxes.

### Registering a custom post type

[](#registering-a-custom-post-type)

To register a custom post type, create a new PHP file in the `inc/post-types` directory. You can find example file from the `inc/post-types` directory. Filename should follow `camelCase` convention. This will be converted to correct slugs and names in the registration process. For example, `ExamplePostType.php` will be converted to `example-post-type` and `Example` will be converted to a slug `example`.

Basic structure of the file should be as follows:

```
namespace MyTheme\Namespace;

use HeikkiVihersalo\CustomPostTypes\PostType;
use HeikkiVihersalo\CustomPostTypes\Interfaces\PostTypeInterface;

class Example extends PostType implements PostTypeInterface {
	/**
	 * @inheritDoc
	 */
	public function register(): void {
		$this->register_custom_post_type();
	}
}
```

Basically this is everything you need to register a custom post type. For more complex implementations, you can override the methods from the `PostType` class. For example, `labels()` method can be overridden to provide custom labels for the post type or `icon()` method can be overridden to provide custom arguments for the post type.

Eventually this will include all the methods from the `register_post_type()` function, so you can override any of the methods from the parent class.

#### Registering metaboxes

[](#registering-metaboxes)

To register metaboxes for the custom post type, you can use the `metaboxes()` method in the `PostType` class. Following array will add all available metaboxes to the custom post type.

Following metaboxes are available:

- Text
- Textarea
- URL
- Number
- Checkbox
- Checkbox Group
- Date
- Image
- Select
- Rich Text
- Radio Group

Also for taxonomies, you can add following metaboxes:

- Checkbox Group
- Select
- Radio Group

```
public function metaboxes(): array {
    return array(
        array(
            'id'    => 'text_input_1',
            'label' => __( 'Text Input 1', 'heikkivihersalo-custom-post-types' ),
            'type'  => 'text',
        ),
        array(
            'id'    => 'textarea_input_1',
            'label' => __( 'TextArea Input', 'heikkivihersalo-custom-post-types' ),
            'type'  => 'textarea',
        ),
        array(
            'id'    => 'url_input',
            'label' => __( 'URL Input', 'heikkivihersalo-custom-post-types' ),
            'type'  => 'url',
        ),
        array(
            'id'    => 'number_input',
            'label' => __( 'Number Input', 'heikkivihersalo-custom-post-types' ),
            'type'  => 'number',
        ),
        array(
            'id'    => 'checkbox_input',
            'label' => __( 'Checkbox Input', 'heikkivihersalo-custom-post-types' ),
            'type'  => 'checkbox',
        ),
        array(
            'id'      => 'checkbox_group_input',
            'label'   => __( 'Checkbox Group Input', 'heikkivihersalo-custom-post-types' ),
            'type'    => 'checkbox-group',
            'options' => array(
                array(
                    'value' => 'option1',
                    'label' => 'Option 1',
                ),
                array(
                    'value' => 'option2',
                    'label' => 'Option 2',
                ),
                array(
                    'value' => 'option3',
                    'label' => 'Option 3',
                ),
            ),
        ),
        array(
            'id'    => 'date_input',
            'label' => __( 'Date Input', 'heikkivihersalo-custom-post-types' ),
            'type'  => 'date',
        ),
        array(
            'id'    => 'image_input',
            'label' => __( 'Image Input', 'heikkivihersalo-custom-post-types' ),
            'type'  => 'image',
        ),
        array(
            'id'      => 'select_input',
            'label'   => __( 'Select Input', 'heikkivihersalo-custom-post-types' ),
            'type'    => 'select',
            'options' => array(
                array(
                    'value' => 'option1',
                    'label' => 'Option 1',
                ),
                array(
                    'value' => 'option2',
                    'label' => 'Option 2',
                ),
                array(
                    'value' => 'option3',
                    'label' => 'Option 3',
                ),
            ),
        ),
        array(
            'id'    => 'rich_text_input',
            'label' => __( 'Rich Text Input', 'heikkivihersalo-custom-post-types' ),
            'type'  => 'rich-text',
        ),
        array(
            'id'      => 'radio_group_input',
            'label'   => __( 'Radio Group Input', 'heikkivihersalo-custom-post-types' ),
            'type'    => 'radio-group',
            'options' => array(
                array(
                    'value' => 'option1',
                    'label' => 'Option 1',
                ),
                array(
                    'value' => 'option2',
                    'label' => 'Option 2',
                ),
                array(
                    'value' => 'option3',
                    'label' => 'Option 3',
                ),
            ),
        ),
        array(
            'id'       => 'taxonomy_checkbox_group_input',
            'label'    => __( 'Taxonomy Checkbox Group', 'heikkivihersalo-custom-post-types' ),
            'type'     => 'taxonomy-checkbox-group',
            'taxonomy' => 'cb-group-taxonomy',
		),
        array(
            'id'       => 'taxonomy_radio_field_input',
            'label'    => __( 'Taxonomy Radio', 'heikkivihersalo-custom-post-types' ),
            'type'     => 'taxonomy-radio',
            'taxonomy' => 'radio-taxonomy',
		),
        array(
            'id'       => 'taxonomy_select_input',
            'label'    => __( 'Taxonomy Select', 'heikkivihersalo-custom-post-types' ),
            'type'     => 'taxonomy-select',
            'taxonomy' => 'select-taxonomy',
        ),
    );
}
```

### Registering a custom taxonomy

[](#registering-a-custom-taxonomy)

To register a custom taxonomy, create a new PHP file in the `inc/taxonomies` directory. You can find example file from the `inc/taxonomies` directory. Filename should follow `camelCase` convention. This will be converted to correct slugs and names in the registration process. For example, `ExampleTaxonomy.php` will be converted to `example-taxonomy` and `Example` will be converted to a slug `example`.

Basic structure of the file should be as follows:

```
namespace MyTheme\Namespace;

use HeikkiVihersalo\CustomPostTypes\Taxonomy;
use HeikkiVihersalo\CustomPostTypes\Interfaces\TaxonomyInterface;

class Example extends Taxonomy implements TaxonomyInterface {
	/**
	 * @inheritDoc
	 */
	public function register(): void {
		$this->register_custom_taxonomy();
	}

	/**
	 * @inheritDoc
	 */
	public function object_types(): string|array {
		return array(
			'example',
		);
	}
}
```

###  Health Score

20

—

LowBetter than 14% of packages

Maintenance57

Moderate activity, may be stable

Popularity0

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity17

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/482b40f00b485b92b63095f8f49cf3ad2f97ba4db41c05ed65e3c20020f776e5?d=identicon)[heikkivihersalo](/maintainers/heikkivihersalo)

---

Top Contributors

[![heikkivihersalo](https://avatars.githubusercontent.com/u/40141346?v=4)](https://github.com/heikkivihersalo "heikkivihersalo (28 commits)")

### Embed Badge

![Health badge](/badges/heikkivihersalo-custom-post-types/health.svg)

```
[![Health](https://phpackages.com/badges/heikkivihersalo-custom-post-types/health.svg)](https://phpackages.com/packages/heikkivihersalo-custom-post-types)
```

###  Alternatives

[daverandom/exceptional-json

JSON encoding and decoding that throws exceptions on failure

321.4M9](/packages/daverandom-exceptional-json)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
