I'm trying to recreate a simple blog functionality and allowing an admin to update a blog post.
My problem is the photo that has its name stored in the blog table under 'thumbnail' is not getting updated correctly. My save a new post function works but my update function does not work.
When you do an update without updating the image the rest of the blog items get updated but the photo name get set to blank and if you do try to update the image the photo does get moved but the field in the database is getting set to the temporary location (/Applications/MAMP/tmp/php/phpx1jwMA).
That may be two separate issues.
In the update form I added a hidden field with the photos name:
{{ Form::hidden('old_photo', $blog->thumbnail) }}
And it produces this in the form as expected:
<input name="old_photo" type="hidden" value="1391122313-2013 12 01_0567.JPG">
And in my controller I have this as my update function:
public function update($id) {
$input = Input::all();
$blog = Blog::find($id);
if(Input::hasFile('thumbnail')) {
$file = Input::file('thumbnail');
$name = time() . '-' . $file->getClientOriginalName();
$file = $file->move(public_path() . '/images/blog/', $name);
$blog->thumbnail = $name;
}
$blog->save();
return View::make('admin.blog.index', [
'blogs' => Blog::all()
]);
}
I'm trying to say in that code that if there is a new file in the thumbnail then create a unique name, move the file and set 'thumbnail' to that name (That is how my create function works) but if there has been no uploaded file to 'thumbnail' then set the 'thumbnail' to the old name.
Is there a better way to handle this process? Obviously there is because this way does not work. I am just learning Laravel and I have 3 books on it but none of them cover how to do this.
Thanks.
Instead of $blog->update($input); use $blog->save();. You already modified the model, just save it. With the update() method, all key/value pairs of the array you pass in will be assigned to the model.
Also you don't need your else case. If you don't want to change a models property just don't do it. You don't need to assign the value explicitly if you don't want to change it.
Omit your else case.
Side note on that:
Assigning Model properties manually e.g.
$model = Model::find(5);
$model->prop = 'val';
$model->save();
is better most of the time than Mass Assigning them e.g.
$model->find(5)->update($newvalues);
You have more control over what get's inserted and updated, when mass-assigning you have to take care of what's going to be assigned otherwise just every property could be changed. That's a security issue. (However laravel comes with $guarded and $fillable)
Also in your case you would not want to pass the whole input since you probably don't want certain fields to get updated if they did not change. So if nothing changed you had to explicitly exclude the Key/Value pairs you don't want to update when you just pass your whole Input to it (this is because the keys exist but the values are empty).
Well you get what I mean. When you assign your values manually you have full control on when and what you assign.
Happy Coding!
Related
I'm trying to figure out how to properly code the update() function in eloquent to return either 0 or 1 based on user input in a form. For example, if I hit the update button without making any changes, it returns 1. Shouldn't it return 0?
I tried researching for solutions like here in stackoverflow to see if anyone has the same problem as I am facing. But so far not luck. I also tried modifying the code, but no luck.
public function update(Request $request, $id)
{
$UCPost = UCPost::find($id);
$UCPost->gown_2019 = $request->input('Gown2019');
$UCPost->gown_2017_2018 = $request->input('Gown20172018');
$UCPost->gown_2016 = $request->input('Gown2016');
$UCPost->gown_2015 = $request->input('Gown2015');
$UCPost->Light_Blue = $request->input('LightBlue');
$UCPost->Seconds = $request->input('Seconds');
$UCPost->Velveteen = $request->input('Velveteen');
$UCPost->Velveteen_discolored = $request->input('Velveteen_discolored');
$UCPost->Rental = $request->input('Rental');
$UCPost->Rentals_Out = $request->input('Rentals_Out');
$UCPost->Rentals_Left = $request->input('Rentals_Left');
return $UCPost->where('id', $id)->update(
[
'gown_2019' => $UCPost->gown_2019,
'gown_2017_2018' => $UCPost->gown_2017_2018,
'gown_2016' => $UCPost->gown_2016,
'gown_2015' => $UCPost->gown_2015,
'Light_Blue' => $UCPost->Light_Blue,
'Seconds' => $UCPost->Seconds,
'Velveteen' => $UCPost->Velveteen,
'Velveteen_discolored' => $UCPost->Velveteen_discolored,
'Rental' => $UCPost->Rental ,
'Rentals_Out' => $UCPost->Rentals_Out,
'Rentals_Left' => $UCPost->Rentals_Left
]
);
}
The code above as I mentioned earlier, it always returns 1 regardless of any changes made to the form. I want it to return 0 if there are no changes by the user or if they accidentally hit the update button. I'm trying to find the equivalent of mysqli_affected_rows in Eloquent.
You are calling the update() method on your model. This will return 1 if the update was successful. It doesn't matter if there were any changes made, always 1 on successful update.
If you would like to only save to the database if there are changes, you can use the save() method instead, which checks to see if changes are present, and only writes to the database if the data is different. You have already created code to do this, by setting the model to have all of the new data from the sheet, so a simple save() at the end (with a check to see if it saves), will do what you want.
However, your current code is doing a lot of extra work. You are assigning all the variables to the model, and then updating based on that assignment of data to the model. You don't have to do all that assignment again in the update method. Once you have set the fields, you can save immediately, you don't have to re-assign all the variables. So:
$UCPost->gown_2019 = $request->input('Gown2019');
// etc..
$UCPost->Rentals_Left = $request->input('Rentals_Left');
$UCPost->save();
Will get you where you want to go and will only save if different.
If you have control over your form, and can change the form element names to match your database, this can be even easier. You can do all of this in one line:
$UCPost->update($request->all());
If you want to check if the model is dirty just call isDirty():
if($UCPost->isDirty()){
// changes have been made
}
Finally, if you want to verify if anything was changed after either method (save or update):
if ($UCPost->wasChanged()) {
// changes have been made
}
Hope this helps
So, I have the following code:
$homepage = Homepage::first();
if (!$homepage) {
$homepage = new Homepage;
}
$homepage->first_presta_title = $request->first_presta_title;
$homepage->first_presta_content = $request->first_presta_content;
$homepage->second_presta_title = $request->second_presta_title;
$homepage->second_presta_content = $request->second_presta_content;
$homepage->third_presta_title = $request->third_presta_title;
$homepage->third_presta_content = $request->third_presta_content;
$homepage->shiatsu_text = $request->shiatsu_text;
$homepage->shiatsu_image = $request->shiatsu_image;
$homepage->doin_text = $request->doin_text;
$homepage->doin_image = $request->doin_image;
$homepage->save();
Everything works, but I wanted to see if there weren't any better way to save datas without asigning every single element to its column, then I found out someone answering to a question by using the following code:
$homepage->save($request->all());
So I tried it by myself, but nothing happened: no error, but also nothing saved in my database.
So, is there any fastest way to save datas ? Is it possible to use a loop to save everything?
Thank you in advance
When you use save(), you are actually using Mass assignment. So, either you explicitly define all the fields in your model to be mass assignable or you could use create() instead.
However, in your particular case, the whole method could be cleaned up to just one line:
return Homepage::updateOrCreate($request->all());
If you want the model to autofill based on a given array you need to create a new model entity Like this
$homepage = HomePage::create($request->all());
$homepage->save()
If you give an array to save() it expects the options for saving not for values to assign
Source:
laravel api docs for model/save()
laravel api docs for model::create()
I'm trying to filter down the fields I get returned within my controller, ideally before getting the results as not to have to loop around the collection after. The hidden fields aren't always the same, and might differ from what was initially set in the model.
This is my current (not working) code:
$model = new Model;
$model->setHidden($toHide);
$results = $model->where($filters)->get();
The above code always defaults back to what was initially set in the hidden variable instead of is currently set.
I know this code works:
$results = Model::where($filters)->get();
foreach($results as $i => $row){
$row[$i] = $row->setHidden($toHide);
}
But ideally I don't want to loop the results to set the hidden on each model.. The idea being I can change the hidden fields based on other attributes (what the user can see, which controller route the user has taken, etc) from within the controller.
I create a GUID everytime a new database entry is being made and will be saved with the database entry to the database. The GUID should be my unique reference for further usage as reference to this entry. This part works fine.
My question: I need this GUID to perform a seach afterwards in the database for this entry, as another function needs the database entry details to work. As all the necessecary information is only created before saving to the database, how do I get a hold of this variable GUID to be used in another function?
public function createIncident(PrepareIncidentRequest $request)
{
$incidentReference = TicketSystem::generateIncidentReference();
$incidentID = TicketSystem::generateIncidentID();
$data = $request->all();
$data = $data + [
'incident_reference' => $incidentReference,
'incident_id' => $incidentID,
];
$incident = Incident::create($data);
Auth::user()->incidents()->save($incident);
}
When the entry is saved, and for example this would happen 100times in an hour, how do I know what to search for in another function? So how do I "pass over" this GUID I created in the function above to be used in another function?
For example here: I want to search for a user, and all the info needed is in a specific database entry. This entry could be found with the GUID I created. But as soon as it is saved, I need a way how to know, what to search for in another function when I want to retrieve the info.
If you need to persist data between the page views then session is the way to do it.
Add data to session like this
Session::put('key', 'value');
And read like that
Session::get('key');
I want to make a single revision option for saving certain objects in Sonata Admin.
I though to do this in the following way:
user edits entry
form is validated
the new information is saved as a separate entry (i'll call it revision)
the original object is not modified, except for a relation to the revision
So the code looks something like this (source Sonata\AdminBundle\Controller\CRUDController::editAction()):
$object = $this->admin->getObject($id);
$this->admin->setSubject($object);
$form = $this->admin->getForm();
$form->setData($object);
$form->bind($this->get('request')); // does this persist the object ?
// and here is what I basically want to do:
$object->setId(null);
$orig = $em->getRepository("MedtravelClinicBundle:Clinic")->find($id);
$orig->setRevision($object);
$this->admin->update($orig);
The problem is that $orig loads the already modified, so var_dump($orig === $object) is true.
I also tried $em->getUnitOfWork()->getOriginalEntityData($object); - which grabs the correct data, but as an array, not as an object (this will probably be the last resort).
So, how can I get (and save) the original object after the form bind took place ?
I think you should use the clone keyword to get a independent instance of the object you want to store. It should works by following these steps:
Load the original entity ($object)
Clone the original entity to get a new temporary entity ($newObject)
Alter the $newObject to make it a new entry: $newObject->setId(null);
Bind $newObject to the form
Save (persist) $newObject as a revision
Add the revision to ($object) and persist it too
I hope that if the form is invalid you won't lose all the data sent by the user.
Just in case, I used this answer to find the differences between the original entity and the one modified by the form.