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

trevorpan's avatar

don't show checkbox if auth()->user has submitted checkbox

Hi, this form shows how many interested bidders there are for a given job. After a user_id has submitted interest to bid, the blade takes away the possibility of resubmitting the form.

http://trevorpan.com/stuff/bidders.jpg http://trevorpan.com/stuff/bidders2.jpg

Having a real tough go on getting the auth()->user to be the conditional. Sometimes they'll hide a form. But then when I log in as another user it shows without form, etc. Feels like whack-a-mole.

    //class BidInterestsController extends Controller @ show


    // $userbidinterests = DB::table('bidinterests')
        //     ->where('user_id', '==', auth()->user->id)->get();
        
        $userbidinterests = DB::table('bidinterests')
                                ->whereExists(function ($query) {
                                    $query->select(DB::raw(1))
                                          ->from('bidderinterested')
                                          ->whereRaw('bidderinterested.user_id = users.id');
                                })
                                ->get();

The blade logic

        @if (!$job->userbidinterests)
            <form action="/jobs/{{ $job->id }}/bidinterests" method="POST">
                @csrf
                <input type="checkbox" name="bidderinterested" value="1" required> I will bid this job.<br>
                <input type="submit" value="Submit">
            </form> 
        @else 
            Thank you for your interest in bidding this job.
        @endif

0 likes
36 replies
Snapey's avatar

seems pretty simple problem, but not answerable based on what you posted because the table/models are unknown, $users is unknown, and instead of $userbidinterests being a boolean, it is instead a collection.

How does the result of the query $userbidinterests end up being an attribute of $job ?

1 like
trevorpan's avatar

@SNAPEY - good morning, and thank you.

I was unclear why the $userbidinterests was not available. In fact, it was puzzling. In the same view $question->body can be accessed—although this was after a `@foreach ($job->questi was established. (still a bit unclear on how this comes together)

With regards to the boolean, I tried the Laravel docs: return DB::table('orders')->where('finalized', 1)->exists(); however, after changing the values for this app, the @if statement read it as if any bidderinterested exists. So, the auth()->userwas not acting as the conditional.

So the above attempts were made using the collection method.

Here's

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class BidInterest extends Model
{
    //
    protected $guarded = [];
    
    public $table = "bidinterests";

    public function scopeBidderInterested($query)
    {
        return $query->where('bidderinterested', 1);
    }

    public function user() //$job->user
    {
        return $this->belongsTo(User::class);
    }

    public function job()
    {
        return $this->belongTo(Job::class);
    }
}
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBidinterestsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('bidinterests', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('user_id');
            $table->unsignedInteger('job_id');
            $table->boolean('bidderinterested')->default(false);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('bidinterests');
    }
}
Snapey's avatar

Suppose job_id in $job->id

$hasbid = Auth::user()->bidInterest()->where('job_id',$job->id)->bidderInterested()->exists();

breaks down as Authenticated user, their bids, for this job, in the right state, and one or more results

In this, you must have a bidInterest() relationship on User model;

public function bidInterest()
{
    return $this->hasMany(BidInterest::class);
}

I'm puzzled by your bidderinterested column on the database. This requires the additional scope or where statement. Would this table even have a row for this user and job if they were not interested?

trevorpan's avatar

@SNAPEY - Ha! puzzled ? I'm puzzled, too.

the bidderinterested is a feature which allows a bidder to state their intent to bid. This is so other bidders see how competitive the job is - the logic is if you know 8 bidders are going for a modest job you can pass. My goal is transparency for the users. However, this may be a clumsy way to achieve that function programmatically.

There is a separate bids table which handles the actual dollar amounts. The bids actually happen some distance in the future, depending on the value of the job and research required to make a serious bid.

back to the line you have above is what I was "trying" to do. thank you` The goal of this line is to prevent users who have expressed interest once from repeatedly hitting the select box to inflate the competition.

In User model, I had already placed

public function bidInterests()
{
    return $this->hasMany(BidInterest::class);
}

If the relationship is hasMany is it good to use plural? And if hasOne to use singular? This is just a convention question.

