how to access relationship and pass into a view in laravel - php

a beginner question here, how can i get the building_name column on my buildings table which has a relationship with information, i wanted to access it inside the show function and display in on the show.views? And i also wanted to know how can i call it inside the show view Please help.
<?php
namespace App\Http\Controllers;
use App\Information;
use App\Building;
use Illuminate\Http\Request;
use Session;
class InformationController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
$buildings = new Building();
$buildings::all();
return view('create', compact('buildings'));
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate($request, array(
'building_information' => 'required',
'building_id' => 'required'
));
//store in the db
$information = new Information;
$information->building_information = $request->building_information;
$information->building_id = $request->building_id;
$information->save();
Session::flash('success', 'The information was successfully saved!');
//redirect to other page
return redirect()->route('information.show', $information->id);
}
/**
* Display the specified resource.
*
* #param \App\Information $information
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$information = Information::find($id);
return view('show')->with('information', $infomation);
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Building extends Model
{
public function information()
{
return $this->hasMany('App\Information');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Information extends Model
{
public function building()
{
return $this->belongsTo('App\Building');
}
}

Load the relationship too when getting the Information object:
$information = Information::with('building')->find($id);
If there are multiple buildings associated, you can loop through them in your blade view:
#foreach( $information->building as $building)
<li>{{ $building->building_name }}</li>
#endforeach

Just add relationship and pass it to the view
public function show($id)
{
$information = Information::with('building')->findOrFail($id);
return view('show')->with('information', $infomation);
}
In your view:
{{$information->building->building_name}}

Related

Laravel how to get back relationships from an array of ids

I have a table called addresses, it has a column name user_ids which is an array of the users who have that same address.
When I request to /api/addresses what it returns is {id:1,name:"lorem", user_ids:[1,2]}. I want it to return the users instead of their ids
this is the addresses model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Address extends Model
{
use HasFactory;
protected $fillable = [
'coordinates',
'title',
'description',
'user_ids',
];
protected $appends = ['user_ids'];
protected $casts = [
'user_ids' => 'array',
];
public function users()
{
return $this->belongsToMany(User::class,"addresses");
}
}
this is the create_table_addresses
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('addresses', function (Blueprint $table) {
$table->id();
$table->string('coordinates');
$table->string('title');
$table->string('description');
$table->json("user_ids");
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('addresses');
}
};
addresses controller
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreAddressRequest;
use App\Http\Requests\UpdateAddressRequest;
use App\Models\Address;
class AddressController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return Address::with('users')->get();
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \App\Http\Requests\StoreAddressRequest $request
* #return \Illuminate\Http\Response
*/
public function store(StoreAddressRequest $request)
{
$address = Address::create($request->validated());
return response()->json($address, 201);
}
/**
* Display the specified resource.
*
* #param \App\Models\Address $address
* #return \Illuminate\Http\Response
*/
public function show(Address $address)
{
return $address;
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Models\Address $address
* #return \Illuminate\Http\Response
*/
public function edit(Address $address)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \App\Http\Requests\UpdateAddressRequest $request
* #param \App\Models\Address $address
* #return \Illuminate\Http\Response
*/
public function update(UpdateAddressRequest $request, Address $address)
{
$address->update($request->validated());
return response()->json($address, 200);
}
/**
* Remove the specified resource from storage.
*
* #param \App\Models\Address $address
* #return \Illuminate\Http\Response
*/
public function destroy(Address $address)
{
$address->delete();
return response()->json(null, 204);
}
}
My suggestion would be to use the database for this (since you're already using the with('addresses')).
(Documentation for that relationship starts here)
Migration:
Schema::create('address_user', function (Blueprint $table) {
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('address_id')->unsigned()->index();
$table->foreign('address_id')->references('id')->on('addresses')->onDelete('cascade');
$table->primary(['user_id', 'address_id']);
});
User model:
use App\Models\User;
class Address extends Model {
public function users() {
return $this->belongsToMany(User::class);
}
}
Address model:
use App\Models\Address;
class User extends Model {
public function addresses() {
return $this->belongsToMany(Address::class);
}
}
Now you can use the relationship your application:
$address->users // Get all the users with that address
$user->addresses // Get all the addresses for the user
Address::with('users') // Get addresses with the users as an attribute
User::with('addresses') // Get users with the Address as an attribute
I am assuming that the response comes from a controller so then where you build you response, you need to append the user information.
Maybe something like
User::whereIn('id', [1,2])->get() ...
If you post the controller, then I can tell you exactly where to put this or how to do it better.

Laravel API - Showing individual file through o2m relationship

So I have two models User and File, these are connected with a one-to-many relationship.
I have sorted the API routes and controllers to index all users, show specific user and index all files uploaded by that specific user. I do not know how to write the logic that will allow this route 127.0.0.1:8001/api/2/files/1 to show the first file uploaded by the 2nd user. So/2(seconduser)/files(shows all)/1(shows only 1 file)
This is my API code:
Route::group(["prefix" => "/"], function () {
Route::get("", [Users::class, "index"]); //show all users
Route::group(["prefix" => "{user}"], function () {
Route::get("", [Users::class, "show"]); //show specific user
Route::group(["prefix" => "/files"], function () {
Route::get("", [Files::class, "index"]); //show all files
Route::group(["prefix" => "{file}"], function () {
Route::get("", [Files::class, "show"]); //trying to show specific file
});
});
});
});
Files Controller
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\File;
class Files extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(User $user)
{
return $user->files;
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show(User $user, File $file)
{
}
}
Users Controller
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
class Users extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return User::all();
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show(User $user)
{
return $user;
}
}
So here's what a typical route declaration would look like. Note the user ID is not relevant to the file request, so the files endpoint is made separate from the users endpoint.
Route::get("/users", [Users::class, "index"]);
Route::get("/users/{user}", [Users::class, "show"]);
Route::get("/users/{user}/files", [Files::class, "index"]);
Route::get("/files/{file}", [Files::class, "show"]);
And then in your controller methods, you're simply returning a list or a single item, mostly as in your original code. Note if you're returning API data, you should explicitly return JSON.
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\File;
class Files extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\JsonResponse
*/
public function index(User $user)
{
return response()->json($user->files);
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\JsonResponse
*/
public function show(File $file)
{
return response()->json($file);
// or perhaps something like this?
return response()
->download($file->path, $file->name, ["Content-Type" => $file->type]);
}
}
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
class Users extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\JsonResponse
*/
public function index()
{
return response()->json(User::all());
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\JsonResponse
*/
public function show(User $user)
{
return response()->json($user);
}
}

