I want to select my balance "column" From user table laravel - php

I'm a beginner in laravel framework,I am in the course of developing an API,and I want to select from users table balance of user when I get her Id in api So I do what I found in documentations in my contoller and i use postman to test my work but always I get a error
this is my controller:
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
class MyBalanceController extends Controller
{
public function index(Request $request)
{
# code...
// $Ads = ads::all();
// return $this->sendResponse($Ads->toArray(), 'Ads read succesfully');
// This is the name of the column you wish to search
$input = $request->all();
$validator = Validator::make($input, [
'user_id'=> 'required'
] );
$Cards = User::where('user_id','=', $request->user_id)->pluck('balance')->toArray();
//$user = Auth::user();
// $Cards = DB::select('select balance from users where id = :id', ['id' => 1]);
return response()->json(['Cards'=>$Cards]);
}
}
this is my modal :
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password','username','lastname','tel','adress','balance'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}

At first you can go to your .env file and set APP_DEBUG to true so you can see your exceptions when developing your app.
Regarding your problem try
$balance = User::findOrFail($request->user_id)->balance;
return response()->json($balance);
If no user was found with that id then a 404 HTTP error will be thrown

Related

Laravel define a default key with value on Model

In my Laravel 8 project I have a model called Campaign, my front-end though is build in Vue JS so needs to have some keys on a Campaign for contextual purposes, such as opening and closing a dropdown menu when looping over the elements, a database column isn't nessecery for this.
I'd like to add some default key/value pairs to my Campaign model, for example: dropdown_is_open and should have a default value of false.
I came across the default attributes for a model and tried adding this but cannot see my new key on the object, what am I missing?
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Campaign extends Model
{
use HasFactory, SoftDeletes;
/**
* Indicates if the model's ID is auto-incrementing.
*
* #var bool
*/
public $incrementing = false;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'campaigns';
/**
* The attributes that are mass assignable.
*
* #var array<int, string>
*/
protected $fillable = [
'campaign',
'template'
];
/**
* The model's default values for attributes.
*
* #var array
*/
protected $attributes = [
'dropdown_is_open' => false
];
}
Index function in controller:
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$campaigns = Campaign::where('user_id', Auth::id())
->orderBy('created_at', 'desc')
->get();
if (!$campaigns) {
return response()->json([
'message' => "You have no campaigns"
], 404);
}
return response()->json([
'campaigns' => $campaigns
], 200);
}
I expect to see:
{
campaign: 'my campaign',
template: '',
dropdown_is_open: false <-- my key
}
Previously I was doing a foreach in my index function and adding the contextual keys on each item, but this would only show for the index function and I'd have to add it everywhere.
I hope something like below helps.
Change it from my_custom_field to dropdown_is_open key (and from getMyCustomFieldAttribute to getDropdownIsOpenAttribute method-name).
Custom attribute (or Accessor)
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
protected $appends = ['my_custom_field'];
public function getMyCustomFieldAttribute()
{
return false;
}
}
The $appends in above is required only,
to ensure that my_custom_field is preset/cached, and even sent as JSON-Response.

Laravel delete linked model's data by user_id in booted function of User model