I put the line like so:

public function show(BidInterest $Bidinterest)
    {
    // this shows all the interested bidders in the screenshot above
        $bidinterests = App\BidInterest::withCount('bidderinterested')->get();
        
        foreach ($bidinterests as $bidinterest) {
                echo $bidinterest->bidderinterested_count;
            }
    //end

        $hasbidinterest = Auth::user()->bidInterests()->where('job_id',$job->id)->bidderInterested()->exists();

return view('jobs.show', compact('job'));
}

I've added the $hasbidinterest to the blade file as {{ $hasbidinterest }} (changed slightly to reflect the logic of the app) but it spits out Undefined variable: .

Why does that happen?

Snapey's avatar

If the relationship is hasMany is it good to use plural?

Yes, you are right. It should be plural

it spits out Undefined variable: .

Did you pass your new boolean to the view?

trevorpan's avatar

@SNAPEY - Sweet.

This is where I'm confused in MVC. I added to this line: return view('jobs.show', compact('job', 'bidderinterested)); Read up on compact here: http://php.net/manual/en/function.compact.php Not clear on how that array works, or if 'bidderinterested' even registers with compact in this scenario.

Now the good thing is{{ $job->bidinterests }} spits out the json records in the page.

[{"id":40,"user_id":1,"job_id":22,"bidderinterested":1,"created_at":"2019-02-18 21:10:53","updated_at":"2019-02-18 21:10:53"}]

{{ $job->bidinterests->hasbidinterest }} goes nowhere either. Why is the variable we created not visible?

Property [hasbidinterest] does not exist on this collection instance.

'{{ $job->hasbidinterest }}' nada and {{ $hasbidinterest }} is useless..

Then I thought perhaps echo = $hasbidinterest; in public function show method would make it available in the blade view.

man.

Cronix's avatar
$job->bidinterests

returns an array of bidinterests, not just one, as you can see (the resulting object is within [ ] brackets). So you can't just access a hasbidinterest property because it's not a single object. It's an array of objects. It just so happens there is only one object in this particular array.

Not clear on how that array works, or if 'bidderinterested' even registers with compact in this scenario.

It depends on the names of your variables. If the variable is $hello then it's compact('hello'). It has to be the exact name of the variable minus the $ and within quotes.

1 like
Cronix's avatar

If you're just looking to see if there is a bidinterest = 1 in the collection of many results, there are collection helper methods available to you. You could do something like

@if ($job->bidinterests->contains('bidinterest', 1))
    // this will show if there is a bidinterest = 1 withing the bidinterests collection
@endif

https://laravel.com/docs/5.7/collections#method-contains

trevorpan's avatar

