possible duplicate: How to solve Call to a member function notify() on array? (laravel 5.3)
I am trying to send a database notification to users with admin roles. Since I am using Filament, I also followed the documentation of notifications
First I created a variable called recipients:
$recipients = User::whereHas("roles", function($q) {
$q->whereIn("id", [
1, // Super Admin
6, // Admin
2, // Security Supervisor
5, // Security Manager
]);
})->pluck('email')->toArray();
To check users with the roles id and pluck their emails into an array.
Then I did:
$recipients->notify(
Notification::make()
->title('New Incident Created')
->icon('heroicon-o-document-text')
->toDatabase(),
);
I get an error: Call to a member function notify() on array.
You are doing the notify on an array, also notify needs to be called on the User model as it implements the Notifiable trait: use Notifiable https://laravel.com/docs/9.x/notifications#using-the-notifiable-trait
$recipients = User::role(['Super Admin', 'Admin', 'Security Supervisor', 'Security Manager'])->get();
foreach($recipients as $recipient){
$recipient->notify(
Notification::make()
->title('New Incident Created')
->icon('heroicon-o-document-text')
->toDatabase(),
);
}
Related
I have a coupons table BREAD with Voyager whereby each coupon will have an email address. I would like to send an email to the specific email address which is associated with the coupon when a new coupon has been created.
Coupons table:
For example from the above picture, after I have created the coupon named: haha123, I would like to send an email to cdn#gmail.com.
As I didn't make a custom controller for generating new coupon and has been only using the default BREAD function from Voyager, hence I am unsure where and how should I do it.
SOLVED:
This is most likely not the best way as I didn't make use of the voyager events. Hence, I just do it the troublesome way by adding my own custom voyager CouponsController to overwrite the default controller and add the laravel mail function in the store method of within the custom CouponsController.
Maybe helpful, Send email when model status updated (Laravel Voyager Admin)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Mail;
class Contact extends Model
{
public $table = 'contacts';
public $fillable = ['name', 'email', 'message'];
protected static function boot()
{
parent::boot();
static::updating(function ($contact) {
if ($contact->status == 1) {
Mail::send(
'email',
array(
'name' => $contact->name,
'email' => $contact->email,
'bodyMessage' => $contact->message
),
function ($message) use ($contact) {
$message->from($contact->email);
$message->to('email_address#email.com', 'Name')->subject('Your request status updated');
}
);
}
});
}
}
Voyager just makes your work easy. It creates the model and the controller for you in laravel. You will find the controller and the models in the same place as a custom model or controller created using artisan. I hope it helps.
If you have more questions, please be specific about the issue you are facing.
Cheers
You could very simply hook into the lifecycle of the Coupon model with an event listener:
https://laravel.com/docs/5.6/eloquent#events
First tell the model to fire the CouponCreated event when a new model is created
use App\Events\CouponCreated;
class Coupon extends Model
{
/**
* The event map for the model.
*
* #var array
*/
protected $dispatchesEvents = [
'created' => CouponCreated::class
];
}
That event will be passed the Coupon model which you can use to send the email.
If you want more specific help you'd need to post code. I am sure you could also just do this in the create method of the CouponController if you hunt that down.
I currently have a ticket system built and I would like users to view the status of their Open and Closed tickets.
I can query the database and get all tickets to display, but I only want the logged in users tickets to show. How would I achieve this. Been at it a few days now and I'm at a loss.
What I have:
ROUTE (This returns a 404 due to the {ticketId}) / Note: If I remove the {ticketId} from the Route I get the Type error: *Too few arguments to function App\Http\Controllers\TicketsController::openTickets(), 0 passed and exactly 1 expected"*
Route::get('/tickets/open-tickets/{ticketId}','TicketsController#openTickets')->name('open-tickets');
TICKETS CONTROLLER
public function openTickets($ticketId){
$tickets=Classified::find($ticketId);
$ticketId = Auth::user('id');
$tickets = DB::table('tickets')->orderBy('st_id', 'DESC')->where('status', '=', 'OPEN')->where('user_id', '=', $id)->paginate(4);
return view('tickets.open-tickets',compact('tickets'));
Ticket MODEL
class Ticket extends Model
{
use Notifiable, HasPermissionsTrait;
protected $ticketId = 'st_id';
protected $guarded=[];
protected $dispatchesEvents = [
'created' => Events\NewTicket::class
];
}
WORKING QUERY TO DISPLAY ALL TICKETS
public function openTickets(){
$tickets = DB::table('tickets')->orderBy('st_id', 'DESC')->where('status', '=', 'OPEN')->paginate(4);
return view('tickets.open-tickets',compact('tickets'));
I should mention that I changed my id to st_id on the tickets table as I'm using the ID to display the ticket number like this 201804001
Again I'm just looking for a solution to have the logged in user view their tickets and NOT all tickets in the database.
Image of Tickets Table:
You already have a Ticket model but you're using the DB facade to query the tickets table.
Instead, associate Tickets with Users via a one-to-many relationship.
class Ticket extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
In your User class:
public function tickets()
{
return $this->hasMany(Ticket::class);
}
Now you can do $user->tickets()->where('status', 'OPEN')->get(); to get all the open tickets for that user.
Even further, you can add a scope to the Ticket model.
In your Ticket class:
public function scopeOpen($query)
{
return $query->where('status', 'OPEN');
}
This will allow you to make your queries more fluent:
$user->tickets()->open()->get();
To associate a ticket with a user, simply do something along the following lines:
$user->tickets()->save(new Ticket([
'status' => 'open',
'title' => 'Problem logging in',
'body' => 'Lorem ipsum dolor sit amet'
]));
For more information about Eloquent relationships (specifically one-to-many relationships), see the documentation here.
To list all of a user's open tickets, use the following route:
Route::get('tickets/open-tickets/', 'TicketsController#index');
To show an individual ticket, you'll want the following route:
Route::get('tickets/open-tickets/{ticket}', 'TicketsController#show')
Use the following methods in your TicketsController:
public function index()
{
// user() is a helper for Auth::user()
$tickets = user()->tickets()->open()->paginate(4);
return view('tickets.open-tickets', compact('tickets'));
}
public function show(Ticket $ticket)
{
// If the ticket does not belong to the logged in user, abort
if ($ticket->user_id != user()->id) {
abort(403, 'This is not your ticket');
}
return view('tickets.show', compact('ticket'));
}
You'll notice that the show method in your controller type-hints the Ticket model. This is called route-model binding, which is very useful and you can read more about that here.
It may seem like I'm overcomplicating things compared to your original code, but trust me, it's better to understand these things early on! They'll help you a whole lot during development.
User.php - pretty vanilla hasMany relationship:
public function transactions()
{
return $this->hasMany('App\Transaction');
}
UserTest.php:
public function testTransactionsAttribute()
{
$user = Auth::user();
// Verify logged in user is expected user.
$this->assertTrue($user->username == 'something');
// Pay something.
$transaction = $user->payMembershipFee();
// Verify transaction is in database
$this->seeInDatabase('transactions', ['amount' => 50, 'user_id' => $user->id]);
// Verify transaction belongsTo relationship
$this->assertTrue($transaction->user->username == 'something');
// Verify user hasMany relationship - fails
$this->assertTrue($user->transactions->count() > 0, 'The user should have at least one transaction associated.');
}
Here's where it gets interesting (I did not modify the database tables - just left PHPUnit and switched to Tinker):
$ php artisan tinker
Grab user (verified is same user created from test):
$user = App\User::first()
Copy/Paste assertion:
$user->transactions->count()
=> 1
Also, when I manually go through the steps locally - it works. So, it appears Laravel 5.2 is acting as expected. However, PHPUnit is not.
I'm wondering if it's possible I'm missing something in the way Laravel 5.2 and PHPUnit work with one another?
From outside the model (in the test itself, for example):
$user = $user->fresh();
From inside the model one cannot do something like:
$this = $this->fresh();
So, inside the method that creates the Transaction for the User:
public function createTransaction()
{
$transaction = new Transaction;
...
$transaction->save();
// Refresh the relationship specifically
$this->load('transactions');
// There is also fresh([])
// which is supposed to be able to accept multiple relationships
return $transaction;
}
https://laracasts.com/discuss/channels/testing/refresh-a-model
I am doing an extension build on the User model on larval 5.
What I want to accomplish is once the user registers and is validated I want ANOTHER database table created named userInfo which has a belongsto Relationship with the User model and the User model has a hasOne relationship with userInfo.
Two things.
How to I successfully implement this logic. I was reading
http://laravel.com/docs/master/eloquent-relationships#inserting-related-models
and
http://laravel.com/docs/5.1/events#registering-events-and-listeners
But Im not to sure
And second.
Where best do I implement this logic.
Thanks in advance
PS. I do not what to combine the two database because the user model is when they register and data that lives in userInfo is "optional" for the user to fill out After authentication.
If I am understanding the question correctly, you want to create an additional related model to the user when they register. That should be pretty straightforward - something like:
$user->userInfo()->save(UserInfo::create([
//whatever information you need to save to the userInfo table - if any
]));
as for where to put it, you have options there. You could put it the 'store' method on your registration controller. Or extract it out to a service class 'RegisterUser', and create the user and userInfo there.
something like:
//controller method
public function store(Request $request, RegisterUser $registerUser)
{
$user = $registerUser->handle($request);
return view(....)
}
//RegisterUser class
public function __construct(UserInfo $userInfo)
{
$this->userInfo = $userInfo;
}
public function handle($request)
{
// create your user
$user = .....
$user->userInfo()->save($this->userInfo->create([
.....
]));
// whatever else you need to do - send email, etc
return $user;
}
Edit: If you are using Laravel 5 and the default registration scaffolding, then you can add code to the app\Services\Registar class. This class is called by the postRegister method in the trait. Change the create method:
// app\Services\Registar
public function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
$user->userInfo()->save($this->userInfo->create([
.....
]));
// whatever else you need to do - send email, etc
return $user;
}
If you are using Laravel 5.1 then the Registar class doesn't exist anymore, the create method has been moved to the AuthController (the method is the same, just in a different location) so override it there.
Your answer pointed me in the right direction but I made some simple tweek to your edited question.
$user->userInfo()->firstOrCreate([
'aboutMe' => 'Please Fill out so users can know about you',
'bodyType' => '--',
]);
return $user;
I have a table in database called 'User'. All I want is to get the basic information of the user. I've tried to get data from database but the thing that keep me bugging is that I get all the data inside the table.
UserTable
|id|username|firstname|lasttname|middlename|gender|age|birthdate|address|contact_number|designation|
1 admin lee chiu kim male 47 07-22-87 cebu 0977452445 admin
2 lrose rose loo mar female 27 04-02-88 cebu 0977452445 manager
3 mgray gray men try male 37 01-22-89 cebu 0977452445 employee
UserProfile.php --> Model
<?php
class UserProfile extends Eloquent {
public $timestamps=false;
protected $table = 'users';
protected $fillable=array('firstname','lastname', 'middlename', 'gender', 'age', 'birthdate', 'address', 'contact_number', 'designation');
}
This is the model of my site.
UserProfileContoller.php --> Controller
<?php
class UserProfileController extends \BaseController {
public function index($id)
{
$userprofile = User::find($id);
return View::make('userprofile.index', array('userprofile' => $userprofile));
//return View::make('userprofile.index')->with('UserProfiles',UserProfile::get());
}
For example I am currently log in to username admin and I want to edit and view my profile. How can I get the data just for admin only. Please Help.
The situation hers is that. let say they have 3 employees. So in the table 3 username. lets assume that I'm not the admin. I will log in using lrose. and the other one log in as admin and so.on. If the three of us will go to our profiles the only thing to display there is their own profile and can edit it.
Assuming you property set-up your database why not just use the DB object?
// In the User table find the item with the username 'admin'
DB::table('User')->where('username', '=', 'admin')->get();
To get the information of some user that is logged in (given you have their username), called something like $userprofile. Then all we need to do is find by id then get the username:
// $id is the ID of the logged in user
$userprofile = User::find($id)->username; // get username of logged in user
$userprofile::find($id) will get you the information for admin only, if $id = 1.
find() only returns 1 tuple from the database.
After you call find(), you can access the data as such:
$userprofile->firstname
you mean when you pass $id to index method of User Controller all the data of other users are returned?
That's kinda weird.
$userprofile = User::find($id); change that line to $userprofile = User::find(1); and see if you can only get the data of admin.
If not, probably you are calling other method. Probably you iterate over the index method somewhere else for multiple times so that you get all the data in the database. To confirm both possibilities, just add echo 'I am in' at the entry point of your index method. If no echo message is shown, the first possibility is true. If multiple echo messages occur, the second possibility is true.
Hope this helps.
first of all, you need to use Session after login and store the id of the username in the Session.
e.g.
Step 1:
if($login) //successfull login
{
Session::put('userid', $userid);
//this id, you have to retreive it from the database after successful login
}
Step 2:
Setup the route
Route::get('profile',['uses' => 'UserProfileContoller#index']);
Step 3:
Controller
public function index()
{
if(is_null(Session::get('userid'))) return Redirect::to('login');
return View::make('userprofile.index', ['userprofile' => $this->model->index()]);
// Above code uses dependency injection to retrieve the information from db.
}
Step 4:
UserProfileModel
public function index()
{
return DB::table('user')->where('id','=', Session::get('userid'))->first();
}
p.s. i find it easier to use query builder than eloquent orm. if you want to use orm, change the code where needed.