Setting field visibility on a model, in controller, before getting data? - php

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.

Related

Symfony4 stop handleRequest() from removing values of my object

I am submitting a form and in my controller I use handleRequest to validate the form.
Lets say I try to update my object name 'object' - It has an id, name and color field.
On the same page I also show a lost with the names of all my objects that I fetch from the database
Here is my code:
$object = self::getObjectById($objectId);
$objects = self::getAllObjects();
$objectForm = self::CreateObjectForm($object);
$objectFormForm->handleRequest($request);
dd($objects);
When I submit the form and I leave the name field open,
It throws an error that the field is required when it reloads the page, the name field of the form is still empty which is normal.
But here is the problem, in the list of objects that is also showing on this page the name of the object I tried to update has no name showing anymore in this list.
I don't know why this is happening since I fetched this list of objects completely separately from the form object. When I dd() the objects after the handleRequest() I cans see in the dumped vars that indeed the name field is empty. When I check the database, the name field is not empty and still holds the old name. Which makes sense because the object is not persisted and flushed to de db.
When I dd() the same list before the handleRequest() everything is normal.
How can I prevent this behavior? And why is this happening?
I don't know why this is happening since i fetched this list of objects completely seperatly from the form object.
It's referencing the same entity which get's dumped in it's current, live, dirty state as submitted by the form.
If you need to render the clean, persisted values then you just need to store them in a variable as a string instead of as the object, and before handling the request.
Try something like this:
$object = self::getObjectById($objectId);
$objects = self::getAllObjects();
$persistedObjects = [];
foreach($objects as $obj){
$persistedObjects[$obj->getId()] = $obj->getName();
}
$objectForm = self::CreateObjectForm($object);
$objectFormForm->handleRequest($request);
dd($persistedObjects);

Laravel 5 updating the view using dropdowns

I have an resource controller called AppointmentsController and a model called Appointment. In my model I put a few scopes I use to filter results, like so:
public function scopeStatus($query, $statusId)
{
if($statusId)
{
return $query->where('status_id', '=', $statusId);
}
else {
return false;
}
}
I have this for month, year, label, and a few other settings. I call my query in the controller, like so:
$appointments = Appointment::latest('start')->status($statusId)->get();
All these variables ($statusId, $labelId, and so on) are set using dropdowns. Once I select another value in the dropdown, I will be redirected to my view again, with the correct value set and with the correct query.
The thing I'm struggling with how to set the $statusId (and other variables). If I use a post request I need to use an extra route (since I am using the store route from the resource route to create appointments). Which would be something like:
Route::post('appointments/whatever', 'AppointmentsController#index');
Or:
Route::post('appointments/whatever', 'AppointmentsController#whatever');
So I would fetch the $request values and then update my query accordingly, and then return the view again. Another thing I could do, is store the values in a session (not my preferred way). I could also update the values in the database, then go back to the index method, grab the results from the database and then update my view again.
Any thoughts how I should go about doing this? I can get it to work the amateuristic way but I want to learn how to do this in a proper manner, maybe there is even something I haven't thought of yet or maybe even my code is not good enough. Anything that helps me go in the right direction will answer my question.

Laravel Updating Record with optional image

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!

Cakephp display view fields that is set by select elements in form

I am having problem displaying values set by select elements created by FormHelper. I have searched the internet but doesn't seem to be able to find the answer. Here is the scene:
I have a questionnaire form that has many options. In the model I put those items into an array, say ($frequencyOptions) and when formhelper is used,
$this->Form->input('frequency',array("options"=> $frequencyOptions));
Currently, the option value is the array index, which looks like:
<option value="">(choose one)</option>
<option value="0">Rare</option>
<option value="1">Frequent</option>
<option value="2">Moderate</option>
Of course I know that if I set the key as well when constructing the $frequencyOptions variable like
$frequencyOptions = array("Rare" => "Rare", ...
I will be able to store the value in text.
However, since some of these options are very very long, I would prefer to save them in INT in the database.
Yet the challenge I have at this moment is how to display those fields in the "list" in the index page. When I use the form field to display in the view or edit action, it is okay because the select element will be used again. However, if I want to display it in plain text, how should I "translate" it?
One thing I can think of is to create these "conversion" methods in the Model, but I think calling model method in views is not a good practice in MVC.
Any idea?
I'd think adding a method to your Model would be the way to go. How about this:
// In your Model class
// Store the index-to-name map in the Model as well
var $frequencyOptions = array(...);
public function translateFrequency(&$data) {
foreach ($data as &$record) {
$index = $record['ModelName']['frequency'];
$record['ModelName']['frequency'] = $this->frequencyOptions[$index];
}
}
// In your Controller action:
$data = $this->ModelName->find(...);
$this->ModelName->translateFrequency($data);
And then it should display the human-readable value when passed to the index page. If preferred, the above method could be changed so it works on $this->data inside the Model.
Note: The method has to be changed if it should work for a single record data array as well.

Zend Framework - How to modify a single parameter from the request object

A submitted form on my site returns an array of request data that is accessible with
$data = $this->getRequest();
This happens in the controller which gathers the data and then passes this array to my model for placing/updating into the database.
Here is the problem. What if I want to manipulate one of the values in that array? Previously I would extract each value, assigning them to a new array, so I could work on the one I needed. Like so:
$data = $this->getRequest();
$foo['site_id'] = $data->getParam('site_id');
$foo['story'] = htmlentities($data->getParam('story'));
and then I would pass the $foo array to the model for placing/updating into the database.
All I am doing is manipulating that one value (the 'story' param) so it seems like a waste to extract each one and reassign it just so I can do this. Additionally it is less flexible as I have to explicitly access each value by name. It's nicer to just pass the whole request to the model and then go through getting rid of anything not needed for the database.
How would you do this?
Edit again: Looking some more at your question what I am talking about here all goes on in the controller. Where your form`s action will land.
Well you have a couple of options.
First of all $_GET is still there in ZF so you could just access it.
Second there is:
$myArray = $this->_request->getParams();
or
$myArray = $this->getRequest()->getParams();
Wich would return all the params in an array instead of one by one.
Thirdly if the form is posted you have:
$myArray = $this->_request()->getPost();
Wich works with $this->_request->isPost() wich returns true if some form was posted.
About accessing all that in your view you could always just in controller:
$this->view->myArray = $this->_request->getParams();
edit: right I taught you meant the view not the model. I guess I do not understand that part of the question.
If you want to deal with the post data inside your model just:
$MyModel = new Model_Mymodels();
$data = $this->_request->getParams();
$data['story'] = htmlentities($data['story']);
$myModels->SetItAll($data);
And then inside your model you create the SetItAll() function (with a better name) and deal with it there.
Edit: oh wait! I get it. You hate sanytising your input one by one with your technique. Well then what I showed you about how to access that data should simplify your life a lot.
edit:
There is always the Zend_Form route if the parameters are really coming from a form. You could create code to interface it with your model and abstract all this from the controller. But at the end of the day if you need to do something special to one of your inputs then you have to code it somewhere.

Categories