@CRONIX - thank you much` I understand the array a good bit better and why it works for the count of interested bidders.

one confusing thing here in relation to the single variable $hasbidinterest:

$bidinterests = App\BidInterest::withCount('bidderinterested')->get();
        
        foreach ($bidinterests as $bidinterest) {
                echo $bidinterest->bidderinterested_count;
            }

(this code renders in the page) with {{ $job->bidinterests->count() }}. Is it available in the blade because it was echoed? So in this case a compact('bidinterests') is unnecessary?

@snapey 's line:

$hasbidinterest = Auth::user()->bidInterests()->where('job_id',$job->id)->bidderInterested()->exists();

is what the goal is => Is this user authenticated, have they hit the select box "interested in bidding this job".

My goal is something like

@if(!$hasbidinterest)    
    show the check box
@else 
    thank you for your interest in bidding
@endif 

the above does not work. is this because several variables are being created in the show method? e.g. $bidinterests and $hasbidinterestare they conflicting?

I have changed the code to:

public function show(BidInterest $Bidinterest)
    {

        $bidinterests = App\BidInterest::withCount('bidderinterested')->get();
        
        foreach ($bidinterests as $bidinterest) {
                echo $bidinterest->bidderinterested_count;
            }


        $hasbidinterest = Auth::user()->bidInterests()->where('job_id',$job->id)->bidderInterested()->exists();

        // echo = $hasbidinterest;

        return view('jobs.show', compact('job', 'hasbidinterest'));
    }
Snapey's avatar

Hi

All you needed to do was pass $hasbidinterest to the view ... not bidderinterested

So, is it working now?

trevorpan's avatar

@SNAPEY - omg. idk.

Perhaps the confusing part is there are two operations. I may be trying to do too much in the show method. Please pardon the confusion...

http://trevorpan.com/stuff/bidders2.jpg (top box of screenshot)

1st part: There are ___ many bidders for this job. (here is where the $bidinterests goes. It works)

2nd part: [ ] box if you would like to bid this job. (here is where $hasbidinterest goes. It does not work)

Snapey's avatar

So did you test that boolean was returning the correct value for users that have and have not bid?

For the count, all you need to know is how many rows are in the table for the particular job. Do you have a bidInterests relation on the Job model?

if you did it would be

$job->load('bidInterests');

and then pass '$job' to the view as normal

In the view you can do

{{ $job->bidInterests->count() }}

Thats one way

trevorpan's avatar

@SNAPEY - https://laracasts.com/discuss/channels/eloquent/what-is-the-proper-way-to-check-a-boolean-from-a-db

so many trickses in programming.

 $hasbidinterest = Auth::user()->bidInterests()->where('job_id',$job->id)->bidderInterested()->exists();

Ok I see now after watching a query scope video again that your call to bidderInterested() is utilizing the query scope in BidInterest model.

When printing this{{ !$job->hasbidinterest }}the browser spits out 1, but does nothing when I remove the !.

I gave this a shot, but may be irrelevant with the exists() function.

$yes = App\BidInterest::where('bidderinterested', '>', 0);

        $hasbidinterest = Auth::user()->bidInterests()->where('job_id',$job->id)->bidderInterested($yes)->exists();
Snapey's avatar

I don't understand why it keeps getting so complicated?

This returns true or false

$hasbidinterest = Auth::user()->bidInterests()->where('job_id',$job->id)->bidderInterested()->exists();

Put a return statement after it and see what you get for different scenarios

And then in the blade view its just

@if($hasbidinterest)    
    thank you for your interest in bidding
@else 
    show the check box
@endif 

Work with the logic you have, rather than trying to invert it.

trevorpan's avatar

@SNAPEY - Yea, I had thought about the double negatives, too. I'll keep this in mind for future.

This error is given in the blade: Undefined variable: hasbidinterest (View: /Users/trevorpan/code/bidbird/resources/views

This is the exact method:

    public function show(BidInterest $Bidinterest)
    {
        $job->load('bidInterests');


        $hasbidinterest = Auth::user()->bidInterests()->where('job_id',$job->id)->bidderInterested()->exists();

 
        return view('jobs.show', compact('hasbidinterest'));
    }

It's puzzling.

Cronix's avatar

Another puzzle is where $job comes from and why you're not getting an error about that. It just mysteriously appears in the method without being passed or created, and then you use $job->id to get $hasbidinterest.

trevorpan's avatar

@CRONIX - ok, i'm not going insane! thank you.

There are two controllers. JobsController and BidInterestController. Could they possibly conflict?

Cronix's avatar

Hard to know. Is the url you are accessing going to the correct controller/method from the route? Are you actually showing the correct method for the route being accessed? What do the routes for those 2 controllers look like?

if you put dd('hi'); as the first line of that method above, is that what you see when visiting the route?

trevorpan's avatar

@CRONIX - That's another area that's still a little muddy.

Here's are the current routes:

Route::get('/jobs', 'JobsController@index')->name('jobs.index');
Route::get('/jobs/create', 'JobsController@create');
Route::post('/jobs', 'JobsController@store');
Route::get('/jobs/{job}/edit', 'JobsController@edit');
Route::get('/jobs/{job}', 'JobsController@show')->name('showjobedits');
Route::patch('/jobs/{job}', 'JobsController@update');


Route::post('jobs/media', 'JobsController@storeMedia')
  ->name('jobs.storeMedia');


Route::post('/jobs/{job}/questions', 'QuestionsController@store');


Route::post('/jobs/{job}/bids', 'BidsController@store');
Route::get('/jobs/{job}/edit', 'BidControllers@edit');
Route::patch('/jobs/{job}', 'BidsController@update');


Route::post('/jobs/{job}/bidinterests', 'BidInterestsController@store');
Route::get('jobs/{job}', 'BidInterestsController@show');

dd('hi'); works on JobsController@show but not BidInterestsController@show

Snapey's avatar

your routes are a bit of a mess. for instance get /jobs/{job} is repeated twice. Only the first will ever be called

1 like
Cronix's avatar

There are several things wrong in that route file. Multiple controllers responding to the same endpoint. Your endpoints are not unique. The way routing works, it starts at the top of the file and works its way down line by line to see if the request matches. As soon as it finds the first one that will satisfy the condition, it will use that and ignore the others. I think @snapey pointed out the specific problem in this case, but you also have

Route::patch('/jobs/{job}', 'JobsController@update');
Route::patch('/jobs/{job}', 'BidsController@update');

same url, same method (patch) going to 2 different controllers. The BidsController one will never get called because the first route would always match /jobs/4 first (or whatever id you send). The 2nd one should be Route::patch('/bids/{job}') or something more unique to what it's actually doing. It's not a job url, it's a bid url.

trevorpan's avatar

@CRONIX - Thank you again, as always!

how would you specify the bid route if the bid is submitted on the job page?

Cronix's avatar

All routes going to the BidController would start with /bid in my book. It doesn't matter what "page" the form or whatever is on. It matters where it submits to. If it's dealing with a bid, it should have bid in the url, and use the bid controller.

I really like using resource controllers ( https://laravel.com/docs/5.7/controllers#resource-controllers ). They contain all of the methods needed for a controller, and also create the routes with a simple single command, like Route::resource('jobs', 'JobsController'); which is a lot simpler than

Route::get('/jobs', 'JobsController@index')->name('jobs.index');
Route::get('/jobs/create', 'JobsController@create');
Route::post('/jobs', 'JobsController@store');
Route::get('/jobs/{job}/edit', 'JobsController@edit');
Route::get('/jobs/{job}', 'JobsController@show')->name('showjobedits');
Route::patch('/jobs/{job}', 'JobsController@update');

But for now, just make all of your urls unique and not reuse them for different things.

trevorpan's avatar

@CRONIX - this was helpful. I had tried using the Route::resource before and had other methods mingled in above that call which ruined everything!

now if you want to render the variables from 'BidInterestsController@show' (this OP) on a specific jobs/{job} page can you redeclare the same view? I think this is a major reason this has been troublesome.

JobsController.php:

public function show(Job $job)
    {
        //code

        return view('jobs.show', compact('job'));
    }

BidInterestsController.php:

public function show(Job $job)
    {
        //code

        return view('jobs.show', compact('hasbidinterests'));
    }

or is this a case where return back(); is used?

Snapey's avatar

I think this is something newcomers get stuck with.

In response to a request, laravel routes to a controller method and that controller method prepares or coordinates all the data required for the view. It then returns the view with the data.

You cannot have one view use two different endpoints (in your controller) unless you make a second request from your view with ajax.

So, if you are displaying the job and you want to include in that view, whether the user has already bid then this needs to be prepared in the job show method and not in the bidinterests controller.

trevorpan's avatar

@SNAPEY - would you say in this case BidInterestsController is not needed? There are other methods in use, should these be shuffled to the JobsController and delete BidInterestsController.

Really sorry 'tis forum post left the tracks```

