Laravel Backpack attribute accessor causing bug on update command - laravel-backpack

I am working on Laravel Backpack. I have two fields like this:
$this->crud->addField([ // SELECT2
'label' => 'Type',
'type' => 'select_from_array',
'name' => 'type',
'options' => [
'' => 'select type',
'Movie' => 'Movies',
'Series' => 'Series'
],
]);
$this->crud->addField([ // select2_from_ajax: 1-n relationship
'label' => "Entity", // Table column heading
'type' => 'select2_from_ajax',
'name' => 'entity_id', // the column that contains the ID of that connected entity;
'entity' => 'entity', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'data_source' => url('api/entity'), // url to controller search function (with /{id} should return model)
'placeholder' => 'Select', // placeholder for the select
'include_all_form_fields' => true, //sends the other form fields along with the request so it can be filtered.
'minimum_input_length' => 0, // minimum characters to type before querying results
'dependencies' => ['type'], // when a dependency changes, this select2 is reset to null
// 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
]);
The second field options are dependent on the first one.
In my model, I have:
public function getEntityIdAttribute()
{
$id = $this->attributes['entity_id'];
$type = $this->attributes['type'];
if ($type == "Movie") {
$attribute = Movie::find($id);
} else {
$attribute = Series::find($id);
}
return $attribute->name;
}
Create and List operations work perfectly. But on update, it throws this error:
Undefined array key "entity_id"
Why is this accessor not working on the update? or can we somehow skip the accessor on the update command?

Related

Laravel backpack InlineCreate Operation Method not allowed error

Trying to use inline_create i can create in modal but i can't select i get error
Method not allowed The POST method is not supported for this route.
Supported methods: GET, HEAD.
URL is : http://127.0.0.1:8000/admin/question/fetch/tags
Field
$this->crud->addField(
[
'label' => "Les mote clé",
'minimum_input_length' => 0,
'type' => 'relationship',
'name' => 'tags', // the method that defines the relationship in your Model
'ajax' => true,
// 'method' => 'GET',
'minimum_input_length' => 0,
'attribute' => 'name', // foreign key attribute that is shown to user
'inline_create' => [ // specify the entity in singular
'entity' => 'tag', // the entity in singular
'force_select' => true, // should the inline-created entry be immediately selected?
'modal_class' => 'modal-dialog modal-md', // use modal-sm, modal-lg to change width
'modal_route' => route('tag-inline-create'), // InlineCreate::getInlineCreateModal()
'create_route' => route('tag-inline-create-save'), // InlineCreate::storeInlineCreate()
]
]
);
Question modal
// tags
public function tags()
{
return $this->belongsToMany(Tag::class, 'question_tags', 'question_id', 'tag_id');
}
I finally found the problem.
I needed to define the ajax route to work with the field, either creating my own endpoin, or using FetchOperation https://backpackforlaravel.com/docs/5.x/crud-operation-fetch#about-1.
In QuestionCrudController:
use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
...
public function fetchTags()
{
return $this->fetch(Tag::class);
}

How to set default value on Symfony3 EntityType?

I'm trying to set a default value on EntityType select like this:
$builder
->add('town', EntityType::class, array(
'label' => "TOWN",
'class' => 'AppBundle:Town',
'choice_label' => 'name',
'choice_value' => 'id',
'attr' => array('class' => 'form-control'),
'placeholder' => 'CHOOSE_AN_OPTION',
'required' => false,
'data' => $this->em->getReference('AppBundle:Town', $options['attr']['town'])
));
I was trying to do it using data option. It works fot a ChoiceType, but not for EntityType. I tried to pass to the data option the town entity ID, Name and the entire object.
I create the form object from the controller:
$finder = $this->createForm(UserFinderType::class, null,
array('attr' => array('role' => $this->getUser()->getRole(),
'town' => empty($params['town']) ? null : $townService->findOneById($params['town'])->getId() )));
When I pass Town ID or Name nothing happens, placeholder is shown. If I remove placeholder, blank option is selected.
When I pass entire Town object, this error is returned: Catchable Fatal Error: Object of class AppBundle\Entity\Town could not be converted to string
And, if I implement a __toString method, I get the same result that I get on ID or Name try.
You have to create __toString function in Town class:
AppBundle\Entity\Town
.................
public function __toString(){
return $this->name; // If you have `name` field or u can return `id`
}

Prestashop helper form 'file' type

