Laravel return Has many relationship - php

The relationship is User who can have many Events they are associated to.
I want to be able to make an API call to get all the events associated by the user. I have changed my primary key from id to uuid. I have made the foreign key association to the Events table as well. The primary key in the events table is also a column called UUID.
I am getting error
Return value of App\Http\Controllers\UsersController::getAllEvents() must be an instance of App\Http\Resources\UserResource, instance of Illuminate\Database\Eloquent\Relations\HasMany returned
My routes table:
Route::apiResource('/users', 'UsersController');
Route::apiResource('/events', 'EventsController');
Route::get('/users/allevents/{user}', 'UsersController#getAllEvents');
So the URL im hitting is:
http://127.0.0.1:8000/api/users/allevents/0a0jqZ7qzuhemKnzB3wOPUc2Ugp2
0a0jqZ7qzuhemKnzB3wOPUc2Ugp2 is the UUID of a user. I want to get all the events associated to that user.
My User model:
class User extends Model
{
use Notifiable;
use SoftDeletes;
protected $dates = ['deleted_at'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'uuid', 'email', 'firstName', 'lastName', 'level', 'venmo'
];
public function getRouteKeyName()
{
return 'uuid';
}
public function events() {
return $this->hasMany(Event::class);
}
}
My Event Model:
class Event extends Model
{
use SoftDeletes;
protected $table = 'events';
protected $dates = ['deleted_at'];
// public function getRouteKeyName()
// {
// return 'uuid';
// }
protected $fillable = [
'id', 'availableSpots', 'uuid', 'chosenDate', 'date', 'epochTime', 'level', 'price', 'time', 'created_at', 'updated_at', 'user_uuid'
];
public $incrementing = false;
protected $primaryKey = 'uuid';
protected $keyType = 'string';
public function user(){
return $this->belongsTo(User::class, 'user_uuid', 'uuid');
}
}
My UsersController:
class UsersController extends Controller
{
public function show(User $user): UserResource
{
return new UserResource($user);
}
/**
* #param Request $request
* #param User $user
* #return UserResource
*/
public function update(Request $request, User $user): UserResource
{
$user->update($request->all());
return new UserResource($user);
}
/**
* #param User $user
* #return UserResource
* #throws \Exception
*/
public function destroy(User $user): UserResource
{
$user->delete();
return new UserResource($user);
}
public function getAllEvents(User $user): UserResource {
return $user->events();
}
}

You are using wrong type of the method return it doesn't return UserResource it return events array so by removing the wrong type it will work
public function getAllEvents(User $user) {
return $user->events;
}

public function getAllEvents(User $user)
{
return $user->events;
}

Related

Return all relationship data in laravel

I want to retrieve data using eloquent model and return it in the following json response.
user[
transactions[],
clients[
ubications[],
contactos[],
plans[],
]
]
Currently I am receiving user,transcation and clients data but I am not able to retreive the data inside client property e.g ubications[],contactos[] and plans[].So I need help regarding the sub properties as I have already implemented the relationship.
Here are the models I am using
User.php
class User extends Authenticatable
{
use Notifiable,HasApiTokens;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function token(){
return $this->access_token;
}
public function transaction(){
return $this->hasMany(Transaction::class);
}
public function plan(){
return $this->hasManyThrough(Plan::class,Client::class);
}
public function ubication(){
return $this->hasManyThrough(Ubicacion::class,Client::class);
}
public function contacto(){
return $this->hasManyThrough(Contacto::class,Client::class);
}
public function client(){
return $this->hasMany(Client::class);
}
}
Client.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Client extends Model
{
protected $fillable=[
'nombre',
'ruc',
'status',
'user_id'
];
public function contacto(){
return $this->hasMany(Contacto::class);
}
public function feedback(){
return $this->hasMany(Feedback::class);
}
public function plan(){
return $this->hasMany(Plan::class);
}
public function ubication(){
return $this->hasMany(Ubicacion::class);
}
public function user(){
return $this->belongsTo(User::class);
}
}
You can use nested data Eager Loading:
Laravel Documentation Eager Loading
$user = User::find(1)
->with('clients', 'clients.contacto', 'clients.ubications', 'clients.plans')
->get();

Insert into many to many relation table in Laravel

