Too few arguments to function Illuminate\Database\Eloquent\Model::setAttribute(), 1 passed - php

i want to ask about error "Too few arguments to function Illuminate\Database\Eloquent\Model::setAttribute(), 1 passed "
i try to register users, i use php artisan make:auth to build my authentication. But, i add one field in users migration. and i try to use uuid. this is my code :
User Model
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Traits\Uuids;
class User extends Authenticatable
{
use Notifiable;
use Uuids;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $guarded = ['id'];
protected $table = 'users';
protected $fillable = [
'name', 'email', 'password','phone_number',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
Register Controller
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'phone' => 'required|numeric|min:8',
'password' => 'required|string|min:6|confirmed',
'password_confirmation' => 'required|same:password',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'phone_number' => $data['phone'],
'password' => Hash::make($data['password']),
]);
}
}
Users Migration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->uuid('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->integer('phone_number');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
Uuids Trait
<?php
namespace App\Traits;
trait Uuids
{
/**
*
*/
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->{$model->uuid} =
str_replace('-', '', \Uuid::generate(4)->string);
});
}
}
Please give me advice. Thank You.

I can't find any reference about property or magic property you wrote as below (like a method getUuidAttribute for example)
$model->{$model->uuid} = str_replace('-', '', \Uuid::generate(4)->string);
So, I assume above code would compiled as
$model->{null} = str_replace('-', '', \Uuid::generate(4)->string);
I guess you're looking for $model->id which has the type of database column as a uuid. But, obviously, you can't have a dynamic database column name as it is wrong at all. Example of dynamic column if your snippet is working properly
$model->'6b324d55-433c-455a-88b6-feb2ee6c3709' = 'c3bec822-e5ee-4d91-b1a3-f5f552fd004a';
Something isn't right, right? It would be better if it look like this.
$model->id = 'c3bec822-e5ee-4d91-b1a3-f5f552fd004a';
And of course, make your latest snippet be something as follow
<?php
namespace App\Traits;
trait Uuids {
// to make model run this 'boot' method, append it with your trait name
protected static function bootUuids() { // <-- bootUuids
// parent::boot();
static::creating(function ($model) {
$model->id = str_replace('-', '', \Uuid::generate(4)->string);
});
}
}

Assuming your tables use UUID for primary key
$table->uuid('id')->primary();
Review your trait by setting the value directly to the id
<?php
namespace App\Traits;
use Illuminate\Support\Str;
trait UsesUuid
{
protected static function bootUsesUuid()
{
static::creating(function ($model) {
if (! **$model->id**) {
**$model->id** = (string) Str::uuid();
}
});
}
public function getIncrementing()
{
return false;
}
public function getKeyType()
{
return 'string';
}
}
Now use trait in your model
<?php
namespace App\Models;
use App\Traits\UsesUuid;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Group extends Model
{
use HasFactory;
**use UsesUuid;**
The full post is here
Create good solutions out there guys :)

Related

laravel 9 - Call to undefined method App\Models\User::create() with KeycloakUser

