How To Handle Array From Laravel Payment Gateway - laravel

I just started learning laravel by building a site with a payment platform.
After a successful payment i get an array returned when i do dd($paymentDetails);
I want to store the reference into the user database but sadly I don't know how to do that.
Here's my controller
public function handleGatewayCallback(Request $request)
{
$paymentDetails = Paystack::getPaymentData();
//dd($paymentDetails);
if ($request) {
$result = json_decode($request, true);
}
if (array_key_exists('data', $paymentDetails) && array_key_exists('status', $paymentDetails['data']) && ($paymentDetails['data']['status'] === 'success')) {
echo "Transaction was successful";
//Perform necessary action
}else{
echo "Transaction was unsuccessful";
}
// Now you have the payment details,
// you can store the authorization_code in your DB to allow for recurrent subscriptions
// you can then redirect or do whatever you want
}
I'll appreciate it if I am pointed to beginner friendly reading materials or tutorials that'll help.

You shouldn't store the reference directly on the users table, instead create an new table that set a relationship to users and stores the reference. This way a User -> HasMany -> Payments:
php artisan make:migration Payments --create=payments
// in your CreatePaymentsTable migration
$table->increments('id');
$table->unsignedInteger('user_id');
$table->unsignedInteger('reference');
...
// add more columns as needed
...
$table->foreign('user_id')->references('id')->on('users');
Create the Payment model and then add the relation in your User model:
public function payments()
{
return $this->hasMany(Payment::class);
}
Now you can store the reference in your controller as follows:
auth()->user()->payments()->create(['reference' => data_get($paymentDetails, 'data.reference')]);

Related

Getting 2 lots of relationship data from a Laravel collection with Yajra Datatables

I am trying to get my Yajra Datatable working correctly but struggling.
Basically I want to get all clients appointments in which the client belongs to the logged in user. I then want to access the Client name and then the appointment data. I have used the following to get the appointment data
$user = User::find(Auth::user()->id);
$data = $user->clients()->with('appointments')->get()->pluck('appointments')->flatten();
return Datatables::of($data)
->make(true);
This allows me to show a row for each appointment that exists for the user-owned clients appointments. But how can I also access the clients name from this?
I have tried many different ways but if I use something like
$data = $user->clients()->with('appointments')->get();
I can access all of the data I need but it shows the existing clients in each row, not all appointments owned by the clients.
My setup is
User Model
public function clients(){
return $this->hasMany(Client::class);
}
public function appointments()
{
return $this->hasManyThrough(Appointment::class, Client::class);
}
Client Model
public function appointments(){
return $this->hasMany(Appointment::class);
}
public function users(){
return $this->belongsTo(User::class);
}
Appointment Model
public function client(){
return $this->belongsTo(Client::class);
}
Thank you
You might be looking for whereHas:
$appointments = Appointment::with('client')
->whereHas('client.users', function ($query) use ($user) {
$query->where('users.id', $user->id)
})
->get();
This translates to: "Give me all the appointments that belong to clients of a specific user".
Just a suggestion, it might be wise (not required at all) to alter your database structure to something more flexible. What if you for instance keep track in you appointment which user is present?
appointments
- user_id
- client_id
This would make your query a bit simpler
// In User
public function appointments()
{
return $this->hasMany(Appointment::class);
}
$user->appointments()->with('client')->get();
You could go even further by making the relation between User and Appointment, Client and Appointment many to many so you could have appointments with more than one user and/or client.

how to show authenticated user data from relations

I'm trying to show the data of the authenticated user from his relation with other tables but can't get it to work, and I'm pretty new to laravel.
the user table has a relation with level table thru level_id, and the level table has a morph relation with the languages table, I'm trying to show the language of the level of the current user
here is my user model relation
public function level()
{
return $this->belongsTo(Level::class, 'level_id');
}
and my level model
public function languages()
{
return $this->morphMany(Language::class, 'langable');
}
and in the language table, I need to get back the title of 0 or 1 like
languages['0']title.
here is my controller
public function profile()
{
$user= User::with('level')->with('offers')->get();
return view('pages.user.index',compact('user'));
}
and here is how I got the auth user
{!! auth()->user()->first_name . ' ' . auth()->user()->last_name !!}
I'm trying to get this to work
{{auth()->user()->level()->languages()->title['0']}}
but it shows me this
Try {{ $user->level->languages->title['0'] }} in your index.blade file since you are passing the $user var from your controller to it. Currently you are using the user from session.
i got the answer guys it goes like this
{{Auth::user()->level->languages[0]->title}}
that'd show the level of the current user
Okay, there are a few steps you need to get done
in your controller:
public function profile()
{
$user = Auth::user(); // gets the logged in user
return view('pages.user.profile', compact('user')); // return view with $user variable
}
in your user model add:
// appends the level data to the $user model
// so every time you retrieve a user, the level data is included and accessible
// after that you can use $user->level in your view file
protected $appends = [
'level'
];
in your level model add:
// appends the languages data to the $user model
// so every time you retrieve a level, the languages data is included and accessible
// after that you can use $level->languages in your view file
protected $appends = [
'languages'
];
NOTE: In Step 3 you are retrieving multiple languages for a level. Is that correct ?
usage in view
$user->level->languages[specificLanguage]->title // if level has multiple languages
$user->level->language->title // if level has one language

