Laravel: return redirect after saving correctly throws SQLSTATE[23000]: Integrity constraint violation - eloquent

I'm using Laravel 6.11 with MAMP and after saving correctly data form into my database table I got the following error.
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'name'
cannot be null (SQL: insert into products (name, price,
description, long_description, updated_at, created_at) values
(?, ?, ?, ?, 2020-02-05 19:00:35, 2020-02-05 19:00:35))
http://localhost:8000/admin/products
Routes
Route::get('/admin/products', 'ProductController#index');
Route::get('/admin/products/create', 'ProductController#create');
Route::get('/admin/products', 'ProductController#store');
ProductController
public function create()
{
return view('admin.products.create');
}
public function store(Request $request)
{
$product = new Product();
$product->name = $request->input('name');
$product->price = $request->input('price');
$product->description = $request->input('description');
$product->long_description = $request->input('long_description');
$product->save(); //IT WORKS!! ALL DATA SAVED!!
return redirect('/admin/products');
}
Create.blade
<form method="put" action="{{ url('/admin/products') }}">
.
.
Any ideas on how can I fix it?

Is it because you have two the same routes declared. These are.
Route::get('/admin/products', 'ProductController#index');
Route::get('/admin/products', 'ProductController#store');
Now, when this line executed redirect('/admin/products');, Laravel will not invoke the first route you defined which is Route::get('/admin/products', 'ProductController#index');
rather invoke the last route you defined, the Route::get('/admin/products', 'ProductController#store');.
After invoking your store method in product controller, the method expect a request which includes the name, price and etc..
Since you just redirected only without passing any argument, now laravel will throw you an error like what you had presented above.
To solve that, change your second route method for ProductController#store. Like this
Route::post('/admin/products', 'ProductController#store');

Is it possible that the problem is related to having the route::get to the same url twice?
So I suppose it wants to redirect to index after the first time storing the product, it tries to store another product with no values.

Related

Index method not accepting parameters in ASP.NET Core MVC with Entity Framework

I am working on a webpage where I have to filter results using value from the select menu's selected option when the user clicks on filter button by sending a get parameter to the index method.
refId is never passed into the Index method
In your code, we can find that you specify asp-for="#Model.FirstOrDefault().RefereeId" for your <select> tag, if you check the source code of this dropdown in browser, you would find name attribute value is RefereeId (not refId) as below. So it would pass something like RefereeId=168 through querystring to your action, and parameter refId of your action would always be 0, which cause the issue.
To fix it, you can try to rename your action parameter to RefereeId, like below.
public async Task<IActionResult> Index(int RefereeId)
{
//code logic here
Or modify view page code to set name of <select> tag with "refId".
<select name="refId" asp-items="#ViewBag.PersonId"></select>
If you don't have a custom route defined, the default routing in asp.net core uses id.
Replace the refId parameter to id.
public async Task<IActionResult> Index(int id)
{
// ...
if (id != 0) //always remains 0
{
games = games.Where(g => g.RefereeId == id);
}
// ...
}

Laravel backpack form request getting empty input

Laravel backpack auto generated form request for crud. How should i get the input from the form request to use it in unique validation eg: email?
I've tried dd($this), but all the value is empty or null. i think the request is not passing in at all ?
public function rules()
{
return [
'email' => 'required|unique:users,email', $this->id
];
}
I expect to get the id from the request and using it in my unique form validation
We can get the id with the below simple way , i have tried it and it works for me.
public function rules()
{
$id = $this->get('id') ?? request()->route('id');
return [
'email' => 'required|unique:users,email', $id
];
}
Referenced from the below mentioned url
https://github.com/Laravel-Backpack/PermissionManager/blob/master/src/app/Http/Requests/UserUpdateCrudRequest.php
If you dd($this) you will get nothing because the method rules() is called on page load and not only on form submission. If you want to check the submitted values, you can use something like:
if (!$this->id) dd($this);
Then, under request->parameters, you can see the value of all the fields included in the request.

How to give a fixed Uid to my Action

Hy,
I'm trying to call my action with allways a fixed Uid (configured by TS) so I could put a plugin on my page to register for a specific Event. And don't have to go over a Event List click the Event click register.
I tried the following which did not work out:
public function newAction(
\XYZ\xyz\Domain\Model\Registration $newRegistration = NULL,
\XYZ\xyz\Domain\Model\Event $event = 'DD8B2164290B40DA240D843095A29904'
)
The next didn't one work either!
public function newAction(
\XYZ\xyz\Domain\Model\Registration $newRegistration = NULL,
\XYZ\xyz\Domain\Model\Event $event = Null
) {
$myinstance = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
'XYZ\\xyz\\Domain\\Model\\Event'
);
$event = $myinstance->findByUid('DD8B2164290B40DA240D843095A29904');
.......
}
So I was woundering is there a way to give my fixed Uid to the action?
In TYPO3 calling Extbase actions is done in the routing and dispatching components - to pass anything from the outside that is different from a numeric uid value a custom property TypeConverter would have to be implemented that transforms a particular string pattern into a value domain object of type Event.
However, there's a simpler approach by using configuration:
1) Provide configuration in TypoScript
Extbase uses a strong naming convention based on the extension name and optionally the plugin name. Thus, either tx_myextension or tx_myextension_someplugin can be used - latter is more specific for for according somePlugin. Besides that settings are automatically forwarded and provided in an Extbase controller context - accessible by $this->settings.
plugin.tx_xyz {
settings {
newActionEventIdentifier = DD8B2164290B40DA240D843095A29904
}
}
2) Retrieve data via repository
\XYZ\xyz\Domain\Repository\EventRepository
Use a dedicated EventRepository::findByIdentifier(string) method to retrieve the data. The property names are just assumptions since there are no explicit mentions how exactly the event data is persisted and whether it is persisted in a relational DBMS at all.
<?php
namespace XYZ\xyz\Domain\Repository;
class EventRepository
{
public function findByIdentifier($identifier)
{
$query = $this->createQuery();
$query->matching(
$query->equals('event_id', $identifier)
);
return $query->execute();
}
}
3) Putting all together in the according controller
The $event property was removed from the action since that entity is pre-defined and cannot be submitted from the outside (and to support the string to Event entity transformation a custom TypeConverter would be required as mentioned earlier).
public function newAction(
\XYZ\xyz\Domain\Model\Registration $newRegistration = null
) {
$event = $this->eventRepository->findByIdentifier(
$this->settings['newActionEventIdentifier']
);
if ($event === null) {
throw new \RuntimeException('No event found', 1522070079);
}
// the regular controller tasks
$this->view->assign(...);
}

