Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mjonat's avatar

Best way to send data from controller to view?

I am going to simplify things so please bear that in mind. Also please assume "User" in the following comes from the model created after a php artisan Make:Auth.

So I have something very similar to the following:

$user = User::find($id);
return view('auth.editProfile', compact('user'));

But say I want to add a check for something and then send the result to the view...this is how I am currently doing it:

$user = User::find($id);
$check;
if($condition){
    $check = true;
}
return view('auth.editProfile', compact('check','user'));

This works fine for smaller things but in my controller I have a few functions leading to different pages. If 'auth.editProfile' is one of them I have to make sure that I then add all the variables I have created in another function just to satisfy laravel when it gets to the view and $check is called but I have more than one check and my code is becoming very needlessly bloated.

Ideally I guess I would just like to maybe create $user in the controller class but outside all of the functions so that I could just add the variables to the $user collection at that point and then just change them as necessary at the right points in the code. The problem with this is that my IDE says I'm doing something wrong if I declare a variable inside a class and not a function...also I have tried just adding to the $user collection within a function in my class but as its a collection it just errors out...I dont know how to add to a collection.

Thanks,

Matt

0 likes
14 replies
otepas's avatar

@mjonat, I don´t know if I understand your question correcly. You should be able to add a property to your User class. Can you show the code where you are trying to add that property?

BTW, I am confused about your mention of collections. In your code there is only a User class, and there are no collections.

bestmomo's avatar

To avoid multiply variables and depending their nature you may create some accessors in your User model to manage your checkings.

mjonat's avatar

@otepas - when i do a dd($user); it shows me what I understand to be a collection? It doesn't look like an array to me and it doesnt look like an object either so I guess its a collection?

@bestmomo - I think this may be exactly what I'm looking for! thanks!

mjonat's avatar

OK so I just read the docs for accessors and mutators and then watched a video on youtube about it and its not quite what im looking for.

I guess simplifying things isnt working so I'm gonna show entire code blocks now to properly illustrate whats going on and what I need:

function updateProfile(Request $request, SpokenLanguages $spokenLanguages, WorkingHours $workingHours, JobType $jobType, $id){
        $user = User::find($id);
        //Languages
        $setLang = $user->with('spokenLanguages')->find($id)->spokenLanguages; //Find already set values
        $spokenLangInput = $request->languages; //Get user input
        $spokenLangInput = explode(",",$spokenLangInput); //create array from input
        //Remove whitespace from all of the items in array and create new array
        $spokenLangInput = removeWhiteSpace($spokenLangInput);
        //Function in helpers.php please see this file for further commentary
        insertMultiple($setLang,$spokenLangInput,$id,$spokenLanguages,'languages');

        //Working Hours
        $setHours = $user->with('workingHours')->find($id)->workingHours; //Already set
        $hoursInput = $request->preferred_hours; //Input from user
        insertMultiple($setHours,$hoursInput,$id,$workingHours,'hours');

        //Job type
        $jobsInput = $request->job_type; //Jobs Input
        $setJobs = $user->with('jobType')->find($id)->jobType; //Already Set values
        //Gotta check if the input is greater than 3 and return to the page with an error message if not
        $jobsInputCount = 0;
        $moreThanThreeJobs = "false";
        foreach($jobsInput as $job){
            //First check the amount selected, if more than 3 return to the same page with error message else continue
            if($jobsInputCount >= 3){
                //Mostly copied from function above as these vars are called on editProfile
                $setLanguages = $user->spokenLanguages->toArray();
                $setLanguages = arrayToString($setLanguages);
                $moreThanThreeJobs = "true";
                $user->workingHours;
                $user->jobType;
                $eNoFile = false;
                //Adding this so that values that were input are put back.
                //Unfortunately it does not work...trips up when workingHours or jobType is required
                //Gonna figure it out but not now haha
                //$user = $request;
                return view('auth.editProfile', compact('eNoFile','moreThanThreeJobs','setLanguages','user'));
            }
            $jobsInputCount++;
        }
        //If Jobs input is less than 3 then continue
        if($jobsInputCount <= 3){
            insertMultiple($setJobs,$jobsInput,$id,$jobType,'job');
        }else{
            dd('Input count = '.$jobsInputCount);
        }

        $user->update($request->all());
        return view('auth.profile',compact('user'));
    }

This is the mega function that started it all...you can ignore most of it but about half way through theres a foreach counting if theres more than 3 selected options and then returns to the edit profile page with an error. Then theres this function:

