How to call variables in controller Laravel - php

I'm trying to use Auth::user()->id; and post them with another model under 'user_id' so I don't have to manually give users a 'user_id'.
I've checked and included the required files and I'm getting the users "id" from Users Table
$user_id = Auth::user()->id;
echo $user_id; //this is returning right user "id"
I'm having trouble calling variables and posting it to DB in controller functions any help would be fine.
public function store(Request $request)
{
$user_id = Auth::user()->id;
$this->validate($request, [
'token1' => 'required',
'token2' => 'required'
]);
$tokens = new Tokens([
'user_id' => $user_id,
'token1' => $request->get('token1'),
'token2' => $request->get('token2')
]);
$tokens->save();
return view('/home');
}
Post the User "id" from User table into Tokens table's "user_id" so I can work with models
Getting this error:
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL
constraint failed: tokens.user_id (SQL: insert into "tokens"
("token1", "token2", "updated_at", "created_at") values (asddsadf,
sdfasdf, 2019-09-24 11:53:57, 2019-09-24 11:53:57))
My migration is:
$table->bigIncrements('id');
$table->integer('user_id');
$table->string('token1');
$table->string('token2');
$table->timestamps();

You should avoid filling the user_id in this way.
The error is thrown because user_id is not a fillable property. But the correct way to handle this is with the relationships.
So I suppose that Tokens has a belongsTo relation because of its user_id foreign key (that anyway should be an unsignedInteger column) and in your model you have something like:
public function user() {
return $this->belongsTo(User::class)
}
If you have a look at the offical documentation you will see that you should change your code in this way:
public function store(Request $request)
{
$this->validate($request, [
'token1' => 'required',
'token2' => 'required'
]);
$tokens = new Tokens([
// 'user_id' => $user_id, This is useless
'token1' => $request->get('token1'),
'token2' => $request->get('token2')
]);
// With this method you're going to set the user_id column
$token->user()->associate(auth()->user());
$tokens->save();
return view('/home');
}

Related

General error: 1364 Field 'title' doesn't have a default value while doing update

Hello I faced the following error:
SQLSTATE[HY000]: General error: 1364 Field 'title' doesn't have a default value.
It happens when I try to update amount of views on specific post.
I've just set default value of points while initializing it specified in the model in $attributes table.
Posts table migration:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->longText('text');
$table->integer('points');
$table->bigInteger('views');
$table->integer('user_id')->unsigned()->nullable();
$table->integer('is_closed');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('set null');
});
}
Post model:
const POINTS = 0;
const VIEWS = 0;
const IS_CLOSED = 0;
protected $attributes = [
'points' => self::POINTS,
'views' => self::VIEWS,
'is_closed' => self::IS_CLOSED,
'title' => null,
'text' => null,
'user_id' => null,
];
protected $fillable = [
'title',
'text',
'user_id',
];
My Service where I try to increment the value of views:
public function incrementPostViews($id)
{
$post = $this->post->findOrFail($id);
$post->views++;
return $post->save();
}
I did use the Request rule but only while creating new post:
public function rules()
{
return [
'title' => ['required', 'max:50'],
'text' => ['required', 'max:1000'],
'user_id' => ['numeric', 'nullable'],
];
}
So by default the points, views and is_closed fields are set to 0 while creating new Post. To be honest I do not have any ideas why it is causing an error.
Update:
In Post model I've changed the $attributes array and added title, text and user_id which default value is set to null. Those three fields stays in $fillable array also. I'm not sure if it's the right way to fix it. If it's not, please correct me.
In the migration there are not changes made.
All changes are visible above.
You declared your title item as required in your table but you didn't declare a default value. And your insert operation doesn't give a value for that column, so it fails.
The easiest way to fix this is probably to declare title as nullable instead.
But if you have a good reason to make it required, you'll have to revisit the way you insert your rows so you can offer a value for that column.
You must create THE post first, once that post has been created you can then update its attributes.
$user = Post::create([
'title' => $request->title,
'text' => $request->text,
'points' => 0,
'views' => 0,
'is_closed' => $request->is_closed,
]);

Laravel exists custom validation rule unable to validate user id with phpunit

I have a validation rule taken from the Laravel Documentation which checks if the given ID belongs to the (Auth) user, however the test is failing as when I dump the session I can see the validation fails for the exists, I get the custom message I set.
I have dumped and died the factory in the test and the given factory does belong to the user so it should validate, but it isn't.
Controller Store Method
$ensureAuthOwnsAuthorId = Rule::exists('authors')->where(function ($query) {
return $query->where('user_id', Auth::id());
});
$request->validate([
'author_id' => ['required', $ensureAuthOwnsAuthorId],
],
[
'author_id.exists' => trans('The author you have selected does not belong to you.'),
]);
PHPUnit Test
/**
* #test
*/
function adding_a_valid_poem()
{
// $this->withoutExceptionHandling();
$user = User::factory()->create();
$response = $this->actingAs($user)->post(route('poems.store'), [
'title' => 'Title',
'author_id' => Author::factory()->create(['name' => 'Author', 'user_id' => $user->id])->id,
'poem' => 'Content',
'published_at' => null,
]);
tap(Poem::first(), function ($poem) use ($response, $user)
{
$response->assertStatus(302);
$response->assertRedirect(route('poems.show', $poem));
$this->assertTrue($poem->user->is($user));
$poem->publish();
$this->assertTrue($poem->isPublished());
$this->assertEquals('Title', $poem->title);
$this->assertEquals('Author', $poem->author->name);
$this->assertEquals('Content', $poem->poem);
});
}
Any assistance would be most appreciated, I'm scratching my head at this. My only guess is that the rule itself is wrong somehow. All values are added to the database so the models are fine.
Thank you so much!
In your Rule::exists(), you need to specify column otherwise laravel takes the field name as column name
Rule::exists('authors', 'id')
Since column was not specified, your code was basically doing
Rule::exists('authors', 'author_id')

