We created three tables called 'users', 'corso', 'iscrizione' which is a middle table between users and corso, it has two attributes that are PK/FK. We successfully built the methods to create/update/read/delete rows inside 'corso' and we populated manually 'users'. We are trying to realize a create method for iscrizione but when we try to test it on Postman it gives us an error: 🧨 Illegal offset type
We learned that Eloquent doesn't support composite keys (which is a shame) and the only way to bypass this limit is to override the method setKeysForSaveQuery() from Eloquent inside the model of our table.
Sadly it gives us this error:
Method 'App\Models\Iscrizione::setKeysForSaveQuery()' is not compatible with method 'Illuminate\Database\Eloquent\Model::setKeysForSaveQuery()'.intelephense(1038)
Iscrizione Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class Iscrizione extends Model
{
use HasFactory;
protected $hidden = ['idCorso', 'idUtente'];
protected $table = 'iscrizione';
protected function setKeysForSaveQuery(Builder $query){
return $query->where('idCorso', $this->getAttribute('idCorso'))
->where('idUtente', $this->getAttribute('idUtente'));
}
}
You need to make it match change the below code
protected function setKeysForSaveQuery(Builder $query){
to
protected function setKeysForSaveQuery($query){
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
Im new to laravel, i am trying to query a specific table in my DB. I only have 1 data table and the standard user auth tables. I am getting a error: BadMethodCallException
Call to undefined method App\Figures::table().
Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Figures extends Model
{
}
controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Figures;
class figuresController extends Controller
public function figurespag2() {
$dummyDetails = Figures::table('figures')->where('name', 'batman');
return view ( 'pagination2.index' )->withUsers($dummyDetails);
}
route
Route::get ( '/pagination2', 'figuresController#figurespag2' );
I know it's going to be something obvious, but I am new to this.
this is wrong
$dummyDetails = Figures::table('figures')->where('name', 'batman');
Method 1---------- laravel eloquent
Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Figures extends Model
{
protected $table = 'figures';
}
Controller
$dummyDetails = Figures::where('name', 'batman')->get();
and
Method 2 ---------- laravel Query Builder
$dummyDetails = \DB::table('figures')->where('name', 'batman')->get();
Use this you not need to define table name
public function figurespag2() {
$dummyDetails = Figures::where('name', 'batman')->get();
return view ( 'pagination2.index' )->withUsers($dummyDetails);
}
First you may need to know laravel model rules.
If you create a table name like "figures" (plural) you need to create its model by Figure (singular).
if you create a table other then this rule then you have to mentioned table name in model like this.
protected $table = "table_name";
you can access table with where condition in controller like this.
public function figurespag2() {
$dummyDetails = Figure::where('name', 'batman')->get();
return view ( 'pagination2.index' )->withUsers($dummyDetails);
}
Hope this may help you.
I am using the nested set for the first time with arcanedev/laravel-nestedset.
I am following a tutorial and setup my model accordingly. But when I call the create method it gives me following error.
Symfony\Component\Debug\Exception\FatalThrowableError thrown with message "Argument 1 passed to App\Models\AmazonCategoryIndices::appendToNode() must be an instance of Arcanedev\LaravelNestedSet\Contracts\Nodeable, instance of App\Models\AmazonCategoryIndices given, called in E:\TestProjects\pld-v4-admin\vendor\arcanedev\laravel-nestedset\src\NodeTrait.php on line 1074".
The data I am using is the same as it is in tutorial.
Here is my Model
==================================
namespace App\Models;
use Arcanedev\LaravelNestedSet\NodeTrait;
use Illuminate\Database\Eloquent\Model;
class AmazonCategoryIndices extends Model
{
protected $table = 'amazon_category_indices';
protected $guarded = [];
use NodeTrait;
}
==================================
foreach ($shops as $key => $value) {
AmazonCategoryIndices::create($value);
}
Based on the error message, the parameter passed to App\Models\AmazonCategoryIndices::appendToNode() is an instance of App\Models\AmazonCategoryIndices while it expects an instance of Arcanedev\LaravelNestedSet\Contracts\Nodeable
So, adding the contract Arcanedev\LaravelNestedSet\Contracts\Nodeable in your model should resolve your error.
namespace App\Models;
use Arcanedev\LaravelNestedSet\NodeTrait;
use Illuminate\Database\Eloquent\Model;
use Arcanedev\LaravelNestedSet\Contracts\Nodeable;
class AmazonCategoryIndices extends Model implements Nodeable
{
protected $table = 'amazon_category_indices';
protected $guarded = [];
use NodeTrait;
}
When you said: "ARCANEDEV/LaravelNestedSet" package uses "lazychaser/laravel-nestedset " at its backend.
...It's not. They are two different packages and doesn't work the same. Arcanedev credited lazychaser for his work on which he probably used a lot of resources.
Now that's been said, I wouldn't recommend using arcanedev's package since it doesn't seems to be maintenained.
I have three relational table attached below.
https://drive.google.com/file/d/1q1kdURIwFXxHb2MgdRyBkE1e3DMug7r-/view?usp=sharing
I have also three separate models where defined relation among all of my table's.I can read the City Model's information from Country model using hasManyThrough() relation But cannot read the Country information from City model. I have tried to retrieve City model's using ``hasManyThrough``` but didn't get result (attached as commented country method ). Please read my model and it's relational method here..
Is there someone to help me for getting City model's information using Eloquent method hasManyThrough / hasManyThrough or using inverse of hasManyThrough / hasManyThrough ?
01.
<?php
namespace App\Hrm;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Country extends Model
{
//use SoftDeletes;
protected $fillable = ['name','description','status'];
public function districts(){
return $this->hasMany(District::class);
}
public function cities(){
return $this->hasManyThrough(City::class,District::class);
}
}
02.
<?php
namespace App\Hrm;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class District extends Model
{
//use SoftDeletes;
protected $fillable = ['country_id','name','description','status'];
public function country(){
return $this->belongsTo(Country::class);
}
public function cities(){
return $this->hasMany(City::class);
}
}
3.
namespace App\Hrm;
use App\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class City extends Model
{
//use SoftDeletes;
protected $fillable = ['district_id','name','description','status'];
public function district(){
return $this->belongsTo(District::class);
}
// public function country(){
// return $this->hasOneThrough(Country::class, District::class);
// }
Doesn't look like there is a native way to define the inverse of a "hasManyThrough" relationship yet in Laravel. There have been a few issues opened on github to request it, but they were closed.
You could use the staudenmeir/belongs-to-through package if you don't mind installing a third-party package for this functionality. Then you should be able to define a belongsToThrough relationship like this:
class City extends Model
{
use \Znck\Eloquent\Traits\BelongsToThrough;
public function country() {
return $this->belongsToThrough(Country::class, District::class);
}
}
Why can't use parent method?
$city = City::find(1);
$country = $city->district->country();
i just had a similar situation i was able to accomplish a belongsToThrough with hasOneThrough
public function country()
{
return $this->hasOneThrough(
Country::class, // model we are trying to get
District::class, // model we have an _id to
'id', // WHERE `district`.`id` = `city`.`district_id`
'id', // `countries`.`id`
'district_id', // local column relation to our through class
'country_id' // `district`.`country_id`
);
}
what this should generate is
SELECT * FROM `countries`
INNER JOIN `districts`
ON `districts`.`country_id` = `countries`.`id`
WHERE `districts`.`id` = ?
-- ? == city.district_id
Database structure:
City:
id: increments
district_id: integer
...
Country:
id: increments
...
District:
id: increments
country_id: integer
...
we can then do $city->country
note: i have not fully tested this but with the testing that i have done it 'works'
Edit: i originally thought that i needed to leave the localKey
parameter null otherwise the relation wont work. it turns out i didnt
fully understand what that column was doing and that was wrong. That
key is the local column that relates to our through column (unless i
still have more to learn/figure out), when left the value as null, it
would use the local id column which a. is the wrong value, b. can also
be out of range (which is how i discovered it was using the wrong
value)
in my testing i only had two rows, both with the same relations. what
i didnt realize though was that on the "through table" both row 1 and
2 and the same related (relation where are trying to reach) so i didnt
notice the issue right away. hopefully now its all working
I'm trying to map an existing one to one relationship in my database using Eloquent following the Laravel tutorial and I'm receiving a string conversion error.
I have to use an existing database that is used by other program, so I can't change the database structure.
This are my models:
Pessoa.php
namespace App\Models;
use Illuminate\Support\Facades\Log; use
Illuminate\Database\Eloquent\Model;
class Pessoa extends Model {
protected $table = 'pessoas';
public function estadoCivil(){
//return EstadoCivil::find($this->estado_civil_id);
return $this->hasOne('App\Models\EstadoCivil', 'estado_civil_id');
}
}
EstadoCivil.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class EstadoCivil extends Model
{
protected $table = 'estados_civis';
}
I don't know what to do, but I am getting this error:
Object of class Illuminate\Database\Eloquent\Relations\HasOne could not be converted to string
I searched for typos and other mistakes and couldn't find anything. I'm not even trying to convert anything to string to get this error, the types in the database for the id and the foreign key are the same too.
Here is the controller that is using it:
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Pessoa as Pessoa;
class Eu extends Controller
{
public function __construct()
{
}
public function dadosCompletos(Request $request){
return Pessoa::find($request->user()->pessoa_id)->estadoCivil();
}
}
If I just use return Pessoa::find($request->user()->pessoa_id) it works fine and returns the data correctly from pessoas table.
you are returning the relation not the actual EstadoCivil collection.
use return Pessoa::find($request->user()->pessoa_id)->estadoCivil without parenthesis
You have to use ->estadoCivil instead of ->estadoCivil()