In my app admin users can create articles. Articles table is: ID | user_id | title ...
For every Article other user (which not admin) can post an offer and Offer table is: ID | user_id(not admin) | article_id | price ...
Now I need to get all users for an admin user which post Offer to their Article... I try:
public function userbase()
{
$id = Auth::user()->id;//get admin id
$articles = Article::where('user_id', $id)->get();//select all admin articles
foreach ($articles as $article) {
$users = Offer::where('article_id', $article['id'])->orderBy('created_at', 'desc')->get(); //get all admin users
}
return $users;
}
but I get just: []
also my Model is:
Article:
public function offers() {
return $this->hasMany('App\Offer');
}
Offer:
public function user() {
return $this->belongsTo('App\User');
}
public function article() {
return $this->belongsTo('App\Article');
}
So how I can get all user details which was posted offer to an admin user?
UPDATE
I also try this:
$articles = Article::with([
'offers' => function($query) {
$query->orderBy('created_at', 'desc');
$query->with('user'); // if you want to eager load users for each offer too...
}
])->where('user_id', Auth::id())->get();
and I get this data:http://i.imgur.com/0kBVGrx.png
but how to access user data? I try ->get('user') but dont work...
2. UPDATE:
I also try:
public function userbase()
{
$articles = Auth::user()->articles()->get();
foreach ($articles as $article) {
$offers = Offer::where('article_id', $article['id'])->orderBy('created_at', 'desc')->get();
}
foreach ($offers as $offer) {
$users = User::where('id', $offer['user_id'])->orderBy('created_at', 'desc')->get();
}
return $users;
}
but I get undefined variable users
Try this :
First, you may add an attribute 'isAdmin' in your User model.
public function userbase()
{
return Offer::select('users.*')
->where('users.isAdmin', false)
->join('articles','articles.id','=','offers.article_id')
->join('users','users.id','=','articles.user_id')
->where('articles.user_id', Auth::user()->id)
->orderBy('offers.created_at', 'desc')
->groupBy('users.id')
->get();
}
Updating Your solution :
public function userbase()
{
$articles = Auth::user()->articles;
foreach ($articles as $article) {
$offers = Offer::where('article_id',$article->id)->orderBy('created_at', 'desc')->get();
}
$users = array();
foreach ($offers as $offer) {
$users[] = User::where('id', $offer['user_id'])->orderBy('created_at', 'desc')->get();
}
return $users;
}
Related
I have the following tables :
orders : id, etc...
order_lines : id, order_id, product_id, etc...
products : id, name, etc...
Foreign keys are defined.
My Laravel Models are defined as :
class Order
public function orderLine()
{
return $this->hasMany('App\OrderLine');
}
class OrderLine
public function order()
{
return $this->belongsTo('App\Order');
}
public function product()
{
return $this->belongsTo('App\Product');
}
class Product
public function orderLine()
{
return $this->hasMany('App\OrderLine');
}
I've tried many things, but nothing is working. Here is the best solution for me, but it's not working.
class OrderController
public function show($id)
{
$user = Auth::user();
$order = Order::where('user_id', '=', $user->id)->with(['orderLine.product'])->findOrFail($id);
return view('layouts/order/index', compact('order'));
}
I struggle to display the following data in the view :
#foreach($order->orderLine as $key => $orderLine)
<tr>
<td>{{$orderLine->product->name}}</td>
<tr>
#endforeach
Product object is not loaded. I want to display the product name in the above loop.
Try to do like this:
public function show($id)
{
$user = Auth::user();
$order = Order::with(['orderLines', 'orderLines.product'])
->where('user_id', '=', $user->id)
->findOrFail($id);
return view('layouts/order/index', compact('order'));
}
class OrderLine
public function order()
{
return $this->belongsTo(\App\Order::class, 'order_id');
}
public function product()
{
return $this->belongsTo(\App\Product::class, 'product_id');
}
class Order
public function orderLines()
{
return $this->hasMany(\App\OrderLine::class);
}
Change name of orderLine to orderLines because order has many orderLines.
And in your blade:
#foreach($order->orderLines as $orderLine)
<tr>
<td>{{$orderLine['product']->title}}</td>
<tr>
#endforeach
Hello Dezaley and welcome to StackOverflow!
Let's investigate your problem.
As far as I can see you are selecting the model in the wrong way. Let me help you:
$order = Order::where(['id' => $id, 'user_id' => $user->id])->with('orderLine.product')->firstOrFail();
The answer from mare96, who was very friendly to help me, is working. However, I found out someting.
You can implement as (mare96 solution)
public function show($id)
{
$user = Auth::user();
$order = Order::with(['orderLines', 'orderLines.product'])
->where('user_id', '=', $user->id)
->findOrFail($id);
return view('layouts/order/index', compact('order'));
}
#foreach($order->orderLines as $orderLine)
<tr>
<td>{{$orderLine['product']->title}}</td>
<tr>
#endforeach
In the view, I don't like the array syntax "$orderLine['product']->title". The following solution without the array is also working.
Solution is below :
public function show($id)
{
$user = Auth::user();
$order = Order::with('orderLines', 'orderLines.product')
->where('user_id', '=', $user->id)
->findOrFail($id);
return view('layouts/order/index', compact('order'));
}
#foreach($order->orderLines as $orderLine)
<tr>
<td>{{$orderLine->product->title}}</td>
<tr>
#endforeach
In fact, my issue was that product was defined to null in the model, so Product was always null in the view.
Class OrderLine extends Model {
public $product = null
I remove line "public $product = null" and it's working as expected. Thanks to the people who helped me.
give it a try -
#foreach($order as $ordr)
<tr>
<td>{{$ordr->product_id->name}}</td>
<tr>
#endforeach
protected function show()
{
$users = User::all();
$letters = Letter::with('user');
$userLetter = $letters->where(['user_id' => 2])->count();
//Here function work right. Shows that we have 10 users
foreach ($users as $user) {
$userLetter = $letters->where(['user_id' => $user->id])->first();
if($userLetter){
//Here it shows that only the first user exists, returns null for the rest users.
}
}
}
We get an error when we sort the array with foreach.
No record is found in the database except the first.
For other entries, return null.
outside foreach no errors.
Just move your object inside the loop like below.
protected function show()
{
$users = User::all();
$userLetter = $letters->where(['user_id' => 2])->count();
//Here function work right. Shows that we have 10 users
foreach ($users as $user) {
$userLetter = Letter::with('user')->where(['user_id' => $user->id])->first();
if($userLetter){
}
}
}
You would probably be better off using a letter relationship on the User.
On the User model you could do something like :
public function letter()
{
return $this->hasOne(Letter::class, 'user_id');
}
Then you could in the controller:
protected function show()
{
$users = User::with('letter')->get();
foreach ($users as $user) {
if ($user->letter) {
// do things
}
}
}
I have products which have a many to many relationship with filters
The user may choose multiple filters and I want to display all products that match the selected filters. But by matching them I mean containing all of them (not only some of them). Here's an example to explain what I mean, let's say that the user is on the cars category page and he wants to filter all cars that are from year 2013 AND have 4x4. Now if the user selects those filters it will show all the cars that are from year 2013 OR have 4x4.
Here's my code in the controller:
public function showFilteredProducts(Request $request)
{
$products = collect([]);
$this->request = $request;
foreach ($request->filters as $filter_id => $active) {
$this->filter_id = $filter_id;
$queriedProducts = Product::whereHas('filters', function($query) {
$query->where('filters.id', $this->filter_id);
})
->whereHas('category', function($query) {
$query->where('slug', $this->request->category_slug);
})
->get();
foreach ($queriedProducts as $product) {
if (!$products->contains($product)) {
$products[] = $product;
}
}
}
return response()->json($products->chunk(3));
}
As i explained this now returns the products if they match only one of the filters, but I want them to match all of them.
try this
public function showFilteredProducts(Request $request)
{
$filters = $request->filters;
$query = Product::query();
foreach ($filters as $filter_id => $active) {
$query = $query->whereHas('filters', function($query) use ($filter_id) {
$query->where('filters.id', $filter_id);
});
}
$query = $query->whereHas('category', function($query) use ($request) {
$query->where('slug', $request->category_slug);
})
$products = $query->get();
return $products->chunk(3);
}
alternatively, based on your previous code, you can use array_intersect like this:
public function showFilteredProducts(Request $request)
{
$products = collect([]);
$this->request = $request;
foreach ($request->filters as $filter_id => $active) {
$this->filter_id = $filter_id;
$queriedProducts = Product::whereHas('filters', function($query) {
$query->where('filters.id', );
})
->whereHas('category', function($query) {
$query->where('slug', $this->request->category_slug);
})
->get();
$products = array_intersect($queriedProducts, $products);
}
return response()->json($products->chunk(3));
}
I think you want to use orWhereHas() instead of whereHas() on the second table that you are checking against.
So as I write at title I need to get all users who post offer to an admin user article...
So I write:
public function userbase()
{
return Offer::select('users.*')
->where('users.admin', 9)
->join('articles','articles.id','=','offers.article_id')
->join('users','users.id','=','articles.user_id')
->where('articles.user_id', Auth::user()->id)
->orderBy('offers.created_at', 'desc')
->groupBy('users.id')
->get();
}
but I get just [] (which is not true) ...
I also try:
public function userbase()
{
$user_ids = Article::where('user_id', Auth::id())
->join('offers')->on('offers.article_id', '=', 'articles.id')
->join('users')->on('offers.user_id', '=', 'users.id')
->select('users.id')
->distinct()
->get();
$users = User::whereIn('id', $user_ids);
return $users;
}
but I get:
Missing argument 2 for Illuminate\Database\Query\Builder::join()
attempt was:
public function userbase() { $articles = Auth::user()->articles()->get(); foreach ($articles as $article) {
$offers = Offer::where('article_id', $article['id'])->orderBy('created_at', 'desc')->get();
}
foreach ($offers as $offer) {
$users = User::where('id', $offer['user_id'])->orderBy('created_at', 'desc')->get();
}
return $users;
}
but offcource dont work...
Now I really dont know what to do next... PLEASE HELP...
also my MODEL:
Article:
public function offers() {
return $this->hasMany('App\Offer');
}
Offer:
public function user() {
return $this->belongsTo('App\User');
}
public function article() {
return $this->belongsTo('App\Article');
}
So how I can get users who post offer to other user(admin) article...
Try to put this function in the User model:
public function scopeBase($query){
$sql = <<<SQL
id IN(
SELECT DISTINCT users.id FROM articles
INNER JOIN offers
ON articles.id=offers.article_id
INNER JOIN users
ON users.id=articles.user_id
WHERE articles.user_id=? AND users.admin=?
)
SQL;
return $query->whereRaw($sql, [$this->id, 9]);
}
Then in the controller to get the users use this syntax:
class MyController extends Controller{
public function example(){
$users = User::base()->get();
//....
}
}
However if you explain better the table structure you will be grateful.
Did you try this?
foreach (User::all() as $user) {
foreach ($user->offers as $offer) {
if ($offer->article->user->isAdmin())
$select[] = $user;
}
}
I can get the list of Likes that User 1 did on a Media from Store 1
$medias = User::find(1)->likes()->with('media')->whereHas('media', function($q) {
$q->where('store_id', '=', 1);
})->get();
But i need to retrieve the list of medias, so i tried
$medias = User::find(1)->likes()->with('media')->whereHas('media', function($q) {
$q->where('store_id', '=', 1);
})->get()->media;
But then i get
Undefined property: Illuminate\Database\Eloquent\Collection::$media
class User extends Model
{
public function likes()
{
return $this->hasMany('App\Like');
}
}
class Media extends Model
{
public function store()
{
return $this->belongsTo('App\Store');
}
public function likes()
{
return $this->hasMany('App\Like');
}
}
class Like extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
public function media()
{
return $this->belongsTo('App\Media');
}
}
This is because you get media separate for each like. You should use:
$likes = User::find(1)->likes()->with('media')->whereHas('media', function($q) {
$q->where('store_id', '=', 1);
})->get();
foreach ($likes as $like) {
$media = $like->media;
// now you can do something with your media
}
EDIT
If you want to get only media, you should add to your User model the following relationship:
public function medias()
{
return $this->hasManyThrough('App\Media','App\Like');
}
Now to get your media, you should do :
$medias = User::find(1)->medias()->where('store_id', '=', 1)->get();
Made it work with
$store->medias()->whereHas('likes', function($q) use($user) {
return $q->where('user_id', '=', $user->id);
});