I get BadMethodCallException Call to undefined method App\Models\User::identifiableAttribute() - laravel

I get this error after clicking 'New Post' button the frontend of the app:
Posts view
Line from my log file:
[2020-09-27 14:41:03] local.ERROR: Call to undefined method App\Models\User::identifiableAttribute() {"exception":"[object] (BadMethodCallException(code: 0): Call to undefined method App\Models\User::identifiableAttribute() at C:\xampp\htdocs\backpack-demo\vendor\laravel\framework\src\Illuminate\Support\Traits\ForwardsCalls.php:50)
I am using Laravel 7 + Backpack CRDU generator
Posts Controller:
<?php
namespace App\Http\Controllers;
use App\Events\NewPost;
use App\Http\Requests\PostStoreRequest;
use App\Jobs\SyncMedia;
use App\Mail\ReviewPost;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class PostController extends Controller
{
/**
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index(Request $request)
{
$posts = Post::all();
return view('post.index', compact('posts'));
}
/**
* #param \App\Http\Requests\PostStoreRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(PostStoreRequest $request)
{
$post = Post::create($request->validated());
Mail::to($post->author->email)->send(new ReviewPost($post));
SyncMedia::dispatch($post);
event(new NewPost($post));
$request->session()->flash('post.title', $post->title);
return redirect()->route('post.index');
}
}
Posts Model:
class Post extends Model
{
use CrudTrait;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'title',
'content',
'published_at',
'author_id',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'id' => 'integer',
'author_id' => 'integer',
];
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = [
'published_at',
];
public static function create(array $validated)
{
}
public function author()
{
return $this->belongsTo(User::class);
}
}
User model:
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',
];
}

your have forgotten to use 'CrudTrait' in your User Model:
use Backpack\CRUD\app\Models\Traits\CrudTrait;
class User extends Authenticatable
{
use Notifiable,CrudTrait
.......
}

Related

retrive relation table in login request with laravel breeze

Hello I want to include my relation table roles when I login. I used Laravel Breeze for authentication.
Models/User.php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
//old
public function bookmarks(){
return $this->hasMany('App\Model\Post','post_bookmarks','user_id','post_id')->get();
}
public function roles(){
return $this->belongsTo('App\Models\Roles','roles','role_id','id');
}
}
AuthenticatedSessionController.php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AuthenticatedSessionController extends Controller
{
/**
* Display the login view.
*
* #return \Illuminate\View\View
*/
public function create()
{
return view('auth.login');
}
/**
* Handle an incoming authentication request.
*
* #param \App\Http\Requests\Auth\LoginRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(RouteServiceProvider::HOME);
}
/**
* Destroy an authenticated session.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse
*/
public function destroy(Request $request)
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}
LoginRequest.php
namespace App\Http\Requests\Auth;
use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
class LoginRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => ['required', 'string', 'email'],
'password' => ['required', 'string'],
];
}
/**
* Attempt to authenticate the request's credentials.
*
* #return void
*
* #throws \Illuminate\Validation\ValidationException
*/
public function authenticate()
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => __('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
/**
* Ensure the login request is not rate limited.
*
* #return void
*
* #throws \Illuminate\Validation\ValidationException
*/
public function ensureIsNotRateLimited()
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
event(new Lockout($this));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
/**
* Get the rate limiting throttle key for the request.
*
* #return string
*/
public function throttleKey()
{
return Str::lower($this->input('email')).'|'.$this->ip();
}
}
I have used Laravel-breeze for the authentication. It's all working fine but I want to add Role name also when user gets login. As you can see I have also used relationship but I'm confused where can I write the code to get my relation table. This is my code, Can anyone please tell me how can I do?
For Ex.
login email: poojan#gmail.com
role_id = 1
in roles table
id: 1, role_name = "Wholseler"
So when I logged in currently I'm getting user data, But I want roles table data too.
Thanks in Advance
you can use attribute in your user model
protected $appends = ['role_name'];
public function getRoleNameAttribute()
{
return $this->roles->first()->role_name ?? 'N/A';
}
using the above code you will get the role_name attribute in the user instance
if you want roles data into relations of user data try this in user model
protected $with = ['roles'];

How can increase Laravel Sanctum token length

I get a token it has 40 character random string like this...
1|z5F4SMYZRxLo8ScUYMmnExdYtQoJ8eaftQevF0Pa
And I want 240 character random string like this...
1|nvbqwunxjyxujtnqnqcxzhintxyswmsjdunbmuhkifbncgrucxchzirgkybtbcadrjjtjunroewmpidxwiobcvimbolzcjlmeddvusgqzmcakffyzqllbzihnvbqwunxjyxujtnqnqcxzhintxyswmsjdunbmuhkifbncgrucxchzirgkybtbcadrjjtjunroewmpidxwiobcvimbolzcjlmeddvusgqzmcakffyzqllbzih
Please help me for how to increase the length of the Laravel Sanctum Token
Open file: app/Models/User.php then
Check if this file is used Laravel\Sanctum\HasApiTokens trait
Override method: createToken like this:
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
use Laravel\Sanctum\HasApiTokens;
use Laravel\Sanctum\NewAccessToken;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* Create a new personal access token for the user.
*
* #param string $name
* #param array $abilities
* #return \Laravel\Sanctum\NewAccessToken
*/
public function createToken(string $name, array $abilities = ['*'])
{
$token = $this->tokens()->create([
'name' => $name,
'token' => hash('sha256', $plainTextToken = Str::random(240)),
'abilities' => $abilities,
]);
return new NewAccessToken($token, $token->getKey().'|'.$plainTextToken);
}
}
You can use:
$user->createToken('your name token')->plainTextToken;

