I have an activity menu that have three sub-menu. These sub-menu are common to activity but have different table. So I want to use these three table under one model class, how can I do save operation individual to each other?
My code is as follows:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use DB;
class Activity extends Model {
protected $table1 = 'task_management';
protected $table2 = 'call_management';
protected $table3 = 'event_management';
}
use DB;
I have preferred using the DB query whenever i had to work with more than one table, below is a sample query.
$data = DB::table('base table name')
->join('join table name', 'join table name id', '=', 'master table name id')
->select('column 1', 'column 2', 'column 3')
->where('column1', $val);
You can create another class that is built on top of your models or even just uses plain SQL queries as #Peeje mentioned. Model is meant to work with single table in Laravel - I don't think there is an easy way to make it work with different tables.
I would recommend you to follow the Eloquent way,
You should create 3 models and do relationship
It would be simple like
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class CallManagement extends Model
{
/**
* Get the task record associated with the user.
*/
public function task()
{
return $this->hasOne('App\TaskManagement');
}
}
Which allows you to retrive like $task = User::find(1)->TaskManagement;
Note : You should create and customize your model according to your need.
Related
I have a navigation model that can have many items associated with it:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use JetBrains\PhpStorm\ArrayShape;
use Laravel\Scout\Searchable;
class Navigation extends Model
{
use HasFactory;
use Searchable;
protected $guarded = [];
public function navigation_items(): HasMany
{
return $this->hasMany(NavigationItem::class);
}
}
The navigation item model looks like this
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class NavigationItem extends Model
{
use HasFactory;
protected $guarded = [];
public function navigation(): BelongsTo
{
return $this->belongsTo(Navigation::class);
}
public function navigatable(): MorphTo
{
return $this->morphTo();
}
}
Now an item can either be of type Page or Blog, in this case the Page model looks like this:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use JetBrains\PhpStorm\ArrayShape;
use Laravel\Scout\Searchable;
class Page extends Model
{
protected $guarded = [];
public function navigatable(): MorphOne
{
return $this->morphOne(NavigationItem::class, 'navigatable');
}
}
When I try to save a navigation model and associate it with a item, the following error appears:
SQLSTATE[HY000]: General error: 1364 Field 'navigatable_type' doesn't have a default value
I save the model like this:
foreach ($this->selected as $id) {
$this->navigation->navigation_items()->create([
'navigation_id' => $this->navigation->id,
]);
Where $this->selected is the navigation id, it should automatically get the correct navigatable_type and navigatable_id, but this doesn't seem to be working.
passing in the type and id manually works, but this kinda defeats the point of a polymorphic relationship.
any ideas?
On NavigationItem model, since you defined polymorphic relation as 'navigatable' it is expected that NavigationItem model's table contains navigatable_type and navigatable_id. First please ensure this checks out.
Creating records through relation's base function is not a valid method. It is not clear what you are trying to achieve there but when you want to set relation there is two standard way of achieving it:
1- Associate
When a relation is defined as belongsTo, you may use associate() function. Like so:
$account = Account::find(10);
$user->account()->associate($account);
2- Attach
Attach is used when relation is defined belongsToMany (pivot). It allows you to attach multiple records to a model instance/record.
$user = User::find(1);
$user->roles()->attach($roleId);
So if you want to set a 'navigatable' to a Navigation instance, you may:
$somePageInstance=Page::find(55);
$nagivation->navigatable()->associate($somePageInstance)
$nagivation->save();//remember to save, otherwise it won't be
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.
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)
->...
I have the database structure that have a classes table, a users table and users_classes table that matches the other two, because a user can belong to multiple classes. I have a problem now. I have code like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class Classes extends Model
{
protected $table = 'classes';
public function students()
{
}
}
And I want to be able to access the students of the class by typing $class = Classes::find(1) and then $class->students to access the students. How do I define the relationship without using the query builder? I want to use eloquent. Im a noobie in Laravel pls dont downvote.
You use a belongsToMany relation.
If your users_classes table has the fields user_id and class_id you can do the following:
public function students()
{
return $this->belongsToMany(Student::class, 'users_classes', 'class_id', 'user_id');
}
I have a table named tasks and a model named Task. In my controller method when i run this piece of code
<?php
namespace App\Http\Controllers;
use DB;
//use app\Task;
use DateTime;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
class Task_Controller extends Controller
{
//
public function decide()
{
if ($input=="show all task")
{
//$rows=DB::table('task')->get();
$rows=\App\Task::all();
foreach($rows as $values)
{
foreach($values as $key=>$val)
echo "$key : $val <br>";
echo "<br><br>";
}
}
}
It gives me following error:
SQLSTATE[HY000]: General error: 1 no such table: tasks (SQL: select * from "tasks")
That is the model should have linked to the task table instead it is linked to the tasks table Why??.
How to make model gets linked to a specific table.
My model class code goes like this
namespace App;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
//
}
You should name your table tasks, this is the best option.
Another way to fix this is to use $table property:
protected $table = 'task';
Note that we did not tell Eloquent which table to use for our Flight model. By convention, the "snake case", plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the Flight model stores records in the flights table. You may specify a custom table by defining a table property on your model
https://laravel.com/docs/5.4/eloquent#defining-models
By default, the table name is the plural of the class name. If you want it to point to a different table, then in your model, add
protected $table = 'task';
By default laravel pluralizes the model names to be be the table names unless stated otherwise in the model by.
protected $table = 'task';