I'm making a function that each time I add a comment to an RMA Ticket it sends an email to the user but I'm getting Trying to get property of non-object when I submit the comment
Below I pasted the code from the CommentController and the Email function
if you want more information just ask and i will post what i could
I'm getting the error on this code - $mailer->sendRmaTicketComments($comment->ticket->user, Auth::user(), $comment->ticket, $comment);
CommentController Code
<?php
namespace App\Http\Controllers\Rma;
use Auth;
use App\User;
use App\Rma\RmaTicket;
use App\Rma\RmaComments;
use App\Mailers\AppMailer;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class RmaCommentController extends Controller
{
public function postComment(Request $request, AppMailer $mailer)
{
$this->validate($request, [
'comment' => 'required',
'user_id' => 'required',
]);
$comment = RmaComments::create([
'rma_ticket_id' => $request->input('ticket_id'),
'user_id' => $request->input('user_id'),
'comment' => $request->input('comment'),
]);
$mailer->sendRmaTicketComments($comment->ticket->user, Auth::user(), $comment->ticket, $comment);
return redirect()->back()->with('successPanel', 'Thank you for your message please allow up to 48 hours for a response.');
}
}
Mail Function Code
<?php
namespace App\Mailers;
use App\Rma\RmaTicket;
use App\Rma\RmaStatus;
use App\SupportTickets\SupportTicket;
use App\SupportTickets\SupportTicketStatus;
use App\User;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Support\Facades\Mail;
class AppMailer
{
protected $mailer;
/**
* Get the email address
*
* #var [type]
*/
protected $to;
/**
* Set the subject for the email
*
* #var [type]
*/
protected $subject;
/**
* Set the template for the email
*
* #var [type]
*/
protected $view;
/**
* Set the data for the email
*
* #var array
*/
protected $data = [];
public function __construct(Mailer $mailer)
{
$this->mailer = $mailer;
}
/**
* Send RMA Comments/Replies to RMA Owner
*
* #param User $ticketOwner
* #param User $user
* #param rmaTicket $rmaTicket
* #param Comment $comment
*
* #return method delivered()
*/
public function sendRmaTicketComments($ticketOwner, $user, RmaTicket $rmaTicket, $comment)
{
$this->to = $ticketOwner->email;
$this->subject = "RE[RMA Ticket # $rmaTicket->rma_ticket_id]";
$this->view = 'emails.rma.rma_comments';
$this->data = compact('ticketOwner', 'user', 'rmaTicket', 'comment');
return $this->deliver();
}
RmaComments Model
<?php
namespace App\Rma;
use Illuminate\Database\Eloquent\Model;
class RmaComments extends Model
{
protected $table = 'rma_comments';
protected $fillable = [
'rma_ticket_id', 'user_id', 'comment'
];
public function ticket()
{
return $this->belongsTo(RmaTicket::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
RMA Model
<?php
namespace App\Rma;
use Illuminate\Database\Eloquent\Model;
class RmaTicket extends Model
{
protected $table = 'rma_tickets';
protected $fillable = [
'user_id', 'rma_ticket_id', 'first_name', 'last_name',
'email', 'fax', 'company', 'marketplace_id', 'returnTypeId',
'product_name', 'quantity', 'order_number', 'address_one',
'address_two', 'city', 'state', 'zip_code', 'sku', 'model_number', 'comment',
'status_id', 'rma_number', 'refund_number', 'return_tracking_number',
'replacement_number', 'return_label'
];
public function returnType()
{
return $this->belongsTo(RmaReturnType::class);
}
public function marketplace()
{
return $this->belongsTo(RmaMarketplace::class);
}
public function status()
{
return $this->belongsTo(RmaStatus::class);
}
public function comments()
{
return $this->hasMany(RmaComments::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Looking at your code and since you have null if you dd($comment->ticket) i believe it's the naming of your foreign keys.
your belongsTo:
public function ticket()
{
return $this->belongsTo(RmaTicket::class);
}
expects an ticket_id but you named it rma_ticket_id.
You could specify a different foreign key name in the second argument in the belongTo relationship
public function ticket()
{
return $this->belongsTo(RmaTicket::class, 'rma_ticket_id');
}
As per the docs:
. Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with _id. However, if the foreign key on the Phone model is not user_id, you may pass a custom key name as the second argument to the belongsTo method:
Related
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;
}
I'm currently using Laravel with Infyom to build a backend, one thing that I'm not understanding is how to have multiple rules for validation depending on the API route, for instance, when I'm creating a user, both fields email and role should be provided to the endpoint, but when updating the user (due to login), only the email and password is required to be present. What I want is to have a different set o rules depending on the endpoint being used, is that possible and how? Currently, the endpoint always returns
{
"message": "The given data was invalid.",
"errors": {
"role": [
"The role field is required."
]
}
}
my routes/api.php looks like this
<?php
use Illuminate\Http\Request;
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::post('login', 'TokenAPIController#loginUser');
Route::put('login/updateToken/{id}', 'TokenAPIController#updateToken');
Route::resource('users', 'UserAPIController');
Route::resource('roles', 'RoleAPIController');
Route::resource('roles', 'roleAPIController');
Route::resource('product_variants', 'Product_variantAPIController');
Route::resource('product_images', 'Product_imageAPIController');
Route::resource('product_categories', 'Product_categoryAPIController');
Route::resource('products', 'ProductAPIController');
Route::resource('orders', 'OrderAPIController');
Route::resource('order_products', 'Order_productAPIController');
Route::resource('notifications', 'NotificationAPIController');
Route::resource('factories', 'FactoryAPIController');
Route::resource('statuses', 'StatusAPIController');
My user app/Models/User.php
<?php
namespace App\Models;
use Eloquent as Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
public $table = 'users';
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at';
protected $dates = ['deleted_at'];
public $fillable = [
'name',
'role',
'email',
'password',
'remember_token',
'notification_token',
'factory',
'api_token'
];
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'id' => 'integer',
'name' => 'string',
'role' => 'integer',
'email' => 'string',
'password' => 'string',
'remember_token' => 'string',
'notification_token' => 'string',
'factory' => 'integer',
'api_token' => 'string'
];
/**
* Validation rules
*
* #var array
*/
public static $rules = [
'role' => 'required',
'email' => 'required'
];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
**/
public function role()
{
return $this->belongsTo(\App\Models\Role::class, 'role');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
**/
public function factory()
{
return $this->belongsTo(\App\Models\Factory::class, 'factory');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
**/
public function orders()
{
return $this->hasMany(\App\Models\Order::class, 'customer');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
**/
public function order1s()
{
return $this->hasMany(\App\Models\Order::class, 'responsible');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
**/
public function notifications()
{
return $this->hasMany(\App\Models\Notification::class, '"from"');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
**/
public function notification2s()
{
return $this->hasMany(\App\Models\Notification::class, '"to"');
}
}
And finally, my TokenAPIController.php
<?php
namespace App\Http\Controllers\API;
use App\Http\Requests\API\CreateUserAPIRequest;
use App\Http\Requests\API\UpdateUserAPIRequest;
use App\Models\User;
use App\Repositories\UserRepository;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use Response;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Hash;
class TokenAPIController extends AppBaseController
{
/** #var UserRepository */
private $userRepository;
public function __construct(UserRepository $userRepo)
{
$this->userRepository = $userRepo;
}
public function loginUser(UpdateUserAPIRequest $request)
{ /** #var User $user */
$input = $request->all();
if (!isset($input['email'])) {
return $this->sendError('Email is required');
}
if (!isset($input['password'])) {
return $this->sendError('Password is required');
}
$user = User::where('email', $input['email'])
->first();
if (empty($user)) {
return $this->sendError('User not found');
}
$validCredentials = Hash::check($input['password'], $user["password"]);
if ($validCredentials) {
return $this->updateToken($user["id"]);
}
return $this->sendError('No match');
}
public function updateToken($id)
{
// $input = $request->all();
/** #var User $user */
$user = $this->userRepository->find($id);
if (empty($user)) {
return $this->sendError('User not found');
}
$token = Str::random(60);
$user->forceFill([
'api_token' => hash('sha256', $token),
])->save();
return $this->sendResponse($user->toArray(), 'User updated successfully');
}
}
Edit your App\Http\Requests\API\UpdateUserAPIRequest file and adjust the rules it returns from rules.
This is my PlayerController, Player & Session Model and Resource.
I want to use the input (sessionId from SessionsTable) to fetch user from the room with the same id (userSession) and return an array in this format: [{userId:1, userName: stacki, userVote:8},{...},...]
I already asked [here][1] to achieve this and now im stuck with this error.
What do I have to change in order to solve this issue? Simply adding ->first() does not solve my issue, I need more than one record.
namespace App\Http\Controllers;
use App\Player;
use Illuminate\Http\Request;
use App\Http\Resources\Players as PlayerResource;
class PlayerController extends Controller
{
public function index(Request $request)
{
$room = $request->input('sessionId');
$currentPlayers = Player::where('userSession', $room)->get();
return PlayerResource::collection($currentPlayers);
}
public function create()
{ }
public function update()
{ }
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Player extends Model
{
protected $fillable = [];
public $sortable = [
'userId',
'userName',
'userVote'
];
public function sessions()
{
return $this->hasMany('App\Session');
}
public function players(){
return $this->belongsToMany('App\Session');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Session extends Model
{
protected $fillable = [];
public function user(){
return $this->belongsToMany('App\Player');
}
public function creator()
{
return $this->hasOne('App\Player', 'userId');
}
}
class Players extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'userId' => $this->sessionId,
'userName' => $this->userName,
'userVote' => $this->userVote
];
}
}
`
[1]: https://stackoverflow.com/questions/58062014/display-db-entries-in-json-array-in-controller-laravel-php
Your Player class might extends the Illuminate\Http\Resources\Json\JsonResource instead of ResourceCollection.
This should solve your problem.
use Illuminate\Http\Resources\Json\JsonResource;
class Players extends JsonResource
{
/**
* Transform the resource collection into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'userId' => $this->sessionId,
'userName' => $this->userName,
'userVote' => $this->userVote
];
}
}
Hope it helps.
Following are my relations in laravel , I am unable to access company using User's Object, but i am getting null when i try to access it, please see my code below to get the picture
following are my models
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Zizaco\Entrust\Traits\EntrustUserTrait;
use Session;
use Illuminate\Support\Facades\DB;
class User extends Authenticatable
{
use Notifiable;
use EntrustUserTrait;
protected $table = 'tbl_users';
protected $primaryKey = 'id';
protected $guarded = ['id'];
const API = 'api';
const WEB = 'web';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'last_login', 'Address', 'Age', 'DateOfBirth', 'created_by', 'deleted_by'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'is_admin' => 'boolean',
];
public function isAdmin()
{
return $this->is_admin;
}
static function GetUserNamebyID($id)
{
$name = User::select("name")->where(["id" => $id])->pluck('name');
if (isset($name[0])) {
return $name[0];
} else {
return '';
}
}
public function loginlogout()
{
$this->hasMany("App\Models\LoginLogoutLogs", 'userID');
}
public function company()
{
$this->hasMany("App\Models\Company", "company_id");
}
}
And following is my companies Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use DB;
use App\Models\CarePlanData;
use Session;
class Company extends Model
{
protected $table = 'companies';
protected $primaryKey = 'id';
protected $guarded = ['id'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'phone_no', 'address', 'password', 'description', 'city', 'company_logo', 'country', 'email'
];
static public function fetchAllActiveCompanies()
{
return DB::table("companies")->where(['is_active' => 1])->pluck('name', 'id');
}
// change company to hasmany
public function users()
{
return $this->hasmany('App\Models\User');
}
}
and this is how i am trying to access the Company , but i am getting null.
public function fetchCompany(){
$User = User::find($user->id);
dd($User->company());
}
First of all if a user belongs to 1 company then it should be:
public function company()
{
$this->belongsTo("App\Models\Company", "company_id");
}
then fetchCompany() should be
public function fetchCompany(){
$User = User::with('company')->find($user->id);
dd($User->company);
}
You need to use with to load the relations. You pass the name of the function which defines the relation in your User model to with like this with('function_name').
Your actual question is:
You have belongTo Relation between User and Company but when you trying to access the Company via user object, you get null
In your User.php Model put the following function but if you already have then leave it:
public function company()
{
$this->belongsTo("App\Models\Company", "company_id");
}
Then
Replace this function:
public function fetchCompany(){
$User = User::find($user->id);
dd($User->company());
}
To is one:
public function fetchCompany(){
$User = User::find($user->id);
if($User){
dd($User->company()->get());
}
}
or to this one:
public function fetchCompany(){
$User = User::find($user->id);
if($User){
dd($User->company);
}
}
actually if your company_id field is on user model, then your relation should be
public function company()
{
$this->belongsTo("App\Models\Company", "company_id");
}
unless a user can have many companies ?
I'm having some trouble getting my Laravel relationships to work out. In my application, there is a one-to-many relationship between users and ideas. (A user may have multiple ideas.) I'm using Ardent.
Here's my User model:
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
use LaravelBook\Ardent\Ardent;
class User extends Ardent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
protected $fillable = array('first_name', 'last_name', 'email', 'password');
public $validation_errors;
public $autoPurgeRedundantAttributes = true;
public $autoHashPasswordAttributes = true;
public $autoHydrateEntityFromInput = true;
public static $passwordAttributes = array('password');
public static $rules = array(
'first_name' => 'required|between:1,16',
'last_name' => 'required|between:1,16',
'email' => 'required|email|unique:users',
'password' => 'required|between:6,100'
);
public function ideas()
{
return $this->hasMany('Idea');
}
}
And here's my Idea model:
use LaravelBook\Ardent\Ardent;
class Idea extends Ardent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'ideas';
protected $fillable = array('title');
public $validation_errors;
public $autoPurgeRedundantAttributes = true;
public $autoHydrateEntityFromInput = true;
public static $rules = array(
'title' => 'required'
);
public function user()
{
return $this->belongsTo('User');
}
}
Finally, here's my controller code:
class IdeasController extends BaseController {
public function postInsert()
{
$idea = new Idea;
$idea->user()->associate(Auth::user());
if($idea->save())
{
return Response::json(array(
'success' => true,
'idea_id' => $idea->id,
'title' => $idea->title),
200
);
}
else
{
return Response::json(array(
'success' => false,
'errors' => json_encode($idea->errors)),
400
);
}
}
}
$idea->save() throws the error:
{
"error": {
"type": "LogicException",
"message": "Relationship method must return an object of type Illuminate\\Database\\Eloquent\\Relations\\Relation",
"file": "\/var\/www\/3os\/vendor\/laravel\/framework\/src\/Illuminate\/Database\/Eloquent\/Model.php",
"line": 2498
}
}
At first, I was trying to set the user_id in the Idea like so:
$idea->user_id = Auth::id();
I then changed it to:
$idea->user()->associate(Auth::user());
But the results were the same.
Any suggestions would be much appreciated.
You cannot use associate in that direction, since it can only be used on a belongsTo relationship. In your case, an idea belongs to a user and not the other way around.
I suspect there is an error when saving, as you create an idea without the required title, and you then try to get the errors by calling $idea->errors, while it should be $idea->errors().
associate will work on belognsTo relationship , in your cause what you have to use is Attaching A Related Model. See more about Attaching A Related Mode in documentation.