https://laracasts.com/series/laravel-from-scratch-2017/episodes/16?autoplay=true

This video showed comments being added to /jobs/{job}/comments and I thought you needed multiple controllers to have multiple things on a page.

trevorpan's avatar

@snapey @cronix ok, got the routes set (at least no errors right now) thank you there.

//jobs
Route::resource('/jobs', 'JobsController');

//job bid interests
Route::post('/jobs/{job}/bidinterest', 'BidInterestsController@store');
Route::get('jobs/{job}/bidinterested', 'BidInterestsController@show');

BidInterest.php (model)

    public static function scopeBidderInterested($query)
    {
        return $query->where('bidderinterested', 1)->exists();
    }

Job.php (model)

    public function bidderinterests()
    {
        return $this->hasMany(BidInterest::class);
    }

User.php (model)

    public function bidinterests()
    {
        return $this->hasMany(BidInterest::class);
    }

The above models now have names that don't conflict (there were 2 bidinterests()).

    public function show(BidInterest $Bidinterest)
    {

        $hasbidinterest = Auth::user()->bidInterests()->where('job_id', '=', $job->id)->BidderInterested();

        return back(compact('job', 'hasbidinterest'));

    }

After clicking a checkbox, the counter ups the number of interested bidders, but the checkbox does not return the if statement.

        @if ($job->user->hasbidinterest)

            Thank you for your interest in bidding this job.
            
        @else 
            <form action="/jobs/{{ $job->id }}/bidinterest" method="POST">
                @csrf
                <input type="checkbox" name="bidderinterested" value="1" required>

                I will bid this job.<br>
                <input type="submit" value="Submit">
            </form> 
        @endif 

