Laravel Model renaming MySQL table to plural on query - php

I am using a model to query a remote MySQL DB and when I run the query, Laravel is trying to connect to the plural version of the table that I need it to connect to. The table's name is activity and the error I get is:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'health.activities' doesn't exist (SQL: select * from `activities`)
I just built the model for this using artisan make:model Activity so I am not sure what is going on. Here is my model:
<?php
namespace App;
use DB;
use Role;
use Illuminate\Database\Eloquent\Model;
class Activity extends Model
{
private $activity;
function __construct()
{
$this->activity = DB::connection('mysql_remote')->table('activity');
}
}
Here is my controller:
public function getDashboard()
{
$data = [
'page_title' => 'Dashboard',
'users' => User::getUser(),
'test' => Activity::get(),
];
return view('dashboard.dashboard', $data);
}
Anyone have any idea why this is happening?

Models expect the table to be named the plural of the name of the Model, in this case the plural of Activitiy is activities which is the table name it expects. If it's different, you need to add a table property to set the name of the table.
In your model, add the following...
protected $table = 'activity';

Related

protected $table = 'users'; Not being respected in relationship on a model extending from User?

Currently I have this "ContactLine" model that is extending from the User model
class ContactLine extends User
{
use HasFactory;
protected $table = 'users';
public function organizations(): BelongsToMany
{
return $this->belongsToMany(Organization::class);
}
}
I have written a test controller where I am trying to inject the ContactLine into the method via route model binding.
class TestContactlineControler extends Controller
{
public function __invoke(ContactLine $contact)
{
return $contact;
}
}
However I am currently getting this error whenever I try to hit the route for this controller
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'incidents.contact_line_id' in 'where clause' (SQL: select count(*) as aggregate from `incidents` where `incidents`.`contact_line_id` = 1 and `incidents`.`contact_line_id` is not null and `closed_at` is null and `incidents`.`deleted_at` is null)
However if I change the controller to inject the User model instead it works fine.
In my user model I have this relationship which I think is causing the error.
public function incidents(): HasMany
{
return $this->hasMany(Incident::class);
}
However I thought setting the table to users in either User or ContactLine model should make it so it looks for incidents.user_id not incidents.contact_line_id
You can define the fields that are used to lookup a releation by settings the second and third param of hasMany
https://laravel.com/docs/9.x/eloquent-relationships#one-to-many
By default, laravel will do a lookup depending on your ClassName, by settings the params you can bypass this.

laravel hasOneThrough with trashed does not remove the softdelete scope of intermediate

How to get all the relational records of timeslots when intermediate(hasOneThrough) has soft deletes.
1. Attendance Model Attendance.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Attendance extends Model
{
protected $fillable = [
'tutor_id',
'center_timeslot_id',
// other attributes are ommited
];
public function timeslot()
{
return $this->hasOneThrough(
Timeslot::class,
CenterTimeslot::class,
'id',
'id', // primary key on timeslots table...
'center_timeslot_id', //local key of this table to primary of centerTimeslots table
'timeslot_id' //local key on centertimeslots table of target table timeslot
)
->withTrashed();//this does not work
}
}
2. CenterTimeslot Model CenterTimeslot.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class CenterTimeslot extends Model
{
use SoftDeletes;
protected $fillable = [
'center_id', 'timeslot_id', 'capacity'
// other attributes are ommited
];
public function timeslot()
{
return $this->belongsTo(Timeslot::class);
}
}
3. Finally Timeslot Model Timeslot.php
<?php
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
class Timeslot extends Model
{
protected $fillable = [
'name',
// other attributes are ommited
];
}
So if any record is soft deleted that is in center_timeslot_table we can not retrieve the model though applying withTrashed() as it only works on direct model on in the through table. So the soft deletes gets still applied as defined in CenterTimeslot Model
So there is no way to get the records.
But I can trick the query builder to have the method like this which does retrieve the records
Attendance.php
public function timeslot()
{
return $this->hasOneThrough(
Timeslot::class,
CenterTimeslot::class,
'id',
'id', // primary key on timeslots table...
'center_timeslot_id', //local key of this table to primary of centerTimeslots table
'timeslot_id' //local key on centertimeslots table of target table timeslot
)
->withTrashed()
->orWhere(function ($query) {
$query->whereNotNull('center_timeslots.deleted_at');
});
Sot it returns the record but I am not satisfied with the hack. So if someone can give some light or a better workaround will be good.
I face the same issue when my project was in the middle of development and my conclusion after searching on this is:
The documentation says at first coming note that:
And you make your pivot table a model therefore SoftDeletes are working.And withTrashed() is working for Timeslot::class but not for pivot table (CenterTimeslot) because laravel was not expecting a model here.
According to documentation, your Central or pivot table line should be
use Illuminate\Database\Eloquent\Relations\Pivot;
class CenterTimeslot extends Pivot
instead of
class CenterTimeslot extends Model
in this way, there will be the issue of SoftDeletes
In my case, I solve this by creating to classes one is extending from Pivot (which I am using for relation calls) and the other from Model (using where SoftDeletes or as a model is required) but I am not sure that this is the proper way or not but is working fine. I Will appreciate it if someone adds a proper way to deal with it but for the current time, it is working as required.
Note: Make the pivot class name different from the model and if the table name is different then you can define $table separately in pivot class.

Laravel Eloquent Model change table name on runtime in a related instance

I am new to Laravel and also asked the question on Laracast without any success so far.
Here is my problem: I have a database layout something like this:
Table: categoryA_products
Table: categoryB_products
Table: categoryC_products
and per default the Laravel user table:
Table: user
I have create a two Laravel Eloquent models:
Product:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
// protected $table = '';
public function users()
{
return $this->belongsTo( User::class );
}
}
User:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function products()
{
return $this->hasMany( Product::class );
}
}
As each product has a different table name I would normally create 1 model for each table but as they are all similar I would like to define the model table name at runtime.
I know I can do this with "$product->setTable()" but as I use the "newRelatedInstance" class from Laravel (hasMany and belongsTo) I cannot initiate the product class and set the table.
Is there a workaround for this?
Yes, I am aware that I could create a category table and link the products to each category but this is a fictional database model. There is a reason for this approach and I can explain it more in detail if needed. That said it make sense for this sample but I cannot use it for the live database.
I have a working solution with a model for each "category" but this is very messy.
Any help would be appreciated.
Since you're unable to load the relations, you could try referencing and re-initializing them like:
$relations = $product->getEagerLoads();
$attributes = $product->getOriginal();
table_name = 'categoryA_products'; // or categoryB_products or categoryC_products
$product->newQuery()
->newModelInstance($attributes)
->setTable($table_name)
->setEagerLoads($relations)
->...

