PHPackages                             fromholdio/silverstripe-superlinker - 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. fromholdio/silverstripe-superlinker

ActiveSilverstripe-vendormodule[Utility &amp; Helpers](/categories/utility)

fromholdio/silverstripe-superlinker
===================================

Superlinker

4.0.0(1w ago)11.4k3[1 issues](https://github.com/fromholdio/silverstripe-superlinker/issues)4BSD-3-ClausePHP

Since May 13Pushed 1w ago1 watchersCompare

[ Source](https://github.com/fromholdio/silverstripe-superlinker)[ Packagist](https://packagist.org/packages/fromholdio/silverstripe-superlinker)[ Docs](https://github.com/fromholdio/silverstripe-superlinker)[ RSS](/packages/fromholdio-silverstripe-superlinker/feed)WikiDiscussions master Synced yesterday

READMEChangelog (10)Dependencies (13)Versions (27)Used By (4)

SilverStripe SuperLinker
========================

[](#silverstripe-superlinker)

A powerful, extensible link management system for SilverStripe that provides a unified interface for creating and managing all types of links in your CMS.

Table of Contents
-----------------

[](#table-of-contents)

- [Overview](#overview)
- [Why SuperLinker?](#why-superlinker)
- [Requirements](#requirements)
- [Installation](#installation)
- [Core Concepts](#core-concepts)
- [Quick Start](#quick-start)
- [Link Types](#link-types)
- [Configuration](#configuration)
- [Usage](#usage)
- [Optional Features](#optional-features)
- [Dependencies](#dependencies)
- [Implementation Modules](#implementation-modules)
- [API Reference](#api-reference)
- [Real-World Examples](#real-world-examples)
- [Migration](#migration)
- [License](#license)

Overview
--------

[](#overview)

SuperLinker is a comprehensive link management system that replaces fragmented link handling with a single, extensible DataObject. It provides:

- **8 built-in link types**: SiteTree, External, Email, Phone, File, System, GlobalAnchor, Null
- **Extensible architecture**: Add custom link types via extensions
- **Optional features**: Description, Icon, Image support
- **Consistent UX**: Same interface for all link types
- **Type-specific settings**: Configure behavior per link type
- **Automatic validation**: Link health checks and orphan detection
- **Template helpers**: isCurrent(), isSection(), LinkingMode()
- **Flexible rendering**: Type-specific templates

Why SuperLinker?
----------------

[](#why-superlinker)

**Before SuperLinker**, managing links in SilverStripe meant:

- Multiple incompatible link modules (Linkable, etc.)
- Inconsistent UX across different link types
- Difficult to add new link types
- No unified validation or health checks
- Fragmented template rendering

**With SuperLinker**, you get:

- Single DataObject for all link types
- Consistent CMS interface
- Easy extension with new types
- Built-in validation and health checks
- Unified template rendering
- Type-specific configuration

Requirements
------------

[](#requirements)

- SilverStripe CMS ^6.0
- PHP 8.1+

### Core Dependencies

[](#core-dependencies)

- fromholdio/silverstripe-dbhtmlanchors ^2.1.0
- fromholdio/silverstripe-dependentgroupeddropdownfield ^4.0.0
- fromholdio/silverstripe-externalurlfield ^2.0.0
- fromholdio/silverstripe-globalanchors ^2.1.0
- fromholdio/silverstripe-minigridfield ^2.0.0
- fromholdio/silverstripe-systemlinks ^2.0.0
- innoweb/silverstripe-international-phone-number-field ^6.0.0
- unclecheese/display-logic ^4.0.0

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

[](#installation)

```
composer require fromholdio/silverstripe-superlinker
```

Run dev/build:

```
vendor/bin/sake dev/build flush=1
```

Core Concepts
-------------

[](#core-concepts)

### Link Types

[](#link-types)

A **link type** defines a category of link (e.g., 'sitetree', 'external', 'email'). Each type:

- Has a unique key (e.g., 'sitetree')
- Provides its own fields and validation
- Can have type-specific settings
- Is implemented via Extension

### Type Extensions

[](#type-extensions)

Link types are added via **SuperLinkTypeExtension** subclasses that:

- Define the type key and label
- Add database fields for the type
- Provide CMS fields
- Implement URL generation logic
- Handle validation

### Settings

[](#settings)

**Settings** control optional features:

- `link_text` - Custom link text field
- `open_in_new` - Open in new tab option
- `no_follow` - SEO nofollow option
- `link_description` - Description field (optional extension)
- `link_image` - Image upload (optional extension)
- `icon` - Icon upload (optional extension)

Settings can be enabled globally or per-type.

### Link Health

[](#link-health)

SuperLinker tracks link health:

- **Valid**: Has type, type is available, not orphaned, not empty
- **Orphaned**: Container object doesn't exist (future feature)
- **Empty**: No URL generated

### Template Rendering

[](#template-rendering)

Links render via templates with fallback chain:

```
ClassName_TypeKey.ss
ClassName.ss
SuperLink_TypeKey.ss
SuperLink.ss

```

Quick Start
-----------

[](#quick-start)

### 1. Basic has\_one Relation

[](#1-basic-has_one-relation)

```
use Fromholdio\SuperLinker\Model\SuperLink;

class Page extends SiteTree
{
    private static $has_one = [
        'CTALink' => SuperLink::class
    ];
}
```

### 2. Add CMS Fields

[](#2-add-cms-fields)

```
use Fromholdio\HasOneEdit\HasOneMiniGridField;

public function getCMSFields(): FieldList
{
    $fields = parent::getCMSFields();

    $fields->addFieldToTab('Root.Main',
        HasOneMiniGridField::create('CTALink', 'Call to Action', $this)
    );

    return $fields;
}
```

### 3. Use in Templates

[](#3-use-in-templates)

```

    $CTALink

```

Or with custom markup:

```

        $CTALink.Title

```

### 4. has\_many Relations

[](#4-has_many-relations)

```
class Page extends SiteTree
{
    private static $has_many = [
        'Links' => SuperLink::class
    ];
}
```

```
use Fromholdio\MiniGridField\MiniGridField;

$fields->addFieldToTab('Root.Main',
    MiniGridField::create('Links', 'Links', $this)
        ->setLimit(10)
);
```

Link Types
----------

[](#link-types-1)

### SiteTree Link

[](#sitetree-link)

Links to pages within your SilverStripe site.

**Features**:

- TreeDropdownField for page selection
- Optional anchor selection (page content + global anchors)
- isCurrent() and isSection() support
- Configurable tree root

**Configuration**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  types:
    sitetree:
      allow_anchor: true
```

**Usage**:

```
$link->getLinkedSiteTree(); // Returns SiteTree object
$link->getLinkedSiteTreeAnchor(); // Returns anchor string
```

### External Link

[](#external-link)

Links to external URLs.

**Features**:

- ExternalURLField with validation
- Protocol/scheme validation
- Query string and fragment support
- Internal URL blocking (optional)

**Configuration**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  types:
    external:
      is_internal_url_allowed: false
      allowed_schemes:
        https: true
        http: true
        ftp: false
```

### Email Link

[](#email-link)

Creates mailto: links with optional subject and body.

**Features**:

- Email validation
- Optional CC/BCC fields
- Subject and body fields
- Automatic mailto: URL generation

**Configuration**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  types:
    email:
      cc: false
      bcc: false
      subject: true
      body: true
```

### Phone Link

[](#phone-link)

Creates tel: links for phone numbers.

**Features**:

- International phone number field
- Automatic formatting
- tel: URL generation

**Usage**:

```
$link->getURL(); // Returns tel:+61412345678
```

### File Link

[](#file-link)

Links to files in the assets folder.

**Features**:

- TreeDropdownField or UploadField
- Force download option
- Configurable starting folder
- Upload enable/disable

**Configuration**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  types:
    file:
      use_upload_field: false
      allow_uploads: false
      starting_folder_path: 'downloads'
      allow_force_download: true
```

**Usage**:

```
$link->getLinkedFile(); // Returns File object
$link->isDownloadForced(); // Returns boolean
```

### System Link

[](#system-link)

Links to system routes (login, logout, etc.).

**Features**:

- Dropdown of configured system links
- Dynamic URL generation
- Special URL processing ($Login, $Logout, etc.)

**Configuration**:

```
Fromholdio\SystemLinks\SystemLinks:
  links:
    login:
      url: /Security/login
      title: Login
    logout:
      url: /Security/logout
      title: Logout
```

**Usage**:

```
$link->getLinkedSystemLink(); // Returns ArrayData
```

### Global Anchor Link

[](#global-anchor-link)

Links to globally-defined page anchors.

**Features**:

- Dropdown of configured anchors
- Relative or absolute URL generation
- Current page context awareness

**Configuration**:

```
Fromholdio\GlobalAnchors\GlobalAnchors:
  anchors:
    nav: 'Main Navigation'
    content: 'Page Content'
    footer: 'Footer'
```

**Usage**:

```
$link->getLinkedGlobalAnchor(); // Returns anchor key
```

### Null Link

[](#null-link)

Text-only, no actual link.

**Features**:

- Displays text without href
- Useful for disabled menu items
- No URL generated

**Usage**: Automatically renders as text without `` tag.

Configuration
-------------

[](#configuration)

### Enabling/Disabling Link Types

[](#enablingdisabling-link-types)

```
# Allow only specific types
Fromholdio\SuperLinker\Model\SuperLink:
  allowed_types:
    - sitetree
    - external
    - email

# Or disallow specific types
Fromholdio\SuperLinker\Model\SuperLink:
  disallowed_types:
    - phone
    - file
```

### Type-Specific Settings

[](#type-specific-settings)

```
Fromholdio\SuperLinker\Model\SuperLink:
  types:
    external:
      settings:
        open_in_new: true  # Enable by default
        no_follow: true
    email:
      settings:
        open_in_new: false  # Disable for this type
        no_follow: false
```

### Global Settings

[](#global-settings)

```
Fromholdio\SuperLinker\Model\SuperLink:
  settings:
    link_text: true
    open_in_new: true
    no_follow: true
```

### Custom Type Configuration

[](#custom-type-configuration)

```
Fromholdio\SuperLinker\Model\SuperLink:
  types:
    mytype:
      label: 'My Custom Type'
      sort: 100
      settings:
        link_text: true
        open_in_new: false
```

Usage
-----

[](#usage)

### In PHP

[](#in-php)

#### Getting Link Data

[](#getting-link-data)

```
// Get URL
$url = $link->getURL();
$absoluteURL = $link->getAbsoluteURL();

// Get title
$title = $link->getTitle(); // Custom or default
$defaultTitle = $link->getDefaultTitle(); // Always default

// Get link type
$type = $link->getType(); // 'sitetree', 'external', etc.
$typeLabel = $link->getTypeLabel(); // 'Page on this website', etc.

// Check link health
$isValid = $link->isLinkValid();
$isEmpty = $link->isLinkEmpty();
$isOrphaned = $link->isLinkOrphaned();

// Get HTML attributes
$attrs = $link->getDefaultAttributes(); // ['href' => '...', 'target' => '...', etc.]
$href = $link->getHrefValue();
$target = $link->getTargetValue(); // '_blank' or null
$rel = $link->getRelValue(); // 'nofollow noopener' or null
$class = $link->getClassValue();

// Check settings
$isOpenInNew = $link->isOpenInNew();
$isNoFollow = $link->isNoFollow();
$isNoOpener = $link->isNoOpener();

// Template helpers
$isCurrent = $link->isCurrent(); // For SiteTree links
$isSection = $link->isSection(); // For SiteTree links
$linkingMode = $link->LinkingMode(); // 'link', 'current', or 'section'
```

#### Adding CSS Classes

[](#adding-css-classes)

```
$link->addExtraCSSClass('btn btn-primary');
$link->removeExtraCSSClass('btn-primary');
```

#### Filtering Valid Links

[](#filtering-valid-links)

```
use Fromholdio\SuperLinker\Model\SuperLink;

$links = $page->Links();
$validLinks = SuperLink::excludeInvalidLinks($links);
```

### In Templates

[](#in-templates)

#### Basic Usage

[](#basic-usage)

```

    $CTALink

        $CTALink.Title

```

#### With Attributes

[](#with-attributes)

```

        $CTALink.Title

```

#### Looping Links

[](#looping-links)

```

                $Title

```

#### With Linking Mode

[](#with-linking-mode)

```

            $MenuLink.Title

```

#### Type-Specific Rendering

[](#type-specific-rendering)

```

            $CTALink.Title ↗

            $CTALink.Title ⬇

        $CTALink

```

### Custom Templates

[](#custom-templates)

Create type-specific templates:

**templates/Fromholdio/SuperLinker/Model/SuperLink\_external.ss**:

```

    $Title

```

**templates/Fromholdio/SuperLinker/Model/SuperLink\_file.ss**:

```

    $Title

```

**templates/Fromholdio/SuperLinker/Model/SuperLink.ss** (fallback):

```
$Title
```

Optional Features
-----------------

[](#optional-features)

### Description Extension

[](#description-extension)

Add description field to links.

**Installation**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  extensions:
    - Fromholdio\SuperLinker\Extensions\SuperLinkDescriptionExtension
```

**Configuration**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  link_description_rows: 3  # TextField if 1, TextareaField if > 1
  settings:
    link_description: true
```

**Usage**:

```
$description = $link->getDescription();
$defaultDescription = $link->getDefaultDescription();
```

**Templates**:

```

        $CTALink.Title

            $CTALink.Description

```

**Auto-Generated Descriptions**:

For SiteTree and File links, implement on target:

```
class Page extends SiteTree
{
    public function getSuperLinkDefaultDescription(): ?string
    {
        return $this->MetaDescription ?: $this->Summary;
    }
}
```

### Icon Extension

[](#icon-extension)

Add icon upload to links.

**Installation**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  extensions:
    - Fromholdio\SuperLinker\Extensions\SuperLinkIconExtension
```

**Configuration**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  icon_folder_path: 'link-icons'
  icon_allowed_extensions:
    - svg
    - png
  settings:
    icon: true
```

**Usage**:

```
$icon = $link->getIcon(); // Returns Image object
```

**Templates**:

```

        $CTALink.Title

```

### Image Extension

[](#image-extension)

Add image upload to links.

**Installation**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  extensions:
    - Fromholdio\SuperLinker\Extensions\SuperLinkImageExtension
```

**Configuration**:

```
Fromholdio\SuperLinker\Model\SuperLink:
  link_image_upload_path: 'link-images'
  settings:
    link_image: true
```

**Usage**:

```
$image = $link->getImage(); // Returns Image object
$defaultImage = $link->getDefaultImage();
```

**Templates**:

```

        $CTALink.Title

```

**Auto-Generated Images**:

For SiteTree links:

```
class Page extends SiteTree
{
    private static $has_one = [
        'FeaturedImage' => Image::class
    ];

    public function getSuperLinkDefaultImage(): ?Image
    {
        return $this->FeaturedImage()->exists()
            ? $this->FeaturedImage()
            : null;
    }
}
```

Apply helper extensions:

```
SilverStripe\CMS\Model\SiteTree:
  extensions:
    - Fromholdio\SuperLinker\Extensions\SuperLinkImagePageExtension

SilverStripe\Assets\File:
  extensions:
    - Fromholdio\SuperLinker\Extensions\SuperLinkImageFileExtension
```

Dependencies
------------

[](#dependencies)

SuperLinker relies on several companion modules that provide specific functionality.

### SystemLinks

[](#systemlinks)

**Purpose**: Define static system links (login, logout, etc.) for use in templates and CMS.

**Installation**: Included with SuperLinker

**Configuration**:

```
Fromholdio\SystemLinks\SystemLinks:
  links:
    login:
      url: /Security/login
      title: Login
    logout:
      url: /Security/logout
      title: Logout
    lostpassword:
      url: /Security/lostpassword
      title: Lost Password
    admin:
      url: /admin
      title: CMS Admin
```

**Special URLs**:

- `$Login` - Automatically resolves to Security::login\_url()
- `$Logout` - Automatically resolves to Security::logout\_url() with token
- `$LostPassword` - Automatically resolves to Security::lost\_password\_url()

**Usage in Templates**:

```
$SystemLink('login').Title
```

**Usage in PHP**:

```
use Fromholdio\SystemLinks\SystemLinks;

$link = SystemLinks::get_link('login'); // Returns ArrayData
$url = $link->URL;
$title = $link->Title;

// Get as map for dropdown
$map = SystemLinks::get_map(); // ['login' => 'Login', ...]
```

**Documentation**: See `vendor/fromholdio/silverstripe-systemlinks/README.md`

### GlobalAnchors

[](#globalanchors)

**Purpose**: Define static global HTML anchors for use across the site.

**Installation**: Included with SuperLinker

**Configuration**:

```
Fromholdio\GlobalAnchors\GlobalAnchors:
  anchors:
    nav: 'Main Navigation'
    content: 'Page Content'
    footer: 'Footer'
    sidebar: 'Sidebar'
```

**Usage in Templates**:

```
...
...
...
...
```

**Usage in PHP**:

```
use Fromholdio\GlobalAnchors\GlobalAnchors;

$anchors = GlobalAnchors::get_anchors(); // ['nav' => 'Main Navigation', ...]
$title = GlobalAnchors::get_anchor_title('nav'); // 'Main Navigation'
```

**Documentation**: See `vendor/fromholdio/silverstripe-globalanchors/README.md`

### RelativeURLField

[](#relativeurlfield)

**Purpose**: Form field for entering URL slugs with collision detection.

**Installation**: Included with SuperLinker

**Features**:

- Base URL display
- Collision checking against SiteTree
- Query string support (optional)
- Full path support (optional)
- Auto-incrementing on collision

**Usage**:

```
use Fromholdio\RelativeURLField\Forms\RelativeURLField;

$field = RelativeURLField::create('URLSegment', 'URL');
$field->setBaseURL('https://example.com/redirects/');
$field->setIsQueryStringAllowed(true);
$field->setIsFullPathAllowed(false);
```

**Documentation**: See `vendor/fromholdio/silverstripe-relativeurlfield/README.md`

### HasOneEdit

[](#hasoneedit)

**Purpose**: Inline editing of has\_one relations.

**Installation**: Included with SuperLinker

**Usage**:

```
use Fromholdio\HasOneEdit\HasOneMiniGridField;

$fields->addFieldToTab('Root.Main',
    HasOneMiniGridField::create('SuperLink', 'Link', $this)
);
```

**Note**: This module is aging and may be replaced in future versions.

**Documentation**: See `vendor/fromholdio/silverstripe-hasoneedit/README.md`

### Other Dependencies

[](#other-dependencies)

- **DBHTMLAnchors**: Extracts anchors from HTML content
- **DependentGroupedDropdownField**: Dropdown that depends on another field
- **ExternalURLField**: URL field with validation
- **MiniGridField**: Compact GridField for has\_many relations
- **InternationalPhoneNumberField**: Phone number field with formatting

Implementation Modules
----------------------

[](#implementation-modules)

SuperLinker provides base functionality. These modules extend it for specific use cases.

### superlinker-ctas

[](#superlinker-ctas)

**Purpose**: Call-to-Action / Button DataObjects

**Status**: Superseded by SuperLinker v3+. For new projects, create custom subclasses as needed.

**Installation**:

```
composer require fromholdio/silverstripe-superlinker-ctas
```

**What it provides**:

- `CTA` class extending `SuperLink`
- Pre-configured for button/CTA use cases

**Usage**:

```
use Fromholdio\SuperLinkerCTAs\Model\CTA;

class Page extends SiteTree
{
    private static $has_one = [
        'PrimaryCTA' => CTA::class
    ];
}
```

**Documentation**: See `vendor/fromholdio/silverstripe-superlinker-ctas/README.md`

### superlinker-redirection

[](#superlinker-redirection)

**Purpose**: Redirector pages using SuperLink targets

**Installation**:

```
composer require fromholdio/silverstripe-superlinker-redirection
```

**What it provides**:

- `RedirectionPage` - Replacement for core RedirectorPage
- `Redirection` DataObject - Standalone redirects
- Admin interface for managing redirects
- Support for all SuperLink types as targets

**Features**:

- Redirect to any link type (not just internal/external)
- HTTP status code selection (301, 302, 303, 307, 308)
- Redirect from custom URL paths
- Collision detection
- Hidden from site tree

**Usage**:

```
// Create redirector page
$page = RedirectionPage::create();
$page->Title = 'Old Page';
$page->RedirectLink()->LinkType = 'sitetree';
$page->RedirectLink()->SiteTreeID = $newPage->ID;
$page->write();
```

**Documentation**: See `vendor/fromholdio/silverstripe-superlinker-redirection/README.md`

### superlinker-targets

[](#superlinker-targets)

**Purpose**: Basic link/target DataObjects

**Installation**:

```
composer require fromholdio/silverstripe-superlinker-targets
```

**What it provides**:

- `Target` class extending `SuperLink`
- Generic link objects for various uses

**Usage**:

```
use Fromholdio\SuperLinkerTargets\Model\Target;

class Page extends SiteTree
{
    private static $has_many = [
        'RelatedLinks' => Target::class
    ];
}
```

**Documentation**: See `vendor/fromholdio/silverstripe-superlinker-targets/README.md`

API Reference
-------------

[](#api-reference)

### SuperLink Core Methods

[](#superlink-core-methods)

#### Link Information

[](#link-information)

```
public function getType(): ?string
public function getTypeLabel(?string $type = null): ?string
public function getTitle(): string
public function getDefaultTitle(): string
```

#### URL Methods

[](#url-methods)

```
public function getURL(): ?string
public function getAbsoluteURL(): ?string
public function getHrefValue(): ?string
```

#### Link Health

[](#link-health-1)

```
public function isLinkValid(): bool
public function isLinkOrphaned(): bool
public function isLinkEmpty(): bool
public static function excludeInvalidLinks(SS_List $links): ArrayList
```

#### HTML Attributes

[](#html-attributes)

```
public function getDefaultAttributes(): array
public function getTargetValue(): ?string
public function getRelValue(): ?string
public function getClassValue(): ?string
public function addExtraCSSClass(string $class): self
public function removeExtraCSSClass(string $class): self
```

#### Settings

[](#settings-1)

```
public function isLinkTextEnabled(?string $type = null): bool
public function isOpenInNewEnabled(?string $type = null): bool
public function isOpenInNew(): bool
public function isNoFollowEnabled(?string $type = null): bool
public function isNoFollow(): bool
public function isNoOpener(): bool
```

#### Template Helpers

[](#template-helpers)

```
public function isCurrent(): bool
public function isSection(): bool
public function LinkOrCurrent(): string
public function LinkOrSection(): string
public function LinkingMode(): string
public function forTemplate(): string
```

#### CMS Fields

[](#cms-fields)

```
public function getCMSFields(): FieldList
public function getCMSLinkFields(string $fieldPrefix = ''): FieldList
```

### Type Extension Methods

[](#type-extension-methods)

#### SiteTreeLink

[](#sitetreelink)

```
public function getLinkedSiteTree(): ?SiteTree
public function getLinkedSiteTreeAnchor(): ?string
public function getAvailableSiteTreeAnchors(int|string|null $siteTreeID): array
public function getAllowedLinkedSiteTreeRoot(): ?SiteTree
```

#### ExternalLink

[](#externallink)

```
// Uses ExternalURL field - no additional methods
```

#### EmailLink

[](#emaillink)

```
// URL generated from Email, EmailCC, EmailBCC, EmailSubject, EmailBody fields
```

#### PhoneLink

[](#phonelink)

```
// Uses PhoneNumber field (DBPhone) - no additional methods
```

#### FileLink

[](#filelink)

```
public function getLinkedFile(): ?File
public function isDownloadForced(): bool
```

#### SystemLink

[](#systemlink)

```
public function getLinkedSystemLink(): ?ArrayData
```

#### GlobalAnchorLink

[](#globalanchorlink)

```
public function getLinkedGlobalAnchor(): ?string
```

### Optional Extension Methods

[](#optional-extension-methods)

#### SuperLinkDescriptionExtension

[](#superlinkdescriptionextension)

```
public function getDescription(): ?string
public function getDefaultDescription(): ?string
public function isLinkDescriptionEnabled(?string $type = null): bool
```

#### SuperLinkIconExtension

[](#superlinkiconextension)

```
public function getIcon(): ?Image
```

#### SuperLinkImageExtension

[](#superlinkimageextension)

```
public function getImage(): ?Image
public function getDefaultImage(): ?Image
public function isLinkImageEnabled(?string $type = null): bool
```

Real-World Examples
-------------------

[](#real-world-examples)

### Example 1: Navigation Menu with SuperLinks

[](#example-1-navigation-menu-with-superlinks)

```
class Page extends SiteTree
{
    private static $has_many = [
        'MenuLinks' => SuperLink::class
    ];
}
```

```
public function getCMSFields(): FieldList
{
    $fields = parent::getCMSFields();

    $fields->addFieldToTab('Root.Menu',
        MiniGridField::create('MenuLinks', 'Menu Links', $this)
            ->setLimit(10)
    );

    return $fields;
}
```

**Template**:

```

                $Title

```

### Example 2: CTA Buttons with Images

[](#example-2-cta-buttons-with-images)

```
Fromholdio\SuperLinker\Model\SuperLink:
  extensions:
    - Fromholdio\SuperLinker\Extensions\SuperLinkImageExtension
    - Fromholdio\SuperLinker\Extensions\SuperLinkDescriptionExtension
```

```
class HomePage extends Page
{
    private static $has_many = [
        'FeatureCards' => SuperLink::class
    ];
}
```

**Template**:

```

            $Title

                $Description

```

### Example 3: Footer Links with Icons

[](#example-3-footer-links-with-icons)

```
Fromholdio\SuperLinker\Model\SuperLink:
  extensions:
    - Fromholdio\SuperLinker\Extensions\SuperLinkIconExtension
```

```
class SiteConfig extends DataExtension
{
    private static $has_many = [
        'SocialLinks' => SuperLink::class
    ];
}
```

**Template**:

```

                    $Title

```

### Example 4: Custom Link Type

[](#example-4-custom-link-type)

Create a custom link type for YouTube videos:

```
namespace App\Extensions;

use Fromholdio\SuperLinker\Extensions\SuperLinkTypeExtension;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TextField;

class YouTubeLink extends SuperLinkTypeExtension
{
    private static $extension_link_type = 'youtube';

    private static $types = [
        'youtube' => [
            'label' => 'YouTube Video',
            'settings' => [
                'open_in_new' => true
            ]
        ]
    ];

    private static $db = [
        'YouTubeID' => 'Varchar(20)'
    ];

    public function updateDefaultTitle(?string &$title): void
    {
        if (!$this->isLinkTypeMatch()) return;
        $title = 'Watch on YouTube';
    }

    public function updateURL(?string &$url): void
    {
        if (!$this->isLinkTypeMatch()) return;
        $id = $this->getOwner()->getField('YouTubeID');
        $url = empty($id) ? null : 'https://www.youtube.com/watch?v=' . $id;
    }

    public function updateCMSLinkTypeFields(FieldList $fields, string $type, string $fieldPrefix): void
    {
        if (!$this->isLinkTypeMatch($type)) return;
        $fields->push(
            TextField::create($fieldPrefix . 'YouTubeID', 'YouTube Video ID')
                ->setDescription('e.g., dQw4w9WgXcQ')
        );
    }
}
```

Apply extension:

```
Fromholdio\SuperLinker\Model\SuperLink:
  extensions:
    - App\Extensions\YouTubeLink
```

### Example 5: Versioned SuperLinks

[](#example-5-versioned-superlinks)

For versioned content:

```
use Fromholdio\SuperLinker\Model\VersionedSuperLink;

class Article extends Page
{
    private static $has_one = [
        'RelatedArticleLink' => VersionedSuperLink::class
    ];
}
```

Migration
---------

[](#migration)

### From Linkable or Similar Modules

[](#from-linkable-or-similar-modules)

1. **Install SuperLinker**:

```
composer require fromholdio/silverstripe-superlinker
```

2. **Update DataObject Relations**:

```
// Before
private static $has_one = [
    'ExternalLink' => Link::class
];

// After
private static $has_one = [
    'ExternalLink' => SuperLink::class
];
```

3. **Update CMS Fields**:

```
// Before
$fields->addFieldToTab('Root.Main',
    LinkField::create('ExternalLinkID', 'Link')
);

// After
$fields->addFieldToTab('Root.Main',
    HasOneMiniGridField::create('ExternalLink', 'Link', $this)
);
```

4. **Update Templates**:

```

    $ExternalLink.Title

    $ExternalLink.Title

```

5. **Run dev/build**:

```
vendor/bin/sake dev/build flush=1
```

6. **Migrate Data**: Write a migration task to convert existing link data to SuperLink format.

License
-------

[](#license)

BSD-3-Clause

Support
-------

[](#support)

- **GitHub**:
- **Issues**:

Contributing
------------

[](#contributing)

Contributions are welcome! Please open an issue or pull request on GitHub.

Credits
-------

[](#credits)

Developed by [Luke Fromhold](https://fromhold.io)

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance78

Regular maintenance activity

Popularity21

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity70

Established project with proven stability

 Bus Factor1

Top contributor holds 83.3% 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.

###  Release Activity

Cadence

Every ~101 days

Recently: every ~163 days

Total

26

Last Release

10d ago

Major Versions

1.0.2 → 2.0.02019-08-21

2.x-dev → 3.0.02024-01-07

3.1.0 → 4.x-dev2025-11-17

3.x-dev → 4.0.02026-05-02

### Community

Maintainers

![](https://www.gravatar.com/avatar/40e135ad117686bee39707c1d9286cc5e915e219c26a10d13858ca44d14f1eb0?d=identicon)[dizzystuff](/maintainers/dizzystuff)

---

Top Contributors

[![dizzystuff](https://avatars.githubusercontent.com/u/576903?v=4)](https://github.com/dizzystuff "dizzystuff (60 commits)")[![xini](https://avatars.githubusercontent.com/u/1152403?v=4)](https://github.com/xini "xini (12 commits)")

---

Tags

linksilverstripesuperlinker

### Embed Badge

![Health badge](/badges/fromholdio-silverstripe-superlinker/health.svg)

```
[![Health](https://phpackages.com/badges/fromholdio-silverstripe-superlinker/health.svg)](https://phpackages.com/packages/fromholdio-silverstripe-superlinker)
```

###  Alternatives

[sheadawson/silverstripe-linkable

A couple of handy form fields and objects for managing external and internal links on DataObjects

39316.2k24](/packages/sheadawson-silverstripe-linkable)[silverstripe/redirectedurls

Provides a system for users to configure arbitrary redirections in the CMS

32522.2k10](/packages/silverstripe-redirectedurls)

PHPackages © 2026

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