Add new comment
Batch API vs. Pro Drupal Development 2
Idézet a címbeli könyv 564-565. oldaláról:
A batch set can have the following keys in its associative array. Only the operations key is required.
(...)
* file: If the callback functions for operations and finished are not in scope during a normal Drupal request, the path of the file containing these functions must be given. The path is relative to the base_path() of the Drupal installation and can be conveniently built using drupal_get_path(). It is unnecessary to define file if the functions are already in scope.
Magyar nyersfordításban:
Egy batchet leíró asszociatív tömb az alábbi kulcsokkal rendelkezhet. Csak az operations kulcs kötelező.
(...)
* file: Ha az operations és finished kulcsoknál megadott callback függvények nem elérhetőek egy normál Drupal hívás során, meg kell adni az őket tartalmazó fájlok elérési útját. Ezen elérési út a Drupal telepítés base_path()-jához képest relatív, és kényelmesen előállítható a drupal_get_path() használatával. Szükségtelen megadni a file kulcsot, ha a függvények már elérhetőek.
Nos, ez a legutóbbi mondat nem (vagy nem teljesen így) igaz - de ez csak az egyik probléma, mely a Drupal Batch API-jával való ismerkedésem során felmerült.
Megírtam a hívandó függvényeket, a batchet elindító page callbacket, elhelyeztem mindet ugyanazon .inc fájlban (amit nyilván a hook_menu()-ben is megadtam), és bár az állapotjelző csík megjelent, a callback függvényeim nem futottak le - cserébe viszont hibaüzenetet sem kaptam. Néhány szál hajammal kevesebb lett, mire rájöttem: ezt a file kulcsot igenis meg kell adni, hogy működjön a kötegelt feldolgozás. (Lehet, hogy a Form API myform_submit()-jából indítva a batchet nem kell megadni, de ugye jelen esetben a batchnek nem volt szüksége semmilyen, a felhasználótól érkező paraméterre, tehát egyszerűen page callbackbe került a batchet indító kód.)
A másik probléma az egyes batch callbackek utolsó, &$context['sandbox'] paraméterével kapcsolatos. Idézet az 567. oldalról:
* sandbox: This area is open to use by callback functions. You can store anything you need in here and it will persist. In our example, we store some information about the number of users to import, the user currently being imported, and so forth. Use this instead of $_SESSION for storing information during batch processing. If you use $_SESSION and the user opens a new browser window, bad things could happen.
Magyar nyersfordításban:
* sandbox: Ez a terület szabadon használható a callback függvények számára. Itt bármit tárolhatunk, amire szükség van, s ezek az adatok meg is maradnak. A példánkban itt tárolunk információt az importálandó felhasználók számáról, az éppen importált felhasználóról, és így tovább. A kötegelt feldolgozás során ezt a területet kell használni információtárolásra a $_SESSION helyett. Ha a $_SESSION-t használjuk és a felhasználó egy új böngészőablakot nyit, rossz dolgok történhetnek.
Nos, ez is csak részben igaz. Lássuk az alábbi kódot.
function mymodule_batch_start() {
$operations = array();
$operations[] = array('mymodule_batch_first', array());
$operations[] = array('mymodule_batch_second', array());
$batch = array(
'operations' => $operations,
// This is definitely needed since we are called from a page callback, not from FAPI.
'file' => drupal_get_path('module', 'mymodule') .'/mymodule.batch.inc',
);
batch_set($batch);
// This is needed as well, for the same reason.
batch_process('mymodule_page');
}
function mymodule_batch_first(&$context) {
// Store some information to the sandbox.
$context['sandbox']['mymodule_info'] = t('Information stored by my module.');
}
function mymodule_batch_second(&$context) {
// Retrieve the stored information.
drupal_set_message(t('Stored information:') .' '. $context['sandbox']['mymodule_info']);
}
Lehet tippelni, mit fog kiírni a drupal_set_message(), de inkább elmondom, hogy csak ennyit: Stored information: - ugyanis a sandbox-ban tárolt információk csak ugyanazon callback többszöri meghívása között őrződnek meg, két callback között nem. Megoldásként a variable_set() és variable_get() párost használtam (valamint írtam egy finished callbacket, mely ugye a batch végén fut le, s többek között egy variable_del() hívást is tartalmaz a szemét eltakarítása végett), de egyáltalán nem vagyok benne biztos, hogy ez a legjobb megoldás.
