Get table names with Symfony+Doctrine excluding tables made from relations - php

I'd like to get all table names from my PSQL DB using Doctrine, but I don't want relation tables, e.g.:
Tables:
users
clients
users_clients <-- not this
I'm currently fetching them using
$em->getConnection()->getSchemaManager()->listTables();
Any way to do it without excluding results from array using strpos()?

The following code should work:
public class MyController {
public function listTables(EntityManagerInterface $em) {
$allMetadata = $em->getMetadataFactory()->getAllMetadata();
$tableNames = array_map(
function(ClassMetadata $meta) {
return $meta->getTableName();
},
$allMetadata);
// do something with the table names
}
}
Doctrine documentation: ClassMetadata#getTableName()

Here is how I would do it...
public function getTables(): bool|array {
// get connection any way you do
$connection = BasePDO::getInstance()->getEntityManager()->getConnection();
$query = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'";
$statement = $connection->prepare($query);
// First column is the table name
return $statement->executeQuery()->fetchFirstColumn();
}

I wrote a code that currently works for me, but it's not finished yet. If you got here to find an answer to the same question I had, feel free to analyse code.
But keep in mind that I'm not a pro (far from it).
This I have inside ReportController:
// Returns an array with my entities
$entities = $em->getMetadataFactory()->getAllMetadata();
//Generate my table names, according to Franz's answer
$tableNames = [
function(ClassMetadata $meta) {
return $meta->getTableName();
},
$entities
];
foreach ($tableNames[1] as $tableKey=>$tableName) {
$table[$tableKey] = $tableName->getTableName();
}
// Generate an array of columns from $table
// Code from generateColumnNames() below
$column[] = $this->getDoctrine()
->getRepository(Chamados::class)
->generateColumnNames($table);
//Since I'm displaying some Entity names in PT-BR, I need to treat them.
//I wish I had a better way to do this without having to treat them one by one
foreach ($entities as $entity) {
$e = explode('\\',$entity->getName());
if ($e[2] === "User") {
$e[2] = "Usuários";
}
else if ($e[2] === "Tramite") {
$e[2] = "Trâmites";
}
else if ($e[2] === "Clients") {
$e[2] = "Clientes";
}
$entKey[] = $e[2];
}
//Insert each name into each array value to display them in my form
$entities = array_combine($entKey, $entities);
//Generate the form
$form = $this->createFormBuilder(['aaa'])
->add('entity', ChoiceType::class, [
'required' => true,
'placeholder' => '',
'attr' => [
'style' => 'text-transform:capitalize',
'class' => 'entity-class general-control'
],
'choices' => $entities
])
->add('type', ChoiceType::class, [
'label' => 'Tipo de relatório',
'required' => true,
'placeholder' => '',
'attr' => [
'style' => 'display: none',
'class' => 'type-class general-control'
],
'choices' => [
'Campo' => 0,
'Quantidade' => 1,
'Tudo' => 2,
]
])
->add('select', ChoiceType::class, [
'label' => 'Campos',
'required' => false,
'multiple' => true,
'attr' => [
'style' => 'text-transform:capitalize; display: none',
'class' => 'select-class general-control'
],
'choices' => $column
])
->add('where', ChoiceType::class, [
'label' => 'Onde',
'placeholder' => '',
'attr' => [
'style' => 'text-transform:capitalize; display: none',
'class' => 'where-class general-control'
],
'choices' => $column
])
->add('operator', ChoiceType::class, [
'label' => false,
'attr' => [
'style' => 'display: none',
'class' => 'operator-class general-control'
],
'choices' => [
'Igual a' => '=',
'Diferente de' => '!=',
'Contém' => 'LIKE',
'Entre' => 'BETWEEN',
'Maior ou igual a' => '>=',
'Menor ou igual a' => '<=',
]
])
->add('parameter', TextType::class, [
'label' => false,
'attr' => [
'style' => 'display: none',
'placeholder' => 'Parâmetro',
'readonly' => 'true',
'class' => 'parameter-class general-control'
]
])
->add('submit', SubmitType::class, [
'label' => 'Gerar relatório',
'attr' => [
'class' => 'button-blue submit-class general-control',
'style' => 'display: none'
]
])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//Get each form value to use it on generateReport() (code below)
$entity = $form->get('entity')->getData();
$type = $form->get('type')->getData();
$select = $form->get('select')->getData();
$where = $form->get('where')->getData();
$operator = $form->get('operator')->getData();
$parameter = $form->get('parameter')->getData();
//Generate the report, returning an array
$result = $this->getDoctrine()
->getRepository(Chamados::class)
->generateReport($entity, $type, $select, $where, $operator, $parameter);
return $this->redirectToRoute('generalResult', [
'result' => $result,
'entity' => $entity->getTableName()
]);
}
return [
'form' => $form->createView()
];
generateColumnNames() (Inside a Repository):
public function generateColumnNames($table){
$em = $this->getEntityManager();
foreach($table as $t) {
foreach ($em->getConnection()->getSchemaManager()->listTableColumns($t) as $v) {
$column[$t][$v->getName()] = $v->getName();
}
}
return $column;
}
generateReport() (Inside the same Repository):
public function generateReport($entity, int $type, array $selectField, string $whereField, string $operator, string $parameter): array
{
//0 = Fields / 1 = Count / * = Everything
if ($type === 0) {
foreach($selectField as $key=>$value) {
$select[$key] = "c." . $value;
}
$select = implode(", ", $select);
}
else if ($type === 1){
$select = "count('id')";
}
else {
$select = "c";
};
$query = $this->_em->createQueryBuilder()
->select($select)
->from($entity->getName(), 'c');
if ($operator === "LIKE") {
$parameter = "%" . $parameter . "%";
$query->andWhere("LOWER (c." . $whereField . ") " . $operator . " :" . $whereField);
}
else {
$query->andWhere("c." . $whereField . " " . $operator . " :" . $whereField);
}
$query->setParameter(":" . $whereField, $parameter);
$result = $query->getQuery()->getArrayResult();
return $result;
}