making model relationship to user, user can only access its own data

i have 2 main models and some child models with relationController to main models, now i need to add user id to both main and child models so user can only access its own data since users data stay on the same table.
i create belongsToMany relationship from user.php to the models and vice versa with pivot table but nothing happen
i have no idea how to do this since i need simplified database management in case i need to do migration..
can someone share your experience on this..
I can suggest you that you just add user_id [for Backend => backend_users_id ] to models which data you want access to owner only.
now in main model you can define belongsTo relation and in user you can define hasMany relation
main model relationship [if you want to restrict the user in backend side then you need to add backend user relation and same in backend user model]
class MainModel extends Model
{
// Adding relation to user model
public $belongsTo = [
'user' => 'RainLab\User\Models\User',
'backend_users' =>'Backend\Models\User' // for Backend
];
}
adding a relation to the user model [ you need to put this code in your plugin's boot method ]
// Extending User Model
\RainLab\User\Models\User::extend(function($model) {
$model->hasMany['mainmodel'] = ['HardikSatasiya\Plugin\Models\MainModel'];
});
// for Backend users
\Backend\Models\User::extend(function($model) {
$model->hasMany['mainmodel'] = ['HardikSatasiya\Plugin\Models\MainModel'];
});
Now access data [ Front-end side ]
// Returns the signed in user
$user = \Auth::getUser();
dd($user->mainmodel); // it will return collection of related mainmodels
// it will return related data and now its filter by owner
dd($user->mainmodel[0]->otherRelatin);
// for Backend users
// Returns the signed in user
$user = \BackendAuth::getUser();
dd($user->mainmodel); // it will return collection of related mainmodels
// it will return related data and now its filter by owner
dd($user->mainmodel[0]->otherRelatin);
Example filter data in listview based on logged in admin user [ OctoberCMS do not give such functionality out of the box, you can not hide a portion of data records you can hide entire menu or all records based on rights and roles but can not hide partial records ]
public function listExtendQuery($query)
{
$user = \BackendAuth::getUser();
$query->where('backend_users_id', $user->id);
}
to add backend_users_id you can use this code
class MainModel extends Model {
public function beforeSave()
{
$user = \BackendAuth::getUser();
$this->backend_users_id = $user->id;
}
}
if any doubt please comment.

Laravel DB relations

I'm trying to connect users table with user_info. I've found some posts about it and it works, but I've troubles with user_info->id autoincrement.
If I set it to:
$table->increments('id');
I'm getting error that no default value is set, it works only if I add
$table->integer('id')->nullable($value = true);
Here is what I got for now:
User model
public function userinfo()
{
return $this->hasOne('App\Userinfo');
}
Userinfo model
public function user()
{
return $this->belongsTo('App\User');
}
Migration/table structure
public function up()
{
Schema::create('user_info', function (Blueprint $table) {
//There is a problem, if I don't add user_id it says that user_id doesnt exists, so I created user_id and decided to set id to autoincrement but it doesnt works so I made it like that
$table->integer('id')->nullable($value = true);
$table->foreign('id')->references('id')->on('users');
$table->integer('user_id');
$table->string('avatar',255)->default('notset.jpg')->nullable($value = true);
$table->string('looking_for',255)->nullable($value = true);
$table->string('steam_nick',40)->nullable($value = true);
$table->integer('age')->length(3)->nullable($value = true);
$table->integer('isFriendly')->length(2)->nullable($value = true);
$table->integer('isToxic')->length(2)->nullable($value = true);
$table->integer('isLeader')->length(2)->nullable($value = true);
$table->integer('isFunny')->length(2)->nullable($value = true);
$table->integer('isSkilled')->length(2)->nullable($value = true);
$table->text('description')->nullable($value = true);
$table->timestamps();
});
}
Finally UserinfoController
public function update(Request $request, $id)
{
$user = User::findOrFail($id); //Get role specified by id
$this->validate($request, [
'steam_nick'=>'max:120',
'looking_for'=>'required',
'avatar'=>'',
'description'=>'max:450',
'age'=>'min:2'
]);
$input = $request->only(['steam_nick', 'looking_for', 'description','avatar','age']); //Retreive the name, email and password fields
$userinfo = new Userinfo();
if ($userinfo->user_id == null ) {
$userinfo->steam_nick = $request->steam_nick;
$userinfo->looking_for = $request->looking_for;
$userinfo->description = $request->description;
$userinfo->avatar = $request->avatar;
$userinfo->age = $request->age;
$user->Userinfo()->save($userinfo);
} else {
$user->Userinfo()->update($input);
}
}
Phpmyadmin
img
All I need is to set id in user_info same as id in users. I don't need user_id, but couldn't make it works other way, but I'm sure it's wrong.
Okay, let's break it down piece by piece.
First, what I like to do is specifically declare what my table column is as the second argument on any hasOne and belongsTo in a model. It's not strictly necessary since Laravel does some voodoo magic to guess what the table name is - but I recommend it because it makes the relationship very clear. So, I would do this on the user model:
public function userinfo()
{
return $this->hasOne('App\Userinfo', 'user_id'); // it references user_id on your user_info table.
}
Next, let's look at your user_info migration. You were having problems with your primary key id because you were trying to set it as integer when it needs to be increments. We'll tweak the first three lines:
$table->increments('id')->unsigned();
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users'); // foreign references the user_id field in this table, since that's what's making the connection between users and users_info, we point back to the user's id
At this point, if you are able, I recommend php artisan migrate:fresh --seed. It might help with any weird database structures you have prior. This is optional, though. You can try it if it doesn't work straight away.
Now in the controller, I noticed that you were previously referencing $user->Userinfo()->update($input);, but you named the relationship userinfo() in your user model. This is probably one of the things that was giving you an issue. They must match. Try setting up your controller like so:
public function update(Request $request, $id)
{
$user = User::findOrFail($id); //Get role specified by id
$this->validate($request, [
'steam_nick'=>'max:120',
'looking_for'=>'required',
'avatar'=>'',
'description'=>'max:450',
'age'=>'min:2'
]);
$input = $request->only(['steam_nick', 'looking_for', 'description','avatar','age']); //Retreive the name, email and password fields
// Does this user have an info record? If not, create it, else update it.
if (is_null($user->userinfo)) {
// Since you already collected the data in the $input variable, we simply array_merge it with the user's id
Userinfo::create(array_merge([
'user_id' => $user->id,
], $input));
} else {
$user->userinfo()->update($input);
}
return redirect()->back();
}
So, basically what we are doing is checking to see if the user has a related record in the user_info table. If not, create it with the data. If so, simply update it. Since in our migration we declare that user_id cannot be null, we have to grab the user's id off the $user variable, and you've already grabbed all of the necessary data for the user_info table and put it in the $input variable, we simply array_merge() those two arrays when creating the user's info record.
Otherwise, if the related record already exists, we simply update the user_info record using our relationship ->userinfo().
Try that and let me know how it works.

How to use where condition in laravel eloquent

I am using laravel eloquent. I have fetched data from two table using eloquent.
I have post table and chat table. For post table I have model Post.php and for chat table I have model Chat.php. Here is the the eloquent relation I have created to fetch chat for individual post for a user.
in Post.php
public function TeamMessage()
{
return $this->hasMany('App\Chat','post_id');
}
And in Chat.php
public function ChatRelation()
{
return $this->belongsTo('App\Post');
}
it is working perfect. But this relation fetch all messages for a specific post. I want to fetch all unread message from chat table. I have a column named unread in chat table.
Now my question is how I can fetch only unread message for a specific post.
While the other answers all work, they either depend on scopes (which are very useful in many circumstances) or on you having already instantiated an instance of $post, which doesn't let you eager load multiple posts with their messages.
The dynamic solution is this, which will let you fetch either 1 or more posts and eager load their messages with subquery:
$posts = Post::with(['TeamMessage' => function ($query) {
$query->where('unread', true); // This part applies to the TeamMessage query
}])->get();
See in documentation
Edit:
If you, however, want to filter the posts, to only show those that have unread messages, you need to use whereHas instead of with:
$posts = Post::whereHas(['TeamMessage' => function ($query) {
$query->where('unread', true); // This part applies to the TeamMessage query
}])->get();
More in the documentation.
You can also chain whereHas(...) with with(...).
For querying relationships, you have to call them as functions instead of properties, like this:
$unreadPosts = $post->TeamMessage()->where('unread', true)->get();
For more information on this you can take a look at the docs.
You need to create a local scope on your model, information on local scopes can be found here: https://laravel.com/docs/5.6/eloquent#local-scopes
public function scopeUnread($query)
{
return $query->where('unread', 1);
}
Then in your controller/view
$unread = $yourmodel->unread()
First I would change your relation names to the name of the entity in lower case:
in Post.php
public function chats()
{
return $this->hasMany('App\Chat','post_id');
}
And in Chat.php
public function post()
{
return $this->belongsTo('App\Post');
}
public function scopeUnread($query)
{
return $query->where('unread', 1);
}
Then you can use
$post->chats()->unread()->get();

Resources