Laravel UpdateOrCreate - laravel

I'm trying to if there are records just update and if there are not records just create. Problem is:
Already has records case: It creates records when there are already have record in database.
public function store(Request $request)
{
$time = $request->input('time');
foreach ($request->input('number') as $key => $value) {
Choice::UpdateOrCreate([
'user_id' => Auth::id(),
'time' => $time,
'topic_id' => $key,
'question_number' => $value,
]);
}
}

You have to pass two parameters to the UpdateOrCreate the first is the attributes of searching records the second is the values in the doc of the method we have :
Create or update a record matching the attributes, and fill it with values.
So if you search the record just with the user_id you have to do it like this :
public function store(Request $request)
{
$time = $request->input('time');
foreach ($request->input('number') as $key => $value) {
Choice::UpdateOrCreate([
'user_id' => Auth::id()
],
[
'time' => $time,
'topic_id' => $key,
'question_number' => $value,
]);
}
}

use this way :
$matchThese=array('user_id' => Auth::id())
Choice::updateOrCreate($matchThese,['topic_id'=>$key,'question_number' => $value,'time' => $time]);

As per Rest Update in crud UpdateOrCreate creates a record if it doesn't finds a matching record. So, you format of Choice::UpdateOrCreate must be like this
Choice::updateOrCreate(['user_id' => Auth::id(),
'time' => $time,], [
'topic_id' => $key,
'question_number' => $value,
])
where ['user_id' => Auth::id(),
'time' => $time,] is the check for existance of a record.

Try replacing the code in the loop with this:
...
Choice::UpdateOrCreate(
['user_id' => Auth::id(), 'time' => $time],
['topic_id' => $key, 'question_number' => $value]
);
...
This will search for a record of user at specific time and create one if there is not, but if there is it will update its topic_id and question_number.

Related

Error column not found, but I did not declare the column?

I'm inserting a record to a polymorphic imageable table, however it says column thread_id not found. I have not declared this thread_id column and I don't know where it's pulling it from. Here is the code it's trying to run.
protected static function bootRecordImage()
{
if (auth()->guest()) return;
foreach (static::getMethodToRecord() as $event) {
static::$event(function ($model) use ($event) {
$body = request()->body;
preg_match_all('/<img .*?(?=src)src=\"([^\"]+)\"/si', $body, $matches);
$images = $matches[1];
if($event == 'created') {
foreach ($images as $image) {
$model->images()->create([
'user_id' => auth()->id(),
'imageable_id' => $model->id,
'imageable_type' => get_class($model),
'path' => $image
]);
}
}
if($event == 'deleting') {
foreach ($images as $image) {
$model->images()->delete([
'user_id' => auth()->id(),
'imageable_id' => $model->id,
'imageable_type' => get_class($model),
'path' => $image
]);
if (File::exists(public_path($image))) {
File::delete(public_path($image));
}
}
}
});
}
}
My store method:
public function store(Request $request, Channel $channel, Spam $spam)
{
if (!auth()->user()) {
return back()->withInput()->with('flash', 'Sorry! You must be logged in to perform this action.');
}
if (!auth()->user()->confirmed) {
return back()->withInput()->with('flash', 'Sorry! You must first confirm your email address.');
}
$this->validate($request, [
'title' => 'required',
'body' => 'required',
'channel_id' => 'required|exists:channels,id',
'g-recaptcha-response' => 'required'
// yes it's required, but it also needs to exist on the channels model, specifically on the id
]);
$response = Zttp::asFormParams()->post('https://www.google.com/recaptcha/api/siteverify', [
'secret' => config('services.recaptcha.secret'),
'response' => $request->input('g-recaptcha-response'),
'remoteip' => $_SERVER['REMOTE_ADDR']
]);
// dd($response->json());
if (! $response->json()['success']) {
throw new \Exception('Recaptcha failed');
}
$spam->detect(request('title'));
$spam->detect(request('body'));
$thread = Thread::create([
'user_id' => auth()->id(),
'channel_id' => request('channel_id'),
'title' => request('title'),
'body' => request('body'),
//'slug' => str_slug(request('title'))
]);
return redirect('/forums/' . $thread->channel->slug . '/' . $thread->slug);
}
As you can see, no where is a thread_id mentioned, yet in the error it looks like it's trying to insert into a thread_id column that I've never declared.
Thanks for reading.
I put the polymorphic relation in the model and the trait. Remove it from the Model and you're good to go.

