Chcę programowo usunąć widok sklepu . Patrząc na Mage_Adminhtml_System_StoreController::deleteStorePostAction()
to, jest to dość łatwe (nieco skrócony kod):
$model = Mage::getModel('core/store')->load($id);
if ($model->getId() && $model->isCanDelete()) {
$model->delete();
Mage::dispatchEvent('store_delete', array('store' => $model));
}
Chcę umieścić ten kod w skrypcie aktualizacji danych, aby usunięcie zostało wykonane automatycznie.
Problem polega na tym, że podczas wykonywania skryptów aktualizacji w data/
Magento wywołuje tylko obserwatorów zdarzeń skonfigurowanych w tym global
obszarze (patrz Aktualizacje struktury Magento vs. Aktualizacje danych ). Niektórzy obserwatorzy, tacy jak enterprise_cms
i enterprise_search
dla zdarzenia, store_delete_after
są zdefiniowani w adminhtml
obszarze, więc nie zostaną straceni. Usunięcie widoku sklepu nie będzie traktowane jak usunięcie wykonane w wewnętrznej bazie danych.
Jak sobie radzisz z takimi operacjami? Sam załaduj dodatkowe obszary zdarzeń w skryptach aktualizacji (obawiam się, że)? Czy nie modyfikujesz danych w skrypcie aktualizacji, ale umieszczasz swoje magiczne skrypty w świętym, ukrytym miejscu i wykonujesz je ręcznie?
źródło
Odpowiedzi:
Więc krótko po tym, jak napisałem to na Twitterze do Macieja, przeszedłem w ciszy radiowej. Mam nadzieję, że poczułeś napięcie, czekając na odpowiedź od kilku tygodni.
To, co rozumiem przez „robię to w kolejce”, jest bezpośrednią odpowiedzią na:
Metoda kolejki:
Kiedy wiem, że istnieją pewne zdarzenia, które nie będą uruchamiane we właściwym kontekście (głównie dla EE, ale mogą mieć zastosowanie w innych kontekstach), zwykle usuwam usunięcie z kolejki, aby działało w kontekście, w którym musi .
Innymi słowy, utwórz tabelę kolejek (lub kolejkę / temat w RabbitMQ itp.), Która zawierałaby szczegóły transakcji i haczyki zdarzeń, których powinna nasłuchiwać. Może to być tak eleganckie lub tak proste, jak chcesz. Oto podstawowa
A potem pracuj w kolejce później w CRON, gdzie masz teraz kontrolę nad tym, który sklep „działa” (czyli po prostu uruchamiasz go tak, jakby to był administrator, sklep 0):
Oczywiście, jeśli masz ochotę, zawijaj try / catch i zawijaj transakcję. Myślę, że rozumiesz.
Jest to realnie jedyny sposób kontrolowania kontekstu, w którym wydarzenie się uruchamia.
Metoda zdarzenia tandemowego:
Możesz samodzielnie uruchomić metodę „adminhtml” - Alan daje całkiem przyzwoite wyjaśnienie, co byś zrobił, aby na to wpłynąć , ale zasadniczo jest to to samo:
Administracyjna wersja składowania klienta wywołuje zwykłe zapisywanie modelu, a następnie wywołuje zdarzenie adminhtml. Możesz zrobić to odwrotnie u obserwatora, jeśli chcesz.
źródło
Cholera, kocham mnie trochę dziwactwa, ale muszę się nie zgodzić ze złożonością / kruchością transportu parametrów zadania i obszaru ( adminhtml | crontab | frontend | global | install ) do kolejki, szczególnie jeśli ta kolejka będzie się uruchamiać kontekst Magento. Jeśli istnieją konteksty mieszane, które wymagają obsługi, rozwiązanie kolejki stanowi ponowną implementację bieżącego „problemu”!
Myślę, że podejście do kolejki jest kruche. Moim argumentem jest to, że przedwczesne ładowanie obszarów zdarzeń wcale nie jest problemem. Aby to wyjaśnić, cofnijmy się i spójrzmy na problem:
Aby to zrozumieć, musimy zbadać obszary zdarzeń w kontekście wykonania. Matthias, wyobrażam sobie, że już to wiesz, ale dla budowania innych:
Skrypty konfiguracji danych są wykonywane
Mage_Core_Model_App::run()
przed wysłaniem żądania do kontrolera frontowego:Do czasu wykonania skryptów konfiguracji danych globalny obszar zdarzeń jest ładowany. Obszary zdarzeń kontekstu routingu ( frontend lub adminhtml ) są ładowane później w
Mage_Core_Controller_Varien_Action::preDispatch()
wyniku dopasowania routera do akcji kontrolera (area
nazwa jest ustawiana poprzez dziedziczenie):Tak więc normalnie podczas inicjalizacji aplikacji będą wykonywane tylko obserwatory skonfigurowane w obszarze globalnych zdarzeń. Jeśli skrypt instalacyjny robi coś takiego jak
wtedy są tylko dwa niebezpieczeństwa:
controller_front_init_before
lubcontroller_front_init_routers
# 1 powinno być łatwe do pozyskania. # 2 jest prawdziwym problemem i myślę, że Refleksja może rozwiązać problem (zauważ, że jestem bardzo niedoświadczony w używaniu refleksji):
Nie przetestowałem tego, ale usuwa indeks zdarzeń adminhtml i odpowiadający mu
Mage_Core_Model_App_Area
obiekt.źródło