I m working on prestasshop and I created a helper form inside a controller (for back office). My question is how to upload a document by using the type:'file' from the helper form. Here is the code:
public function __construct()
{
$this->context = Context::getContext();
$this->table = 'games';
$this->className = 'Games';
$this->lang = true;
$this->addRowAction('edit');
$this->addRowAction('delete');
$this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'),
'confirm' => $this->l('Delete selected items?')));
$this->multishop_context = Shop::CONTEXT_ALL;
$this->fieldImageSettings = array(
'name' => 'image',
'dir' => 'games'
);
$this->fields_list = array(
'id_game' => array(
'title' => $this->l('ID'),
'width' => 25
)
);
$this->identifier = 'id_game';
parent::__construct();
}
public function renderForm()
{
if (!($obj = $this->loadObject(true)))
return;
$games_list = Activity::getGamesList();
$this->fields_form = array(
'tinymce' => true,
'legend' => array(
'title' => $this->l('Game'),
'image' => '../img/admin/tab-payment.gif'
),
'input' => array(
array(
'type' => 'select',
'label' => $this->l('Game:'),
'desc' => $this->l('Choose a Game'),
'name' => 'id_games',
'required' => true,
'options' => array(
'query' => $games_list,
'id' => 'id_game',
'name' => 'name'
)
),
array(
'type' => 'text',
'label' => $this->l('Game Title:'),
'name' => 'name',
'size' => 64,
'required' => true,
'lang' => true,
'hint' => $this->l('Invalid characters:').' <>;=#{}'
),
array(
'type' => 'file',
'label' => $this->l('Photo:'),
'name' => 'uploadedfile',
'id' => 'uploadedfile',
'display_image' => false,
'required' => false,
'desc' => $this->l('Upload your document')
)
)
);
$this->fields_form['submit'] = array(
'title' => $this->l(' Save '),
'class' => 'button'
);
return AdminController::renderForm();
}
Now how can I upload the document?
Do I have to create a column in the table of the db (games table) for storing the file or something related?
Thanks in advance
I assume this AdminController for your model. Now a model obviously can't hold a file in table column. What you can do is hold path to the uploaded file. That's what you can save.
You should look in AdminController class (which you extended). When you submit a form, one of two method are executed:
processAdd()
processUpdate()
Now investigate the flow logic in these methods. Other methods are called from within this methods, such as:
$this->beforeAdd($this->object); -> calls $this->_childValidation();
$this->validateRules();
$this->afterUpdate($object);
As you can see, there these are the methods where you can do you custom stuff. If you look up these functions in AdminController class, the're empty. They are purposely added so people can override them and put their custom logic there.
So, using these functions, you can validate your uploaded file fields (even though it isnt in the model itself), if it validates you can then assign path to the object; and then in beforeAdd method you can actually move the uploaded file to the desired location (because both child validation and default validation has passed).
The way I've done it:
protected function _childValidation()
{
// Check upload errors, file type, writing permissions
// Use $this->errors['file'] if there is an error;
protected function beforeAdd($object)
{
// create filename and filepath
// assign these fields to object;
protected function afterAdd($object)
{
// move the file
If you allow the file field to be updated, you'll need to to these steps for Update methods as well.
you can get uploaded file using $_FILES['uploadedfile'] in both the functions processAdd() and processUpdate(), you can check all the conditions there and before calling $this->object->save(); to save the form data you can write the code to upload the file in the desired location like
move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)
since you can't save the file in database you need to save only the name of the file or location on the database
Hope that helps

Module Forms - Store Value of addField to a Variable

I have something like in my custom module:
$fieldset->addField('orderinfo', 'link', array(
'label' => Mage::helper('web')->__('Order Info'),
'style' => "",
'href' => Mage::helper('adminhtml')->getUrl('adminhtml/sales_order/view', array('order_id' => $order_id)),
'value' => 'Magento Blog',
'after_element_html' => '',
));
And as you can see from the code, I am trying to link that field to the Order Tab in the back-end. I'm having trouble getting the ID though. I'm planning to just save the Order ID in the database, and then using the addField I could have the correct url.
But how can I save an addField value to a variable?
I want to store the value in "$order_id".
Is it possible?
I am not sure in which context you are using this fieldset but if it is used for example for creating or editing object you can try something like that:
In controller:
public function editAction()
{
$id = $this->getRequest()->getParam('id');
$model = Mage::getModel('module/model')->load($id);
Mage::register('model_name', $model);
}
and then in the block:
protected function _prepareForm()
{
$model = Mage::registry('model_name');
// add fieldset to form
$fieldset->addField('orderinfo', 'link', array(
'label' => Mage::helper('web')->__('Order Info'),
'style' => "",
'href' => Mage::helper('adminhtml')->getUrl('adminhtml/sales_order/view', array('order_id' => $model->getOrderId())),
'value' => 'Magento Blog',
'after_element_html' => '',
));
//rest of the elements
}
Answering my own post again. (src: https://magento.stackexchange.com/questions/682/module-forms-store-value-of-addfield-to-a-variable)

Magento, add and set a checkbox on grid and form backend

I've a fully working backend page with a grid and a corresponding form to edit the changes on the corresponding model. I added a new field on the table, bit type, as it will answer to a yes/no configuration option from the user. I added the checkbox on both grid and form.
My problem is that after a couple of hours of searching and trying different approaches I can not set the checkbox checked value both on the grid and the form reading the corresponding field from the database. Also when I click on save on the form the value corresponding to the checkbox is always saved with 1. Everything else on the grid and the form works as it should. I have read here, here, here, here and some more sites and SO questions/answers but still no clue on what I'm doing wrong. Some solutions recommend using a combo box with YES/NO options, but I want a checkbox, can't be so difficult.
Grid code inside the function _prepareColumns():
protected function _prepareColumns() {
...
$this->addColumn('banner_gral', array(
'header' => Mage::helper('banners')->__('General'),
'align' => 'center',
'index' => 'banner_gral',
'type' => 'checkbox',
'values' => $this->getBannerGral()==1 ? 'true' : 'false',
));
...
}
public function __construct()
{
parent::__construct();
$this->setId('bannersgrid');
$this->setDefaultSort('bannerid');
$this->setDefaultDir('asc');
$this->setSaveParametersInSession(true);
$this->setUseAjax(true);
}
public function getGridUrl()
{
return $this->getUrl('*/*/grid', array('_current'=>true));
}
protected function _prepareCollection()
{
$collection = Mage::getModel('banners/bannersadmin')->getCollection();
$this->setCollection($collection);
return parent::_prepareCollection();
}
Form code to add the checkbox inside the function _prepareForm():
protected function _prepareForm()
{
$id = $this->getRequest()->getParam('id');
$params = array('id' => $this->getRequest()->getParam('id'));
if (Mage::registry('banners_data')->getdata()) {
$data = Mage::registry('banners_data')->getdata();
}
elseif (Mage::getSingleton('adminhtml/session')) {
$data = Mage::getSingleton('adminhtml/session')->getdata();
Mage::getSingleton('adminhtml/session')->getdata(null);
}
else {
$data = array();
}
$form = new Varien_Data_Form(array(
'id' => 'edit_form',
'action' => $this->getUrl('*/*/save', $params),
'method' => 'post',
'enctype' => 'multipart/form-data',
));
...
$fieldset->addField('banner_gral', 'checkbox', array(
'label' => Mage::helper('banners')->__('Is general'),
'name' => 'banner_gral',
'class' => 'banner_gral',
'checked' => $this->getBannerGral()==1 ? 'true' : 'false',
'onclick' => 'this.value == this.checked ? 1 : 0',
'note' => Mage::helper('banners')->__('blablablabla'),
'tabindex' => 2
));
...
}
On the saveAction() of my form I have:
$campaign->setbanner_gral(!empty($data['banner_gral']));
In your controller saveAction() when saving the checkbox data do
$banner_gral = isset($your_form_Data['banner_gral']) ? 1 : 0;
For Grid and Form Page
In your controller you should have Mage::register(...)->getData() or Mage::register(...)
public function editAction()
....
Mage::register('example_data', $model);
On your form _prepareForm()
$model = Mage::registry('example_data'); // NOTE registry('example_data'); NOT registry('example_data')->getData();
$fieldset->addField('entire_range', 'checkbox', array(
....
'checked' => $model->getBannerGral()==1 ? 'true' : 'false',
......
))
see http://www.magentocommerce.com/boards/viewthread/20536/
On your grid _prepareColumns()
$this->addColumn('banner_gral', array(
....
'type' => 'checkbox',
'index' => 'banner_gral',
'values' => array(1,2),
'field_name' => 'checkbox_name',
....
));
#R.S answered one issue, how to save the checkbox value on the corresponding model/database field. But the issue on how to correctly display the checkbox on both the grid and the form was not solved. After doing some more searches I finally got to these two links that helped me solve my problem.
To correct the grid issue: Understanding the Grid Serializer Block
Now the part of code where the checkbox column is added, see that I added array(1,2) on the values element.
$this->addColumn('banner_gral', array(
'header' => Mage::helper('banners')->__('General'),
'width' => '20px',
'type' => 'checkbox',
'align' => 'center',
'index' => 'banner_gral',
'values' => array(1,2),
'editable' => 'false',
));
Also if you take a look into the core code of Magento, the class Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Checkbox returns an array of values. Taking a look here finally got me into the right path.
/**
* Returns values of the column
*
* #return array
*/
public function getValues()
{
if (is_null($this->_values)) {
$this->_values = $this->getColumn()->getData('values') ? $this->getColumn()->getData('values') : array();
}
return $this->_values;
}
To correct the form issue: Mage_Adminhtml_Block_System_Store_Edit_Form Class Reference
The issue on this case was that I was trying to use the $this but what I needed to use was the $data that is loaded at the beginning of the _prepareForm function. #R.S pointed the right direction, but it is not possible to use $model->getBannerGral() as the $data on the registry is an array, not a model. So, using $data["banner_gral"] I could get the needed value for the checkbox. Tested and it is working.
$fieldset->addField('banner_gral', 'checkbox', array(
'label' => Mage::helper('banners')->__('Is general'),
'name' => 'banner_gral',
'checked' => $data["banner_gral"],
'onclick' => 'this.value = this.checked ? 1 : 0;',
'note' => Mage::helper('banners')->__('blablablabla'),
'tabindex' => 2
));