Related

How do I unit-test table filter function in lumen

This is the my back-end code. I wrote the test for this function as follows:
public function index(Request $request)
{
$fields = 'in:' . implode(',', Schema::getColumnListing('suppliers'));
$messages = [
'order_by.in' => 'The selected column name is invalid.',
];
$this->validate($request, [
'page' => ['numeric'],
'per_page' => ['numeric'],
'order_direction' => ['in:desc,asc,DESC,ASC'],
'order_by' => [$fields],
], $messages);
$perPage = 10;
$filter = '';
$orderBy = 'id';
$orderDirection = 'DESC';
try {
if ($request->has('per_page')) $perPage = (int)$request->per_page;
if ($request->has('filter')) $filter = $request->filter;
if ($request->has('order_by')) $orderBy = $request->order_by;
if ($request->has('order_direction')) $orderDirection = strtoupper($request->order_direction);
$suppliers = Supplier::select('id', 'firstname', 'lastname', 'phone', 'email', 'custom_field_1', 'custom_field_2')->where('store_id', Auth::user()->store);
if (!!$filter) {
$suppliers->where('id', 'LIKE', "%{$filter}%")
->orWhere('firstname', 'LIKE', "%{$filter}%")
->orWhere('lastname', 'LIKE', "%{$filter}%")
->orWhere('email', 'LIKE', "%{$filter}%")
->orWhere('phone', 'LIKE', "%{$filter}%");
}
$suppliers->orderBy($orderBy, $orderDirection);
$suppliers = $suppliers->paginate($perPage);
return response()->json([
'success' => true,
'data' => $suppliers->toArray(),
], Response::HTTP_OK);
} catch (Exception $e) {
report($e);
return serverExceptionMessage();
}
}
This is what I have tried and test. I'm creating a store because store_id is a foreign key in my supplier table and adding suppliers dynamically and filtering the firstname through the URL and getting the result from seeJson as an array:
public function testSupplierListViewPaginationFilterTest()
{
$user = factory('App\Models\User')->make();
$store = (factory('App\Models\Store')->make())->getAttributes();
$this->actingAs($user)
->post('/create-new-store', $store)
->seeStatusCode(Response::HTTP_OK);
$attributes = [
'id' => 1,
'firstname' => 'ashid',
'lastname' => 'mhd',
'phone' => 776358547,
'email' => 'ashid#email.com',
'custom_field_1' => 'test',
'custom_field_2' => 'test',
];
$user->store = Store::latest()->first()->id;
$attributes['store_id'] = Auth::user()->store;
$supplier = Supplier::create($attributes);
$this->actingAs($user)
->get('/suppliers?filter=' . $supplier['firstname'], $attributes)
->seeStatusCode(Response::HTTP_OK)->seeJson([
'success' => true,
"data" =>
[
'id' => 1,
'firstname' => 'ashid',
'lastname' => 'mhd',
'phone' => 776358547,
'email' => 'ashid#email.com',
'custom_field_1' => 'test',
'custom_field_2' => 'test',
]
]);
}
I'm getting following error:
1) SupplierTest::testSupplierListViewPaginationFilterTest
Unable to find JSON fragment
["data":"custom_field_1":"test","custom_field_2":"test","email":"ashid#email.com","firstname":"ashid","id":1,"lastname":"mhd","phone":776358547}] within [{"data":{"current_page":1,"data":[{"custom_field_1":"test","custom_field_2":"test","email":"ashid#email.com","firstname":"ashid","id":1,"lastname":"mhd","phone":"776358547"}],"first_page_url":"http:\/\/localhost\/suppliers?page=1","from":1,"last_page":1,"last_page_url":"http:\/\/localhost\/suppliers?page=1","next_page_url":null,"path":"http:\/\/localhost\/suppliers","per_page":10,"prev_page_url":null,"to":1,"total":1},"success":true}].
Failed asserting that false is true.
I need a best solution for this problem .