I've read part of the Laravel docs for events and closures for models, I've got various models in my project whereby a user may have data linked to them in another table by a user_id column, the user_id column that I have in my various tables is structured as an unsigned integer (I'm aware I could've gone with a foreignId column by kind of a legacy approach here)
It looks like:
$table->integer('user_id')->unsigned()->nullable()->index();
I'd like to delete user data by their ID within these other tables and rather than creating a delete function and grabbing each model I want to delete data against, I've utilised the closure booted function and what I believe to be an event to listen and delete related model data, but I experience an error when trying to delete my user account, other data in other tables isn't deleted, the error I get is:
Call to undefined method App\Models\User::releationship()
My user model looks like:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject, MustVerifyEmail
{
use Notifiable, SoftDeletes;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name', 'last_name', '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'
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
/**
* Route notifications for the Slack channel.
*
* #param \Illuminate\Notifications\Notification $notification
* #return string
*/
public function routeNotificationForSlack($notification)
{
$url = $this->slack_webhook;
$webhook = (isset($url) && !empty($url)) ? $url : null;
return $webhook;
}
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::deleted(function ($model) {
$model->relationship()->delete();
});
}
}
And an example (of many) model I have, UptimeChecks looks like:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class UptimeChecks extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'uptime_checks';
/**
* Join user table
*/
public function user()
{
return $this->belongsTo('App\User');
}
}
All is then kicked off by a deleteAccount function in my API, which is deleting the user's account, but isn't deleting data in other tables. What am I missing and how could I do a check to make sure other data is deleted before confirming to the user that their account and linked data is gone?
/**
* Delete account
*
* #return Response
*/
public function deleteAccount(Request $request)
{
// attempt to delete account
try {
$user = User::findOrFail(Auth::id());
$user->delete();
// everything went okay!
return response()->json(['success' => true, 'message' => 'Your account has been deleted'], 200);
} catch (Exception $e) {
// catch the error
return response()->json(['success' => false, 'message' => 'We was unable to delete your account at this time'], 422);
}
}
In Laravel, when doing $model->relationship()->delete(); you will need to have the relationship defined and relationship() seems like it is copy pasted code snippet. Simply add the relationship to your User model.
class User extends Authenticatable implements JWTSubject, MustVerifyEmail
{
...
public function uptimeChecks() {
return $this->hasMany(UptimeChecks::class);
}
}
Now you can access and delete the relationship in your boot method.
$model->uptimeChecks()->delete();
You need to create a function in User.php
public function uptimeCheck()
{
return $this->hasOne('App\UptimeChecks');
}
and change the boot function
$model->uptimeCheck()->delete();
This way you need to do for all related relations.
This probably should be: $model->user()->delete() instead. There's nothing else.
If this shouldn't be the intention, reconsider the direction of the relationship.

Userpermission pivot-function is only accessible via the Auth class

I have a simple Userpermission System consisting of 3 tables: users, permissions and the pivot table permission_user.
This is the User model:
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
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',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function permissions()
{
return $this->belongsToMany('App\Permission');
}
}
and here is the Permission Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'description', 'level', 'parentpermission',
];
public function users()
{
return $this->belongsToMany('App\User');
}
}
Now when I try to get all the permissions of the currently logged in user with this:
$user_permissions = Auth::user()->permissions()->get();
it works without problems.
But when I try to get another Users Permissions like this:
$user_permissions = User::where('id', '=', $userid)->permissions()->get();
I get the following error:
Method Illuminate\Database\Eloquent\Collection::permissions does not exist.
How do I proceed?
I think you're missing first() here, since you can't get relations of a query builder object. Try this :
$user_permissions = User::where('id', '=', $userid)->first()->permissions()->get();
This first() will actually return User object, and then you can load its relations.
simply you can just add first() method to get just one record and get it's permissions, try this:
$user_permissions = User::where('id', '=', $userid)->first()->permissions;
There's no need to use get() method, this will get all the user permissions directely
Do this -
$user_permissions = User::find($userid)->permissions()->get();

Subscription won't update in database after subscription is updated in Stripe using Laravel Cashier and Jenssegers MongoDB