Laravel error Column not found

Error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'products.id' in 'where clause' (SQL: select * from products where products.id = 1 limit 1)
I do have table 'products' with a 'product.id' field. Not sure why I am getting this error. I get this error when I
access /product/{{product_id}}
access /edit
Home Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
return view('home')->with('products',$user->products);
}
}
ProductController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\product;
class productController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth',['except' => ['index','show']]);
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$products = product::orderBy('created_at','desc')->paginate(10);
//$products = product::where('type','major')->get();
return view('products.index')->with('products',$products);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('products.create');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate($request,[
'title' => 'required',
]);
//create product
$product = new product;
$product->title = $request->input('title');
$product->venue = $request->input('venue');
$product->city = $request->input('city');
$product->country = $request->input('country');
$product->description = $request->input('description');
$product->date = $request->input('date');
$product->user_id = auth()->user()->id;
$product->save();
return redirect('/products')->with('success','product Created');
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$product = product::find($id);
return view('products.show');
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
$product = product::find($id);
return view('products.edit')->with('product',$product);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$this->validate($request, [
'title' => 'required'
]);
$product = product::find($id);
$product->title = $request->input('title');
$product->save();
return redirect('/products')->with('success','product updated');
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
$product = product::find($id);
$product->delete();
return redirect('/products')->with('success','product deleted');
}
}
Show.blade.php
#extends('layouts.app')
#section('content')
<div class="container">
<h1 class="centre">{{$product->title}}</h1>
<div class="well-xs">
#if(!Auth::guest())
#if(Auth::user()->id == $product->user_id)
Edit
{!!Form::open(['action' => ['productcontroller#destroy', $product->product_id], 'method' => 'POST'])!!}
{{Form::hidden('_method', 'DELETE')}}
{{Form::submit('Delete', ['class' => 'btn btn-danger'])}}
{!!Form::close()!!}
#endif
#endif
</div>
<div>
<div>
<h4>product Date: {{$product->date}}</h4>
<h4>product Venue: {{$product->venue}}</h4>
<h4>product Location:{{$product->city}}</h4>
<h4>product Description: </h4>
<p>{{$product->description}} </p>
</div>
</div>
<hr>
Written on
</hr>
</div>
#endsection
Products table schema: I added user_id manually in sql. migrate wasnt working when I tried making a separate migration to add_user_id_to_table
{
Schema::create('products', function (Blueprint $table) {
$table->increments('product_id');
$table->string('title',200);
$table->string('venue',200);
$table->text('city',200);
$table->text('country',200);
$table->string('description');
$table->date('date',200);
$table->timestamps();
});
}
user.php model:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function products(){
return $this->hasMany('App\Product');
}
}
Product.php model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
//Table NAME
protected $table = 'products';
//PRIMARY KEY
public $primaryKey = 'id';
//Timestamps
public $timestamps =true;
public function user(){
return $this->belongsTo('App\User');
}
}
When you modify your migrations, you still need to update the database. So you should try
php artisan migrate:fresh
That will erase your database and migrate it again
Also, you don't need to query for the current user in your controller
Instead of this:
public function index()
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
return view('home')->with('products',$user->products);
}
You can simply use:
public function index()
{
return view('home')->with('products', auth()->user()->products);
}
EDIT:
Your products migration doesn't have a column called id defined but product_id instead.
Also, you're declaring a belongsTo relation in product to user while you don't have the id of the user on that table.
A relation belongsTo means that you have the id of the related model. For example
class User extends Model
{
public function posts()
{
return $this->hasMany(App\Post::class);
}
}
class Post extends Model
{
public function user()
{
return $this-belongsTo(App\User::class);
}
}
This is possible because posts table has a field called user_id. Because a Post belongs to a user.
You don't need this code:
//Table NAME
protected $table = 'products';
//PRIMARY KEY
public $primaryKey = 'id';
//Timestamps
public $timestamps =true;
Laravel handle all of that automatically, you're defining the default values
Change in your User model
public function products(){
return $this->hasMany("App\Product","product_id","product_id");
//return $this->hasMany("App\Product","foreign_key","local_key");
}