Symfony Selection of Entity using Doctrine

i need some help.
I have a Form where i would like to either choose an existing Entity or submit a new one. So i have a Class Dolmetscher (Interpreter for languages) with title, name, surname and language. To create the Form i have a Class InterpreterType with the function
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('anrede', ChoiceType::class, array(
'choices' => array(
'Herr' => 'Herr',
'Frau' => 'Frau'
)
))
->add('vorname')
->add('nachname')
->add('sprache')
->add('dolmetscher', EntityType::class, array(
'class' => 'AppBundle:Dolmetscher',
'placeholder' => 'Dolmetscher wählen',
'label' => 'Dolmetscher',
'choice_value' => 'id',
'choice_label' => function ($dolmetscher) {
return $dolmetscher->getAnrede() . ' ' .
$dolmetscher->getVorname() . ' ' .
$dolmetscher->getNachname();
},
'mapped' => false,
))
->add('select', SubmitType::class, array(
'label' => 'Übernehmen',
'attr' => array(
'class' => 'btn btn-default',
'formnovalidate' => 'formnovalidate'
)
))
->add('save', SubmitType::class, array(
'label' => 'OK',
'attr' => array(
'style' => 'float: right',
'class' => 'btn btn-default'
)
))
->add('reset', SubmitType::class, array(
'label' => 'Zurücksetzen',
'attr' => array(
'style' => 'float: right; margin-right: 10px',
'class' => 'btn btn-warning',
'formnovalidate' => 'formnovalidate'
)
));
}
So i have a selection with Entities, which is working, with a 'select' Button and Form fields for a new Dolmetscher with a 'save' Button. Also a 'reset' Button
My Controller Class looks like
/**
* #Route("/u01/5", name="u1_5")
*/
public function dolmetscherAction(Request $request) {
$session = $this->get("session");
var_dump($session->get("foo"));
if (!$session->get("dolmetscher")) {
$dolmetscher = new Dolmetscher();
} else {
$dolmetscher = $session->get("dolmetscher");
}
$dolmetscherForm = $this->createForm(DolmetscherType::class, $dolmetscher);
$dolmetscherForm->handleRequest($request);
if ($dolmetscherForm->get('select')->isClicked()) {
$dolmetscher = $dolmetscherForm->get('dolmetscher');
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('u1_5');
}
if ($dolmetscherForm->get('reset')->isClicked()) {
$dolmetscher = new Dolmetscher();
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('u1_5');
}
if ($dolmetscherForm->get('save')->isClicked() && $dolmetscherForm->isSubmitted() && $dolmetscherForm->isValid()) {
$dolmetscher = $dolmetscherForm->getData();
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('homepage');
}
return $this->render('urkunden/u01/5.html.twig', [
'form' => $dolmetscherForm->createView(),
'page_title' => 'U01'
]);
}
I want to put the Dolmetscher from the selection into $_SET for later use ,e.g. persist in DB, which works fine for a new Dolmetscher but not for my selection. I get an Exception
Serialization of 'Closure' is not allowed
I'm not sure if I'm doing this right at all (I have some OneToMany Relations and wanted to have a view for each Entity/Form and persist everything at once at the end so that i don't have only a Dolmetscher in my DB when the user quits in mid process)
I also thought it might be possible to populate the Form fields from the selection which I couldn't get to work. Can someone please help me, i would appreciate it.
This part of code is probably the origin of your problems :
if ($dolmetscherForm->get('select')->isClicked()) {
$dolmetscher = $dolmetscherForm->get('dolmetscher'); <------ this one
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('u1_5');
}
you are trying to serialize a form object which contains a closure. Closure can not be serialized ( visit this link for more insights Exception: Serialization of 'Closure' is not allowed )
If you dump $dolmetscher variable you will probably get a form object not the entity you want. try to replace the line :
$dolmetscher = $dolmetscherForm->get('dolmetscher');
with :
$dolmetscher = $dolmetscherForm->get('dolmetscher')->getData();

Ordering categories alphabetically in Prestashop top menu

I have set up a Prestashop 1.7 website for a client and I'm importing his new products with a script every day. These products are put in categories that I create if they don't yet exist. My problem is that the newly created categories are put at the end of the drop down top menu, and it would be much better to have them displayed alphabetically. I know I can do that in the back office by drag and dropping them in place, but I want my script to do it automatically.
I've already overriden the Category.phpclass to make other changes so I can edit this file. I tried to change every ORDER BY clauses I found from depth or position to name. It had some effects as categories were indeed sorted by name but a lot of them simply disappeared from the menu (i.e. out of say 10 categories sorted by position, only 4 remained sorted by name).
Do you know a way to achieve this?
You can do this 2 ways.
My approach is to do this when the menu is created, this way it's sorted in every language. To do so, just use this override for ps_mainmenu module:
use PrestaShop\PrestaShop\Core\Module\WidgetInterface;
class Ps_MainMenuOverride extends Ps_MainMenu implements WidgetInterface
{
protected function generateCategoriesMenu($categories, $is_children = 0)
{
$categories = $this->sortCategories($categories);
return parent::generateCategoriesMenu($categories, $is_children);
}
public function sortCategories($categories)
{
uasort($categories, 'cmpcat');
foreach($categories as $k => $category)
{
if (isset($category['children']) && !empty($category['children'])) {
$children = $this->sortCategories($category['children']);
$categories[$k]['children'] = $children;
}
}
return $categories;
}
}
function cmpcat($a, $b) {
return strcmp($a['name'], $b['name']);
}
The other option is to sort when creating the menu. But I would have to see the current import code, and even then could be more difficult.
This is for the children categories. For the main categories it would be necessary to override another function.
The problem is the query, if, for example, the child category name starts with a and parent with b, prestashop doesn't show it, you must add a primary "order by", in this case: level_depth.
I hope my override code will be useful:
use PrestaShop\PrestaShop\Core\Module\WidgetInterface;
class Ps_MainMenuOverride extends Ps_MainMenu implements WidgetInterface
{
protected function makeMenu()
{
$root_node = $this->makeNode([
'label' => null,
'type' => 'root',
'children' => []
]);
$menu_items = $this->getMenuItems();
$id_lang = (int)$this->context->language->id;
$id_shop = (int)Shop::getContextShopID();
foreach ($menu_items as $item) {
if (!$item) {
continue;
}
preg_match($this->pattern, $item, $value);
$id = (int)substr($item, strlen($value[1]), strlen($item));
switch (substr($item, 0, strlen($value[1]))) {
case 'CAT':
$categories = $this->generateCategoriesMenu(
Category::getNestedCategories($id, $id_lang, false, $this->user_groups,true,'',' ORDER BY c.`level_depth`,cl.`name` ASC ')
);
$root_node['children'] = array_merge($root_node['children'], $categories);
break;
case 'PRD':
$product = new Product((int)$id, true, (int)$id_lang);
if ($product->id) {
$root_node['children'][] = $this->makeNode([
'type' => 'product',
'page_identifier' => 'product-' . $product->id,
'label' => $product->name,
'url' => $product->getLink(),
]);
}
break;
case 'CMS':
$cms = CMS::getLinks((int)$id_lang, array($id));
if (count($cms)) {
$root_node['children'][] = $this->makeNode([
'type' => 'cms-page',
'page_identifier' => 'cms-page-' . $id,
'label' => $cms[0]['meta_title'],
'url' => $cms[0]['link']
]);
}
break;
case 'CMS_CAT':
$root_node['children'][] = $this->generateCMSCategoriesMenu((int)$id, (int)$id_lang);
break;
// Case to handle the option to show all Manufacturers
case 'ALLMAN':
$children = array_map(function ($manufacturer) use ($id_lang) {
return $this->makeNode([
'type' => 'manufacturer',
'page_identifier' => 'manufacturer-' . $manufacturer['id_manufacturer'],
'label' => $manufacturer['name'],
'url' => $this->context->link->getManufacturerLink(
new Manufacturer($manufacturer['id_manufacturer'], $id_lang),
null,
$id_lang
)
]);
}, Manufacturer::getManufacturers());
$root_node['children'][] = $this->makeNode([
'type' => 'manufacturers',
'page_identifier' => 'manufacturers',
'label' => $this->trans('All brands', array(), 'Modules.Mainmenu.Admin'),
'url' => $this->context->link->getPageLink('manufacturer'),
'children' => $children
]);
break;
case 'MAN':
$manufacturer = new Manufacturer($id, $id_lang);
if ($manufacturer->id) {
$root_node['children'][] = $this->makeNode([
'type' => 'manufacturer',
'page_identifier' => 'manufacturer-' . $manufacturer->id,
'label' => $manufacturer->name,
'url' => $this->context->link->getManufacturerLink(
$manufacturer,
null,
$id_lang
)
]);
}
break;
// Case to handle the option to show all Suppliers
case 'ALLSUP':
$children = array_map(function ($supplier) use ($id_lang) {
return $this->makeNode([
'type' => 'supplier',
'page_identifier' => 'supplier-' . $supplier['id_supplier'],
'label' => $supplier['name'],
'url' => $this->context->link->getSupplierLink(
new Supplier($supplier['id_supplier'], $id_lang),
null,
$id_lang
)
]);
}, Supplier::getSuppliers());
$root_node['children'][] = $this->makeNode([
'type' => 'suppliers',
'page_identifier' => 'suppliers',
'label' => $this->trans('All suppliers', array(), 'Modules.Mainmenu.Admin'),
'url' => $this->context->link->getPageLink('supplier'),
'children' => $children
]);
break;
case 'SUP':
$supplier = new Supplier($id, $id_lang);
if ($supplier->id) {
$root_node['children'][] = $this->makeNode([
'type' => 'supplier',
'page_identifier' => 'supplier-' . $supplier->id,
'label' => $supplier->name,
'url' => $this->context->link->getSupplierLink(
$supplier,
null,
$id_lang
)
]);
}
break;
case 'SHOP':
$shop = new Shop((int)$id);
if (Validate::isLoadedObject($shop)) {
$root_node['children'][] = $this->makeNode([
'type' => 'shop',
'page_identifier' => 'shop-' . $id,
'label' => $shop->name,
'url' => $shop->getBaseURL(),
]);
}
break;
case 'LNK':
$link = Ps_MenuTopLinks::get($id, $id_lang, $id_shop);
if (!empty($link)) {
if (!isset($link[0]['label']) || ($link[0]['label'] == '')) {
$default_language = Configuration::get('PS_LANG_DEFAULT');
$link = Ps_MenuTopLinks::get($link[0]['id_linksmenutop'], $default_language, (int)Shop::getContextShopID());
}
$root_node['children'][] = $this->makeNode([
'type' => 'link',
'page_identifier' => 'lnk-' . Tools::str2url($link[0]['label']),
'label' => $link[0]['label'],
'url' => $link[0]['link'],
'open_in_new_window' => $link[0]['new_window']
]);
}
break;
}
}
return $this->mapTree(function ($node, $depth) {
$node['depth'] = $depth;
return $node;
}, $root_node);
}
}

magento saveAction - for beginners

I am a Magento beginner so please bear with me...
I am creating a simple extension for my site to add a custom field to my Tags in adminhtml. The custom field is just a number which I need to identify a specific Z-block (cms block extension) so that I can access it as a widget and show it on the frontend in the Tag "category".
I have created a custom module which is working: I set a field in the form using $fieldset and have extended TagController.php, both of which are being used (I made a simple trial to see whether or not they had been recognized). However, I do not know how to go about saving my custom field to DB (whether amending saveAction is enough, and I haven't done it properly, or if I need to add a custom Model or sql install).
Sorry for the "basic" question but I'm new at this, and have mostly done frontend dev (so my extension knowledge is simply limited).
Thank you to anyone who can help...
Claudia
NEW TAG FORM:
public function __construct()
{
parent::__construct();
$this->setId('tag_form');
$this->setTitle(Mage::helper('tag')->__('Block Information'));
}
/**
* Prepare form
*
* #return Mage_Adminhtml_Block_Widget_Form
*/
protected function _prepareForm()
{
$model = Mage::registry('tag_tag');
$form = new Varien_Data_Form(
array('id' => 'edit_form', 'action' => $this->getData('action'), 'method' => 'post')
);
$fieldset = $form->addFieldset('base_fieldset',
array('legend'=>Mage::helper('tag')->__('General Information')));
if ($model->getTagId()) {
$fieldset->addField('tag_id', 'hidden', array(
'name' => 'tag_id',
));
}
$fieldset->addField('form_key', 'hidden', array(
'name' => 'form_key',
'value' => Mage::getSingleton('core/session')->getFormKey(),
));
$fieldset->addField('store_id', 'hidden', array(
'name' => 'store_id',
'value' => (int)$this->getRequest()->getParam('store')
));
$fieldset->addField('name', 'text', array(
'name' => 'tag_name',
'label' => Mage::helper('tag')->__('Tag Name'),
'title' => Mage::helper('tag')->__('Tag Name'),
'required' => true,
'after_element_html' => ' ' . Mage::helper('adminhtml')->__('[GLOBAL]'),
));
$fieldset->addField('zblock', 'text', array(
'name' => 'zblock_id',
'label' => Mage::helper('tag')->__('Z-Block Id'),
'title' => Mage::helper('tag')->__('Z-Block Id'),
'required' => true,
'after_element_html' => ' ' . Mage::helper('adminhtml')->__('[GLOBAL]'),
));
$fieldset->addField('status', 'select', array(
'label' => Mage::helper('tag')->__('Status'),
'title' => Mage::helper('tag')->__('Status'),
'name' => 'tag_status',
'required' => true,
'options' => array(
Mage_Tag_Model_Tag::STATUS_DISABLED => Mage::helper('tag')->__('Disabled'),
Mage_Tag_Model_Tag::STATUS_PENDING => Mage::helper('tag')->__('Pending'),
Mage_Tag_Model_Tag::STATUS_APPROVED => Mage::helper('tag')->__('Approved'),
),
'after_element_html' => ' ' . Mage::helper('adminhtml')->__('[GLOBAL]'),
));
$fieldset->addField('base_popularity', 'text', array(
'name' => 'base_popularity',
'label' => Mage::helper('tag')->__('Base Popularity'),
'title' => Mage::helper('tag')->__('Base Popularity'),
'after_element_html' => ' ' . Mage::helper('tag')->__('[STORE VIEW]'),
));
if (!$model->getId() && !Mage::getSingleton('adminhtml/session')->getTagData() ) {
$model->setStatus(Mage_Tag_Model_Tag::STATUS_APPROVED);
}
if ( Mage::getSingleton('adminhtml/session')->getTagData() ) {
$form->addValues(Mage::getSingleton('adminhtml/session')->getTagData());
Mage::getSingleton('adminhtml/session')->setTagData(null);
} else {
$form->addValues($model->getData());
}
$this->setForm($form);
return parent::_prepareForm();
}
NEW CONTROLLER:
public function saveAction()
{
if ($postData = $this->getRequest()->getPost()) {
if (isset($postData['tag_id'])) {
$data['tag_id'] = $postData['tag_id'];
}
$data['name'] = trim($postData['tag_name']);
$data['zblock'] = $postData['zblock_id'];
$data['status'] = $postData['tag_status'];
$data['base_popularity'] = (isset($postData['base_popularity'])) ? $postData['base_popularity'] : 0;
$data['store'] = $postData['store_id'];
if (!$model = $this->_initTag()) {
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Wrong tag was specified.'));
return $this->_redirect('*/*/index', array('store' => $data['store']));
}
$model->addData($data);
if (isset($postData['tag_assigned_products'])) {
$productIds = Mage::helper('adminhtml/js')->decodeGridSerializedInput(
$postData['tag_assigned_products']
);
$model->setData('tag_assigned_products', $productIds);
}
try {
$model->save();
Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('The tag has been saved.'));
Mage::getSingleton('adminhtml/session')->setTagData(false);
if (($continue = $this->getRequest()->getParam('continue'))) {
return $this->_redirect('*/tag/edit', array('tag_id' => $model->getId(), 'store' => $model->getStoreId(), 'ret' => $continue));
} else {
return $this->_redirect('*/tag/' . $this->getRequest()->getParam('ret', 'index'));
}
} catch (Exception $e) {
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
Mage::getSingleton('adminhtml/session')->setTagData($data);
return $this->_redirect('*/*/edit', array('tag_id' => $model->getId(), 'store' => $model->getStoreId()));
}
}
return $this->_redirect('*/tag/index', array('_current' => true));
}
The custom field I'm trying to add is "zblock"...thanks and, again, bear with me! :)
First add the field in database table.
For example if you want to add in your custom table.
ALTER TABLE myCustomModuleTable ADD COLUMN 'myCustomField' int(10);
Thenafter, In your controller action take the model object of that table and set the field.
If you are adding data in existing table row:
$value = 6;
$rowInWhichIWantToSave = Mage:getModel('companyname/modulename')->load($rowId);
$rowInWhichIWantToSave->setData('myCustomField',$value)->save();
If you are adding a new row:
$value = 6;
$rowInWhichIWantToSave = Mage:getModel('companyname/modulename');
$rowInWhichIWantToSave->setData('myCustomField',$value)->save();
Hope this helps!!

Handling a complex Symfony2 form with multiple entities relationship

I have a form (still not finished and is missing many fields) that is handled as a wizard with steps, in which fields from multiple entities are handled. This is the form itself:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tipo_tramite', 'entity', array(
'class' => 'ComunBundle:TipoTramite',
'property' => 'nombre',
'required' => TRUE,
'label' => "Tipo de Trámite",
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('q')
->where('q.activo = :valorActivo')
->setParameter('valorActivo', TRUE);
}
))
->add('oficina_regional', 'entity', array(
'class' => 'ComunBundle:OficinaRegional',
'property' => 'nombre',
'required' => TRUE,
'label' => "Oficina Regional",
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('q')
->where('q.activo = :valorActivo')
->setParameter('valorActivo', TRUE);
}
))
->add('procedencia_producto', 'entity', array(
'class' => 'ComunBundle:ProcedenciaProducto',
'property' => 'nombre',
'required' => TRUE,
'label' => "Procedencia del Producto"
))
->add('finalidad_producto', 'entity', array(
'class' => 'ComunBundle:FinalidadProducto',
'property' => 'nombre',
'required' => TRUE,
'label' => "Finalidad del Producto"
))
->add('condicion_producto', 'entity', array(
'class' => 'ComunBundle:CondicionProducto',
'property' => 'nombre',
'required' => TRUE,
'label' => "Condición del Producto"
))
->add('lote', 'integer', array(
'required' => TRUE,
'label' => "Tamaño del Lote"
))
->add('observaciones', 'text', array(
'required' => FALSE,
'label' => "Observaciones"
));
}
I have a question regarding how to handle the parameter data_class in this case so I do not have to do magic in the controller. When I say magic I mean the following:
public function empresaAction()
{
$entity = new Empresa();
$form = $this->createForm(new EmpresaFormType(), $entity);
return array( 'entity' => $entity, 'form' => $form->createView() );
}
public function guardarEmpresaAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->container->get('fos_user.user_manager');
/** #var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->container->get('event_dispatcher');
/** #var $mailer FOS\UserBundle\Mailer\MailerInterface */
$mailer = $this->container->get('fos_user.mailer');
$request_empresa = $request->get('empresa');
$request_sucursal = $request->get('sucursal');
$request_chkRif = $request->get('chkRif');
$request_estado = $request_empresa[ 'estado' ];
$request_municipio = $request->get('municipio');
$request_ciudad = $request->get('ciudad');
$request_parroquia = $request->get('parroquia');
$user = $userManager->createUser();
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse())
{
return $event->getResponse();
}
$entity = new Empresa();
$form = $this->createForm(new EmpresaFormType(), $entity);
$form->handleRequest($request);
$success = $url = $errors = "";
if ($form->isValid())
{
if ($request_sucursal != NULL || $request_sucursal != "")
{
$padreEntity = $em->getRepository('UsuarioBundle:Empresa')->findOneBy(array( "padre" => $request_sucursal ));
if (!$padreEntity)
{
$padreEntity = $em->getRepository('UsuarioBundle:Empresa')->findOneBy(array( "id" => $request_sucursal ));
}
if ($request_chkRif != NULL || $request_chkRif != "")
{
$rifUsuario = $request_empresa[ 'tipo_identificacion' ] . $request_empresa[ 'rif' ];
}
else
{
$originalRif = $padreEntity->getRif();
$sliceRif = substr($originalRif, 10, 1);
$rifUsuario = $originalRif . ($sliceRif === false ? 1 : $sliceRif + 1);
}
$entity->setPadre($padreEntity);
}
else
{
$rifUsuario = $request_empresa[ 'tipo_identificacion' ] . $request_empresa[ 'rif' ];
}
$user->setUsername($rifUsuario);
$user->setRepresentativeName($request_empresa[ 'razon_social' ]);
$user->setEmail($request_empresa[ 'usuario' ][ 'email' ]);
$user->setPlainPassword($request_empresa[ 'usuario' ][ 'plainPassword' ][ 'first' ]);
$pais = $em->getRepository('ComunBundle:Pais')->findOneBy(array( "id" => 23 ));
$user->setPais($pais);
$estado_id = $request_estado ? $request_estado : 0;
$estado = $em->getRepository('ComunBundle:Estado')->findOneBy(array( "id" => $estado_id ));
$user->setEstado($estado);
$municipio_id = $request_municipio ? $request_municipio : 0;
$municipio = $em->getRepository('ComunBundle:Municipio')->findOneBy(array( "id" => $municipio_id ));
$user->setMunicipio($municipio);
$ciudad_id = $request_ciudad ? $request_ciudad : 0;
$ciudad = $em->getRepository('ComunBundle:Ciudad')->findOneBy(array( "id" => $ciudad_id ));
$user->setCiudad($ciudad);
$parroquia_id = $request_parroquia ? $request_parroquia : 0;
$parroquia = $em->getRepository('ComunBundle:Parroquia')->findOneBy(array( "id" => $parroquia_id ));
$user->setParroquia($parroquia);
...
}
else
{
$errors = $this->getFormErrors($form);
$success = FALSE;
}
return new JsonResponse(array( 'success' => $success, 'errors' => $errors, 'redirect_to' => $url ));
}
Since the 'data_classonEmpresaFormTypeis set toUsuarioBundle\Entity\Empresa` then I need to handle any extra parameter as example above show with getter/setter and that's a lot of work for complex/big forms.
In the sample form, the fields tipo_tramite will persist in the class ComunBundle\Entity\Producto but the field oficina_regional will persist in the class ComunBundle\Entity\SolicitudUsuario and so with others who are not placed even here but they are in the form, in total should persist as 3 or 4 entities including relationships in many cases, how do you handle this?
I know there is CraueFormFlowBundle that maybe cover this process/flow but not sure if it is the solution to go.
Any advice?
Just worked with multi-step form few days ago. I think you need embedded forms here. Anyway can suggest you another nice bundle for creating wizard: SyliusFlowBundle. IMO it's more flexible and easier to understand than CraueFormFlowBundle.
BTW why do you want to store all in one form? We've used one form for each step, and I liked this approach.

Categories