Laravel ORM relationship method 'BelongsToMany' throwing error - php

Summary
I am receiving the following error when trying to call the relationship:
Object of class Illuminate\Database\Eloquent\Relations\BelongsToMany
could not be converted to string
My setup is very basic, and consists of two models, User and Role.
User Model [User.php]
<?php
use Illuminate\Auth\UserInterface;
class User extends Eloquent implements UserInterface {
protected $table = 'users';
protected $hidden = array('password');
protected $fillable = array('id', 'username', 'password');
public function getAuthIdentifier() {
return $this->getKey();
}
public function getAuthPassword() {
return $this->password;
}
}
Role Model [Role.php]
<?php
class Role extends Eloquent {
protected $table = "roles";
protected $fillable = array(
'id',
'code',
'name'
);
public function foo() {
return $this->belongsToMany('User', 'map_role_user', 'role_id', 'user_id');
}
}
And finally I'm calling the method foo in the routes file, example:
Route::get('role', function() {
return Role::find(1)->foo();
});

From
https://laravel.com/docs/5.3/eloquent-relationships or https://laravel.com/docs/4.2/eloquent#relationships
If a collection is cast to a string, it will be returned as JSON:
<?php
$roles = (string) User::find(1)->roles;

If you dont want to add further constraints to the query then you have to use dynamic properties concept. So,
$user = App\User::find(1);
foreach ($user->posts as $post) {
//
}
If you want to add more constraints then do this
App\User::find(1)->posts()->where('title', 'LIKE', '%Best%')->get()

Related

how to access a function from model file

