Skip to content

Content Model

A content model in WNCMS represents a type of data entity that stores user-generated or website-managed content — such as Links, Channels, Posts, or Pages. Each content model extends the BaseModel class to gain WNCMS-wide features such as multi-site support, tag handling, and translatable attributes.


Typical Structure

A standard content model in WNCMS may include:

  • HasFactory — for Laravel factory support.
  • HasTranslations — for multilingual field support.
  • InteractsWithMedia — for image or file uploads.
  • Constants such as ICONS, ROUTES, and STATUSES for backend metadata.
  • Optional accessors for derived attributes (like thumbnails or icons).

php
namespace Wncms\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Wncms\Models\BaseModel;
use Wncms\Translatable\Traits\HasTranslations;

class Link extends BaseModel implements HasMedia
{
    use HasFactory;
    use InteractsWithMedia;
    use HasTranslations;

    protected static string $packageId = 'wncms';
    protected $guarded = [];

    protected $translatable = ['name', 'description', 'slogan'];

    protected $casts = [
        'expired_at' => 'datetime',
        'hit_at' => 'datetime',
    ];

    public const ICONS = [
        'fontawesome' => 'fa-solid fa-link'
    ];

    public const ROUTES = [
        'index',
        'create',
    ];

    public const STATUSES = [
        'active',
        'inactive',
    ];

    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('link_thumbnail')->singleFile();
        $this->addMediaCollection('link_icon')->singleFile();
    }

    public function getThumbnailAttribute()
    {
        $media = $this->getMedia('link_thumbnail')->first();
        if ($media) return $media->getUrl();
        return $this->external_thumbnail;
    }

    public function getIconAttribute()
    {
        $media = $this->getMedia('link_icon')->first();
        if ($media) return $media->getUrl();
    }
}

Key Concepts

1. Translatable Fields

The HasTranslations trait allows you to define which attributes support multilingual content.

php
protected $translatable = ['name', 'description', 'slogan'];

WNCMS will automatically handle storing translations in the translations table, and you can access them directly:

php
$link->name;              // Current locale
$link->getTranslation('name', 'en'); // Specific locale

2. Media Collections

By implementing HasMedia and using InteractsWithMedia, models can manage file uploads through the Spatie Media Library.

php
public function registerMediaCollections(): void
{
    $this->addMediaCollection('link_thumbnail')->singleFile();
    $this->addMediaCollection('link_icon')->singleFile();
}

Each collection can hold images, documents, or other file types. You can then retrieve URLs easily with accessors:

php
$link->thumbnail; // Returns media URL or fallback
$link->icon;      // Returns icon image URL

3. Constants for Metadata

Constants make your model more expressive and standardized across the CMS.

ConstantPurposeExample
ICONSIcon used for backend UI or menus'fontawesome' => 'fa-solid fa-link'
ROUTESDefines CRUD routes used in backend['index', 'create']
STATUSESDefines possible states of the model['active', 'inactive']

4. Accessors for Dynamic Attributes

You can define custom attribute accessors to provide computed values.

Example:

php
public function getThumbnailAttribute()
{
    $media = $this->getMedia('link_thumbnail')->first();
    return $media ? $media->getUrl() : $this->external_thumbnail;
}

This approach lets your templates access $link->thumbnail even if it is dynamically generated or externally stored.


5. Package Awareness

Each content model should declare which package it belongs to:

php
protected static string $packageId = 'wncms';

This ensures that translation keys, configurations, and migrations are scoped correctly when the model is part of a composer package (e.g., wncms-faqs, wncms-ecommerce).


Example: Channel Model

A simpler content model without media or translation:

php
namespace Wncms\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Wncms\Models\BaseModel;

class Channel extends BaseModel
{
    use HasFactory;

    protected $guarded = [];

    public const ICONS = [
        'fontawesome' => 'fa-solid fa-star'
    ];

    public const ROUTES = [
        'index',
        'create',
    ];

    public function clicks()
    {
        return $this->hasMany(wncms()->getModelClass('click'));
    }
}

This example shows how a model can remain lightweight while still inheriting BaseModel features such as tags and multisite support.


Summary

FeatureDescription
Extends BaseModelInherits multisite, tag, and translation capabilities
Supports TranslationsEasily manage localized content
Media CollectionsManage images and files using Spatie Media Library
Standard ConstantsDefine UI icons, route names, and statuses
Package-awareWorks seamlessly within WNCMS and custom packages
Custom AccessorsAdd computed fields for templates and APIs

Example Usage

php
$link = wncms()->getModel('link')->find(1);

echo $link->name;        // Localized name
echo $link->thumbnail;   // Media URL
echo $link->status;      // Active or inactive

By following this structure, your content models remain consistent, translatable, and fully integrated with the WNCMS ecosystem.

Built with ❤️ for WNCMS