In this second tutorial, we will dive deeper into developing plugins. Before you continue, we recommend finishing the My first plugin tutorial.
In this tutorial, you will learn how to develop a plugin which renders your top-selling items in the browser. The top items will be displayed as bootstrap cards with the following item information:
In the first tutorial, you learned how to set up the folder structure with a minimum of required files to create a working plugin. Our new plugin has a similar structure, but it also has additional content in the resources folder. Create the following basis for your plugin.
TopItems/ ├-- resources/ │ └── views/ │ ├── content/ │ │ └── TopItems.twig // actual content │ │ │ └── PageDesign.twig // frame for the content │ ├── src/ │ ├── Controllers/ │ │ └── ContentController.php │ │ │ └── Providers/ │ ├── TopItemsServiceProvider.php │ └── TopItemsRouteServiceProvider.php │ └── plugin.json // plugin information
We start by creating the plugin.json
file. We will also need a ServiceProvider, a RouteServiceProvider and a ContentController in the src folder of our plugin. Create these files and copy the code examples.
TopItems/plugin.json
{ "name" :"TopItems", "description" :"Plugin to render a list of top items", "namespace" :"TopItems", "author" :"Your name", "type" :"template", "serviceProvider" :"TopItems\\Providers\\TopItemsServiceProvider" }
TopItems/src/Providers/TopItemsServiceProvider.php
<?php namespace TopItems\Providers; use Plenty\Plugin\ServiceProvider; class TopItemsServiceProvider extends ServiceProvider { public function register() { $this->getApplication()->register(TopItemsRouteServiceProvider::class); } }
TopItems/src/Providers/TopItemsRouteServiceProvider.php
<?php namespace TopItems\Providers; use Plenty\Plugin\RouteServiceProvider; use Plenty\Plugin\Routing\Router; class TopItemsRouteServiceProvider extends RouteServiceProvider { public function map(Router $router) { $router->get('topitems', 'TopItems\Controllers\ContentController@showTopItems'); } }
TopItems/src/Controllers/ContentController.php
<?php namespace TopItems\Controllers; use Plenty\Plugin\Controller; use Plenty\Plugin\Templates\Twig; use Plenty\Modules\Item\DataLayer\Contracts\ItemDataLayerRepositoryContract; class ContentController extends Controller { public function showTopItems(Twig $twig, ItemDataLayerRepositoryContract $itemRepository):string { $itemColumns = [ 'itemDescription' => [ 'name1', 'description' ], 'variationBase' => [ 'id' ], 'variationRetailPrice' => [ 'price' ], 'variationImageList' => [ 'path', 'cleanImageName' ] ]; $itemFilter = [ 'itemBase.isStoreSpecial' => [ 'shopAction' => [3] ] ]; $itemParams = [ 'language' => 'en' ]; $resultItems = $itemRepository ->search($itemColumns, $itemFilter, $itemParams); $items = array(); foreach ($resultItems as $item) { $items[] = $item; } $templateData = array( 'resultCount' => $resultItems->count(), 'currentItems' => $items ); return $twig->render('TopItems::content.TopItems', $templateData); } }
search
method. We need this method later.showTopItems
function uses the $itemRepository
variable to access our repository. In the showTopItems
function we define the database columns ($itemColumns
) to be searched. Then we set the filters ($itemFilter
) and the parameters ($itemParams
) to be used for the search.itemBase.isStoreSpecial
to filter for store specials and only display the top items ('shopAction' => [3]
).$itemParams
to specify that our item texts are saved in English. Make sure to enter the item's name and description in the respective language in the plentymarkets back end. If the text fields are empty, no text will be displayed in the top item card.search
method from our repository. The search is carried out and it returns a list of items. The items in the list are counted and rendered in the linked template file.
In this step, we create the template file that contains the page design. This file is the HTML frame for our content retrieved from the database. The content itself and its layout will be discussed in step 4. Add a new twig file in the resources/views folder and name the file PageDesign.twig
. Insert the code example below.
TopItems/resources/views/PageDesign.twig
<!DOCTYPE html> <html lang="en"> <head> <!-- Required meta tags always come first --> <title>Top items</title> <!-- CSS --> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="stylesheet" type="text/css"> </head> <body> <div id="page-body"> {% block PageBody %} <!-- inserts content of TopItems.twig here --> {% endblock %} </div> </body> </html>
<body>
, we use a <div>
and the twig {% block %}
tag, which allows us to insert content from another file. This way, you can use the PageDesign.twig
for other content files, too.
Last but not least, we need a file for the item information retrieved from the database. Create a new content subfolder in the resources/views folder and add a TopItems.twig
file.
TopItems/resources/views/content/TopItems.twig
{% extends "TopItems::PageDesign" %} {% block PageBody %} <h1 style="text-align: center">{{ resultCount }} top items found!</h1> <div class="col-xs-12 card-deck-wrapper" style="overflow: auto"> <ul class="list-unstyled card-deck" style="height: 380px"> {% if currentItems is not null %} {% for item in currentItems %} <li class="card" style="width: 280px"> <div class="card-block"> <h4 class="card-title">{{ item.itemDescription.name1 }}</h4> <h6 class="card-subtitle text-muted">ID: {{ item.variationBase.id }}</h6> </div> {% set image = item.variationImageList | first %} <img class="col-lg-12" src="{{ image.path }}" alt="{{ image.cleanImageName }}"> <div class="card-block"> <p class="card-text">{{ item.itemDescription.description }}</p> </div> <div class="card-footer bg-primary"> <h4 style="text-align: center">Price: {{ item.variationRetailPrice.price }} €</h4> </div> </li> {% endfor %} {% else %} <li>No items found!</li> {% endif %} </ul> </div> {% endblock %}
{% extends %}
tag. Within this tag, the {% block %}
tag defines our content with a header and a <div>
container wrapping our card deck.if-else
statement defines the output for a search with and without results. If the search was successful, then list items are generated in the form of cards. These list items represent our top items.card-block
with the item name and the variation ID. The {% set %}
tag selects the first image from the image list. Next we use another card-block
to display the item description. The price will be displayed in the card-footer
.
Provided that you have already set up some top items in your plentymarkets backend, the plugin will be filled with the requested data. To display the top item cards, open a new browser tab and type in your domain adding /topitems
at the end. Don't forget to push your changes to GitHub. You also have to update the plugin in your plentymarkets inbox by pulling the changes from GitHub. Finally, you have to deploy the plugin again to display your top items in your browser. Good job!