I am trying to use the laravel 5.3 notification system. I have a many to many relationship on a couple of models. What I need to do is loop through all of the request data and send a notification to everyone appropriate. It seems that the notification methods won't work within a foreach loop. The error is:
BadMethodCallException in Builder.php line 2448:
Call to undefined method Illuminate\Database\Query\Builder::routeNotificationFor()
The code I am trying to figure out is:
public function storeHoursused(Request $request, Lessonhours $lessonhours)
{
$this->validate($request, [
'date_time' => 'required',
'numberofhours' => 'required|numeric',
'comments' => 'required|max:700'
]);
$hoursused = new Hoursused();
$hoursused->date_time = $request['date_time'];
$hoursused->numberofhours = $request['numberofhours'];
$hoursused->comments = $request['comments'];
$lessonhours->hoursused()->save($hoursused);
foreach($lessonhours->players as $player){
$player->users;
Notification::send($player, new HoursusedPosted($player->user));
//$lessonhours->player->notify(new HoursusedPosted($lessonhours->player->users));
}
return back()->with(['success' => 'Hours Used successfully added!']);
}
Is there a way to collect related data and pass to notification methods?
UPDATE:
The Players model looks like:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Collective\Html\Eloquent\FormAccessible;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Notifiable;
use Carbon\Carbon;
class Players extends Model
{
public $table = "players";
protected $fillable = array('fname', 'lname', 'gender', 'birthdate');
public function users()
{
return $this->belongsTo('App\User', 'users_id');
}
public function lessonhours()
{
return $this->belongsToMany('App\Lessonhours', 'lessonhour_player', 'players_id', 'lessonhours_id')
->withTimestamps();
}
public function getFullName($id)
{
return ucfirst($this->fname ) . ' ' . ucfirst($this->lname);
}
protected $dates = ['birthdate'];
protected $touches = ['lessonhours'];
public function setBirthdateAttribute($value)
{
$this->attributes['birthdate'] = Carbon::createFromFormat('m/d/Y', $value);
}
}
Your $player model needs to use the Illuminate\Notifications\Notifiable trait.
Related
Updated
User model
class User extends Authenticatable
{
use HasFactory, Notifiable, HasApiTokens, HasRoles;
const MALE = 'male';
const FEMALE = 'female';
protected $guard_name = 'sanctum';
public function educationalBackgrounds()
{
return $this->hasMany("App\Models\Users\EducationalBackground", "user_id");
}
public function seminars()
{
return $this->hasMany("App\Models\Users\Seminar", "user_id");
}
}
I have child table EducationalBackground which is related to User table
class EducationalBackground extends Model
{
use HasFactory;
protected $table = 'users.educational_backgrounds';
protected $fillable = [
'user_id',
'studies_type',
'year',
'course',
];
public function user()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
public function educationalAwards()
{
return $this->hasMany("App\Models\Users\EducationalAward", "educational_background_id");
}
}
And a third table that i want to access the award field
class EducationalAward extends Model
{
use HasFactory;
protected $table = 'users.educational_awards';
protected $fillable = [
'educational_background_id',
'award',
'photo',
];
public function educationalBackground()
{
return $this->belongsTo('App\Models\Users\EducationalBackground', 'educational_background_id');
}
}
I have api get route here
Route::get('/educational-background/{id}', [UserProfileController::class, 'getEducationalBackground']);
Here is my api method it works fine. But i want to go deeper and access the data of third table.
public function getEducationalBackground($id)
{
$educationalBackground = EducationalBackground::with('user')->where('user_id', $id)->get();
return response()->json($educationalBackground, 200);
}
It looks like you're not really grasping the concept of relations yet. Also, I'd advise you to look into route model binding :) What you basically want to be doing is:
public function getEducationalBackground($id)
{
$user = User::find($id);
return $user->educationalBackgrounds()->with('educationalAwards')->get();
}
Also, when you're pretty sure that whenever you want to use backgrounds, you also want to use the awards, you can add the with(...) to the model definition like so:
class EducationalBackground extends Model
{
...
protected $with = ['educationalAwards'];
}
That way, you can simplify your controller method to:
public function getEducationalBackground($id)
{
$user = User::find($id);
return $user->educationalBackgrounds;
}
I have two models (Categories and Channels) in a Morph Relation with Status (active, inactive).
In the moment of creating a new category or a new Channel I need to assign the active status to the new created element. For that, I need to pass the $type (channel or category) and the id of the "statusable" element.
Here is my CategoryController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\CategoriesRequest;
use App\Profile;
use App\Status;
use Session;
use Auth;
class CategoriesController extends Controller
{
public function store(CategoriesRequest $request)
{
$category = Category::create([
'title' => $request->title,
'slug' => str_slug($request->title, '-'),
'about' => $request->about,
]);
$category->save();
$type = 'categories';
$id = $category->id;
$status = (new Status)->create($id, $type); <-- Hier I am passing the two variables to the function CREATE in Status Model
Session::flash('success', 'Category successfully created!');
return redirect()->route('categories.show', $category->slug);
}
}
And hier the STATUS Model with the CREATE method which receive the two variables
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use App\Status;
Relation::morphMap([
'channels' => 'App\Channel',
'categories' => 'App\Category',
]);
class Status extends Model
{
protected $fillable = [
'status',
'statusable_type',
'statusable_id',
];
public function statusable()
{
return $this->morphTo();
}
public static function create($id, $type)
{ // I do hier dd($id); and dd($type) and the two variables have a value
$status = Status::create([
'statusable_id' => $id,
'statusable_type' => $type,
'status' => 'active', // I get the error here!
]);
$status->save();
return $status;
}
}
I confirmed that the two variables arrived to the CREATE method (I see then if I dd() it) right at the beginning of the method. However two lines after I get this error:
Type error: Too few arguments to function App\Status::create(), 1 passed in C:\laragon\www\streets\app\Status.php on line 41 and exactly 2 expected
What am I doing wrong?
EDIT: I have got myself the solution:
If anybody is interested
I have changed the call in Controller to:
$type = 'categories';
$id = $category->id;
Status::create_status($id, $type);
and then in Status model:
public static function create_status($id, $type)
{
$status = new Status;
$status->statusable_id = $id;
$status->statusable_type = $type;
$status->status = 'active';
$status->save();
return $status;
}
i'm trying to retrieve a column from my database with laravel.. i've confirmed the column actually exists but apparently laravel doesn't think the same.. any help? thanks!
The error is the following..
"Property [Salt] does not exist on this collection instance."
accounts model:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class accounts extends Authenticatable
{
protected $table = "accounts";
public $pkey = 'id';
protected $salt = 'Salt';
protected $fillable = ['id', 'Username', 'Key'];
public $timestamps = false;
}
CustomAuthController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Auth;
class CustomAuthController extends Controller
{
//Login
public function showLoginForm()
{
return view('auth.login');
}
public function login(Request $request)
{
$this->validate($request, [
'username' => 'required|max:255',
'Key' => 'required|max:255',
]);
$user= User::where('Username', '=', $request->username)->get();
$hashedpw = hash('whirlpool', $request->Key);
if(Auth::attempt(['Username' => $request->username, 'Key' => $request->Key]))
{
return 'Logged in successfully';
}
else
{
return 'error'. $request->username. ' '. $user->Salt; #problematic variable <-
}
}
}
Thanks!
Jack
Hi, Again.. I've narrowed down the problem although i cant figure out how to fix it.. If my account isn't logged in on my website i cant seem to access the salt column. But, if i'm logged into the site i can select it?..
use first() instead of get() -
$user= User::where('Username', '=', $request->username)->first();
As mentioned in #Sohel0415 answer, your query returns collection not a single user model. You should use first() instead of get()
Also your salt property visibility identifier is protected, you should change this to public for access property from outside.
You have Salt defined as protected $salt
so try $user->salt;
and it should work fine.
I am using Laravel 5.3 and this model:
namespace App\Models;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Storage;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use SoftDeletes;
protected $table = 'categories';
protected $fillable = [
'name',
'slug',
'description',
'thumbnail',
'parent',
'created_by'
];
protected $hidden = [
'created_by'
];
protected $dates = ['deleted_at'];
public static function getSubcategories($category)
{
return Category::whereParent(Category::whereSlug($category)->first()->id)->get();
}
}
It works perfectly on my localhost server, but when I upload it on my production server, it outputs following error:
Trying to get property of non-object (on line ....)
It is on this line:
return Category::whereParent(Category::whereSlug($category)->first()->id)->get();
(Lines are hidden, because this model has much more functions and would be too long for this post)
Full trace:
its because the Category::whereSlug($category)->first() is returning null and that you are trying to get id of that null. so its as the error states that you are trying to get a property of non object.
I see that you are trying to get self reference category. you could so it this way as a relationships.
//children
public function categories()
{
return $this->hasMany(self::class, 'parent');
}
//parent
public function parent()
{
return $this->belongsTo(self::class, 'parent');
}
if you want to select recursively you could add this too.
public function parentRecursive()
{
return $this->parent()->with('parentRecursive');
}
public function categoriesRecursive()
{
return $this->categories()->with('categoriesRecursive');
}
I wan't to get the name of the user who created is own thread. Like Michael did a thread about food. So at the bottom of the food-thread should be the name of Michael.
I've wrote the code for this but it doesn't really works. Maybe someone of you can find the mistake.
I have two models. A thread Model and a users model.
thread model:
<?php
namespace App\Models\Thread;
use Illuminate\Database\Eloquent\Model;
use App\User;
class Thread extends Model {
public $table = 'thread';
public $fillable = [
'thread',
'content',
'user_id'
];
public function userthread() {
return $this->belongsTo('User','user_id', 'id');
user model:
<?php
namespace App;
use ...
protected $table = 'users';
protected $fillable = ['name', 'email', 'password'];
protected $hidden = ['password', 'remember_token'];
public function threaduser() {
return $this->hasMany('App\Models\Thread\Thread','user_id', 'id');
}
}
and now the controller method, where I'm trying to get the name:
public function show($id)
{
$thread = Thread::query()->findOrFail($id);
$threaduser = Thread::where('user_id', Auth::user()->id)->with('userthread')->get();
return view('test.show', [
'thread' => $thread,
'threaduser' => $threaduser
]);
}
in my html:
{{$threaduser->name}}
The error message I get is :
Undefined property: Illuminate\Database\Eloquent\Collection::$name (View: /var/www/laravel/logs/resources/views/test/show.blade.php)
I hope someone can help me there.
change it to
{{$threaduser->userthread->name}}
change userthread() function in your Thread Class to
public function userthread() {
return $this->belongsTo('App\User','user_id', 'id');
}
get() gives you a Collection not a Model you either have to do a foreach on it like
#foreach ($threadusers as $threaduser)
{{ $threaduser->userthread->name }}
#endforeach
Or use first instead of get if there is only one Thread per User.
Depending on what you want to do, of course.