Laravel 8 factories

Can someone tell me how can I make a factory with relationships etc...
I have a post table with 2 foreign keys: user_id and category_id
I need to generate dummy data but I don't know how to do it.
I have tried to make categories first then to do something with posts and users but did not work.
PostFactory:
public function definition()
{
$title = $this->faker->sentence;
$slug = Str::slug($title);
return [
'title' => $title,
'slug' => $slug,
'image' => $this->faker->imageUrl(900, 300),
'content' => $this->faker->text(300),
];
}
CategoryFactory:
public function definition()
{
$category = $this->faker->words(2, true);
$slug = Str::slug($category);
return [
'category' => $category,
'slug' => $slug
];
}
And user factory is just default one :)
You can check if you have enough records, and query the DB to find a random User and Category to use on each Post. But if there not enough records (20 Users and 7 Categories), create a new one.
PostFactory:
public function definition()
{
$title = $this->faker->sentence;
$slug = Str::slug($title);
$user = User::count() >= 20 ? User::inRandomOrder()->first()->id: User::factory();
$category = Category::count() >= 7 ? Category::inRandomOrder()->first()->id: Category::factory();
return [
'title' => $title,
'slug' => $slug,
'image' => $this->faker->imageUrl(900, 300),
'content' => $this->faker->text(300),
'user_id' => $user,
'category_id' => $category,
];
}

why my updateOrInsert doesn't work laravel

