Basic usage
The Link
model can be used with a has_one
or has_many
relation, depending on whether you want one or multiple links.
Using many_many
relations with the Link
model is not supported. The can*
permission methods on Link
rely on having a single owner record they can inherit permissions from.
See model-level permissions for more information about these methods.
The LinkField
form field is used to manage links in a has_one
relation, and MultiLinkField
is for links in a has_many
relation.
namespace App\Model;
use SilverStripe\LinkField\Form\LinkField;
use SilverStripe\LinkField\Form\MultiLinkField;
use SilverStripe\LinkField\Models\Link;
use SilverStripe\ORM\DataObject;
class MyModel extends DataObject
{
private static array $has_one = [
'HasOneLink' => Link::class,
];
private static $has_many = [
'HasManyLinks' => Link::class . '.Owner',
];
private static array $owns = [
'HasOneLink',
'HasManyLinks',
];
private static array $cascade_deletes = [
'HasOneLink',
'HasManyLinks',
];
private static array $cascade_duplicates = [
'HasOneLink',
'HasManyLinks',
];
public function getCMSFields()
{
$fields = parent::getCMSFields();
// Don't forget to remove the auto-scaffolded fields!
$fields->removeByName(['HasOneLinkID', 'HasManyLinks']);
$fields->addFieldsToTab(
'Root.Main',
[
LinkField::create('HasOneLink'),
MultiLinkField::create('HasManyLinks'),
]
);
return $fields;
}
}
Adding the relationship(s) to the $owns
configuration property is required for versioning (publishing) to work correctly. See cascade publishing to learn more.
The $cascade_deletes
and $cascade_duplicates
configuration is optional but beneficial. Without applying $cascade_deletes
for example, deleting the parent record (a MyModel
record in the example above) will result in orphaned links which are still in your database but not owned by anything. See cascading deletions and cascading duplications for more information.
Multiple has_many
relations on the same model
If you have multiple has_many
relations on the same class, they should all point at the "Owner" has_one
relation on Link
using dot notation. This is important for the permission model to work correctly.
namespace App\Model;
use SilverStripe\LinkField\Models\Link;
use SilverStripe\ORM\DataObject;
class MyModel extends DataObject
{
private static $has_many = [
'HasManyLinksOne' => Link::class . '.Owner',
'HasManyLinksTwo' => Link::class . '.Owner',
];
// ...
}
Validation
Custom links can have validation set using standard model validation. This is true both for the validation of the link data itself, as well as validating relations to the Link
class.
For example you can make sure you have a link in your has_one
or has_many
relation using a RequiredFields
validator:
namespace App\Model;
use SilverStripe\Forms\CompositeValidator;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\LinkField\Models\Link;
use SilverStripe\ORM\DataObject;
class MyModel extends DataObject
{
private static array $has_one = [
'HasOneLink' => Link::class,
];
private static $has_many = [
'HasManyLinks' => Link::class . '.Owner',
];
// ...
public function getCMSCompositeValidator(): CompositeValidator
{
$validator = parent::getCMSCompositeValidator();
$validator->addValidator(RequiredFields::create(['HasOneLink', 'HasManyLinks']));
return $validator;
}
}
You can also update validation logic of a given Link
class by creating an Extension
and implementing the updateCMSCompositeValidator()
method.
Unversioned links
The Link
model has the Versioned
extension applied to it by default. If you wish for links to not be versioned, then remove the extension from the Link
model in the project's app/_config.php
file.
// app/_config.php
use SilverStripe\LinkField\Models\Link;
use SilverStripe\Versioned\Versioned;
Link::remove_extension(Versioned::class);
If you do this, you don't need to apply the $owns
configuration described in basic usage above.
See versioning for more information about the implications of making this change.