Symfony 2 - Change entity's field from Admin while keeping validation using SonataAdminBundle

Using:
Symfony 2.5
SonataAdminBundle
I am trying to change one of the entity fields (title) when data is submitted / saved to database by using two fields from associated entites ex.
DocumentRevision <- Document -> CustomEntity [title] = Document[title]+DocumentRevision[number]
But title of CustomEntity has to be unique - this was the problem I was trying to solve and managed with Database constraints and UniqueEntity validation (not quite - more on this later).
Now the issue is that I change the title data on Doctrine preUpdate/Persist effectivly skipping validation for that field since it's empty at validation time. When user puts wrong data Database layer throws an error about duplicate for unique constraint.
/**
* #ORM\PrePersist
* #ORM\PreUpdate
*/
public function setTitleFromDocumentName() {
$this->setTitle($this->getDocument()->getName() . " rev. " . $this->getDocumentRevision()->getRevisionNumber());
}
The entity itself is using UniqueEntity constraint on field title, so custom constraints or validation groups are pointles from my perspective as it would only duplicate the already used constraint.
/**
* #UniqueEntity(
* fields={"title"}
* )
**/
The simplest solution as it seems would be to get somewhere between post Submit before validation, but it would have to be done from Entity.
My question is how can (can it?) be done without overriding SonataCRUD Controller or it's other parts, is it even possible?
It can be done, but there are issues:
I was able to change the title using Form Events like this:
protected function configureFormFields(FormMapper $formMapper) {
...
$builder = $formMapper->getFormBuilder();
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (!$data) {
return;
}
$data['title'] = $data['document'] . ' rev. ' . $data['documentRevision'];
$event->setData($data);
}
...
formMapper
->add('title',null,array(
...
);
The current problem is that I am getting the IDs of 'document' and 'documentRevision' and I need their names or __toString() representation at least.
Another issue is that although I can set the title using the event it shows error from DB when it should show Form error since validation should be done on FormEvents::SUBMIT - this one I don't understand.
Last thing to note is that if I try to use callback function:
$builder->addEventListener(FormEvents::PRE_SUBMIT, array($this,'onPreSubmit'))
public function onPreSubmit() {
$entity = $this->getSubject();
$entity->setTitleFromDocumentName();
}
I will get null title and errors if Entity tries to get fields from related entites - Calling function on non object.
Regarding entity data maybe this will help you to get the subject:
https://gist.github.com/webdevilopers/fef9e296e77bb879d138
Then you could use getters to get the desired data for instance:
protected function configureFormFields(FormMapper $formMapper)
{
$subject = $this->getSubject();
$formMapper->getFormBuilder()->addEventListener(FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($subject) {
$document = $subject->getDocument();
// ...
});
}
I also posted this on your issue:
https://github.com/sonata-project/SonataAdminBundle/issues/2273
To solved this when I changed the unique entity validation constraints as ones used by me where not completely valid from conceptual perspective.
Also it's important to note that functions that are marked as #PrePersist, #PreUpdate etc. must be public if they are to be used like that, marking them private will make Doctrine fail.
Note that the methods set as lifecycle callbacks need to be public and, when using these annotations, you have to apply the #HasLifecycleCallbacks marker annotation on the entity class.
See: http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#lifecycle-callbacks (first paragraph after the code sample).

Accessing foreign key value (int) in Entity Framework

I just spent the last 3-4 hours trying to retrieve a foreign key value using linq to entities and a stored procedure. Any advice is much appreciated.
public JsonResult GetEvents(double? start, double? end)
{
AnoEntities _dbAno = new AnoEntities();
var events = _dbAno.Events_GetByDateRange(fromDate, toDate);
var eventList = from e in events
select new
{
id = e.id,
title = e.title,
className = e.event_types.type.ToString()
};
return Json(eventList.ToArray());
}
type_id is the foreign key value that i'm trying to reach. I can't get it so appear in the entity data model and I can't seem to get to it. e.event_types and e.event_typesReference are both null so things like e.event_typesReference.EntityKey.EntityKeyValues.First().Value.ToString() aren't working.
Thanks!
I don't see any .Include methods or Load methods on even_types and I'm assuming your returning IEnumerable from your _dbAno.Events_GetByDateRange(fromDate, toDate). Like Craig pointed out in the comments if your return type of GetByDateRange is IQueryable you'd be projecting and EF should eager load for you.
Just a reminder that implicit lazy loading isn't supported out of the box in Entity Framework 1.0. You'll need to manually load the event_types with Load() or use the Include method on ObjectQuery.