Generate YAML fixture for DataObjects
Generate a YAML fixture from DataObjects
composer require chrispenny/silverstripe-data-object-to-fixture
The purpose of this module (at this early stage) is not to create perfect fixtures, but more to provide a solid
guideline for what your fixture should look like.
For example:
Writing unit test fixtures can be difficult, especially when you're needing to visualise the structure and relationships
of many different DataObjects (and then add an extra layer if you're using, say, Fluent).
One goal for the future of this module is for it to work in tandem with the Populate module. I would like to get to a
stage where content authors are able to (for example) "export pages" through the CMS, so that those pages can then be
recreated via Populate (without a dev needing to create the fixture themselves).
This is in very, very early development stages. Please be aware that:
What won't change:
I would not recommend that you use this module (at this stage) for any application critical features, but I would
recommend that you use it as a developer tool (to help you write your own fixtures, either for tests, or to be used
with Populate).
A dev task can be found at /chrispenny/silverstripe-data-object-to-fixture
.
This task will allow you to generate a fixture (output on the screen for you to copy/paste) for any DataObject that
you have defined in your project.
// Instantiate the Service.
$service = new FixtureService();
// Fetch the DataObject that you wish to generate a fixture for.
/** @var Page $page */
$page = Page::get()->byID(1);
// Add the DataObject to the Service.
$service->addDataObject($dataObject);
// Check for warnings? This is somewhat important, because if you have looping relationships (which we have no way of
// creating fixtures for at the moment) this is how you'll know about it.
if (count($service->getWarnings()) > 0) {
Debug::dump($service->getWarnings());
}
// Do something with the fixture output.
highlight_string($service->outputFixture());
// Or maybe save the output to a file?
$fixture = Director::baseFolder() . '/app/resources/fixture.yml';
file_put_contents($fixture, $service->outputFixture());
If you are having issues with "nesting level of '256' reached", then one option is to set a maximum depth that the
Service will attempt to export.
// Instantiate the Service.
$service = new FixtureService();
$service->setAllowedDepth(2);
There might be some classes (like Members?) that you don't want to include in your fixture. The manifest will check
classes for the existence (and truth) of the config variable exclude_from_fixture_relationships
.
You can set this in a yml file:
SilverStripe\Security\Member:
exclude_from_fixture_relationships: 1
SilverStripe\Security\Group:
exclude_from_fixture_relationships: 1
SilverStripe\Security\MemberPassword:
exclude_from_fixture_relationships: 1
SilverStripe\Security\RememberLoginHash:
exclude_from_fixture_relationships: 1
The above examples have been set in _config/model.yml. If you wish to override them, you can also do so by adding your
own yml config "After" dataobjecttofixturemodel
. EG:
Name: my_dataobjecttofixturemodel
After: dataobjecttofixturemodel
---
SilverStripe\Security\Member:
exclude_from_fixture_relationships: 0
Similar to excluding classes, there might be some specific relationships on specific classes that you want to exclude.
Perhaps you have identified a looping relationship, and you would like to exclude one of them to make things
predictable, or perhaps it's just a relationship you don't need in your fixtures.
You can exclude specific relationships by adding excluded_fixture_relationships
to the desired class.
excluded_fixture_relationships
accepts an array of relationship names.
EG:
class MyModel extends DataObject
{
private static $has_one = [
'FeatureImage' => Image::class,
];
}
App\Models\MyModel:
excluded_fixture_relationships:
- FeatureImage
TL;DR: There is a looping relationship between Page
and ElementalArea
in later versions of Elemental. You can
exclude the has_one
on ElementalArea
as follows.
DNADesign\Elemental\Models\ElementalArea:
excluded_fixture_relationships:
- TopPage
Extra info: Issue.
Above are three options that you can use to attempt to reduce this.
I would recommend that you begin by exluding classes that you don't need for your export, then move to excluding
specific relationships that might be causing deep levels of nested relationships, and finally, if those fail, you can
set a max depth.
You might see this error if you have a relationship being defined as simply DataObject::class
, EG:
private static $has_one = [
'Parent' => DataObject::class,
];
This module needs to know what DataObject
it is querying for. Modules like Userforms do this because you can
technically have any Model as the parent. These modules do, however, store the class name for this relationship in
a separate field so that we are able to query for the parent appropriately. For Userforms, the class name for this
relationship is stored in a field called ParentClass
. This module doesn't know that though.
You can tell this module where that class name information lives for any relationship by using the following
configuration (this is using Userforms as the example):
SilverStripe\UserForms\Model\EditableFormField:
field_classname_map:
ParentID: ParentClass
field_classname_map
is the config we want to populate, and it expects an array with the relationship field name as the
key
, and the corresponding class name field as the value
.
The module uses relField()
with the value
, so you could be presenting this information through a data field, or a
method.
has_one
has_many
many_many
where a through
relationship has been defined.many_many
where no through
relationship has been defined (you should be using through
.... Use through
).has_one
relationships that result in a loop of relationships (belongs_to
is the "backward" definition for ahas_one
relationship, unfortunately, this is not currently supported in fixtures, so, we have no way to create aIt is my intention to support Fluent and exporting Localised fields.
Current state does support this, but, again, this is still very early development, so you should be validating
everything before you just go right ahead and assume it's perfect.
_Live
tables. I hope to add _Live
table exports soon(ish).Module rating system helping users find modules that are well supported. For more on how the rating system works visit Module standards
Score not correct? Let us know there is a problem