Laravel unique validation with softdeletes data

I want to use Laravel Unique validator with the implementation of softdeletes. I've been try many times but it produce an error like this. What should i do? Thanks in advance. Here's my code example.
public function store(Request $request)
{
$request->validate([
'nama' => 'required',
'nim' => [
'required',
'size:10',
Rule::unique('students')->where(function ($query) {
return $query->where('deleted_at', NULL);
})
],
'email' => 'required|email',
]);
Student::create([
'major_id' => $request->major_id,
'nama' => $request->nama,
'slug' => Str::of($request->nama)->slug('-'),
'nim' => $request->nim,
'email' => $request->email,
]);
return redirect('/students')->with('status', 'Success');
}
The error you're getting is from a constraint in your database. Nothing you can do in the code can counter that. The database doesnt care for soft delete.
You need to remove the constraint from the database first, then use your solution or the one from this post check-if-name-is-unique-among-non-deleted-items-with-laravel-validation
To remove the constraint, run this query
ALTER TABLE students DROP CONSTRAINT students_nim_unique;
The best practice would be to create a new migration running this query. Carefull for the down() method, you will not be able to put back the constraint if there are dupplicate nim in the table (soft deleted or not)

How to insert into another table after Registration on Laravel?

So, I have a laravel web and have some tables, two of them are users and user_data.
user_data have a foreign key user_id that references to id on users.
users have general attributes like username, email, password, etc. and user_data have 1 on 1 relation with users and have attributes like game_money, game_job, game_tier, etc.
The columns are too long if I combine those 2 into 1 table, so I tought to normalize it.
User registration is working and running smooth. But I don't know how to add a new entry into user_data when a new user registered and add a new entry in users.
The attributes columns in user_data (like game_money,etc.) are filled by external application outside laravel, so all I need is to add an entry to user_data.user_id foreign key, and let the other attributes in user_data use the default values or null before being updated by the external apps.
Here is my user_data migration:
Schema::create('user_data', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
$table->string('account_tier')->default("Free");
$table->float('economy')->default(0);
$table->string('job')->nullable();
$table->timestamps();
});
Where should I put the insert query inside laravel? Or should I handle user_data using the external app?
Thank you very much.
You should use an id on user_data table as your primary key. By the way you can just use the following code for your desired result.
In the registration method use something like below:
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
The user variable is holding the information of the newly created user. Now its time to insert into your user_data table. Assuming the model is UserData.
UserData::create([
'user_id' => $user->id,
............
]);
In RegisterController
inside create function
$user= User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
//UserData is the Model of user_data table
$user->UserData->create(['job'=>$data['job']]);
return $user
Try To This Example:
use Illuminate\Support\Facades\DB;
$user_data= array(
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
);
$role_data= array(
'user_name' => $data['name'],
'email' => $data['email']
);
$response = DB::table('users')->insert($user_data);
$response = DB::table('role')->insert($role_data);
You can use the Model boot events as following when you define relationship each other these models;
public static function boot()
{
parent::boot();
self::created(function($model){
$model->userData()->create([
'user_id' => $model->id,
'job' => $model->job
]);
});
}

Laravel addOrUpdate() on basis of related table values?

Below is something I am trying to do:
I have users table and user_profiles table and I am inserting name, email in users table and phone, address, .... etc in user_profiles table.
I have to match each value to prevent duplication of user, I have found this laravel method addOrUpdate() but it works only for one table. But I have to match user_profiles values too i.e phone,address.
Below is example code
$result = $customer->updateOrCreate([
'name' => $request->name,
'city_id' => $request->city_id,
'area_id' => $request->area_id,
'email' => $request->email
], [
'name' => $request->name,
'city_id' => $request->city_id,
'area_id' => $request->area_id,
'email' => $request->email
]);
There any way to achieve this using Laravel techniques?
Regards
First make a relationship with user and user_profiles model like-
public function userProfile()
{
return $this->hasOne('App\Model\UserProfile','user_id','id');
}
And then in your post controller as you want to match each value to prevent duplication of user-
$result = User::where('name',$request->name)->where('email',$request->email)
->whereHas('userProfile', function($q) use ($request){
$q->where('city_id'$request->city_id)->where('area_id',$request->area_id)
)->first();
if(!$result){
////your registration here
}
If you want to check if a user with exactly the same data exists, you can't use updateOrCreate(). Do this instead:
$user = User::where('name', $request->name)->where('email', $request->email)->first();
$profile = $user->profile()->where('phone', $request->phone)->where('address', $request->address)->count();
if ($user && $profile) {
// User exists.
}
I would recommend using Laravel's Validator Facade. https://laravel.com/docs/5.4/validation#manually-creating-validators
This would check to make sure the name and email fields of the users and users_profile table are unique.
$validator = Validator::make($request->all(), [
'name' => 'required|unique:users|unique:users_profile',
'email' => 'required|unique:users|unique:users_profile',
]);
You could use updateOrCreate for both of your models for sake of uniqueness i assume email should be unique so first updateOrCreate() method will check if user exists for parameter $request->email then update if not then create and return user model instance (in both update/create case)
Second updateOrCreate() on UserProfile will check if there exist any data for user_id then update else add new row, I assume user_id will be a foreign key in user profile table
$user = User::updateOrCreate([
'email' => $request->email
], [
'name' => $request->name,
'email' => $request->email
]);
UserProfile::updateOrCreate([
'user_id' => $user->id
], [
'user_id' => $user->id,
'city_id' => $request->city_id,
'area_id' => $request->area_id
]);

Categories