Stuck with Custom Pivot Model on belongsToMany relationship on Laravel 5.4

I'm trying to figure out how to implement a many to many relationship with a custom intermediate model (pivot table). This is my model:
banners
- id
- title
- description
banner_regions (Pivot)
- id
- region_id
- banner_id
- active
regions
- id
- name
- slug
Eloquent Models code:
class Banner extends Model
{
/**
* Get all of the regions for the banner.
*/
public function regions()
{
return $this->belongsToMany('App\Region', 'banner_regions')
->withPivot('active')
->using(BannerRegion::class);
}
}
class BannerRegion extends Model
{
}
class Region extends Model
{
/**
* Get all of the banners for the region.
*/
public function banners()
{
return $this->belongsToMany('App\Banner', 'banner_regions')
->withPivot('active')
->using(BannerRegion::class);
}
}
Banner Controller code:
class BannerController extends Controller
{
protected $model;
public function __construct(Banner $model)
{
$this->model = $model;
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$region = $request->region; // region model instance
// ??
}
}
So, my question here is how to retrieve the banners for a particular region?
SOLUTION
I've changed my code and now it works as expected.
I changed BannerRegion pivot model to be Pivot instead of Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class BannerRegion extends Pivot
{
// It is just for casting int values into boolean values.
// Useful for JSON responses.
protected $casts = [
'active' => 'boolean',
'for_customers' => 'boolean',
];
}
Banner Model. Nothing to add here, but I've made some changes in order to improve the JSON response, like $appends.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Banner extends Model
{
protected $hidden = ['id', 'regions'];
// Add data from the pivot model
protected $appends = ['for_customers'];
public function getForCustomersAttribute()
{
// Get the attribute 'for_customers' from the pivot model
return $this->regions
->keyBy('pivot.banner_id')
->get($this->id)
->pivot
->for_customers;
}
/**
* Get all of the regions for the banner.
*
*/
public function regions()
{
return $this->belongsToMany('App\Region', 'banner_regions')
->withPivot('for_customers', 'active')
->using('App\BannerRegion');
}
/**
* Scope a query to only include active banners for a specific region.
*
* #param \Illuminate\Database\Eloquent\Builder $query
* #param App\Region $region
* #return \Illuminate\Database\Eloquent\Builder
*/
public function scopeFindbyRegionAndActive($query, Region $region)
{
return $query->whereHas('regions', function($query) use ($region) {
return $query->whereRegionId($region->id)->whereActive(true);
});
}
}
In my Banner controller, I just added:
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Region $region)
{
return $this->model->findbyRegionAndActive($region)->get();
}
Region param is resolved by Dependency Injection (laravel.com/docs/5.4/routing#route-model-binding).
Finally, my route:
Route::group(['prefix' => '/regions/{region}'], function()
{
// Banners
Route::resource('banners', 'BannerController', ['only' => 'index']);
});
The endpoint:
/regions/my-region/banners
The JSON response:
[
{
"title": "a title...",
"description": "a descritpion...",
"link": "http://localhost",
"for_customers": true
}
]

Laravel : send pivot tables data in view

I'm new to Laravel 5 and I have some difficulties with pivot tables, controllers and repositories.
I have the tables 'users', 'sites', 'site_user', and here is what I have now :
App\Models\User
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
protected $table = 'users';
public function sites()
{
return $this->belongsToMany('App\Models\Site')
->withPivot('site_id', 'user_id', 'relation');
}
}
App\Models\Site
class Site extends Model {
protected $table = 'sites';
public function user()
{
return $this->belongsToMany('App\Models\User')
->withPivot('site_id', 'user_id', 'relation');
}
}
App\Repositories\SiteRepository
<?php namespace App\Repositories;
use App\Models\Site, App\Models\User;
class SiteRepository extends BaseRepository
{
/**
* The User instance.
*
* #var App\Models\User
*/
protected $user;
/**
* Create a new SiteRepository instance.
*
* #param App\Models\Site $site
* #return void
*/
public function __construct (Site $sites, User $user)
{
$this->model = $sites;
$this->user = $user;
}
/**
* Get sites collection paginate.
*
* #param int $n
* #return Illuminate\Support\Collection
*/
public function index($n)
{
return $this->model
->latest()
->paginate($n);
}
App\Http\Controllers\SiteController
<?php namespace App\Http\Controllers;
use App\Repositories\SiteRepository;
use App\Repositories\UserRepository;
use App\Http\Requests\SiteCreateRequest;
use App\Http\Requests\SiteUpdateRequest;
use App\Models\Site;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class SiteController extends Controller {
/**
* The SiteRepository instance.
*
* #var App\Repositories\SiteRepository
*/
protected $site_gestion;
/**
* The UserRepository instance.
*
* #var App\Repositories\UserRepository
*/
protected $user_gestion;
/**
* Create a new SiteController instance.
*
* #param App\Repositories\SiteRepository $site_gestion
* #param App\Repositories\UserRepository $user_gestion
* #return void
*/
public function __construct (SiteRepository $site_gestion, UserRepository $user_gestion)
{
$this->site_gestion = $site_gestion;
$this->user_gestion = $user_gestion;
$this->middleware('admin');
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index(SiteRepository $site_gestion)
{
//$counts = $this->site_gestion->counts();
$sites = $site_gestion->index(25);
$links = $sites->render();
return view('back.sites.index', compact('sites'));
}
views\back\sites\table.blade.php
#foreach ($sites as $site)
[...some code...]
#endforeach
What I want to do is to get all the sites of the logged in user. I've tried many things, but none of them are working. And I'm still not sure where to put the code, repository or controller...
I've read tutorials about pivot in Laravel, and I've tried with some things like this in the repo, but it doesn't work...
$user = $this->user->find(auth()->user()->id); //This line is working
foreach ($user->sites as $site) {
return $site
->latest()
->paginate($n);
}
If you want all sites of a logged user simply do it like this:
$sites = Auth::user()->sites;
That's all you need to do to get to these sites. If you want to use query and pagination try like this:
$sites = Auth::user()->sites()->latest()->paginate($n);
So what you've done seems pretty close.
So you pretty much have it, when iterating over the sites they should be instances of the site model.
$user = auth()->user(); // This is a way of saying your first line without a db query for the user
foreach ($user->sites as $site) {
// each site in here is a site model
$site->pivot->relation;
}
The only other thing that looks slightly strange is how you've defined the pivots. Generally when calling withPivot you wouldn't define the joining ids, if you wish to vary from the defaults you can pass it as an argument to the belongsToMany like so.
return $this->belongsToMany('App\Models\User', 'site_user', 'user_id', 'site_id')
->withPivot('relation');

Categories