Laravel model referencing wrong table in query - mysql

I am sure this is because of the eloquent, but the query is using the wrong table in SELECT.
here my model:
class Subcategory extends Model
{
public function subcategory()
{
return $this->belongsTo(Category::class);
}
}
and here is my Controller:
class SubcategoriesController extends Controller
{
public function index()
{
$subcategories = Subcategory::all();
return view('pages.subcategories', compact('subcategories'));
}
}
and finally here my error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'developmnet.site.subcategories' doesn't exist (SQL: select * from `subcategories` where `category_slug` = budgets limit 1)
as you can see from the error the table referenced in the query is subcategories when it should be categories table.
My question is how to reference the correct table in this model as I already have one for my main categories and it is working just fine.

To overwrite the table name of a model you can define the protected $table property. In Your case:
class Subcategory extends Model
{
protected $table = 'categories';
// ..
}
If you don't do that, Laravel will derive the table name from the class name. In your case: Subcategory => subcategories.

Related

Query multiple table relationships using Laravel Eloquent Models

I'm trying to query multiple tables using Laravel Eloquent Models with one to one, one to many and many to many relationships.
I have a forms table, a brands table a users table and a brand_groups pivot table.
Each form has one brand and one user:
forms
ID
user_id
brand_id
Brands do not have any foreign keys:
brands
ID
Users do not have any foreign keys:
users
ID
And there is a pivot table to create a many to many relationship for creating brand groups that have many users like brand members:
brand_groups
brand_id
user_id
I'm trying to get all the forms that belong to a user either by a direct ownership (forms.user_id) or by brand membership, all the forms from all the brands that the user is a member through brand_groups many to many pivot table.
For example, we have 2 brands, 2 users and 1 user is a member of 1 brand:
brand(ID: 1)
brand(ID: 2)
user(ID: 1)
user(ID: 2)
brand_group(brand_id: 1, user_id: 1)
form(ID: 1, user_id: 1, brand_id: null)
form(ID: 2, user_id: null, brand_id: 1)
form(ID: 3, user_id: 2, brand_id: 1)
form(ID: 4, user_id: 1, brand_id: 2)
Using Laravel Eloquent Models (not direct DB facade calls), I'd like to retrieve all the forms that belong to a user. For the user(ID:1) there are 3 forms:
form(ID:1) direct user ownership
form(ID:2) user is a member of brand(ID:1) group which is the brand of form(ID:2)
form(ID:3) user is a member of brand(ID:1) group which is the brand of form(ID:3)
I gave it a shot using Eloquent: Relationships - Has Many Through:
Has Many Through
The "has-many-through" relationship provides a convenient way to access distant relations via an intermediate relation.
I have tried it like this:
class User extends Model
{
public function forms()
{
return Forms::hasManyThrough(
Form::class,
BrandGroups::class,
'brand_id',
'brand_id',
'id',
'form_id',
)->where('id', $this->id);
}
}
But I get errors like:
BadMethodCallException with message 'Call to undefined method App\Models\Form::brand_groups()'
EDIT
After some digging, I have managed to come up with the working MySQL code that will return all the forms for a user:
SELECT * FROM `forms`
WHERE EXISTS (
SELECT `brand_id`, `user_id`
FROM `brand_groups`
WHERE `forms`.`brand_id` = `brand_groups`.`brand_id`
AND `brand_groups`.`user_id` = 1
) OR `forms`.`user_id` = 1
Now I just need to convert that query to an eloquent model relation.
Eloquent Models
User.php
class User extends Authenticatable implements MustVerifyEmail
{
public function brands()
{
return $this
->belongsToMany(Brand::class, 'brand_groups')
->using(BrandGroups::class)
->as('member');
}
public function forms()
{
return $this->hasMany(Form::class, 'user_id');
}
}
Brand.php
class Brand extends Model
{
protected $table = 'brands';
public function forms()
{
return $this->hasMany(Form::class);
}
public function members()
{
return $this
->belongsToMany(User::class, 'brand_groups')
->using(BrandGroups::class)
->as('member');
}
}
Form.php
class Form extends Model
{
protected $table = 'forms';
public function owner()
{
return $this->belongsTo(User::class);
}
public function brand()
{
return $this->belongsTo(Brand::class);
}
}
UPDATE
I manage to find a query to get all forms related to a user like this:
class User extends Authenticatable implements MustVerifyEmail
{
...
public function allForms()
{
return Form::where(function ($q) {
$q->whereExists(function ($q) {
$q->from('brand_groups')
->where('forms.brand_id', DB::raw('brand_groups.brand_id'))
->where('brand_groups.user_id', $this->id);
})->orWhere('owner_id', $this->id);
});
}
}
How this can be converted to a direct User model eloquent relationship?
Have you tried to Eager Load the User model relationships?
Edit
Firstly: the pivot table name should be the singular -snake_case- name of both tables and should be in alphabetical order (brand_user)
Next, try the following:
return User::where(‘id’, $this->id)->with([‘forms’,‘brands.forms’)->get();
This should return the Forms with direct ownership plus the user Brands and their associated Forms

problem with Using pivot table with Eloquent and Laravel

Here is my problem. I have a table called user and table called skills, also I have a pivot table that connects these two called EmployeeSkill. I am trying to fetch the skills that belong to the user but when i use tinker it returns Base table or view not found: 1146 Table 'pfe_sirh_db.skill_user' doesn't exist (SQL: select skills.*, skill_user.user_id as pivot_user_id, skill_user.skill_id as pivot_skill_id, skill_user.employee_id as pivot_employee_id from skills inner join skill_user on skills.id = skill_user.skill_id where skill_user.user_id = 1)' and am using swagger by the way it returns this "withTimestamps": false
class User extends Authenticatable{
protected $table = "users";
public function skills()
{
return $this->belongsToMany(Skill::class);
}
}
and
class Skill extends Model
{
public function User()
{
return $this->belongsToMany(User::class);
}
}
and the pivot table
class EmployeeSkill extends Model
{
protected $table = "employee_skills";
protected $fillable = [
'employee_id', 'skill_id', 'note'
];
}
Your pivot table should be named skill_user (singular) following the model name they belong to. And you don't need a EmployeeSkill model for this relation to work, you only need the table.
As said in the documentation:
to determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method
And then you should exclude this line:
protected $table = "employee_skills";
change your table name to skill_user
And in your pivot table you should use user_id as a foreign key
You can retrieve all skills from a user by doing this:
$user = User::find(1);
$user->skills();
This will give you all the skills from the user with the id 1
Be aware that you can use any table name and any foreign key name but if you do that you need to specify the names on the relations. So i recommend you doing what i 've told you, since is the standard way

Access non associated tables in cakephp3 controller

I am a newbie to cakephp3, I am trying to access a "table A" which is not linked to "table B" in the controller of table 2
I want to user category table in UsersController. How to achieve that?
e.g.
user table has three fields id, name, role
category table has 2 fields id, name
articles table has 3 fields id, user_id, category_id, article
In your controller you can use loadModel() to load another table that is not linked to your controller's default model.
class UsersController extends AppController {
public function initialize() {
parent::initialize();
// You don't have to put it in initiliaze
// but if you want to use it in more than one method it's a good place
$this->loadModel('Categories');
$this->loadModel('Articles');
}
public function index() {
// Categories is now available as $this->Categories thanks to loadModel()
$categories = $this->Categories->find()->select(['id', 'name']);
}
}

Category relationship is giving error when I try to acces category through post

When I try to access articles vie category it works properly here is category.php model
public function articles(){
return $this->belongsToMany('App\Article');
}
but when I try to access category name view article it doesn't work as it's supposed to, I made I mistake there and trying to fix it, but no luck so far. here is the Article model
public function category(){
return $this->hasOne('App\category');
}
and there is a table for relation those two to each others it's called article_category in page where I get all articles for the given tag, I want to do something like $article->category->name there is something sound very wrong to me but I can't figure it out.
The error I'm receiving is
Column not found: 1054 Unknown column 'category.article_id' in 'where clause' (SQL: select * from category where category.article_id = 1 and category.article_id is not null limit 1) (View: C:\wamp64\www\loremipsum\bluhbluhbluh\articleByTag.blade.php)
Btw the way I save the relationship for the article_category when an article is created is
$article->category()->sync($request->category, false);
You've said that article might have only one category. In this case, delete pivot table and add category_id into the articles table.
Then in the Article model define this relationship:
public function category()
{
return $this->belongsTo(Category::class);
}
And in the Category model:
public function articles()
{
return $this->hasMany(Article::class);
}
When you'll do that, you'll be able to access article's category with:
$article->category->name
You have the relationship established incorrectly. Remove the intermediate table and add category_id to the articles table.
Relationships are not set correctly
Category model should be like :
class Category extends Model
{
protected $table='category';
//give me all articles associated with the given category
public function articles()
{
return $this->hasMany('App\Article');
}
}
And Article model
class Article extends Model
{
protected $table='article';
//get the category associated with the given article
public function category()
{
return $this->belongsTo('App\Category');
}
}
for attaching articles to a category:
$article->category()->associate($category)->save();

Joining Two Tables to a Reference Table Laravel

I Have three tables
#1 Table timeline which is my reference table with an Auto incremented ID which is stored in column id
#2 timeline_videos
#3 timeline_else
What happens is on post if a video is uploaded with the post
it will go into Table #2 ,anything else goes into Table #3.
#2-3 have the Auto Increment Id from the Table timeline stored in a column pid
On query of The Timeline I need to join both tables data using id=pid
so I can use the rest of the Relational Data with the post.
I have done a bit of research and can't seem to find a method for doing so.
So far the code I have
Controller
$groupposts = timeline::where([
['owner','=',$owner],['id','<',$lastid],
])
->join('timeline_videos','timeline.id','=','timeline_videos.pid')
//->join('timeline_else','timeline.id','=','timeline_else.pid')
->orderBy('id','desc')
->limit(5)
->get();
This works with no errors with the second Join commented out but I need to also grab the timeline_else data .
Update --
I have now decided to use Eloquent Relationships to join the tables,
my question now is what type of relationship do I have between the
tables?
I realize it basically needs to be able to switch between two tables to
grab data based on the fact that timeline_videos and timeline_else will not be "JOIN" but separated by type .
The tables need to Join with table #1 timeline based on a column I now have named type for clarifying where to look and matching/joining using the id = pid
You can use relationships.
it sounds like timelines has many videos and has many video failures
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many
you would have a model for each table and set up the relationships
timelines model:
public function videos()
{
return $this-> hasMany('App\Videos');
}
public function videoFailures()
{
return $this-> hasMany('App\videoFailures');
}
videos model:
public function timeline()
{
return $this->belongsTo('App\Timelines');
}
videos failures model:
public function timeline()
{
return $this->belongsTo('App\Timelines');
}
You can then go:
$timeLine = Timmeline::find($id);
to find videos of the time lines you would do:
$videos = $timeLine->videos();
to find else:
$videoElse = $timeLine-> videoFailures();
By using some of what Parker Dell supplied and a bit more trial and error
My Models Looks like
timeline
class timeline extends Model
{
protected $table ='timeline';
public $timestamps = false;
public function videos()
{
return $this->hasMany('App\timeline_videos','pid','id');
}
public function else()
{
return $this->hasMany('App\timeline_ect','pid','id');
}
}
timeline_ect.php ,I changed the name of the table
class timeline_ect extends Model
{
protected $table='timeline_ect';
public $timestamps = false;
public function timeline()
{
return $this->belongsTo('App\Models\timeline','pid','id');
}
}
timeline_videos
class timeline_videos extends Model
{
protected $table='timeline_videos';
public $timestamps = false;
public function timeline()
{
return $this->belongsTo('App\timeline','id','pid');
}
}
Then Lastly my Controller
$timeline = timeline::with('videos','else')
->orderBy('id','desc')
->limit(5)
->get();
So far no Problem query is correct.