Massenaktionen (Mass Actions): Aktivieren/Deaktivieren, Löschen
Massenaktionen (Mass Actions): Aktivieren/Deaktivieren, Löschen
~8 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026
Massenaktionen erlauben es, mehrere ausgewählte Zeilen auf einmal zu bearbeiten - typischerweise Löschen oder einen Statuswechsel. Auf der JavaScript-Seite ist dafür nichts weiter zu tun als eine Deklaration in listing.xml; auf der PHP-Seite braucht jede Aktion einen eigenen Controller.
massaction in listing.xml deklarieren
<massaction name="listing_massaction">
<action name="delete">
<settings>
<confirm>
<title translate="true">Delete</title>
<message translate="true">Are you sure you want to delete selected announcements?</message>
</confirm>
<url path="mironsoft_announcement/announcement/massDelete"/>
<type>delete</type>
<label translate="true">Delete</label>
</settings>
</action>
<action name="activate">
<settings>
<url path="mironsoft_announcement/announcement/massStatus">
<param name="status" xsi:type="number">1</param>
</url>
<type>activate</type>
<label translate="true">Activate</label>
</settings>
</action>
<action name="deactivate">
<settings>
<url path="mironsoft_announcement/announcement/massStatus">
<param name="status" xsi:type="number">0</param>
</url>
<type>deactivate</type>
<label translate="true">Deactivate</label>
</settings>
</action>
</massaction>Jede <action> braucht nur eine url, ein optionales confirm für einen Bestätigungsdialog, und optionale statische param-Werte, die bei jedem Aufruf mitgeschickt werden (hier: der Ziel-Status).
Magento\Ui\Component\MassAction\Filter
Der Controller muss die vom Frontend gesendeten IDs nicht selbst aus dem Request auslesen und filtern - dafür gibt es Filter, das direkt eine bereits gefilterte Collection zurückliefert:
<?php
declare(strict_types=1);
namespace Mironsoft\Announcement\Controller\Adminhtml\Announcement;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Ui\Component\MassAction\Filter;
use Mironsoft\Announcement\Model\ResourceModel\Announcement\CollectionFactory;
/**
* Deletes all announcements selected via a grid mass action.
*/
class MassDelete extends Action
{
public const ADMIN_RESOURCE = 'Mironsoft_Announcement::announcement';
/**
* @param Context $context Backend action context.
* @param Filter $filter Applies the grid selection onto a collection.
* @param CollectionFactory $collectionFactory Factory for the announcement collection.
*/
public function __construct(
Context $context,
private readonly Filter $filter,
private readonly CollectionFactory $collectionFactory,
) {
parent::__construct($context);
}
/**
* Deletes the selected announcements and redirects back to the grid.
*
* @return ResultInterface
* @throws LocalizedException
*/
public function execute(): ResultInterface
{
$collection = $this->filter->getCollection($this->collectionFactory->create());
$deleted = 0;
foreach ($collection as $announcement) {
$announcement->delete();
$deleted++;
}
$this->messageManager->addSuccessMessage(
__('A total of %1 record(s) have been deleted.', $deleted)
);
/** @var ResultInterface $resultRedirect */
$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
return $resultRedirect->setPath('mironsoft_announcement/announcement/index');
}
}$this->filter->getCollection() übernimmt automatisch beide Fälle: entweder eine explizite Liste ausgewählter IDs, oder "alle Zeilen, die dem aktuellen Filter entsprechen" (wenn der Benutzer "Alle auswählen" nutzt) - beide Fälle sind ohne zusätzlichen Code korrekt abgedeckt.
MassStatus für Aktivieren/Deaktivieren
<?php
declare(strict_types=1);
namespace Mironsoft\Announcement\Controller\Adminhtml\Announcement;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Ui\Component\MassAction\Filter;
use Mironsoft\Announcement\Model\ResourceModel\Announcement\CollectionFactory;
/**
* Toggles the active status of the announcements selected via a mass action.
*/
class MassStatus extends Action
{
public const ADMIN_RESOURCE = 'Mironsoft_Announcement::announcement';
/**
* @param Context $context Backend action context.
* @param Filter $filter Applies the grid selection onto a collection.
* @param CollectionFactory $collectionFactory Factory for the announcement collection.
*/
public function __construct(
Context $context,
private readonly Filter $filter,
private readonly CollectionFactory $collectionFactory,
) {
parent::__construct($context);
}
/**
* Applies the requested status to the selected announcements.
*
* @return ResultInterface
*/
public function execute(): ResultInterface
{
$status = (int) $this->getRequest()->getParam('status');
$collection = $this->filter->getCollection($this->collectionFactory->create());
foreach ($collection as $announcement) {
$announcement->setIsActive($status)->save();
}
$this->messageManager->addSuccessMessage(__('Status updated.'));
/** @var ResultInterface $resultRedirect */
$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
return $resultRedirect->setPath('mironsoft_announcement/announcement/index');
}
}Achtung: Massenaktionen laufen ohne separate Bestätigung durch die Datenbank durch, wenn kein <confirm> in der XML gesetzt ist - für destruktive Aktionen wie Löschen gehört ein Bestätigungsdialog daher zwingend dazu, nicht nur als Komfortfeature.