How to write a new loader plugin¶
In this tutorial, we will show you how to write a new loader plugin for the Springbok framework.
The loader plugin is responsible for writing data to a file, database, or any other storage medium.
We will create a new loader that writes a “special” file format. The file format will be a plain text file, but formatted in “pizza” style.
The loader will write the file in the following format:
Pizza: Margherita Pizza
Description: A classic Neapolitan pizza with tomato sauce, mozzarella cheese, and fresh basil.
Pizza: Pepperoni Pizza
Description: A classic American pizza topped with tomato sauce, mozzarella cheese, and pepperoni slices.
Pizza: Cheese Pizza
Description: A simple pizza with just tomato sauce and mozzarella cheese.
Pizza: Chicago Deep Dish Pizza
Description: A deep-dish pizza with a thick, buttery crust, tomato sauce, and various toppings.
The loader will be used in the pipeline as follows:
<pizza-style
outputFileName="data/output/pizza.txt"
pizzaNameField="name"
pizzaDescriptionField="description"
/>
Step 1: Create a new loader
First we need to create a new loader that will write the “pizza” file format.
Create a new class called “PizzaLoader” that extends the “AbstractLoader” class.
<?php
namespace Pyz\Zed\TextPizza\Business\Loader;
use Antiloop\Zed\SpringbokCommon\Business\Loader\AbstractLoader;
use Flow\ETL\Loader;
use Flow\ETL\Rows;
class PizzaStyleLoader extends AbstractLoader implements Loader
{
/**
* @var string
*/
private $outputFileName;
/**
* @var mixed
*/
protected mixed $outputFile;
/**
* @var bool
*/
protected bool $fileNotOpened = true;
/**
* @var string
*/
private $pizzaNameField;
/**
* @var string
*/
private $pizzaDescriptionField;
/**
* @param string $outputFileName
* @param string $pizzaNameField
* @param string $pizzaDescriptionField
*/
public function __construct(
string $outputFileName,
string $pizzaNameField,
string $pizzaDescriptionField
) {
$this->outputFileName = $outputFileName;
$this->pizzaNameField = $pizzaNameField;
$this->pizzaDescriptionField = $pizzaDescriptionField;
}
/**
* @param \Flow\ETL\Rows $rows
*
* @return void
*/
public function load(Rows $rows): void
{
if ($this->fileNotOpened) {
$this->outputFile = fopen($this->outputFileName, 'w');
$this->fileNotOpened = false;
}
foreach ($rows as $row) {
$name = $row->valueOf($this->pizzaNameField);
$description = $row->valueOf($this->pizzaDescriptionField);
fwrite($this->outputFile, sprintf('Pizza: %s', $name) . PHP_EOL);
fwrite($this->outputFile, sprintf('Description: %s', $description) . PHP_EOL);
fwrite($this->outputFile, PHP_EOL);
}
}
}
Step 2: Add the loader to the factory
Next, we need to add the loader to the factory so that we can instantiate it.
<?php
namespace Pyz\Zed\TextPizza\Communication;
use Flow\ETL\Loader;
use Pyz\Zed\TextPizza\Business\Loader\PizzaStyleLoader;
use Spryker\Zed\Kernel\Communication\AbstractCommunicationFactory;
class TextPizzaCommunicationFactory extends AbstractCommunicationFactory
{
/**
* @param string $outputFileName
* @param string $pizzaNameField
* @param string $pizzaDescriptionField
*
* @return \Flow\ETL\Loader
*/
public function createPizzaStyleLoader(
string $outputFileName,
string $pizzaNameField,
string $pizzaDescriptionField
): Loader {
return new PizzaStyleLoader(
$outputFileName,
$pizzaNameField,
$pizzaDescriptionField,
);
}
}
Step 3: Create a new loader plugin
Next, we need to create a new loader plugin that will allow us to use the loader in a pipeline.
Create a new class called “PizzaStyleLoaderPlugin” that extends the “AbstractLoaderPlugin” class.
<?php
namespace Pyz\Zed\TextPizza\Communication\Plugins;
use Antiloop\Zed\SpringbokCommon\Communication\Plugins\Loaders\AbstractLoaderPlugin;
use Flow\ETL\Loader;
/**
* @method \Pyz\Zed\TextPizza\Communication\TextPizzaCommunicationFactory getFactory()
*/
class PizzaStyleLoaderPlugin extends AbstractLoaderPlugin
{
/**
* @var string
*/
private const NAME = 'pizza-style';
/**
* @return string
*/
public function getName(): string
{
return self::NAME;
}
/**
* @param array $xml
*
* @return \Flow\ETL\Loader
*/
public function build(array $xml): Loader
{
$outputFileName = $this->getAttribute($xml, 'outputFileName');
$pizzaNameField = $this->getAttribute($xml, 'pizzaNameField');
$pizzaDescriptionField = $this->getAttribute($xml, 'pizzaDescriptionField');
return $this->getFactory()
->createPizzaStyleLoader(
$outputFileName,
$pizzaNameField,
$pizzaDescriptionField,
);
}
}
Step 4: Add the plugin to the dependency provider
Next, we need to add the plugin to the dependency provider so that Springbok can load it.
<?php
namespace Pyz\Zed\Springbok;
use Antiloop\Zed\Springbok\SpringbokDependencyProvider as SpringbokSpringbokDependencyProvider;
use Pyz\Zed\TextPizza\Communication\Plugins\PizzaStyleLoaderPlugin;
class SpringbokDependencyProvider extends SpringbokSpringbokDependencyProvider
/**
* @return array<\Antiloop\Zed\Springbok\Dependency\Plugin\LoaderPluginInterface>
*/
protected function getLoaderPlugins(): array
{
return [
new PizzaStyleLoaderPlugin(),
];
}
}
Step 5: Use the loader in a pipeline
Now you can use the plugin in your pipeline configuration
<pizza-style
outputFileName="data/output/pizza.txt"
pizzaNameField="name"
pizzaDescriptionField="description"
/>
What we have done in this tutorial?
We created a new loader that writes a “pizza” file format.
We added the loader to the factory so that we can instantiate.
We created a new loader plugin that will allow us to use the transformer in a pipeline.
We added the plugin to the dependency provider so that it can be used in the pipeline.
Now you can use the plugin in your pipeline configuration to extract lines from a plain text file. And this concludes the tutorial on how to write a new loader plugin for the Springbok framework.
Further reading:
See the How to write a new extractor plugin for more information on how to write a extractor plugin.
See the How to write a new transformer plugin for more information on how to write a transformer plugin.
See the How to write a new hook plugin for more information on how to write a hook plugin.
See the Pipeline documentation for more information on how to use the plugin in a pipeline.