I am having trouble getting my new subscription to be updated in MongoDB Database. Im using Laravel Cashier, Stripe, and Jenssegers MongoDB.
In the stripe dashboard, users have been successfully added as customers and subscribers.
Here is the ERROR:
[23:24:17] LOG.error: Call to a member function prepare() on null
{"userId":"4ec1b45d36623t2269477d0...
Here is where the ERROR lives:
return true;
}
$statement = $this->getPdo()->prepare($query);
$this->bindValues($statement, $this->prepareBindings($bindings));
Here is my controller:
namespace App\Http\Controllers;
use App\Plan;
use App\User;
use Exception;
use Illuminate\Http\Request;
class CheckoutController extends Controller
{
/**
* The collection name
*
* #var array
*/
public function checkout($plan_id)
{
$plan = Plan::findOrFail($plan_id);
$intent = auth()->user()->createSetupIntent();
return view('billing.checkout', compact('plan', 'intent'));
}
public function process(Request $request)
{
$plan = Plan::findOrFail($request->input('billing_plan_id'));
try {
auth()->user()->newSubscription($plan->name, $plan->stripe_plan_id)-
>create($request->input('payment-method'));
return redirect()->route('billing')->withMessage('Subscribed Successfully');
} catch (Exception $e) {
return redirect()->back()->withError($e->getMessage());
}
}
Here is My User Model:
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Jenssegers\Mongodb\Auth\User as Authenticatable;
use Laravel\Cashier\Billable;
use Illuminate\Foundation\Auth;
class User extends Authenticatable
{
use Billable, Notifiable;
protected $connection = 'mongodb';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'username', 'password', 'phone', 'last_login_at',
'last_login_ip',
];
/**
* The collection name
*
* #var array
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $dates = ['deleted_at'];
/**
* 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',
];
}
Here is My Plan Model:
namespace App;
use Jenssegers\Mongodb\Eloquent\Model;
/**
* #method static findOrFail($plan_id)
*/
class Plan extends Model
{
protected $fillable = [
'name',
'price',
'stripe_plan_id'
];
}
Here is my Subscription Migration:
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Migrations\Migration;
use Jenssegers\Mongodb\Schema\Blueprint;
class CreateSubscriptionsTable extends Migration
{
/**
* The name of the database connection to use.
*
* #var string
*/
protected $connection = 'mongodb';
public function up()
{
Schema::create('subscriptions', function (Blueprint $collection) {
$collection->bigIncrements('id');
$collection->unsignedBigInteger('userid');
$collection->string('name');
$collection->string('stripe_id');
$collection->string('stripe_status');
$collection->string('stripe_plan')->nullable()->change();
$collection->integer('quantity')->nullable()->change();
$collection->timestamp('trial_ends_at')->nullable();
$collection->timestamp('ends_at')->nullable();
$collection->timestamps();
$collection->index(['user_id', 'stripe_status']);
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('subscriptions');
}
}
Please help me figure out the source of this issue and how to solve it.
Make sure your model (i'm guessing it's a model but you didn't mention / show it) that is calling $this->getPdo() is extending Jenssegers eloquent model class and not Laravels.
For example:
Replace
class MyModel extends Model
With
class MyModel extends \Jenssegers\Mongodb\Eloquent\Model
Partial Solution:
Although I am getting the same error below
"Call to a member function prepare() on null {"userId":"4ec1b45d36623t2269477d0...".
In order to get the Subscription to update in the database I went into the Subscription.php file in Cashier and I replaced
use Illuminate\Database\Eloquent\Model;
with
use Jenssegers\Mongodb\Eloquent\Model;
This will fix database update issue, but something wierd is still going on in the Connection.php file causing the error.
$statement = $this->getPdo()->prepare($query);

Laravel Unit test fails with custom attributes

I'm trying to write a unit test on my user model that tests if the soft deleted record is still present in the database.
/**
* check if users are soft deleted only
*
* #return void
*/
public function testUserIsSoftDeleted()
{
$user = factory(User::class)->create();
$user->delete();
$this->assertSoftDeleted('users', $user->toArray());
}
This test runs fine until I add a custom attribute to the model.
<?php
namespace App;
use Laravel\Passport\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use OwenIt\Auditing\Contracts\Auditable;
class User extends Authenticatable implements MustVerifyEmail, Auditable
{
use HasApiTokens, Notifiable, SoftDeletes, HasRoles, \OwenIt\Auditing\Auditable;
protected $guard_name = 'web';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'email', 'password', 'active', 'activation_token', 'email_verified_at'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token', 'activation_token'
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* The attributes that should be added to the JSON response
*
* #var array
*/
protected $appends = ['md5_email'];
/**
* Convert email address into md5 string
*
* #var string
*/
public function getMd5EmailAttribute()
{
return md5(strtolower(trim($this->email)));
}
}
When I run the test I get the following error.
How do I include custom attributes in the Found array?
To skip md5_email from the query, assign the toArray result to an array and unset the md5_email
Something like
public function testUserIsSoftDeleted()
{
$user = factory(User::class)->create();
$user->delete();
$userInfoArray = $user->toArray()
// This should skip md5_email getting added to the query
unset($userInfoArray["md5_email"])
$this->assertSoftDeleted('users', $userInfoArray);
}
As stated by Cerlin the md5_email attribute in not present in the database, that's why you get the error. You have many options to make the test pass. You might simply unset the md5_email from the user array or, for the sake of clarity, rewrite your test as follow:
/**
* check if users are soft deleted only
*
* #return void
*/
public function testUserIsSoftDeleted()
{
$user = factory(User::class)->create();
$user->delete();
$this->assertSoftDeleted('users', $user->only('id', 'name', 'email'));
}

Categories