im using laravel 7.24 and php 7.4 on my project
What i want to is fundementally creating relations between 3 table and using them in 'one' query.
to be specific i need to access 'ordered products' from my order detail page.
public function orderdetail($id)
{ //certainorder model access to 'ShoppingCard'model from below
$orderDetails = CertainOrder::with('ShoppingCard.shoppingCardProducts.product')
->where('ShoppingCard.id' , $id)->firstorFail();
return view('orderdetails', compact ('orderDetails'));
}
CertainOrder model access to 'ShoppingCard' model from top and in the ShoppingCard model it contains shoppingCardProducts function which you will see in below and with shoppingCardProducts function my 'products' table had a relation. the problem is something in relations is wrong and i can't get data from shoppingcardproduct
class ShoppingCard extends Model
{
protected $table = "shopping_card";
protected $fillable = ['id', 'user_id', 'created_at','updated_at'];
public function shoppingCardProducts()
{
return $this->hasMany('App\ShoppingCardProduct');
}
class CertainOrder extends Model
{
protected $table = "certain_orders";
protected $guarded = [];
public function shoppingCard()
{
return $this->belongsTo(ShoppingCard::class, 'sepet_id');
//sepet_id is a foreign key.
}
class ShoppingCardProduct extends Model
{
use SoftDeletes;
protected $table = "shopping_card_product";
protected $fillable = ['id', 'sepet_id', 'urun_id','quantity','price','status','created_at','updated_at','deleted_at'];
public function product()
{
return $this->belongsTo('App\Product');
}
I think you missed it somewhere in the code
class ShoppingCard extends Model
{
protected $table = "shopping_card";
protected $fillable = ['id', 'user_id', 'created_at','updated_at'];
public function shoppingCardProducts()
{
return $this->hasMany('App\ShoppingCardProduct');
}
public function CertainOrder(){
return $this->hasMany('path\to\model');
}
public function ShoppingCardProduct(){
return $this->hasMany('path\to\model');
}
}
class CertainOrder extends Model
{
protected $table = "certain_orders";
protected $guarded = [];
public function shoppingCard()
{
return $this->belongsTo('App\path\to\model', 'sepet_id');
//sepet_id is a foreign key.
}
}
class ShoppingCardProduct extends Model
{
use SoftDeletes;
protected $table = "shopping_card_product";
protected $fillable = ['id', 'sepet_id', 'urun_id','quantity','price','status','created_at','updated_at','deleted_at'];
public function ShoppingCard()
{
return $this->belongsTo('App\ShoppingCard');
}
}
and make the call this way
public function orderdetail($id)
{ //certainorder model access to 'ShoppingCard'model from below
$orderDetails = ShoppingCard::with('CertainOrder, ShoppingCardProduct')
->where('id' , $id)->firstorFail();
return view('orderdetails', compact ('orderDetails'));
}

Call to a member function getQuery() on null Laravel Eloquent

I have worked a lot with Laravel and never got the following error:
Call to a member function getQuery() on null at /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php line 558.
I'm trying to get a record with all the relationships specified. The code that is causing that error is the following:
$id = 7;
$compra = Compra::where('id', $id)
->with(['certificado',
'certificado.duracionServicios',
'certificado.duracionServicios.servicio',
'certificado.duracionServicios.servicio.traducciones' => function($query){
$query->whereHas('idiomas', function($q){
$q->where('codigo_region', 'es_MX');
});
},
'user'])
->first();
If I take out the first() method, I can print the object instance of Builder, but when I try to use it or even use get(), that exception is thrown. Laravel version I'm using is 5.5.
Model Compra
namespace App\Models\Sitio;
use Illuminate\Database\Eloquent\Model;
class Compra extends Model
{
protected $table = 'compras';
protected $fillable = ['folio',
'fecha_compra',
'subtotal',
'total',
'user_id',
'direccion_id',
];
protected $dates = ['created_at', 'updated_at'];
/**
* Get the value of the model's route key.
*
* #return mixed
*/
public function getRouteKey()
{
$hashids = new \Hashids\Hashids(config('app.name'), 5);
return $hashids->encode($this->getKey());
}
public function certificado(){
$this->hasOne('App\Models\Sitio\Certificado', 'compra_id');
}
public function user(){
return $this->belongsTo('App\User', 'user_id');
}
}
Model Certificado
namespace App\Models\Sitio;
use Illuminate\Database\Eloquent\Model;
class Certificado extends Model
{
protected $table = 'certificados';
protected $fillable = ['fecha_servicio',
'hora_servicio',
'compra_id',
];
protected $dates = ['created_at', 'updated_at'];
public function compra(){
return $this->belongsTo('App\Models\Sitio\Compra', 'compra_id');
}
public function duracionServicios(){
return $this->belongsToMany('App\Models\Sitio\DuracionServicio', 'certificados_duracion_servicios', 'certificado_id', 'duracion_id');
}
}
Model DuracionServicio
namespace App\Models\Sitio;
use Illuminate\Database\Eloquent\Model;
class DuracionServicio extends Model
{
protected $table = 'duracion_servicios';
protected $fillable = ['costo',
'servicio_id',
];
protected $dates = ['created_at', 'updated_at'];
public function certificados(){
return $this->belongsToMany('App\Http\Models\Sitio\Certificado', 'certificados_duracion_servicios', 'duracion_id', 'certificado_id');
}
public function servicio(){
return $this->belongsTo('App\Models\Sitio\Servicio', 'servicio_id');
}
public function traducciones(){
return $this->hasMany('App\Models\Sitio\DuracionServicioTraduccion', 'duracion_id');
}
}
Model Servicio
namespace App\Models\Sitio;
use Illuminate\Database\Eloquent\Model;
class Servicio extends Model
{
protected $table = 'servicios';
protected $fillable = ['seccion_id'];
protected $dates = ['created_at', 'updated_at'];
public function traducciones(){
return $this->hasMany('App\Models\Sitio\ServicioTraduccion', 'servicio_id');
}
public function duraciones(){
return $this->hasMany('App\Models\Sitio\DuracionServicio', 'servicio_id');
}
}
Model ServicioTraduccion
namespace App\Models\Sitio;
use Illuminate\Database\Eloquent\Model;
class ServicioTraduccion extends Model
{
protected $table = 'servicios_traducciones';
protected $fillable = ['nombre',
'descripcion',
'contenido',
'idioma_id',
'servicio_id',
];
protected $dates = ['created_at', 'updated_at'];
public function servicio(){
return $this->belongsTo('App\Models\Sitio\Servicio', 'servicio_id');
}
public function idioma(){
return $this->belongsTo('App\Models\Sitio\Idioma', 'idioma_id');
}
}
Model Idioma
namespace App\Models\Sitio;
use Illuminate\Database\Eloquent\Model;
class Idioma extends Model
{
protected $table = 'servicios_traducciones';
protected $fillable = ['nombre',
'codigo_region',
];
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
public function servicios(){
return $this->hasMany('App\Models\Sitio\ServicioTraduccion', 'idioma_id');
}
public function duraciones(){
return $this->hasMany('App\Models\Sitio\DuracionServicioTraduccion', 'idioma_id');
}
}
Ok, so the problem is in your Compra model.
You defined relationship like this:
public function certificado()
{
$this->hasOne('App\Models\Sitio\Certificado', 'compra_id');
}
You forgot to add return. It should be:
public function certificado()
{
return $this->hasOne('App\Models\Sitio\Certificado', 'compra_id');
}
You can't call get_query() on a ->first().
->first() will return the first result of your query, and so execute the SQL query (after the first() you get a null result if no result, or your query result object). You should be able to use get_query() or get() if you remove the first() as you'll have an eloquent query instance, not a result object or collection.
You need to build up a query here by calling the query() method first.
$id = 7;
$compra = Compra::query()->where('id', $id)
->with(['certificado',
'certificado.duracionServicios',
'certificado.duracionServicios.servicio',
'certificado.duracionServicios.servicio.traducciones' => function($query){
$query->whereHas('idiomas', function($q){
$q->where('codigo_region', 'es_MX');
});
},
'user'])
->get();
or you can use ->first();

Send user id and post id with comment

I am following a laravel tutorial and created a form to create a comment on a post with the user_id. I can't seem to understand how I pass the user_id.
Post Model
class Post extends Model
{
protected $guarded = [];
public function comments()
{
return $this->hasMany(Comment::class);
}
public function addComment($body)
{
$this->comments()->create(compact('body'));
}
public function user()
{
return $this->belongsTo(User::class);
}
}
CommentModel
class Comment extends Model
{
protected $guarded = [];
public function post()
{
$this->belongsTo(Post::class);
}
public function user()
{
$this->belongsTo(User::class);
}
}
User Model
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function posts()
{
return $this->hasMany(Post::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function publish(Post $post)
{
$this->posts()->save($post);
}
}
CommentsController.php
class CommentsController extends Controller
{
public function store(Post $post)
{
$this->validate(request(), ['body' => 'required|min:2']);
$post->addComment(request('body'));
return back();
}
}
As you can see I call ->addComment in the Post Model to add the comment. It worked fine untill I added user_id to the Comments table. What is the best way to store the user id? I can't get it to work.
Update your addComment method :
public function addComment($body)
{
$user_id = Auth::user()->id;
$this->comments()->create(compact('body', 'user_id'));
}
PS : Assuming that the user is authenticated.
UPDATE
public function addComment($body)
{
$comment = new Comment;
$comment->fill(compact('body'));
$this->comments()->save($comment);
}
Create a new instance of the comment without savingit and you only need to save a comment in the post because a post already belongs to a user
There is no need to handle ids manually, let eloquent handle it for you:
$user = Auth::user(); // or $request->user()
$user->comments()->save(new Comment());
more information about saving eloquent models.

Laravel HasOne relationship empty

I am trying to create a relationship between Player and Roleplay and its returning null. I know for a fact it should be working because the following code works perfectly:
Roleplay::find(Auth::user()->id);
And returns the correct data, a full array of the correct data.
When trying to access it this way:
Auth::user()->roleplay->user_id;
It doesn't work, can someone help me find out why?
How do you know its empty?
Because {{var_dump(Auth::user()->roleplay)}} in blade view returns EMPTY
When using it the view I also get a undefined error.
Primary key of roleplay table (srp_user_statistics) is user_id, and the primary key of player table (users) is id
here is the code:
Player:
<?php
namespace App\Database\Frontend\User;
use Hash;
use Eloquent;
use \Illuminate\Auth\Authenticatable;
use \Illuminate\Contracts\Auth\Authenticatable as Authentication;
class Player extends Eloquent implements Authentication
{
use Authenticatable;
protected $primaryKey = 'id';
protected $table = 'users';
public $timestamps = false;
protected $fillable = [];
public function setPasswordAttribute($value)
{
$this->attributes['password'] = Hash::make($value);
}
public function setUsernameAttribute($value)
{
return $this->attributes['username'] = $value;
}
public function roleplay()
{
return $this->hasOne('App\Database\Frontend\User\Roleplay', 'user_id');
}
}
Roleplay:
use Eloquent;
class Roleplay extends Eloquent
{
protected $primaryKey = 'user_id';
protected $table = 'srp_user_statistics';
public $timestamps = true;
protected $fillable = [];
public function user()
{
return $this->belongsTo('App\Database\Frontend\User\Player', 'user_id', 'id');
}
public function government_role()
{
return $this->belongsTo('App\Database\Frontend\Roleplay\GovernmentRole', 'government_id');
}
}
I thinks you should add 'id' to hasOne() in the User model
public function roleplay()
{
return $this->hasOne('App\Database\Frontend\User\Roleplay', 'user_id', 'id');
}
And remove 'id' from belonsTo() in Roleplay model.
Side notes
This working
Roleplay::find(Auth::user()->id);
Is not a guarantee your relationships are set properly. All it does is
Roleplay::find(1); //$user->id returns an integer.

Laravel Eloquent::firstOrCreate Problems

Ok so I am trying to have use the Eloquent method "firstOrCreate" within another Eloquent model.
FriendRequest Eloquent
class FriendRequest extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
public $table = 'requests';
protected $guarded = array('id');
protected $softDelete = true;
public function friend() {
return $this->hasOne('User', 'id', 'friend_id');
}
public function user() {
return $this->hasOne('User', 'id', 'user_id');
}
public function accept() {
// FIRST YOU MUST MARK REQUEST AS ACCEPTED
// THEN SOFT DELETE REQUEST SO IT DOESN'T
// SHOW UP AS ACTIVE FRIEND REQUEST
$this->accepted = '1';
$this->save();
// CREATE FRIENDSHIP USER -> REQUESTED
$friend = Friend::firstOrNew(array('user_id' => Auth::user()->id, 'friend_id' => $this->friend_id));
$friend->save();
// CREATE FRIENDSHIP REQUESTED -> USER
$friend2 = Friend::firstOrNew(array('user_id' => $this->friend_id, 'friend_id' => Auth::user()->id));
$friend2->save();
// SOFT DELETE REQUEST BEING MARKED ACCEPTED
$status = $this->delete();
if (!$status):
return false;
else:
return true;
endif;
}
}
I've tried both firstOrCreate and firstOrNew as shown but with both times 'friend_id' and 'user_id' given in the array are set as '0'.
There is no default on the rows or indexes.
Here's the Friend Eloquent Model
class Friend extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
public $table = 'friends';
protected $guarded = array('id');
public function user() {
return $this->hasOne('User', 'id', 'user_id');
}
public function friend() {
return $this->hasOne('User', 'id', 'friend_id');
}
}
The create() method does mass assignment and this is a big security issue, so Laravel has a protection against it. Internally it has guarded = ['*'], so all your columns will be protected against mass assignment. You have some options:
Set the fillable columns of your model:
class User extends Eloquent {
protected $fillable = array('first_name', 'last_name', 'email');
}
Or set only the ones you want to keep guarded:
class User extends Eloquent {
protected $guarded = array('password');
}
You may, at your own risk also do:
class User extends Eloquent {
protected $guarded = array();
}
Also on the difference between the firstorcreate, and firstornew:
The firstOrNew method, like firstOrCreate will attempt to locate a record in the database matching the given attributes. However, if a model is not found, a new model instance will be returned. Note that the model returned by firstOrNew has not yet been persisted to the database. You will need to call save manually to persist it:
You can also go through the Facade and use the follwing:
class Settings extends Eloquent
{
protected $table = 'settings';
protected $primaryKey = 'name';
public static function get($settingName)
{
return Settings::firstOrCreate(array('name' => $settingName));
}
}
I believe you should put your accept() function in one of your controllers instead of the model. I'm not sure how and where you're calling this function, but I think it's in the wrong place.

Categories