I'm writing a sample ecommerce website with Laravel 5.
I have 2 Tables:
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('description');
$table->float('price');
$table->integer('category_id');
$table->timestamps();
});
and
Schema::create('featureds', function (Blueprint $table) {
$table->integer('product_id')->unique()->unsigned();
});
Schema::table('featureds', function($table) {
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
});
Models
class Product extends Model
{
public function category(){
return $this->belongsTo('App\Category');
}
}
class Featured extends Model
{
public function product(){
return $this->hasOne('App\Product', 'product_id');
}
}
Then, I have a Controller, where I take 4 featured products:
$featured_products = Featured::limit(4)->get();
return view('home', ['featured_products' => $featured_products]);
Now, I'm trying to show these featured products in my view. If i show the product_id from the Featured model, everything is ok:
#foreach($featured_products as $prod)
{{$prod->product_id}}
#endforeach
But I want to take the name of the product referred by the featured. I tried this way:
#foreach($featured_products as $prod)
#foreach($prod as $p)
{{$p->name}}
#endforeach
#endforeach
Because featured_products (in the controller) seems to be a collection, but it doesn't work!
In your Featured model, you have a relationship in method product() when you want to access the relation from the view, you could call the method name as property, in you case, you have a method named product() so you have to call product property like this:
#foreach($featured_products as $prod)
{{ $prod->product->name }}
#endforeach
It will automatically write the product name based on the relationship you have configured in the model.
Reference: https://laravel.com/docs/5.2/eloquent-relationships
Edit:
Sorry my bad, I guess you are defining a wrong relation, your Product model, should have a featured() method which uses hasOne relation, while Featured model should have a product() method using belongsTo relation. So in you App\Featured model, you have to define the relation like this:
return $this->belongsTo('App\Product');
And in your App\Product model you should define relation like so:
return $this->hasOne('App\Featured');
Hope it works
Related
I don't understand how to return info back to blade template if I have two related tables:
First table is standard Laravel 'users' table
Second table:
Schema::create('recipes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('code', 10);
$table->string('description');
$table->float('size');
$table->bigInteger('created_by')->unsigned();
$table->string('status')->default('pending');
$table->boolean('deleted');
$table->timestamps();
$table->foreign('created_by')
->references('id')
->on('users')
->onDelete('cascade');
}
Than I have two Controllers: User and Recipe
Recipe have
public function user()
{
return $this->belongsTo(\App\User::class);
}
and User have
public function recipes()
{
return $this->hasMany(\App\Recipe::class);
}
actual output looks like this (RecipesController):
$recipes = Recipe::latest()->paginate($perPage);
return view('admin.recipes.index', compact('recipes'));
everything looks OK but column created_by contain users primary key witch is integer. How can I display users name? This is something like inner join but is it possible to do that in eloquent? Or I completely misunderstanding those public functions in a Model?
Your user relationship in your Recipe model is missing the foreignKey:
public function user()
{
return $this->belongsTo(\App\User::class, 'created_by');
}
You can then eager load the users with your recipes in the controller:
$recipes = Recipe::with('user')->latest()->paginate($perPage);
return view('admin.recipes.index', compact('recipes'));
And finally you can access the user in the view:
#foreach($recipes as $recipe)
{{ $recipe->user->name }}
#endforeach
You can read more about the inverse of the one-to-many relationship in the docs.
Ok so I need to get data from the table this way but I would like to get
Vehicle Maker name too
I tried using join or
just doing auth()->user()->vehicles->VehicleMaker but it doesn't work
Migration of Table Vehicle
Schema::create('vehicles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id');
$table->bigInteger('category_id');
$table->bigInteger('vehicle_maker_id');
$table->string('name');
$table->double('price', 8 , 2);
$table->year('manufacture_year');
$table->bigInteger('mileage');
$table->string('vehicle_image');
$table->boolean('admin_verification')->nullable();
$table->timestamps();
});
Migration of vehicle_makers
Schema::create('vehicle_makers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Controller
public function show(){
$vehicles = auth()->user()->vehicles; -- what shoul i add here
return view('/home', [
'vehicles' => $vehicles
]);
}
Edit
I forget to mention that I already made a relationship and they work in artisan tinker when I try to do something like this:
Vehicles->find(1)->VehicleMaker
What I want is to do is
auth()->user()->vehicles and get vehicle teble with vahicle_maker name not id so some kind of join that would work in this case
Okay base on Laravel Model Relationship.
You first need to create a migration.
Vihicle Migration
Schema::create('vehicles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('category_id');
$table->unsignedBigInteger('vehicle_maker_id');
$table->string('name');
$table->double('price', 8 , 2);
$table->year('manufacture_year');
$table->bigInteger('mileage');
$table->string('vehicle_image');
$table->boolean('admin_verification')->nullable();
$table->timestamps();
});
I used unisignedBigInteger to determine it is a foreign key or you can also use index().
In your model you should place what relation ship you will use. In your case I assumed you are using One To Many Relationship. So that your user model should look like this:
User Model
...
public function vehicles() {
return $this->hasMany(Vehicle::class);
}
So that you can use the convention auth()->user()->vehicles;.
Note: the auth()->user()->vehicles; return a array of object you can loop it in foreach.
Vehicle Model
public function user() {
return $this->belongsTo(User::class);
}
In when you have this in your model you can use it 2 way.
In your controller you can call the relationship of those 2.
Controller
$vehicles = auth()->user()->vehicles;
dd($vehicles);
INFO
You can also refer to this tutorial.
EDIT
Controller
$vehicles = auth()->user()->vehicles();
foreach($vehicles as $vehicle) {
dd($vehicle->VehicleMaker);
}
Note: The $vehicles is returning an array of object. So you can loop it through foreach loop to throw a single instance.
There should be a relationship between the user and vehicles then another relationship between vehicles and vehicle_makers. If you already created your models(Vehicle, VehicleMaker) with their migrations, You can do the following
//add this to your User model.
public function vehicle(){
return this->belongsTo(App\Vehicle);
}
// add this to your Vehicle model
public function user(){
return this->hasMany(App\Vehicle); // implying that a user can have many vehicles
}
//add this to your vehicleMaker model
public function vehicle(){
return this->belongsTo(App\Vehicle);
}
When that is done, you can use Laravel's lazy loading to fetch relationships. You can do something like
$vehicles = auth()->user()->vehicle
return view('/home', [
'vehicles' => $vehicles
]);
I am reading laravel 5.2 docs to implement many to many polymorphic relation in my Laravel Application.
I have Many models like Blog, Question, Photo etc and I want to have Tagging system for all of them.
I have created Tag table with following schema
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('slug')->unique();
$table->timestamps();
});
Below is pivot table schema. Pivot table name is entity_tags
Schema::create('entity_tags', function (Blueprint $table) {
$table->increments('id');
$table->integer('tag_id')->unsigned();;
$table->integer('taggable_id')->unsigned();
$table->string('taggable_type');
$table->timestamps();
$table->index('tag_id');
$table->index('taggable_id');
$table->index('taggable_type');
});
This is the relationship defined in Tag model for Question model
public function questions()
{
return $this->belongsToMany('App\Question', 'entity_tags', 'tag_id', 'taggable_id');
}
And the following relation is defined in Question Model
public function tags()
{
return $this->belongsToMany('App\Tag', 'entity_tags', 'taggable_id', 'tag_id');
}
Now I want to define Many to Many Polymorphic relationship as defined in Laravel 5.2.
My Question are
how I can define them?
Should I remove the Many to Many
relationship and only define Many to Many polymorphic relationship ?
If yes, then how to manage custom pivot table name ?
Also is it required to suffix column name with word able that are part of
polymorphic relationship ?
Use return $this->morphToMany() instead of belongsToMany, and in the Tag model, write 3 methods with return $this->morphedByMany() for the reverse relationship.
You only need polymorphic definitions, no need for the many to many normal ones. The name of the pivot table is with 'able' at the end by the default convention but you can name it anything you want.
no, you don't have to have a word with 'able' at the end, it's just a way to define that it's something more general, you can name it anything you want.
Naming is based on some default convention by Laravel.
Update:
You have the following pivot table schema:
Schema::create('entity_tags', function (Blueprint $table) {
$table->increments('id');
$table->integer('tag_id')->unsigned();;
$table->integer('entity_id')->unsigned();
$table->string('entity_type');
$table->timestamps();
$table->index('tag_id');
$table->index('entity_id');
$table->index('entity_type');
});
and the tags table:
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('slug')->unique();
$table->timestamps();
});
So you want to create the relationships for blog, video and question tables / models:
Tag.php Model:
public function questions()
{
return $this->morphedByMany('App\Question', 'entity', 'entity_tags');
}
public function blogs()
{
return $this->morphedByMany('App\Blog', 'entity', 'entity_tags');
}
public function videos()
{
return $this->morphedByMany('App\Video', 'entity', 'entity_tags');
}
Question.php / Blog.php / Video.php
public function tags()
{
return $this->morphToMany('App\Tag', 'entity', 'entity_tags');
}
I am trying to grab an InvoiceDetails record and the matching Product record via the product foreign key.
This isn't working:
$r = InvoiceDetail::with('products')->find(52184)->toArray();
The 2 database calls are
SELECT * FROM `invoice_details` WHERE `id` = '52184' LIMIT 1
SELECT * FROM `products` WHERE `products`.`id` in ('0')
Where am I going wrong?
Table Structure of invoice details:
Schema::create('invoice_details', function (Blueprint $table) {
$table->increments('id');
$table->integer('invoice_id')->unsigned();
$table->integer('product_id')->unsigned();
$table->integer('quantity');
$table->foreign('product_id')->references('id')->on('products')->onDelete('restrict')->onUpdate('cascade');
$table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade')->onUpdate('cascade');
});
Table structure for Products:
Schema::create('products', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
});
Products Model:
class Product extends \Eloquent
{
public function products()
{
return $this->hasMany('InvoiceDetail');
}
}
Invoice Details Model:
class InvoiceDetail extends \Eloquent
{
public function details()
{
return $this->belongsTo('Invoice');
}
public function products()
{
return $this->belongsTo('Product');
}
}
Your relationships are weird. (Okay, that wasn't really any longer.)
Assuming that an Invoice can belong to many Products (with specific details about each such as quantity), and that a Product can belong to many Invoices, you have a classic pivot table scenario. In which case, you're doing extra work and making life more difficult for yourself than it has to be.
If that's the case, there are a few steps you can take to reduce your code and make life easier:
Remove the InvoiceDetails model. Laravel can handle pivot tables on its own pretty well. So unless you have something really custom that you need the pivot table model to handle, you don't need it.
Update your Product model. You have a products() method in the Product model. That doesn't really make any sense. Don't products belong to invoices? Let's fix that.
class Product extends Eloquent
{
public function invoices()
{
return $this->belongsToMany('Invoice', 'invoice_details', 'product_id', 'invoice_id');
}
}
The additional parameters indicate the pivot table name, the column name for the Product model identifier, and the column name for the Invoice model identifier, respectively.
Update your Invoice model. You didn't paste it here, but I'll assume it has a relationship for invoice details. If not, well, oops! Because an invoice can belong to many products, essentially the inverse of the products relationship we just defined, it's defined it pretty much the exact same way.
class Invoice extends Eloquent
{
public function products()
{
return $this->belongsToMany('Product', 'invoice_details', 'invoice_id', 'product_id');
}
}
You now have a many-to-many relationship between Products and Invoices, that is retrieved using intuitive relationship methods! Huzzah.
Hey wait, where's my quantity?
You'll have to figure that one out on your own. :)
Got the answer (there is 2 hours of my life I'm never getting back) I had to manually add the fk and pk. So in my InvoiceDetails model it should have looked like this
public function products()
{
return $this->belongsTo('Product', 'product_id', 'id');
}
// models:
class Hometype extends Eloquent {
public function development() {
return $this->belongsTo('Development');
}
}
class Development extends Eloquent {
public function hometypes() {
return $this->hasMany('Hometype', 'dev_id');
}
}
with that, I can do:
// controller:
$development = Development::where('stuff')->first();
// view:
#foreach ($development->hometypes as $hometype)
{{ $hometype->stuff }}
#endforeach
which is perfectly lovely.
but I can't seem to do:
// controller:
$hometype = Hometype::where('stuff')->first();
// view:
{{ $hometype->development->stuff }} // <- fails
How do I access a field on the parent Development model from within $hometype?
I'm resorting to:
'development' => Development::find($hometype->dev_id),
which seems silly.
Possible duplicate of: Laravel 4 - Can't retrieve data in a one-to-many relationship, but I'm not camelCasing...
Also similar to: Laravel 4 hasOne / belongsTo relationship (no answers here)
As I can see, there might be two problems:
The foreign key in Hometype is wrong (if you're using a different column name than "column"_id then you have to specify it)
You might be fetching a Hometype record whose development row doesn't exist
Accessing data and methods between hasMany and belongsTo
First get required models and then loop through
These are the model:
class ExpenseCategory extends Model
public function expense_transactions()
{
return $this->hasMany('App\ExpenseTransaction');
}
class ExpenseTransaction extends Model
public function expense_category()
{
return $this->belongsTo('App\ExpenseCategory');
}
Schema for the above model:
Schema::create('expense_transactions', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('expense_category_id')->nullable();
$table->unsignedInteger('day_sheet_id')->nullable();
$table->string('expense_title')->nullable();
$table->unsignedInteger('amount');
$table->timestamps();
$table->foreign('expense_category_id')
->references('id')->on('expense_categories')
->onDelete('cascade');
$table->foreign('day_sheet_id')
->references('id')->on('day_sheets')
->onDelete('cascade');
Schema for category:
Schema::create('expense_categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
find only expense transactions for day sheet id in model
$expenseTransactions = ExpenseTransaction::where('day_sheet_id', $id)->get();
show their category name
access in blade:
in a foreach loop
#foreach($expense_transactions as $expense_transaction)
{{ $expense_transaction->expense_category->name }}