Database Relationships in Laravel

I have Author model that looks like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Author extends Model {
public $timestamps = false;
public function role()
{
return $this->hasOne('App\Role');
}
}
And Role model that looks like:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
public $timestamps = false;
}
My AuthorController.php looks like:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Author;
class AuthorController extends Controller
{
public function index(){
$role = Author::find(5)->role->pareigos;
return view('authors', ['role' => $role]);
}
}
But I get error like:
"SQLSTATE[42S22]: Column not found: 1054 Unknown column
'roles.author_id' in 'where clause' (SQL: select * from roles where
roles.author_id = 5 and roles.author_id is not null limit 1)
Where does the author_id even come from?
I have two tables in database, first one is authors that has id,firstname,lastname,role_id. Second one is roles that has two rows - id and pareigos. So I use this command:
$role = Author::find(5)->role->pareigos;
To find Author by id (5) and check his role_id in roles table and return pareigos if the ID's matches.
Don't know if I have described the problem clearly - if not, just let me know I eill add more details.
Your relationship is setup incorrectly. The table that has the key pointing to another table, belongs to that other table.
class Author ...
{
public function role()
{
return $this->belongsTo(Role::class);
}
...
This will want to look for a role_id key on authors table. By default, unless you pass more arguments to override it, Laravel uses the calling function name to decide the name of the foreign key for belongsTo relationships. [ method is named role, so it knows to look for role_id ... methodname + _id ]

Base table or view not found in laravel 5.3

I have a model
Education.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Education extends Model
{
public $timestamps = FALSE;
public function Member(){
return $this->belongsTo('App\Member');
}
}
In database i have a table named educations
In controller when I'm trying to access the data of the educations table through App\Education model I'm getting this error
QueryException in Connection.php line 770: SQLSTATE[42S02]: Base table
or view not found: 1146 Table 'dsse.education' doesn't exist (SQL:
select * from education)
Why laravel is searching for education table in the database where it should search for educations table. What is the problem?
here is the controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Member as Member;
use App\Education as Education;
class memberController extends Controller
{
public function addMember(){
$education = Education::all();
var_dump($education);
}
}
Add this to your model. You may set any custom table name as follow
protected $table = 'educations';
I had the same problem before,
and yes it is a solution to add
protected $table = 'educations';
but the problem is because laravel uses a class called
Illuminate\Support\Pluralizer
inside
Illuminate\Support\Str
and this class is not just adding "s" at the end of words or ies...
it is real pluralizer and education is an uncountable word, so is information...
so you need to add $table to your model.

Categories