Any ideas?

Cronix's avatar
@if ($job->user->hasbidinterest)

There is no user property/method named hasbidinterest that I can see from what you are showing. There is a bidinterests method on the user object though.

Your show method is sending a $hasbidinterest variable to the view. That's a straight up variable and not a property on an object.

@if ($hasbidinterest)

I'm not saying that will give you the correct result, but it's why you have the problem you currently are as far as I can tell.

trevorpan's avatar

@CRONIX - ok, got that cleaned up. @if($hasbidinterest) yields a Undefined variable: hasbidinterest.

Stepping back . . . if a bidder has clicked the checkbox it registers as a 1 in the bidderinterested column, if they do not click the checkbox it never registers.

Is it possibile for a query scope in BidderInterest.php, to positively show, or not show the checkbox to someone who has expressed their interest to bid?

<?php

namespace App\Http\Controllers;

use App\Job;
use App\BidInterest;
use Illuminate\Http\Request;

class BidInterestsController extends Controller
{
    //

    protected $bidinterest;

    public function __construct()
    {
        $this->middleware('auth');
    }


        /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Job $job)
    {
        $this->validate(request(), [
            'bidderinterested' => 'required',
        ]);

        // add bidder interest to job
        $bidinterest = auth()->user()->bidInterests()->create([
            'bidderinterested' => request('bidderinterested'),
            'job_id' => $job->id
            ]);
        
        return back();
    }

    public function show(BidInterest $Bidinterest)
    {
        // dd('hi');

        // DB::table('bidinterests')->where('bidderinterested', 1)->exists();
        // $hasbidinterest = Auth::user()->whereRaw('$job->id = jobs.id')->BidderInterested();

        $hasbidinterest = Auth::user()->bidInterests()->where('job_id', '=', $job->id)->BidderInterested();
        
        return view('jobs.jobfull', compact('hasbidinterest'));
    }
}

thank you`

trevorpan's avatar

@cronix

After a lot of hunting down, I found that the variable was not available because the show method in the JobsController.php did not have the logic.

In this case, the full sized job display page (not a list of thumbnail descriptions) has a number of controllers being referenced.

JobsController:

    public function show(Job $job)
    {

        // $thumbnail = $job->getFirstMedia('document');
        $fullpageimage = $job->getFirstMedia('document');
    

        $downloads = $job->getMedia('document');
    
        $hasbidinterest = BidInterest::BidderInterested(1)->get();

        return view('jobs.show', compact('job', 'downloads', 'fullpageimage', 'thumbnail', 'hasbidinterest'));
    }

After adding the line above and referencing the query scope, it at least does not crash the page.

Do you handle multiple controllers on a page? Is this a case to return back() on the BidInterestsController.php controller, as opposed to a return view()?

Next

Please or to participate in this conversation.