Symfony II. rész – admin generator
Tovább mennék az első rész folyamányaként. Admin generátorról lesz itt is szó, néhány általános probléma megoldását tenném közzé:
- a listában szereplő mezők változtatása
- kapcsolt táblák szerinti rendezés
Eljött az idő hogy egy pici, de konkrét adatbázist kreáljunk.
Futtasuk le akár a már telepített phpmyadminban
CREATE DATABASE sandbox; USE sandbox; CREATE TABLE `categories` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `products` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) NOT NULL, `price` float(9,3) default '0.000', `category_id` int(11) default NULL, PRIMARY KEY (`id`), KEY `category_id` (`category_id`), CONSTRAINT `products_fk` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Az első leírásban létrehozott sandbox projectünket fogjuk átszerkeszteni.
Tehát állítsuk be a config könyvtárban lévő adatbázisokhoz tartozó fájlokat (propel.ini és databases.yml) az előbb létrehozott sandbox adatbázisra.
Majd futtassuk le az alábbi parancsokat is:
# generáljuk le a schema.yml fájlt ./symfony propel:build-schema #hozzuk létre a formokat, filtereket, modeleket, -C direktiva kihagyja az sql-t (classes only) ./symfony propel:build-all -C # és a két táblánkhoz tartozó admin felületet készítsük el: ./symfony propel:generate-admin --module=CategoriesAdmin frontend categories # az apps/frontend/modules/CategoriesAdmin modulunkat # és a route (apps/frontend/config/routing.yml) szabályt is létre fogja hozni ./symfony propel:generate-admin --module=ProductsAdmin frontend products
Máris érdemes létrehozni a PROJECT_DIR/apps/frontend/templates/layout.php fájlban a 2 menüpontunkat. Közvetlenül a body nyitótagja után tegyük be az alábbi sorokat.
<ul id="menu">
<li><a href="<?php echo url_for('@categories')?>"></a>Kategóriák</a></li>
<li><a href="<?php echo url_for('@products')?>">Termékek</a></li>
</ul>
A http://mydomain/sandbox/frontend_dev.php/CategoriesAdmin érjük el az alkalmazásunkat. Most próbáljuk meg feltölteni adatokkal. Először vigyünk fel kategóriákat. Majd próbáljunk meg, felvinni termékeket is. Elvileg el kell akadnunk amiatt, hogy a categories modelunknek még nincs __toString() metódusa. Ez egy PHP metódus, ami egy objektum kiíratására szolgál. Jelen esetünkben, mi, a name mezővel jelenítenénk meg a tábla egyes rekordjait. Így hát hozzuk létre ezt a metódust a PROJECT_DIR/lib/model/categories.php fájlban.
class Categories extends BaseCategories {
public function __toString()
{
return $this->getName();
}
} // Categories
Ezután már sikeresen megjeleníthetjük a listát, és rögzíthetünk új rekordokat. De mint láthatjuk a termékek listában nem a kategóriák neve, hanem annak azonosítója (id) szerepel, ráadásul a felhasználóknak a termékek id-ja is megjelent. Sajnos a generátorunk nem tökéletes, így a létrehozott fájlokat jó pár helyen módosítanunk kell.
Elsőként magát a PROJECT_DIR/apps/frontend/modules/ProductsAdmin/config/generator.yml fájlt módosítjuk. Figyelve a .yml fájlokra jellemző szabályokra (legfőképp, hogy behúzás nem tabulátor, hanem 2 üres hely) a listát tartalmazó sort egészítsük ki:
list: display: [categories, name, price ] # felsoroljuk a megjelenített mezőket, kapcsolt tábla esetén a classt peer_method: doSelectJoinAll # modelpeer osztályunk metódusa
Másodikként tekintsük meg a létrehozott PROJECT_DIR/apps/frontend/modules/ProductsAdmin/actions/action.class.php fájlt. Mint láthatjuk a ProductsAdminActions osztályunk az autoProductsAdminActions osztályból származik. Ez pedig a cache könyvtárban keresendő, a PROJECT_DIR/cache/frontend/dev/modules/ProductsAdmin/actions/action.class.php fájlban. Ennek az osztálynak kell 2 függvényét felül definiálnuk:
class ProductsAdminActions extends autoProductsAdminActions
{
protected function addSortCriteria($criteria)
{
if (array(null, null) == ($sort = $this->getSort()))
{
return;
}
if ($sort[0] == 'categories.name')
{
$column = CategoriesPeer::NAME;
}
else
{
$column = ProductsPeer::translateFieldName($sort[0], BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_COLNAME);
}
if ('asc' == $sort[1])
{
$criteria->addAscendingOrderByColumn($column);
}
else
{
$criteria->addDescendingOrderByColumn($column);
}
}
protected function isValidSortColumn($column)
{
if (in_array($column, array('categories.name')))
{
return true;
}
else
{
return parent::isValidSortColumn($column)
}
}
}
Majd hozzuk létre a PROJECT_DIR/apps/frontend/modules/ProductsAdmin/_list_th_tabular.php fájlt. Ezt is a cacheből másoltam ki és módosítottam.
<?php slot('sf_admin.current_header') ?>
<th class="sf_admin_text sf_admin_list_th_categories">
<?php if ('categories.name' == $sort[0]): ?>
<?php echo link_to(__('Categories', array(), 'messages'), '@products', array('query_string' => 'sort=categories.name&sort_type='.($sort[1] == 'asc' ? 'desc' : 'asc'))) ?>
<?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/'.$sort[1].'.png', array('alt' => __($sort[1], array(), 'sf_admin'), 'title' => __($sort[1], array(), 'sf_admin'))) ?>
<?php else: ?>
<?php echo link_to(__('Categories', array(), 'messages'), '@products', array('query_string' => 'sort=categories.name&sort_type=asc')) ?>
<?php endif; ?>
</th>
<?php end_slot(); ?>
<?php include_slot('sf_admin.current_header') ?>
<?php slot('sf_admin.current_header') ?>
<th class="sf_admin_text sf_admin_list_th_name">
<?php if ('name' == $sort[0]): ?>
<?php echo link_to(__('Name', array(), 'messages'), '@products', array('query_string' => 'sort=name&sort_type='.($sort[1] == 'asc' ? 'desc' : 'asc'))) ?>
<?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/'.$sort[1].'.png', array('alt' => __($sort[1], array(), 'sf_admin'), 'title' => __($sort[1], array(), 'sf_admin'))) ?>
<?php else: ?>
<?php echo link_to(__('Name', array(), 'messages'), '@products', array('query_string' => 'sort=name&sort_type=asc')) ?>
<?php endif; ?>
</th>
<?php end_slot(); ?>
<?php include_slot('sf_admin.current_header') ?><?php slot('sf_admin.current_header') ?>
<th class="sf_admin_text sf_admin_list_th_price">
<?php if ('price' == $sort[0]): ?>
<?php echo link_to(__('Price', array(), 'messages'), '@products', array('query_string' => 'sort=price&sort_type='.($sort[1] == 'asc' ? 'desc' : 'asc'))) ?>
<?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/'.$sort[1].'.png', array('alt' => __($sort[1], array(), 'sf_admin'), 'title' => __($sort[1], array(), 'sf_admin'))) ?>
<?php else: ?>
<?php echo link_to(__('Price', array(), 'messages'), '@products', array('query_string' => 'sort=price&sort_type=asc')) ?>
<?php endif; ?>
</th>
<?php end_slot(); ?>
<?php include_slot('sf_admin.current_header') ?>
Ezzel a fájllal azonban már sikerült teljesen elontanunk a generátort. Hiszen ha új mezőket teszünk be, vagy veszünk ki, akkor ezt a fájlt újra és újra szerkesztenünk kell. Ez ellen a legjobb módszer talán az lenne, ha a cache könyvtárban lévő fájl tennénk bele egy slotba és valami grepes megoldással átírnánk a kategóriák oszlop fejlécét.
Talán később még módosítom ezt a leírást ezen ötletemmel. Feltéve hogy nem találok jobbat. De ez a leírás mindenképp fejlődni fog, ahogy a generátorokkal kapcsolatban problémákba ütközöm. Aki hasznosnak vélte az eddigi rizsámat, érdemes visszatérni.

Ide kérjük a választ!