Cannot sava data in database in notification file in Laravel

I'm using Laravel Notification and i want to save data in my database table if i write my insert query then i'm getting following error otherwise Notification are running :
TypeError: Return value of App\User::getLogNameToUse() must be of the
type string, null
This is the query
public function toMail($notifiable)
{
$users = User::find($notifiable->id);
$users->verification_link=$link;
$users->save();
...
...
}
Model:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Notifications\ResetPasswordNotification;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Activitylog\Traits\LogsActivity;
class User extends Authenticatable
{
use Notifiable, LogsActivity;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'role_id', '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 role()
{
return $this->belongsTo(Models\Role::class);
}
}
Seems like the error is with the logName and without looking at more code and data it is difficult to pinpoint exactly what is wrong.
Following could work
/**
* Get the log name to use for the model.
*
* #param string $eventName
* #return string
*/
public function getLogNameToUse(string $eventName = ''): string
{
return Str::kebab(Str::plural(class_basename($this)));
}
This is just overriding the piece of code causing issue. Give it a try.

Custom cast ignored after updating model

After I update my model, the cast is ignored and an old value that comes from classCastCache is shown.
I'm getting a Illuminate\Http\Testing\File instead of 'GETTING'.
Create a custom cast:
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class Image implements CastsAttributes
{
/**
* Cast the given value.
*
* #param \Illuminate\Database\Eloquent\Model $model
* #param string $key
* #param mixed $value
* #param array $attributes
* #return mixed
*/
public function get($model, $key, $value, $attributes)
{
return 'GETTING';
}
/**
* Prepare the given value for storage.
*
* #param \Illuminate\Database\Eloquent\Model $model
* #param string $key
* #param mixed $value
* #param array $attributes
* #return mixed
*/
public function set($model, $key, $value, $attributes)
{
return 'SETTING';
}
}
Apply it to a model:
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Casts\Image;
class Product extends Model
{
use HasFactory;
/**
* Mass assignable attributes.
*
* #var string[]
*/
protected $fillable = [
'name',
'image',
];
/**
* Model's attribute casting.
*
* #var array
*/
protected $casts = [
'image' => Image::class,
];
}
Create a test for it:
/** #test */
public function it_can_change_product_image()
{
Storage::fake();
$business = Business::factory()->create();
$product = Product::factory()->for($business)->create();
$this->authenticate($business->owner); // Helper to authenticate with Sanctum. Ignore.
// The important part here, sending a fake image.
$response = $this->putJson(route('v1.products.update', $product), [
'image' => UploadedFile::fake()->image('example.jpg'),
]);
$response->assertOk(); // Among other tests that are hidden due demo purposes.
}
Create a Controller action to update the value of it.
/**
* Update the specified resource in storage.
*
* #param UpdateRequest $request
* #param Product $product
* #return ProductResource
*/
public function update(UpdateRequest $request, Product $product): ProductResource
{
// The custom request validator checks for:
// 'image' => ['sometimes', 'file', 'max:1024', 'image', 'mimes:jpg,bmp,png']
// This should update the product image based on the cast.
// The current DB value should be `SETTING`.
$product->update($request->validated());
// This should be `GETTING`.
// Instead, it is: Illuminate\Http\Testing\File
dd($product->image);
// a BAD workaround is to:
$product->refresh();
// This is the correct value `GETTING`.
dd($product->image);
}

laravel policy gves flalse

I am new to laravel and now trying to learn policies so I created the following models:
class group extends Model
{
protected $fillable = [
'id','book_id',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
];
public function users(){
return $this->belongsToMany('BOOK_DONATION\User')->withPivot('last_seen_id');
}
}
and :
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email','country','state/provience','city', 'token', 'password','postal_code',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password','verfied', 'remember_token',
];
public function Book(){
return $this->hasMany('App\Book');
}
public function groups(){
return $this->belongsToMAny('BOOK_DONATION\group')->withPivot('last_seen_id');
}
}
and :
class group_user extends Model
{
//
protected $table='group_user';
protected $fillable = [
'user_id','group_id','last_seen_id'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
];
}
now the group_user is model for the intermidate table required for the many to many relation between users and groups
and here is my policy:
class group_userPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view the group_user.
*
* #param \BOOK_DONATION\User $user
* #param \BOOK_DONATION\group_user $groupUser
* #return mixed
*/
public function view(User $user, group_user $groupUser)
{
//
return in_array($user->id,$groupUser->user_id);
}
}
and here is the specific programming lines from controller related :
$grouUser=group_user::where('group_id',$group_id)->pluck('user_id');
if(Auth::user()->cant('joinChat',$grouUser)) return redirect('/sorry');
now I always get redirected to sorry page but I have the right yo join chat so what is wrong?

Resources