Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 71b698d

Browse files
authored
feature #10395 [Docs] How to add your custom fixtures? (Tomanhez)
This PR was merged into the 1.4 branch. Discussion ---------- | Q | A | --------------- | ----- | Branch? | 1.3 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | License | MIT <!-- - Bug fixes must be submitted against the 1.3 or 1.4 branch (the lowest possible) - Features and deprecations must be submitted against the master branch - Make sure that the correct base branch is set --> Commits ------- f3fa4af Add new field in list e285308 Add fixture guide
2 parents 9cfbb9a + e285308 commit 71b698d

2 files changed

Lines changed: 309 additions & 0 deletions

File tree

docs/customization/fixtures.rst

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
Customizing Fixtures
2+
====================
3+
4+
What are fixtures?
5+
~~~~~~~~~~~~~~~~~~
6+
7+
Fixtures are just plain old PHP objects, that change system state during their execution - they can either
8+
persist some entities in the database, upload some files, dispatch some events or do anything you think is needed.
9+
10+
.. code-block:: yaml
11+
12+
sylius_fixtures:
13+
suites:
14+
my_suite_name:
15+
fixtures:
16+
my_fixture: # Fixture name as a key
17+
priority: 0 # The higher priority is, the sooner the fixture will be executed
18+
options: ~ # Fixture options
19+
20+
They implement the ``Sylius\Bundle\FixturesBundle\Fixture\FixtureInterface`` and need to be registered under
21+
the ``sylius_fixtures.fixture`` tag in order to be used in suite configuration.
22+
23+
.. note::
24+
25+
The former interface extends the ``ConfigurationInterface``, which is widely known from ``Configuration`` classes
26+
placed under ``DependencyInjection`` directory in Symfony bundles.
27+
28+
Why would you customize a fixtures?
29+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30+
31+
If you want to operate on the test data of objects appearing in your store
32+
e.g: ``Currency``, ``Country``, ``User`` etc.
33+
34+
How to add new Fixtures?
35+
~~~~~~~~~~~~~~~~~~~~~~~~
36+
37+
In Sylius part of fixtures are added in ``src/Sylius/Bundle/CoreBundle/Resources/config/app/fixtures.yml``, where is defined ``default`` suite that is partially-configured.
38+
If you are planning to add new fixtures in default command ``sylius:fixtures:load``, only what you have to do is add new items in ``config\packages\_sylius.yml``
39+
40+
Adding new items in shop by standard yaml configuration:
41+
42+
.. code-block:: yaml
43+
44+
sylius_fixtures:
45+
suites:
46+
default: # this key is always called wherever we use sylius:fixtures:load, below we are extending that about new fixtures
47+
fixtures:
48+
currency:
49+
options:
50+
currencies: ['PLN','HUF','EUR']
51+
channel:
52+
options:
53+
custom:
54+
pl_web_store: # creating new channel
55+
name: "PL Web Store"
56+
code: "PL_WEB"
57+
locales:
58+
- "%locale%"
59+
currencies:
60+
- "PLN"
61+
enabled: true
62+
hostname: "localhost"
63+
hun_web_store:
64+
name: "Hun Web Store"
65+
code: "HUN_WEB"
66+
locales:
67+
- "%locale%"
68+
currencies:
69+
- "HUF"
70+
enabled: true
71+
hostname: "localhost"
72+
shipping_method:
73+
options:
74+
custom:
75+
ups_eu: # creating new shipping_method and adding channel to it
76+
code: "ups_eu"
77+
name: "UPS_eu"
78+
enabled: true
79+
channels:
80+
- "PL_WEB"
81+
ups: # adding channel to existing shipping_method
82+
channels:
83+
- "HUN_WEB"
84+
payment_method:
85+
options:
86+
custom:
87+
cash_on_delivery_pl:
88+
code: "cash_on_delivery_eu"
89+
name: "Cash on delivery_eu"
90+
channels:
91+
- "PL_WEB"
92+
bank_transfer:
93+
code: "bank_transfer_eu"
94+
name: "Bank transfer_eu"
95+
channels:
96+
- "PL_WEB"
97+
- "HUN_WEB"
98+
enabled: true
99+
100+
Fixtures in sylius are loaded and initialized using class located at ``src/Sylius/Bundle/CoreBundle/Fixture/*``
101+
102+
Below is presented class ``Sylius\Bundle\CoreBundle\Fixture\CurrencyFixture`` that load our currencies from yaml configuration:
103+
104+
.. code-block:: php
105+
106+
<?php
107+
108+
...
109+
110+
class CurrencyFixture extends AbstractFixture
111+
{
112+
...
113+
114+
// here we load our options array from yaml file
115+
public function load(array $options): void
116+
{
117+
foreach ($options['currencies'] as $currencyCode) {
118+
/** @var CurrencyInterface $currency */
119+
$currency = $this->currencyFactory->createNew();
120+
121+
$currency->setCode($currencyCode);
122+
123+
$this->currencyManager->persist($currency);
124+
}
125+
126+
$this->currencyManager->flush();
127+
}
128+
129+
...
130+
131+
// here we configure our restriction from our input
132+
protected function configureOptionsNode(ArrayNodeDefinition $optionsNode): void
133+
{
134+
$optionsNode
135+
->children()
136+
->arrayNode('currencies')
137+
->scalarPrototype()
138+
;
139+
}
140+
}
141+
142+
This fixture is registered in ``src/Sylius/Bundle/CoreBundle/Resources/config/services/fixtures.xml``:
143+
144+
.. code-block:: xml
145+
146+
<service id="sylius.fixture.currency" class="Sylius\Bundle\CoreBundle\Fixture\CurrencyFixture">
147+
<argument type="service" id="sylius.factory.currency" />
148+
<argument type="service" id="sylius.manager.currency" />
149+
<tag name="sylius_fixtures.fixture" />
150+
</service>
151+
152+
``Currency`` is simple and short example created fixtures but many models need additionally factory to create new items.
153+
Factories must implements ``Sylius\Bundle\CoreBundle\Fixture\Factory\ExampleFactoryInterface`` and ``Sylius\Bundle\CoreBundle\Fixture\Factory\AbstractExampleFactory``
154+
155+
`Products` are most complicated because have more dependencies than rest models
156+
Sylius delivered four ready implementation of ``Product``:
157+
158+
* BookProductFixture
159+
* MugProductFixture
160+
* StickerProductFixture
161+
* TshirtProductFixture
162+
163+
How to add new custom Fixtures?
164+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
165+
166+
If you want to write custom fixture you must create class that implements ``Sylius/Bundle/FixturesBundle/Fixture/FixtureInterface``
167+
168+
Best ways to write custom fixture is extend class ``Sylius/Bundle/FixturesBundle/Fixture/AbstractFixture`` or ``Sylius/Bundles/FixturesBundle/Fixture/AbstractResourceFixture``:
169+
170+
* Extending ``AbstractFixtures`` that is basic class giving only sample configuration, next we must override methods: load() and configureOptionsNode()
171+
* In most cases enought extend ``AbstractResourceFixture``, this class is partially-configured, only what we have to do is override configureOptionsNode()
172+
173+
How to add new custom Fixtures in custom Models?
174+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
175+
176+
.. tip::
177+
178+
Below Example is based on other example showing how to extends entity with a new field.
179+
You can browse the full implementation of this example on `this GitHub Pull Request
180+
<https://github.com/Sylius/Customizations/pull/23>`__.
181+
182+
**1** First we extended our entity ``App\Entity\Shipping\ShippingMethod`` with a new field ``deliveryConditions``.
183+
184+
**2** Next we need extends our factory ``Sylius\Bundle\CoreBundle\Fixture\Factory\ShippingMethodExampleFactory`` with this field
185+
in ``App\Entity\Factory\ShippingMethodExampleFactory``:
186+
187+
.. code-block:: php
188+
189+
<?php
190+
191+
...
192+
193+
final class ShippingMethodExampleFactory extends BaseShippingMethodExampleFactory implements ExampleFactoryInterface
194+
{
195+
...
196+
197+
public function create(array $options = []): ShippingMethodInterface
198+
{
199+
/** @var ShippingMethod $shippingMethod */
200+
$shippingMethod = parent::create($options);
201+
202+
// here we protect object if part of our objects don't have new field
203+
if (!isset($options['deliveryConditions'])) {
204+
return $shippingMethod;
205+
}
206+
207+
foreach ($this->getLocales() as $localeCode) {
208+
$shippingMethod->setCurrentLocale($localeCode);
209+
$shippingMethod->setFallbackLocale($localeCode);
210+
211+
$shippingMethod->setDeliveryConditions($options['deliveryConditions']);
212+
}
213+
214+
return $shippingMethod;
215+
}
216+
217+
protected function configureOptions(OptionsResolver $resolver): void
218+
{
219+
parent::configureOptions($resolver);
220+
221+
$resolver
222+
->setDefault('deliveryConditions', 'some_default_value')
223+
->setAllowedTypes('deliveryConditions', ['null', 'string'])
224+
;
225+
}
226+
227+
private function getLocales(): iterable
228+
{
229+
...
230+
}
231+
}
232+
233+
**3** Now we extended ``Sylius\Bundle\CoreBundle\Fixture\ShippingMethodFixture`` in ``App\Entity\Fixture\ShippingMethodFixture``:
234+
235+
.. code-block:: php
236+
237+
<?php
238+
239+
...
240+
241+
final class ShippingMethodFixture extends BaseShippingMethodFixture implements FixtureInterface
242+
{
243+
public function getName(): string
244+
{
245+
return 'shipping_method';
246+
}
247+
248+
protected function configureResourceNode(ArrayNodeDefinition $resourceNode): void
249+
{
250+
parent::configureResourceNode($resourceNode);
251+
252+
$resourceNode
253+
->children()
254+
->scalarNode('deliveryConditions')->end()
255+
;
256+
}
257+
}
258+
259+
**4** Here we create ``config/packages/fixtures.xml`` and override our services:
260+
261+
.. code-block:: xml
262+
263+
<?xml version="1.0" encoding="UTF-8"?>
264+
265+
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
266+
<services>
267+
<defaults public="true" />
268+
269+
<service id="sylius.fixture.shipping_method" class="App\Entity\Fixture\ShippingMethodFixture">
270+
<argument type="service" id="sylius.manager.shipping_method" />
271+
<argument type="service" id="sylius.fixture.example_factory.shipping_method" />
272+
<tag name="sylius_fixtures.fixture" />
273+
</service>
274+
275+
<service id="sylius.fixture.example_factory.shipping_method" class="App\Entity\Factory\ShippingMethodExampleFactory">
276+
<argument type="service" id="sylius.factory.shipping_method" />
277+
<argument type="service" id="sylius.repository.zone" />
278+
<argument type="service" id="sylius.repository.shipping_category" />
279+
<argument type="service" id="sylius.repository.locale" />
280+
<argument type="service" id="sylius.repository.channel" />
281+
</service>
282+
</services>
283+
</container>
284+
285+
**5** At the end, only what you have to do is add new ``shipping_method`` in ``config\packages\_sylius.yml``
286+
287+
.. code-block:: yaml
288+
289+
sylius_fixtures:
290+
suites:
291+
default:
292+
fixtures:
293+
...
294+
shipping_method: # our new configuration with a new field
295+
options:
296+
custom:
297+
geis:
298+
code: "geis"
299+
name: "geis"
300+
enabled: true
301+
channels:
302+
- "PL_WEB"
303+
deliveryConditions: "delivered"
304+
305+
Learn more
306+
##########
307+
308+
* :doc:`FixtureBundle </components_and_bundles/bundles/SyliusFixturesBundle/index>`

docs/customization/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The Customization Guide is helpful while wanting to adapt Sylius to your persona
1919
state_machine
2020
grid
2121
tips_and_tricks
22+
fixtures
2223
fixture_suites
2324

2425
.. include:: /customization/map.rst.inc

0 commit comments

Comments
 (0)