Lock already exists for id "layout"
Пн, 2 Лют 2009Використовуючи нову для себе компоненту Zend_Layout зіткнувся з дивним повідомленням про помилку. Пошукавши рішення в інтернет я не зміг зясувати в чому тут справа. Всі вирішення які мені довелося знайти, а їх було лише 2, вказували на взагалі різні причини цєї проблеми. В першому випадку була проблема в конфігу бази даних, в іншому з помилкою в Action Helper.
Єдине що було спільне в усіх описаних випадках так це те що логіку представлення виконано за технікою Метью Вейєр О’Фейнні яку він продемонстрував своїм Pastebin Application на концеренції ZendCon 2008. Деталі тут Pastebin app and conference updates.
Я потратив добряче часу щоб з’ясувати в чому проблема. Подивившись на вихідний код де виникає це повідомлення я зрозумів тільки одне:
Lock already exists for id “layout” – в даному випадку лише підступне повідомлення про помилку, що не вказує на справжню причину проблеми.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /** * Begin capturing content for layout container * * @param string $id * @param array $params * @param array $attribs * @return void */ public function captureStart($id, array $params = array(), array $attribs = array()) { if (array_key_exists($id, $this->_captureLock)) { require_once 'Zend/Dojo/View/Exception.php'; throw new Zend_Dojo_View_Exception(sprintf('Lock already exists for id "%s"', $id)); } $this->_captureLock[$id] = true; $this->_captureInfo[$id] = array( 'params' => $params, 'attribs' => $attribs, ); return ob_start(); } |
Як видно з вихідного коду, маємо помилку суть якої полягає в тому що спроба захоплення блоку через “captureStart” виявилася невдалою оскільки контейнер з таким іменем вже захоплено. Дане повідомлення про помилку призначено для того щоб уникнути перезаписання блоків різного змісту але з однаковими ідентифікаторами.
Вже пізніше я з’ясував що в моєму випадку збій відбувся через регістр символів в назві Action Helper, оскільки робоча машина Windows XP а сервер на Linux то проблема виникла тільки підчас розгортання проекту он-лайн.
При помилці відбувається повторне захоплення блоків після перенаправленні на Error Controller, бо реєструється ще один контейнер представлення з ідентифікатором “layout”.
Одним з варіантів вирішення цієї проблеми я знайшов на сторінці Pastebin app and conference updates в коментарях користувачів:
1. Закоментовуємо всі виклики captureStart(), captureEnd() по порядку їх викликання, до того часу коли ми не отримаємо коректної роботи Error Controller і відповідно отримаємо власне оригінальне повідомлення про помилку що спричинило такий коллапс системи.
2. Вже знаючи справжню причину порушення в роботі відслідковуємо і виправляємо баг!
Як альтернатива цьому варіанту моїм власним рішенням є перемкнути Front Controller з режиму перенаправлення на Error Controller в режим викидання Exceptions в bootstrap файлі.
1 2 3 | // Prepare the front controller for debug $frontController = Zend_Controller_Front::getInstance(); $frontController->throwExceptions(true); |
Успішного вам Zend Framework-ування!!