function updateProfilePic(Request $request, $id){
        $user = User::find($id);
        if($request->hasFile('profile_pic')){
            $profilePic = $request->file('profile_pic');
            $filename = $user->first_name.'-'.$user->$id.time().'.'.$profilePic->getClientOriginalExtension();
            $rebuild = Image::make($profilePic);
            $rebuild->save(public_path('/uploads/profile-pics/'.$filename));
            $user->profile_picture = $filename;
            $user->save();
        }else{
            $eNoFile = true;
            //Mostly copied from function above as these vars are called on editProfile
            $setLanguages = $user->spokenLanguages->toArray();
            $setLanguages = arrayToString($setLanguages);
            $moreThanThreeJobs = "true";
            $user->workingHours;
            $user->jobType;
            return view('auth.editProfile',compact('eNoFile','moreThanThreeJobs','setLanguages','user'));
        }

        return view('auth.profile',compact('user'));
    }

Again this is checking if anything is wrong and redirect to the edit profile page if it is but now I have to pass in the extra variables that i created in the previous function so that the view in laravel is happy.

And finally:

function editProfile($id){
        $user = User::find($id);
        $user->jobType;
        $user->workingHours;
        $setLanguages = $user->spokenLanguages->toArray();
        $setLanguages = arrayToString($setLanguages);
        $moreThanThreeJobs = "false";
        $eNoFile = false;
        return view('auth.editProfile', compact('eNoFile','moreThanThreeJobs','setLanguages','user'));
    }

This is the main function that loads the edit profile page and all I really wanna do here is convert the languages array to a string and send that back but I have to re-declare all of the variables and pass them through otherwise it breaks...

I hope that clarifies things...

Matt

otepas's avatar

@mjonat, User::find($id) returns an instance of the model, or a Collection of Users if $id is an array of ids. In any case, it always returns an object, never an array.

Anyways, the class you have to modify is User. You can either add a property or use an accessor as bestmomo suggested.

mjonat's avatar

My understanding of accessors is that they can just modify the output of a database value without actually changing the value...while that can be uesfull I dont see how this would allow me to create extra variables or add values to the $user instance...

Did u get a chance to look at the long post I made before this one? It might help explain my problem a bit more...

otepas's avatar

@mjonat, instead of returning the view in updateProfile or updateProfilePicture (you are not redirecting), you can redirect to the edit profile route so that the editProfile function is called and it would handle all the preparation of the data for the view.

return redirect()->route('editProfile_route_name');
mjonat's avatar

So is it generally best practice to redirect instead of view()?

I get the feeling this will ultimately fail though? For example in my view I am directly refering to user like so:

<h3>First Name</h3>
<p>
    {{ $user->first_name }}
</p>

And this is how I would refer to one of the other variables passed through in that same way:

@if($setLanguages == "")
    placeholder="Languages"
@else
    value="{{$setLanguages}}"
@endif

Surely that will now break? If that's the case I am back to square one....using redirectTo() how do I then pass data back from the controller?

otepas's avatar

After a form submission it is common to redirect instead of returning a view. This will avoid a form resubmission if the user hits the browser's reload button.

It shouldn't cause a problem. What you are doing with redirect is creating a new Request. That means the appropriate controller function will be called (in this case editProfile) and it will populate all the variables that the view 'auth.editProfile' needs.

This is the same behaviour as when you use FormRequests. When the validation fails in a POST request, the user is redirected to the previous page (your editProfile in your case) and a GET request to display the form is processed.

pmall's avatar

So is it generally best practice to redirect instead of view()?

Yes of course.

while that can be uesfull I dont see how this would allow me to create extra variables or add values to the $user instance...

An accessor can have any name and return any value. It is basically a way to pass a method call to the usage of a model attribute. At worst you can just add method to the model. But you have useless code repeats here as you should use redirect in many places.

mjonat's avatar

OK so I get what you guys are saying in regards to redirect()->to() and this is definitely a better way to do things...I see this now although what about when, for example, the user is uploading a picture but forgets to actually choose a picture but just goes straight to clicking the upload button and my function just says to redirect back to the edit profile page...how do I give an error message...if i just redirect then surely it will just load the page as if nothing happened or nothing went wrong?

pmall's avatar

@mjonat Of course laravel provides a way to validate inputs and to display errors when redirected back. You faces problems just because you are not familiar enough with the framework features. I think it is a great time for you to reread the doc or to watch jeffrey's full application video tutorial / What's new with L5. Because now you faced the problems you'll identify the way of handling them with laravel.

mjonat's avatar

Yeah...I watched that whole series before I started with Laravel a couple weeks ago and have been going back to it for info but perhaps its worth another watch through in its entirety...

tbh I think the validation is the best way to go in this case...I was making my own errors and then returning those where I should just be getting laravel to validate and then send errors through that way...it just means I have to re-write a lot of my code which is a real pain in the ass haha...

Please or to participate in this conversation.