In my laravel project, I have tables that i want to insert a many to many relationship between 2 of them. I want to bind an User(that must be a cleaner kind) to one House of many from current Host user authenticated. To do so, I'm implementing the following function in Controller:
public function hireCleanerToHouse (Request $request)
{
$house_id = $request->houseAssign;
$email = $request->email;
$house = House::find($house_id);
$cleanerUser = User::where('email', $email)->first();
if ($cleanerUser && $house){
$cleanerUser->houses()->attach($house);
}
return response()->json('success', 200);
}
May I am missing a detail of logic that cant let me insert any data. Im pretty new using laravel and the Eloquent ORM.
to help understand better, here are the Models from project. The functions that take care of a separates tables (CRUD) are all working fine.
If there are some other tip to improve legibity or if I'm ignoring some best pratice, I will gladly accept it.
User:
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 host()
{
return $this->hasOne(Host::class);
}
public function cleaner()
{
return $this->hasOne(Cleaner::class);
}
}
House:
class House extends Model
{
protected $fillable = ['name', 'address', 'host_id'];
protected $dates = ['created_at', 'updated_at'];
protected $appends = ['next_cleaning'];
public function host()
{
return $this->belongsTo(Host::class);
}
public function cleaners()
{
return $this->belongsToMany(
Cleaner::class,
'cleaners_houses',
'house_id',
'cleaner_id'
);
}
public function cleanings()
{
return $this->hasMany(CleaningProject::class);
}
public function getNextCleaningAttribute()
{
return $this->cleanings()->orderBy('created_at', 'desc')->first();
}
}
Cleaner:
class Cleaner extends Model
{
protected $dates = ['created_at', 'updated_at'];
public function houses()
{
return $this->belongsToMany(
House::class,
'cleaners_houses',
'cleaner_id',
'house_id'
);
}
public function hosts()
{
return $this->belongsToMany(
Host::class,
'cleaners_hosts',
'cleaner_id',
'host_id'
);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function cleanings()
{
return $this->hasMany(CleaningProject::class);
}
public function getNameAttribute()
{
return $this->user->name;
}
}
Host
class Host extends Model
{
protected $dates = ['created_at', 'updated_at'];
protected $appends = ['name'];
public function houses()
{
return $this->hasMany(House::class);
}
public function cleaners()
{
return $this->belongsToMany(
Cleaner::class,
'cleaners_hosts',
'host_id',
'cleaner_id'
);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function getNameAttribute()
{
return $this->user->name;
}
}
And also the migration that bind many Cleaners to many House is already created:
Migration
class CreateCleanersHousesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('cleaners_houses', function (Blueprint $table) {
$table->increments('id');
$table->integer('cleaner_id')->references('id')->on('cleaners');
$table->integer('house_id')->references('id')->on('houses');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('cleaners_houses');
}
}
here's the solution that I found:
public function hireCleanerToHouse (Request $request)
{
$email = $request->email;
$houseId = $request->idHouse;
$idUserEmail = User::where('email', $email)->first();
$cleaner = Cleaner::where('user_id', $idUserEmail->id)->first();
$house = House::find($houseId);
$cleaner->houses()->attach($house->id);
return response()->json([$cleaner, $house], 200);
}
As you may see the problemn was because the model Cleaner only contains 'id' and 'user_id', so i had to get first the user.id and find the cleaner where user_id = user.id.
Also I don't passed the $house->id in the attach() to match the relationship. Its now working fine. hope it helps someone else.

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 5.4 Model Accessor Methods not working

i'm trying make an accessor, for post permalink. If i understand correctly it will change my premalink when i create new entry, but it doesn't
<?php
class Story extends Model
{
use UuidTrait;
public $incrementing = false;
protected $table = 'stories';
protected $fillable = [
'title', 'text', 'tags', 'user_id', 'permalink',
];
public function user()
{
return $this->belongsTo('App\Model\User', 'user_id');
}
/**
* Set the permalink.
*
* #param string $value
* #return void
*/
public function sePermalinkAttribute($value)
{
if(empty($value)){
$value = $this->attributes['title'];
}
$this->attributes['permalink'] = str_slug($value);
}
}
But i get NULL when save my model. Why does accessor not working?
$user->stories()->create($data['data']);

Accociate a user name to the post they created

If I created a blog post, how can I have my name associated with it? For example, on a page that lists all blog posts, I will see the user name of the post they created. Yes?
In my post controller:
public function __construct(Post $post, User $user)
{
$this->middleware('auth',['except'=>['index','show',]]);
$this->post = $post;
$this->user = $user;
}
public function show($id)
{
$user = $this->user->first(); // This seems to show the first user
$post = $this->post->where('id', $id)->first(); // Grabs the assigned post
}
In my show.blade.php:
{{ $user->name }}
How can I display the name of the user who created the post? I thought this $user = $this->user->first(); would work. Im new to Laravel and I am using Laravel 5.
Thanks!
EDIT
User Model:
class User extends Model implements AuthenticatableContract, CanResetPasswordContract, BillableContract {
use Authenticatable, CanResetPassword;
use Billable;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'password', 'company_url', 'tagline','company_name', 'company_description'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* #var array
*
*/
protected $dates = ['trial_ends_at', 'subscription_ends_at'];
public function posts()
{
return $this->hasMany('App\Post')->latest()->where('content_removed', 0);
}
}
Post Model:
class Post extends Model {
/**
* Fillable fields for a new Job.
* #var array
*/
protected $fillable = [
'post_title',
'post_description',
'post_role',
'post_types',
'post_city',
'post_country',
'template',
'content_removed',
];
public function users()
{
return $this->hasMany('App\User')->orderBy('created_at', 'DESC');
}
public function creator()
{
return $this->belongsTo('App\User');
}
}
first
you need to add the following line to your post model
public function creator()
{
return $this->belongsTo('App\User','user_id', 'ID');
}
then in you show method
public function show($id)
{
$post = $this->post->with('creator')->findOrFail($id);
return view('show',compact('post'));
}
In you show.blade.php
{{ $post->creator->name }}

Categories