I use updateOrInsert to avoid duplicate data, why doesn't the Update function work and always insert data?
foreach($datas as $data){
DB::table('users')->updateOrInsert([
'user_connect_id' => $user->connect_id,
'description' => $data['description'],
'created_by' => $login->name,
'modified_by' => $login->name,
'created_at' => Carbon::now(),
]);
}
Check out [updateOrInsert] this documentation (https://laravel.com/api/6.x/Illuminate/Database/Query/Builder.html#method_updateOrInsert). You need two parameters. One is the matching attributes (i.e., the attributes you would use to identify your record in case it exists), the other is your array (the new values you wish to insert or update the record with).
updateOrInsert(array $attributes, array $values = [])
Example
DB::table('users')->updateOrInsert(
[
'user_connect_id' => $user->connect_id
],
[
'user_connect_id' => $user->connect_id,
'description' => $data['description'],
'created_by' => $login->name,
'modified_by' => $login->name,
'created_at' => Carbon::now(),
]);
There are two arguments in updateOrInsert method.The updateOrInsert method accepts two arguments: an array of conditions by which to find the record, and an array of column and value pairs containing the columns to be updated.
For e.g :
DB::table('users')
->updateOrInsert(
['email' => 'john#example.com', 'name' => 'John'],
['votes' => '2']
);
Check this link for syntax : Laravel Doc
// Inseart code
public function create()
{
return view('admin.category.create');
}
public function store(Request $request)
{
$this->validate($request,[
'name' => 'required'
]);
$category = new Category();
$category->name = $request->name;
$category->slug = str_slug($request->name);
$category->save();
Toastr::success('Category Successfully Saved','Success');
return redirect()->route('admin.category.index');
}
// Update code
public function edit($id)
{
$category =Category::find($id);
return view('admin.category.edit',compact('category'));
}
public function update(Request $request, $id)
{
$this->validate($request,[
'name' => 'required|unique:categories'
]);
$category = Category::find($id);
$category->name = $request->name;
$category->slug = str_slug($request->name);
$category->save();
Toastr::success('Category Successfully Updated','Success');
return redirect()->route('admin.category.index');
}

Using isDirty in Laravel

I'm using the isDirty() method in my controller to check if any field is changed. Then I am saving the old data of a field and the new data in a table. The code is working fine; however, how can I optimize this code?
By using the below code, I will have to write each field name again and again. If request->all() has 20 fields, but I want to check six fields if they are modified, how can I pass only 6 fields in the below code, without repeating?
Controller
if ($teacher->isDirty('field1')) {
$new_data = $teacher->field1;
$old_data = $teacher->getOriginal('field1');
DB::table('teacher_logs')->insert(
[
'user_id' => $user->id,
'teacher_id' => $teacher->id,
'old_value' => $old_data,
'new_value' => $new_data,
'column_changed' => "First Name",
]);
}
You can set a list of what fields you want to be checking for then you can loop through the dirty fields and build your insert records.
use Illuminate\Support\Arr;
...
$fields = [
'field1' => 'First Name',
'field2' => '...',
...
];
$dirtied = Arr::only($teacher->getDirty(), array_keys($fields));
$inserts = [];
foreach ($dirtied as $key => $value) {
$inserts[] = [
'user_id' => $user->id,
'teacher_id' => $teacher->id,
'old_value' => $teacher->getOriginal($key),
'new_value' => $value,
'column_changed' => $fields[$key];
];
}
DB::table(...)->insert($inserts);
i tried following code after getting idea by lagbox in comments, and i have found solution to my problem.
$dirty = $teacher->getDirty('field1','field2','field3');
foreach ($dirty as $field => $newdata)
{
$olddata = $teacher->getOriginal($field);
if ($olddata != $newdata)
{
DB::table('teacher_logs')->insert(
['user_id' => $user->id,
'teacher_id' => $teacher->id,
'old_value' => $olddata,
'new_value' => $newdata,
'column_changed' => "changed",
]);
}
}

Laravel 5.6 how to delete if there are any records of User

I'm trying to use updateOrCreate in that case but didn't work. So that's why i'm using this. I'll check database before store data. If there are any records of this user I'll delete that record. If there aren't any records I'll create records. Problem is how to delete if there are any records of User.
public function store(Request $request,Choice $choice){
$time = $request->input('time');
$user = Choice::where('user_id','=',Auth::id())->first();
if ($user === null) {
foreach ($request->input('number') as $key => $value) {
Choice::create([
'user_id' => Auth::id(),
'time' => $time,
'topic_id' => $key,
'question_number' => $value,
]);
}
return redirect()->route('choices.index');
}
else{
$choices = Choice::where('user_id',Auth::id())->orderBy('id')->get()->toArray();
dd($choices);
foreach ($choices as $index) {
$index->delete();
}
foreach ($request->input('number') as $key => $value) {
Choice::create([
'user_id' => Auth::id(),
'time' => $time,
'topic_id' => $key,
'question_number' => $value,
]);
}
return redirect()->route('choices.index');
}
}
Your function will be look like this,
public function store(Request $request,Choice $choice){
$time = $request->input('time');
$choice = Choice::where('user_id','=',Auth::id())->first();
if ($choice === null) {
foreach ($request->input('number') as $key => $value) {
Choice::create([
'user_id' => Auth::id(),
'time' => $time,
'topic_id' => $key,
'question_number' => $value,
]);
}
}
else{
$choices = Choice::where('user_id',Auth::id())->delete();
foreach ($request->input('number') as $key => $value) {
Choice::create([
'user_id' => Auth::id(),
'time' => $time,
'topic_id' => $key,
'question_number' => $value,
]);
}
}
return redirect()->route('choices.index');
}
If any confusion feel free to ask and I hope you understand.
You can simply call delete by user id which will make sure if there are any previous record it will be deleted.
public function store(Request $request,Choice $choice){
$time = $request->input('time');
// delete records which belong to user
Choice::where('user_id', Auth::id())->delete();
// add new records
foreach ($request->input('number') as $key => $value) {
Choice::create([
'user_id' => Auth::id(),
'time' => $time,
'topic_id' => $key,
'question_number' => $value,
]);
}
return redirect()->route('choices.index');
}

Resources