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

aleksov's avatar

Create store() which need to get user_id and article_id

I create a simple app with users, articles and offers. Now User can create article and offers to that article. SO User hasMany Article and hasMany Offers, article belogsTo User and hasMany Offers and offers belongsTo User and Article... so I write:

at User model:


 public function articles(){
        return $this->hasMany('App\Article');
    }

    public function offers(){
        return $this->hasMany('App\Offer');
    }

at Article model:


 public function user(){
        return $this->belongsTo('App\User');
    }

    public function offers(){

        return $this->hasMany('App\Offer');
    }

and at Offer model I write:


public function user(){
        return $this->belongsTo('App\User');
    }

    public function article(){
        return $this->belongsTo('App\Article');
    }

But Now I have a probem how to create store() function in my OffersController - I try:


 public function store(Requests\OfferRequest $request)
    {
        $offer = new Offer($request->all());

        Auth::user()->articles()->offers()->save($offer);

        Alert::success('Auction is succesfully added!','Good job!')->persistent("Close");

        return redirect('offers');
    }

but I get error...

also my form code is:


 {!! Form::open(['url'=>'offers']) !!}
        <div class="form-group">
            {!! Form::label('price','Price') !!}
            {!! Form::text('price', null, ['class'=>'form-control']) !!}
        </div>
        <div class="form-group">
            {!! Form::submit('Add Offer',  ['class'=>'btn btn-primary form-control']) !!}
        </div>
        {!! Form::close() !!}

and my route is:


Route::resource('offers', 'OffersController');

How to add Offer and that offer need to have user_id of Auth::user and article_id ...

0 likes
9 replies
aleksov's avatar

When I use just: Auth::user()->articles()->offer()->save($offer); then store fine but offcource without article_id ... so how I can fetch and add article id...

I know that I can put {{$article->id}} at blade template and fetch them but its security high risk...

tykus's avatar

If the article hasMany offers, then the relationship between a user and an offer is a hasManyThrough:

User.php

public function offers()
{
    return $this->hasManyThrough('App\Offer', 'App\Article')
}

You will have to save the offer to the related article, not to the user; so you'll have to pass in the article_id as a hidden form field, or maybe from select field

OffersController:

public function store(Requests\OfferRequest $request)
{
    $offer = new Offer($request->all());

    $article = Article::findOrFail($request->get('article_id'));

    $article->save($offer);

    Alert::success('Auction is succesfully added!','Good job!')->persistent("Close");

    return redirect('offers');
}
aleksov's avatar

@tykus_ikus by this way I get:

FatalErrorException in OffersController.php line 46: Class 'App\Http\Controllers\Article' not found

and when I try to add: use App\Article then I get error: ModelNotFoundException in Builder.php line 129: No query results for model [App\Article].

Also only admin user create articles and simple user can just put an offer to that article (just user can create article , so becouse that I need user_id at offer...)

tykus's avatar

Oh, okay I misunderstood. What is your schema?

I would think that the Offer should be a pivot for the user and article models because an article can have many offers by many users. If your user making the offer is authenticated then you will have the user_id available through Auth::user() object, you you must still pass in the article_id to the controller, whether this is a hidden field in the offer form, or you decide to nest the Offers resource inside the Articles resource and post to /articles/{article_id}/offers is up to you; the former is simpler...

aleksov's avatar

My shemas is:

public function up() { Schema::create('articles', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->string('title'); $table->text('body'); $table->timestamps(); $table->timestamp('roba_spremna'); $table->timestamp('auction_end'); $table->string('key');

        $table->foreign('user_id')
              ->references('id')
              ->on('users')
              ->onDelete('cascade');
    });
}

and

public function up() { Schema::create('offers', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->integer('article_id'); $table->integer('price'); $table->string('comment'); $table->timestamps();

        $table->foreign('user_id')
            ->references('id')
            ->on('users')
            ->onDelete('cascade');

        $table->foreign('article_id')
            ->references('id')
            ->on('articles')
            ->onDelete('cascade');
    });
}
tykus's avatar

So in your Models:

User:

// For the admin user
public function articles()
{
    return $this->hasMany('App\Article');
} 
// For the 'public' users the offers table acts as a pivot for the articles that the user has made an offer on.
public function offer_articles()
{
    return $this->hasManyThrough('App\Article', 'App\Offer');
}
public function offers() 
{
    return $this->hasMany('App\Offer');
}

Article.php

// for the admin user
public function owner()
{
    return $this->belongsTo('App\User');
}
public function offers()
{
    return $this->hasMany('App\Offer');

Offer.php

public function user()
{
    return $this->belongsTo('App\User');
}
public function article()
{
    return $this->belongsTo('App\Article');
}

Your form must include a reference to the article id that the offer is being made on:

{!! Form::open(['url'=>'offers']) !!}
    {!! Form::hidden('article_id', $article->id) !!}
    <div class="form-group">
        {!! Form::label('price','Price') !!}
        {!! Form::text('price', null, ['class'=>'form-control']) !!}
    </div>
    <div class="form-group">
        {!! Form::submit('Add Offer',  ['class'=>'btn btn-primary form-control']) !!}
    </div>
{!! Form::close() !!}

In the OffersController:

use App\Offer;
use App\Article;

public function store(Requests\OfferRequest $request)
{
    // try this, and we can refactor later if necessary
    $offer = new Offer;
    $offer->price = $request->get('price');
    $offer->user_id = Auth::user();
    $offer->comment = ''; // nothing coming from your form for the `comment` field, it is not nullable in your schema?

    // ensures that the article exists to place an offer on - this may have been the reason for your previous failure
    $article = Article::findOrFail($request->get('article_id'));   

    $article->save($offer);

    Alert::success('Auction is success  fully added!','Good job!')->persistent("Close");

    return redirect('offers');
}
aleksov's avatar

I did it on that way but witout public function offer_articles() { return $this->hasManyThrough('App\Article', 'App\Offer'); } Why is that important?

Also my controller code is: public function store(Requests\OfferRequest $request) { $offer = new Offer($request->all());

    Auth::user()->offer()->save($offer);

    Alert::success('Offer is succesfully added!','Good job!')->persistent("Close");

    return redirect('auctions/'.$offer['article_id']);
}

Also how I can redirect at the same page becouse I have same unique page /auctions/{key} but I dont know key, so how I can redirect to the same page? Is there some buildIn function or I must gt key from Form ?

tykus's avatar

It is only important if you need it -- the hasManyThrough will return the 'public' user's articles - because these are accessible only through that user's offers. The user_id stored on the articles table is the id of the admin user who created the article.

You are not passing in the article_id that the offer is being made on, so your offer cannot be saved. I asked you to try it my way first so you can see all of the data that a new offer instance should have - your way is perfectly fine, but I think it is obscuring the fact that you do not pass in the article_id or the comment.

Also, if you insist on going your way, then you should be doing it this way - User does not have an offer() relation.

Auth::user()->offers()->save($offer);

How does the auction key relate to the article???

Please or to participate in this conversation.