I have a new Laravel 9 application and I am trying to use Keycloak as an SSO.
I am using this package to achieve that. I created the migrations and the seeders to have some data. I am using my own user model extending the KeycloakUser provided by the package.
My seeder does not run and I get this error message:
Call to undefined method App\Models\User::create()
My Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Vizir\KeycloakWebGuard\Models\KeycloakUser;
class User extends KeycloakUser
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array<int, string>
*/
protected $fillable = [
'firstname',
'surname',
'email',
'role',
];
/**
* Get the company that owns the user.
*/
public function company()
{
return $this->belongsTo(Company::class);
}
/**
* Get the comments for the user.
*/
public function comments()
{
return $this->hasMany(Comment::class);
}
}
The migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('firstname');
$table->string('surname');
$table->string('email')->unique();
$table->unsignedBigInteger('company_id')->nullable();
$table->enum('role', ['user', 'admin', 'superadmin'])->default('user');
$table->rememberToken();
$table->timestamps();
$table->foreign('company_id')->references('id')->on('companies');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
};
The seeder
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\User;
class UserSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
User::create([
'firstname' => 'Aaaa',
'surname' => 'Bbbb',
'email' => 'ab#first.com',
'role' => 'superadmin',
]);
}
}
What you can try to do is copy KeycloakUser into app\Models.
Rename the file and class to User and than add extends Model.
namespace Vizir\KeycloakWebGuard\Models;
use Auth;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements Authenticatable
{
....
// all of these methods are originated from KeycloakUser
And dont forget to adjust your config/auth.php
'providers' => [
'users' => [
'driver' => 'keycloak-users',
'model' => App\Models\User::class,
],
// ...
]

How can if fix this Laravel one to many with a custom foreign key behavior

I'm new to laravel and trying to make two tables with a one (customer) to many(table) relation and a custom Foreign Key tables.customer(I can not change this)
The connection is over customers.id on tables.customer.
After Running php artisan migrate:fresh --seed everything is created as expected. But tables.customer is always 0.
I don't get any errors. And both tables are created correctly.
What do I miss?
Here are my settings:
Models:
Customers.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Customers extends Model {
use HasFactory;
public function tables() {
return $this->hasMany(Tables::class, 'customer');
}
public $timestamps = false;
}
Tables.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Tables extends Model {
use HasFactory;
public function customers() {
return $this->belongsTo(Customers::class, 'customer');
}
public $timestamps = false;
}
Migration:
customers
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up() {
Schema::create('customers', function (Blueprint $table) {
$table->string('id', 6)->primary();
$table
->string('img', 23)
->nullable()
->default(null);
$table->tinyText('name');
$table->tinyInteger('active')->default(1);
$table->bigInteger('created'); // unix timestamp when created
$table
->bigInteger('status')
->nullable()
->default(null); // null not deleted / unix timestamp when deleted
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down() {
Schema::dropIfExists('customers');
}
};
tables
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up() {
Schema::create('tables', function (Blueprint $table) {
$table->string('id', 8)->primary();
$table->tinyText('number');
$table->string('customer', 6); // TODO: repalce with uuid
$table->bigInteger('created'); // unix timestamp when created
$table
->bigInteger('status')
->nullable()
->default(null); // null not deleted / unix timestamp when deleted
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down() {
Schema::dropIfExists('tables');
}
};
Factories:
CustomersFactory.php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* #extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Customers>
*/
class CustomersFactory extends Factory {
/**
* Define the model's default state.
*
* #return array<string, mixed>
*/
public function definition() {
return [
'id' => $this->faker->unique()->regexify('[A-Za-z0-9]{6}'),
'name' => $this->faker->company(),
'active' => $this->faker->boolean(),
'created' => $this->faker->unixTime(),
'status' => $this->faker->boolean() ? null : $this->faker->unixTime(),
];
}
}
TablesFactory.php
namespace Database\Factories;
use App\Models\Customers;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* #extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Tables>
*/
class TablesFactory extends Factory {
/**
* Define the model's default state.
*
* #return array<string, mixed>
*/
public function definition() {
return [
'id' => $this->faker->unique()->regexify('[A-Za-z0-9]{8}'),
'number' => $this->faker->unique()->numberBetween(1, 1000),
'customer' => Customers::factory()->create()->id,
'created' => $this->faker->unixTime(),
'status' => $this->faker->boolean() ? null : $this->faker->unixTime(),
];
}
}
Seeders:
customersSeeder.php
namespace Database\Seeders;
use App\Models\Customers;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class CustomersSeeder extends Seeder {
/**
* Run the database seeds.
*
* #return void
*/
public function run() {
Customers::factory()
->count(10)
->hasTables(20)
->create();
}
}
TablesSeeder.php
namespace Database\Seeders;
use App\Models\Tables;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class TablesSeeder extends Seeder {
/**
* Run the database seeds.
*
* #return void
*/
public function run() {
//
}
}
DatabaseSeeder.php
namespace Database\Seeders;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder {
/**
* Seed the application's database.
*
* #return void
*/
public function run() {
$this->call([CustomersSeeder::class]);
}
}
Your issue is that you did not tell each model that the id is not an integer, it is by default (check the source code).
So add this to both models:
protected $keyType = 'string';
public $incrementing = false;
Read about that here.
By inspecting your models, you are recommended to define the table name first.
// ========== SPECIFY TABLE TO USE (https://stackoverflow.com/a/51746287/19250775) ========== //
protected $table = "users";
And then you need to define fillable properties in order to mass assign your database, as the docs said.
// ========== MASS ASSIGNABLE ATTRIBUTES ========== //
protected $fillable =
[
'id',
'name',
'email',
];
Or if you want every column becomes fillable just add guarded attribute.
protected $guarded = [];

ErrorException Trying to get property 'User' of non-object ( laravel )

I am getting the error:
ErrorException Trying to get property 'User' of non-object
from the statements below which don't seem to work:
$user = Mobile::find(3)->User;
dd($user);
rest of the code is as follows:
usercontroller.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\Mobile;
use Hash;
class UserController extends Controller
{
public function addUserMobile()
{
$user = new User;
$user->name = "Test Name";
$user->email = "test#mnp.com";
$user->password = Hash::make("12345678");
$user->save();
$mobile = new Mobile;
$mobile->mobile = '123456789';
$user->mobile()->save($mobile);
}
public function index()
{
// get user and mobile data from User model
$user = User::find(3);
// var_dump($user->name);
// var_dump($user->mobile->mobile);
// // get user data from Mobile model
$user = Mobile::find(3)->User;
dd($user);
// // get mobile number from User model
// $mobile = User::find(3)->mobile;
// dd($mobile);
}
}
mobile.php
<?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;
class User extends Authenticatable
{
use HasFactory, 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 mobile()
{
return $this->hasOne(Mobile::class);
// note: we can also inlcude Mobile model like: 'App\Mobile'
}
}
mobile table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMobilesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('mobiles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->string('mobile');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('mobiles');
}
}
mobile database
user database
"3" is user_id btw.
The problem is you are querying the Mobile with id 3 (which does not exist) and then calling the user relation.
$user = Mobile::find(3)->user;
Since Mobile::find with an id that doesn't exist returns null, you are calling ->user on null, and you will get the error you mentioned.
Also, you should add a belongsTo relation in your Mobile model:
public function user()
{
return $this->belongsTo(User::class);
}
Now, after fixing your query to use user_id, you can do:
$user = Mobile::where('user_id', 3)->first()->user;

function attempt return false when use username instead of email in laravel 5.8

I want to create auth and use username instead of email
when I use email, it returns true but when I use username, returns false.
This controller handles authenticating users for the application and
redirects them to your home screen. The controller uses a trait
to conveniently provide its functionality to your application.
my LoginController.php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Auth;
use App;
class LoginController extends Controller
{
/**
* Where to redirect users after login.
*
* #var string
*/
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
}
public function login(Request $request){
//$this->validate($request, [
// 'name' => 'required',
// 'password' => 'required|min:3'
//]);
$credentials = [
'email' => $request->input('username'),
'password' => $request->input('password'),
];
if (Auth::attempt($credentials)) {
return redirect()->intended('/dashboard');
}
else
{
$user=new app\User();
return $user::get();
}
}
public function logout(){
Auth::logout();
return route("login");
}
}
this is my model. User.php:
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', '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 getAuthIdentifierName()
{
return "username";
}
}
route.php:
Route::get('/login',function(){
return view("admin.auth.login");
})->name('login');
Route::post('/login',"Auth\LoginController#login");
Route::get('/logout',"Auth\LoginController#logout")->name('logout');
migration code:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements("id");
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Username Customization
By default, Laravel uses the email field for authentication. If you would like to customize this, you may define a username method on your LoginController:
public function username()
{
return 'username';
}
You can put any field in the Auth::attempt() method.
$credentials = [
'username' => $request->input('username'),
'password' => $request->input('password'),
];
Auth::attempt($credentials)
: this will select the user with this username then check if the password match.

Generating Uuid as Primary Key

Please i am having an issue generating a uuid as primary key in my user model. i always PHP Error: Class 'App/Traits/boot' not found in C:/xampp/htdocs/twingle/app/Traits/UsesUuid.php on line 11. Tried various method but this error persist
User Model (App\User)
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Traits\UsesUuid;
class User extends Authenticatable
{
use Notifiable,UsesUuid;
protected $keyType = 'string';
public $incrementing = false;
/**
* 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',
];
}
which use a Trait
UseUuid(App\Traits)
<?php
namespace App\Traits;
use Ramsey\Uuid\Uuid;
trait UsesUuid
{
public static function UsesUuid()
{
boot::creating(function ($model) {
$model->setAttribute($model->getKeyName(), Uuid::uuid4());
});
}
}
User mIgration
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Please any help will be deeply appreciated. thanks
Your trait code looks really inconsistent. It should look something like this:
namespace App\Traits;
use Ramsey\Uuid\Uuid;
trait UsesUuid
{
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->setAttribute($model->getKeyName(), Uuid::uuid4());
});
}
}
That way when the trait is used in a model, it will automatically hook into that model's creating event, and will make sure the primary key is generated as a UUID.
Go for a model Observer. It's much cleaner and the perfect fit. https://laravel.com/docs/5.8/eloquent#observers

Categories