Newbie question. How to handle Storefront Form Submit in Shopware 6? How to save the data from form to database? I have an entity, form shown in storefront and a controller but i have no idea how to save the data to entity. Thanks in advance.
you would have to be more specific with the description, of what exactly you are trying to achieve.
But in general, if you already have a controller, that receives the data, then you can get them from the request like this:
$data = $request->request->all();
By this, you have all the values from your form saved in an array $data. You have written, that you already have an entity, so from that I assume, that your entity is already mapped to your database table. So the only thing you have to do, is to use the repository to save the data. For thta, you just need to inject it into your class and get a context. The context depends on where you currently are, so for the purpose of the example, I have just created the default context.
It should look like this:
class MyClass
{
protected $myEntityRepository;
public function __construct(
MyEntityRepository $myEntityRepository
)
{
$this->myEntityRepository = $myEntityRepository;
$this->context = \Shopware\Core\Framework\Context::createDefaultContext();
}
public function myMethod ($data)
{
$this->myEntityRepository->upsert($data, $this->context);
}
}
Hope this helps. I have actually written an article on repositories in Shopware 6, so if you want to get some more information and examples, you can check it here: https://shopwarian.com/repositories-in-shopware-6/.
Related
I'm using a Backpack for Laravel CRUD controller and I'm trying to figure out if there's an efficient way to tell if a Model has been updated without loading both the current model and the updated model and then comparing attribute values.
I ended up following the suggestion in the comment and overrode the save() method on my model as such.
public function save(array $options = [])
{
// Update the mode accordingly and perform any
// other actions you need to prior to saving here.
$saved = parent::save($options);
return $saved;
}
I'm new at Apache Isis and I'm stuck.
I want to create my own submit form with editable parameters for search some entities and a grid with search results below.
Firstly, I created #DomainObject(nature=Nature.VIEW_MODEL) with search results collection, parameters for search and #Action for search.
After deeper research, I found out strict implementations for actions (For exapmle ActionParametersFormPanel). Can I use #Action and edit #DomainObject properties(my search parameters for action) without prompts?
Can I implement it by layout.xml?
Then I tried to change a component as described here: 6.2 Replacing page elements, but I was confused which ComponentType and IModel should I use, maybe ComponentType.PARAMETERS and ActionModel or implement my own IModel for my case.
Should I implement my own Wicket page for search and register it by PageClassList interface, as described here: 6.3 Custom pages
As I understood I need to replace page class for one of PageType, but which one should I change?
So, the question is how to implement such issues properly? Which way should I choose?
Thank you!
===================== UPDATE ===================
I've implemented HomePageViewModel in this way:
#DomainObject(
nature = Nature.VIEW_MODEL,
objectType = "homepage.HomePageViewModel"
)
#Setter #Getter
public class HomePageViewModel {
private String id;
private String type;
public TranslatableString title() {
return TranslatableString.tr("My custom search");
}
public List<SimpleObject> getObjects() {
return simpleObjectRepository.listAll();
}
#Action
public HomePageViewModel search(
#ParameterLayout(named = "Id")
String id,
#ParameterLayout(named = "Type")
String type
){
setId(id);
setType(type);
// finding objects by entered parameters is not implemented yet
return this;
}
#javax.inject.Inject
SimpleObjectRepository simpleObjectRepository;
}
And it works in this way:
I want to implement a built-in-ViewModel action with parameters without any dialog windows, smth like this:
1) Is it possible to create smth like ActionParametersFormPanel based on ComponentType.PARAMETERS and ActionModel and use this component as #Action in my ViewModel?
2) Or I should use, as you said, ComponentType.COLLECTION_CONTENTS? As I inderstand my search result grid and my search input panel will be like ONE my stub component?
Thank you.
We have a JIRA ticket in our JIRA to implement a filterable/searchable component, but it hasn't yet made it to the top of the list for implementation.
As an alternative, you could have a view model that provides the parameters you want to filter on as properties, with a table underneath. (I see you asked another question here on SO re properties on view models, so perhaps you are moving in that direction also... I've answered that question).
If you do want to have a stab at implementing that ticket, then the ComponentTYpe to use is COLLECTION_CONTENTS. If you take a look at the isisaddons, eg for excel or gmap3 then it might help get you started.
======= UPDATE TO ANSWER (based on update made to query) ==========
I have some good news for you. v1.15.0-SNAPSHOT, which should be released in the couple of weeks, has support for "inline prompts". You should find these give a user experience very similar to what you are after, with no further work needed on your part.
To try it out, check out the current trunk, and then load the simpleapp (in examples/application/simpleapp). You should see that editing properties and invoking actions uses the new inline prompt style.
HTH
Dan
Just a question to poll how you guys would tackle this in Laravel:
I have a user preferences page defined in UserController.php which creates the view at user/preferences.blade.php.
Administrators should of course be able to edit the user's preferences and have some extra administrative fields shown to be changed. Furthermore I'd like to collect all admin functionality concerning users in a separate controller called AdminUserController.php
I'm thinking of some possibilities to achieve this functionality:
Create an additional view (e.g. admin/user/preferences.blade.php) and almost replicate the GET and POST methods of UserController.php to accommodate the extra fields. However this seems to me like a lot of redundant code...
Convert the GET and POST methods of UserController.php to something like this:
public function postPreferences($user = NULL, $admin = FALSE) {
if (!isset($user)) $user = Auth::user();
// Process regular fields.
if ($admin) {
// Process admin fields.
}
}
Add the admin fields to user/preference.blade.php and conditionally show them if $admin is TRUE, and then call the UserController's methods from within AdminUserController, e.g.:
public function postPreferences($user) {
return (new UserController)->postPreferences($user, TRUE);
}
However, there are some drawbacks. First: controllers shouldn't call each other... Second: this only works for the POST method. Upon requesting the GET method from UserController an exception is being thrown...
I'm curious about how you would tackle this!
Thanks.
This is mostly a question of preference, but I really suggest you to completely separate all that is possible here. Administration is a process that is very sensitive and not in any way should it be possible, that a normal user will be able to see it under any circumstance.
I believe that we all are humans and we make mistakes more or less often, that's why we need to make sure that our mistakes in not assigning right value to the right variable or making a type of = instead of == not to ruin business logic.
I think you should make a separate view and a separate controller for user self management and administration and never tie them up. If you want to keep your code DRY as much as possible, you may extend your user controller and model from your admin controller and model, but not the other way around. That's just my 2 cents, it all depends on what type of application you are working on and what the stakes are.
<?php
class AdminController extends UserController
{
public function __construct(AdminModel $model)
{
// Use dependency injection
$this->model = $model;
}
// In the original UserController class:
public function postPreferences($user) {
$this->model->edit($user, Input::all());
// you may do it this way so your user only saves user data and
// you admin model saves all the data including administrative
}
// ...
}
Well, imagine that we have a register form of a class Customer and we only ask three fields (name,surname,email) and after, when this user logged first time we want to complete this information.
First, we have in lib/form/doctrine a file called 'CustomerForm.class.php' wich is generated automatic on command line. In this file we 'setup' only 3 fields and validators and if we wanna use we do something like that:
$this->form = CustomerForm();
Second, we create manual another form named 'CustomerFormStep1.class.php' where we can setup for validate the other fields. But when we do..
$this->form = CustomerFormStep1();
it returns error: Fatal error: Class 'CustomerFormStep1' not found
What is wrong?
Thanks.
Assuming you have the form defined as:
class CustomerFormStep1 extends sfForm
or similar (sfFormDoctrine etc), and named correctly like you say (CustomerFormStep1.class.php) and in lib/form, then Symfony should just pick the definition up fine. Did you clear the cache after creating and placing it in the right place? (symfony cc).
Create the new CustomerFormStep1 class as #richsage instructed. Then, in your actions you can write something like:
public function executeLogin(){
//before login
$this->form = new CustomerForm();
}
public function executeLoggedIn(){
$this->form = new CustomerFormStep1();
//other steps
}
Haven't you read the tutorial? Extending forms is perfectly described in context with reh admin generator and can of course be applied to any case.
Hy,
What is correctness in symfony to fill a form in two steps? Imagine that we have a entity called Enterprise and we want to create a form with only required fields and another form, that when the user login can fill the other non-required fields.
How is the correctness form? Now i have a form to registration ('lib/form/doctrine/EnterpriseForm.class.php') and another ('lib/form/doctrine/EnterpriseCompleteForm.class.php').In every class we set labels, validators, ... but the problem is in the second form. When i try to submit it gives me an error because i have'nt post required fields defined in model. How can i do that? Is that way correct? How can i fix this?
thanks.
You should unset every non needed form field in the second form (of course you should keep a hidden field with the ID of the record).
Basically you just update the record with the second form so every required field in your database already as a value.
It would help if you post the code of the second form.
So in summary your approach is valid (maybe there are better ways I don't know), just make sure that your code is correct.
Edit:
So if I got you correctly then the form you use in your code updates an existing object. You should pass this object to the form knows, that the object already exists and can validate the values accordingly:
public function executeStepOne(sfWebRequest $request){
$this->customer = Doctrine::getTable('Customer')->find(1);
$this->forward404Unless($this->customer);
$this->form = new CustomerFormStepOne($this->customer);
if ($request->isMethod(sfRequest::POST)){
$this->processRegisterForm($request, $this->form,'paso2');
}
For the duplicate key error, check your database definition if the primary key of this table gets incremented automatically.
Well Felix, i do it "unset" changes and it works fine... but i have a problem. I try to do update on the same action. My code looks like that.
in actions
public function executeStepOne(sfWebRequest $request){
$this->form = new CustomerFormStepOne();
if ($request->isMethod(sfRequest::POST)){
$this->processRegisterForm($request, $this->form,'paso2');
}else{
$this->customer = Doctrine::getTable('Customer')-> find(1);
$this->forward404Unless($this->customer);
}
}
where processRegisterForm code is :
protected function processRegisterForm(sfWebRequest $request, sfForm $form,$route)
{
$form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
if ($form->isValid())
{
$customer = $form->save();
$this->redirect('customer/'.$route);
}
}
if i try to do this they returns me an error 'primary key duplicate'.