This post comes from the first version of this blog.
Please send me an email if anything needs an update. Thanks!
Jakiś czas temu rozpoczynałem kolejny projekt oparty o framework symfony. Do tej pory tworzenie modeli na podstawie klas wygenerowanych z opisu w pliku schema.yml było najprzyjemniejszą częścią pracy. Okazało się jednak, że nie wszystko wygląda tak różowo, jakby mogło się na pierwszy rzut oka zdawać. Mechanizm przetwarzający ma problem z pewnymi nazwami, który to problem ujawnia się pod postacią dosyć nieciekawego, tytułowego błędu. Zapraszam do lektury.
Fotografia: stephenyeargin, CC-BY-SA.
symfony: Błąd "When using the attribute ATTR_AUTO_ACCESSOR_OVERRIDE you cannot use the field name".
Zdecydowana większość wpisów na tym blogu zawiera ostateczne rozwiązania różnego rodzaju mniej lub bardziej poważnych problemów.Weźmy pod uwagę przykładowy model zawierający problematyczne pole:
CustomModel:
tableName: customModels
columns:
id:
type: integer(4)
primary: true
notnull: true
autoincrement: true
name:
type: string(255)
data:
type: string(255)
Jeśli wykorzystując konsolowe narzędzie symfony wykonamy polecenie:
./symfony doctrine:build --all-classesTo generator w momencie, kiedy natrafi na ten model, szybko wyrzuci na ekran komunikat:
When using the attribute ATTR_AUTO_ACCESSOR_OVERRIDE you cannot use the field name "data".Nie udało mi się ustalić, do czego dokładnie służy rzeczony atrybut, ale na podstawie lektury kilku stron w Internecie podejrzewam, że ma to związek z dynamicznym mapowaniem wywołań metod setX() / getX na odpowiednie pola modelu, gdzie X oczywiście oznacza nazwę konkretnego pola, np. setId(), getId().
Cały problem polega na tym, że niektóre z tych akcesorów kolidują z istniejącymi funkcjami klasy, przez co nasza dowolność w nazewnictwie pól nie jest aż tak nieograniczona jak moglibyśmy chcieć. ;]
Jedynym rozwiązaniem tego problemu, jakie do tej pory znalazłem, to czasowe wyłączenie wymienionego wyżej ustawienia na czas generowania modeli. Tutaj pojawia się jednak kolejna “kłoda pod nogi” - skoro wykonujemy konsolowe polecenie generatora, to nie mamy dostępu do kodu, a nie ma możliwości uruchomienia go z pewnego rodzaju “przełącznikiem”, który ustawiałby odpowiednie wartości zmiennych.
Próbowałem trochę “bić się” z frameworkiem, ale bez większego skutku, dlatego trochę nieśmiało, ale jednak sugeruję rozwiązanie ręczne. Plik do zmiany to:
sfDoctrinePluginConfiguration.class.phpZnajduje się on w drzewie:
/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/config/Linijki 46-51 tego pliku zawierają kilka ustawień:
$manager = Doctrine_Manager::getInstance();
$manager->setAttribute(Doctrine_Core::ATTR_EXPORT, Doctrine_Core::EXPORT_ALL);
$manager->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_NONE);
$manager->setAttribute(Doctrine_Core::ATTR_RECURSIVE_MERGE_FIXTURES, true);
$manager->setAttribute(Doctrine_Core::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
$manager->setAttribute(Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES, true);
Zmieniamy interesującą nas wartość [linia 50] na false, uruchamiamy polecenie, a po jego wykonaniu przestawiamy ponownie na true.
Trochę wstyd programiście stosować takie “hacki”, ale czasem niestety nie ma innej opcji, a projekt sam się nie zrobi, także uprzejmie proszę o wybaczenie. Ważne, że w kodzie końcowym wszystko jest robione tak, jak trzeba. ;]
* AKTUALIZACJA 17.09.2011 *
Jeden z komentujących, Damian Zientalak [dzięki!], zasugerował użycie metody configureDoctrine() do wyłączenia niepotrzebnej opcji. Nie wziąłem tego wcześniej pod uwagę, aczkolwiek trafiła się chwila wolnego czasu, którego efektem jest poniższy kod, jaki należy umieścić w pliku klasy ProjectConfiguration w katalogu config:
|
|
Po zapisaniu pliku nie będziemy mieli już żadnych problemów - skrypt wykrywa kontekst, w jakim się znajduje [w tym przypadku jest to kontekst CLI - konsoli] i jeśli znajdujemy się w “czarnym okienku”, to problematyczna opcja zostaje po prostu wyłączona. W końcu mogę spać spokojnie. ;]