What am I trying?
Get a particular category and it's associated Sub Categories
Category Model
class Category_Model extends Model
{
protected $table = "tblcategory";
protected $primaryKey = "CategoryID";
public $timestamps = false;
public function Subcategories()
{
return $this->hasMany('\App\Models\Skill\SubCategory_Model');
}
}
Sub Category Model
class SubCategory_Model extends Model
{
protected $table = "tblsubcategory";
protected $primaryKey = "SubCategoryID";
public $timestamps = false;
}
Action Method
public function SubCategories($category)
{
$Categories = \App\Models\Skill\Category_Model
::where("Category", "=", $category)
->Subcategories;
dd($Categories);
}
When I run the code. I get below error
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'tblsubcategory.category__model_id' in 'where clause' (SQL: select *
from tblsubcategory where tblsubcategory.category__model_id = 1
and tblsubcategory.category__model_id is not null)
From the comments, it is most likely that your subcategory table doesn't have a category_model_id but likely a category_id. By default, Laravel tries to extrapolate the name of the foreign column from the model name (in this case Category_Model, which explains the category_model_id. Changing the class to:
class Category_Model extends Model
{
protected $table = "tblcategory";
protected $primaryKey = "CategoryID";
public $timestamps = false;
public function Subcategories()
{
return $this->hasMany('\App\Models\Skill\SubCategory_Model', 'category_id')->get(); // Or whatever the column is actually called
}
}
should solve the issue.
To return both the category object and its subcategories, change the action code to:
public function SubCategories($category)
{
$Categories = \App\Models\Skill\Category_Model
::where("Category", "=", $category)
->with("Subcategories")
->first();
dd($Categories);
}
The $Categories should also now contain a Subcategories object, accessed via $Categories->Subcategories, which should return a collection of Subcategory objects. If you wanted to see each one, you would loop through with a foreach
foreach($Categories->Subcategories AS $Subcategory){
echo $Subcategory->name;
// etc etc.
}
Related
I'm trying to create a league table in Laravel but I'm running into some issues with guess what, relationships, again. They never seem to work for me in Laravel. It's like they hate me.
I have a modal for matches
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Match extends Model
{
protected $primaryKey = 'id';
protected $table = 'matches';
public $timestamps = false;
protected $guarded = ['id'];
}
And a modal for teams, but with a matches() function
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
protected $primaryKey = 'id';
protected $table = 'teams';
public $timestamps = false;
protected $guarded = ['id'];
public function matches() {
return $this->hasMany('App\Database\Match', 'team_one_id, team_two_id');
}
}
I think the issue comes with team_one_id, team_two_id as the teams primary key could be in either one of them columns for the other table. When calling count() on matches() it throws an error.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'matches.team_one_id, team_two_id' in 'where clause' (SQL: select count(*) as aggregate from matches where matches.team_one_id, team_two_id = 1 and matches.team_one_id, team_two_id is not null)
can you try this syntax
return $this->hasMany('modelPath', 'foreign_key', 'local_key');
Does Match table have a column maned 'team_id'?
because it's the default naming convention in the laravel docs for mapping the tables.
if you do have the column and populate the data you can just remove the foreign & local keys from matches() relationship. you don't need it. Laravel will automatically map it for you.
if you do not have the 'team_id' on Matches table please add the column and add the respective team ids for matches.
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
protected $primaryKey = 'id';
protected $table = 'teams';
public $timestamps = false;
protected $guarded = ['id'];
public function matches() {
return $this->hasMany('App\Database\Match');
}
}
This way you can implement it, Add these relationship and a method in Team Model
public function homeMatches() {
return $this->hasMany('App\Database\Match', 'team_one_id');
}
public function awayMatches() {
return $this->hasMany('App\Database\Match', 'team_two_id');
}
public function matches() {
return $this->homeMatches->merge($this->awayMatches);
}
Now Fetch the data
$team = Team::find(1);
$matches = $team->matches(); //now it will fetch all matches for both columns
If you want to fetch matches as attributes then you can add one method
in your Team model
public function getMatchesAttribute()
{
return $this->homeMatches->merge($this->awayMatches);
}
Now you can fetch the matches as $matches = $team->matches;
Here is the difference
$team->matches returns Illuminate\Database\Eloquent\Collection
And
$team->matches() returns Illuminate\Database\Eloquent\Relations\{Relation Name}
You can't use matches in Eager loading like Team::with('matches') because matches is not a relationship and that causing your Error. What you can do is add homeMatches and awayMatches in eager loading and then call $team->matches().
$teams = Team::with('homeMatches', 'awayMatches')->get();
$teams->each(function ($team) {
print_r($team);
print_r($team->matches());
});
I have one table named Content which is a master table like
Content : id content_name created_at updated_at
and another table Course like
Course table have many content_id
Course : id content_id course_name created_at updated_at
I have created relation like this.
Content Model
class Content extends Eloquent {
protected $table = 'contents';
protected $guarded = array('id');
public function course()
{
return $this->belongsTo('Course');
}
}
Course Model
class Course extends Eloquent {
protected $table = 'courses';
protected $guarded = array('id');
public function content()
{
return $this->hasMany('Content');
}
}
When i am fething the data like this
$courses=Course::find(1)->content;
It throws error like
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'contents.course_id' in 'where clause' (SQL: select * from contents where contents.course_id = 1)
I am unable to rectify the problem in relations as I am new to laravel.
Close, but you have your relationships backwards. The table that has the foreign key is the one that belongsTo the other one. In this case, your course table has the foreign key content_id, therefore Course belongs to Content, and Content has one or many Courses.
class Content extends Eloquent {
public function course() {
return $this->hasMany('Course');
}
}
class Course extends Eloquent {
public function content() {
return $this->belongsTo('Content');
}
}
in your migrations(create_courses_table) , make sure to set the foreign key like that ,
$table->integer('content_id)->unsigned()->index();
$table->foreign('content_id')
->references('id')
->on('contents')
->onDelete('cascade');
I don't really understand your table design, maybe it should be something like this.
Taking your statement: "Course table have many content_id". I perceive that you are saying that 1 course can have multiple content, is that right? If yes, you might want to change your table design to something like below
Course
======
id
course_name
created_at
updated_at
Content
=======
id
course_id (set this as FK)
content_name
created_at
updated_at
migration code for content
public function up()
{
Schema::create('content', function(Blueprint $table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('course_id')->unsigned();
$table->string('content_name');
});
Schema::table('content',function($table)
{
$table->foreign('course_id')->references('id')->on('course')->onDelete('cascade');
});
}
Then in your model
class Course extends Eloquent
{
protected $table = 'course';
public function content()
{
return $this->hasMany('content', 'course_id', 'id');
}
}
class Content extends Eloquent
{
protected $table = 'content';
public function course()
{
return $this->belongsTo('course', 'course_id', 'id');
}
}
Then to access your data via eager loading
$course = Course::with('content')->get();
OR
$content = Content::with('course')->get();
This is about determining associations. Your associations should be:
Content
Content has many courses
class Content extends Eloquent {
protected $table = 'contents';
protected $guarded = array('id');
public function courses()
{
return $this->hasMany('Course');
}
}
Course
The course belongs to content.
class Course extends Eloquent {
protected $table = 'courses';
protected $guarded = array('id');
public function content()
{
return $this->belongsTo('Content');
}
}
So you can do query association.
For finding content -> courses:
$courses = Content::find(1)->courses;
For finding course -> content:
$content = Course::find(1)->content;
I am setting up two Models. Let's assume we have a portfolio and portfolio_category table
Table portfolio
id
cat_id
name
status
Table portfolio_category
cat_id
cat_name
Model
class Portfolio extends \Eloquent {
protected $fillable = [];
public function portfolio_category()
{
return $this->hasMany('Portfolio_category');
}
}
class Portfolio_category extends \Eloquent {
protected $fillable = [];
public function portfolio()
{
return $this->belongsTo('Portfolio');
}
}
My code:
$data = Portfolio::all();
foreach($data as $value){
$id = $value['id'];
$name = $value['name'];
$cat_name = $value['cat_name'];
}
I want to display category name but it shows null values.
I am pretty confused, what went wrong? any idea!!!
I got my answer
$data = Portfolio::join('portfolio_category', 'portfolio_category.cat_id', '=', 'portfolio.cat_id')->get();
foreach($data as $value){
$id = $value['id'];
$name = $value['name'];
$cat_name = $value['cat_name'];
}
Your relationships are not defined correctly. In your code, you've tried to define the Portfolio as the parent, and the Portfolio_category as the child. However, your tables are setup such that the Portfolio_category is the parent and the Portfolio is the child. Basically, the table that contains the foreign key (portfolio table has foreign key to portfolio_category) should be on the belongsTo side.
So, instead of portfolio hasMany portfolio_category and portfolio_category belongsTo portfolio, it needs to be switched to portfolio_category hasMany portfolio and portfolio belongsTo portfolio_category.
Additionally, I'm assuming these were removed for brevity, but the table names and the primary key on your portfolio_category table do not conform to Laravel conventions, so you need to specify these properties in the model.
Your models should look like:
class Portfolio extends \Eloquent {
protected $table = 'portfolio';
protected $fillable = [];
public function portfolio_category()
{
return $this->belongsTo('Portfolio_category');
}
}
class Portfolio_category extends \Eloquent {
protected $table = 'portfolio_category';
protected $primaryKey = 'cat_id';
protected $fillable = [];
public function portfolios()
{
return $this->hasMany('Portfolio');
}
}
Now you can access the related tables through the relationships:
$data = Portfolio::with('portfolio_category')->get();
foreach($data as $value){
$id = $value->id;
$name = $value->name;
$cat_name = $value->portfolio_category->cat_name;
}
For more on the Eloquent ORM, the documentation can be found here (L4.2) or here (L5.0).
I'm having trouble figuring out how to access a nested relationship within Laravel. The specific example I have is a Movie that has many entires in my Cast table which has one entry in my People table. These are my models:
MOVIE
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
MOVIECAST
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public function person()
{
return $this->hasOne('Person', 'person_id');
}
public function netflix()
{
return $this->belongsTo('Movie', 'movie_id');
}
}
PERSON
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}
In my controller I can access the cast (containing person_id and role_id) like so:
public function movie($id)
{
$movie = Movie::find($id);
$cast = $movie->cast();
return View::make('movie')->with(array(
'movie' => $movie,
'cast' => $cast
));
}
...but I don't know how to access the corresponding name field in my People table.
EDIT 1:
Using the classes exactly as defined below in #msturdy's answer, with the controller method above I try to render the person names like so inside my view:
#foreach($cast->person as $cast_member)
{{$cast_member->person->name}}
#endforeach
Doing this i get the error:
Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$person
I don't know if it makes a difference or not but I have no id field on my People table. person_id is the primary key.
It should be simple, once you have accessed the cast...
Route::get('movies', function()
{
$movie = Movie::find(1);
$cast = $movie->cast;
return View::make('movies')->with(array(
'movie' => $movie,
'cast' => $cast));
});
Note: at this point, $cast is an instance of the Collection class, not a single object of the MovieCast class, as the
relationship is defined with hasMany()
you can iterate over it in the View (in my case /app/views/movies.blade.php
#foreach($cast as $cast_member)
<p>{{ $cast_member->person->name }}</p>
#endforeach
Class definitions used for testing:
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
public $timestamps = false;
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public $timestamps = false;
public function person()
{
return $this->hasOne('Person', 'person_id');
}
}
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public $timestamps = false;
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}
I have three tables: Products, Company, Type. Company and Types has one-to-many relationship with Products.
[type model]
class Type extends BaseModel {
public static $table = "type";
public static $timestamps = true;
public function products() {
return $this->has_many('Products');
}
}
[company model]
class Company extends BaseModel {
public static $table = "company";
public static $timestamps = true;
public function products() {
return $this->has_many('Products');
}
}
[products model]
class Products extends BaseModel {
public static $table = 'products';
public static $timestamps = true;
public function company() {
return $this->belongs_to('Company');
}
public function type() {
return $this->belongs_to('Type');
}
}
In add_product route i have
$product = new Products($new_product);
$company_id = $all_posts['company_id'];
$company = Company::find($company_id);
$company->products()->save($product);
$type_id = $all_posts['type'];
$type = Type::find($type_id);
$type->products()->save($product);
but when I try to insert data to db i get:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '11' for key 'PRIMARY'
How do I update both type_id and company_id in Products table?
If I am not wrong, your products table should have product_id and type_id columns ? Just specify these values:
$new_product['company_id'] = $all_posts['company_id'];
$new_product['type_id'] = $all_posts['type'];
$product = new Products($new_product);
$product->save();
You don't need to use Company and Type model to make relationship between them and a product. You can simply fill the ids.