add a number with the current number in database with Laravel Eloquent - laravel

I have this code to update a payment record if it already exists, if not, just create new one, and it is working ..... but I need to add a new amount to the existing amount for the update case:
try {
Payment::updateOrCreate([
'user_id' => $request->users,
], [
'amount' => $request->amount,
'date' => $mytime,
'number' => $number++,
]);
} catch (\Exception $ex) {
return redirect()->back()->with('status', 'you cannot insert this record');
}

What about using firstOrNew and doing something like this?
https://laravel.com/docs/9.x/eloquent#retrieving-or-creating-models
try {
$payment = Payment::firstOrNew([
'user_id' => $request->users,
], [
'amount' => $request->amount,
'date' => $mytime,
'number' => $number++,
]);
if ($payment->id) {
$payment->amount = $payment->amount + $new_amount;
}
$payment->save();
} catch (\Exception $ex) {
return redirect()->back()->with('status', 'you cannot insert this record');
}
In case a model is found, you will have a payment instance id, then you manipulate the amount.
For new Payment the model instance doesn't have an id then you just save the model.
Note that the model returned by firstOrNew has not yet been persisted to the database. You will need to manually call the save method to persist it.

Related

Not getting data for authenticated user from database in Laravel for setting stripe

I've been trying to get the saved customer id for stripe from database but with no luck.
It works everywhere else, I could get it and save it again if I wanted, but whenever I try to use it in payment intent to automatically renew a subscription, it gives me this error: Trying to get property 'stripecustomerid' of non-object.
this is the bit of the stripe code for recurring charge where the error happens:
public function renew($subscription)
{
\Stripe\Stripe::setApiKey('sk_test_XXXXXXXX');
header('Content-Type: application/json');
try {
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
$user = \Auth::user();
$payment_methods = \Stripe\PaymentMethod::all([
'customer' => $user->stripecustomerid,
'type' => 'card'
]);
$payment_intent = \Stripe\PaymentIntent::create([
'amount' => $subscription->plan->stripePrice(),
'currency' => 'usd',
'customer' => $user->stripecustomerid,
'payment_method' => $payment_methods->data[0]->id,
'off_session' => true,
'confirm' => true,
]);
echo json_encode([
'paymentIntent' => $payment_intent,
]);
}
catch (\Exception $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
}
and stripecustomerid is the name of the column where I saved the customer id.
I can print it in another function, and it works when I use GET, but it just doesn't work when the subscription tries to renew.

Use transaction in laravel

I'm creating new user after that sending notification to user, i don't want to send notifications if user not created whether server side error occurs or on failure of database query. I'm trying to use transaction, but do not have idea where to place transaction code so that if user not created then it should not move to next code block.
$save = new newUser;
if($save->save()){
// Notification block
return response()->json(['status' => true, 'title' => 'Created' , 'message' => 'Data Saved Successfully'],200);
}
else
{
return response()->json(['status' => false ,'title' => 'Error' , 'message' => 'Data Not Saved'],200);
}
Any help is highly appreciated
You can use continue & break in your if else Condition.
If they have user exist then continue otherwise break it.
If there is some error while saving the user, e.g. error in database insert query or some other error, then the $save->save() will throw an exception. So you can handle it like this:
try {
$save->save();
return response()->json(['status' => true, 'title' => 'Created' , 'message' => 'Data Saved Successfully'],200);
} catch (\Exception $e) {
report($e);
return response()->json(['status' => false ,'title' => 'Error' , 'message' => 'Data Not Saved'],200);
}
Furthermore, you can try to catch a particular exception and send an appropriate notification for that failure.

how to perform bulk update with change check in laravel?

I am using laravel, I am using this code in the update function. works fine, but is it possible to save lines of code with bulk insertion?
Example: $product->update($request->all());
But first check if they have sent new data to update.
My Function Update:
public function update(ProductUpdateRequest $request, Product $product)
{
$data = Product::findOrFail($product->id);
$data->category_id = $request->category_id;
$data->name_product = $request->name_product;
$data->description = $request->description;
$data->stock = $request->stock;
$data->price_buy = $request->price_buy;
$data->price_sale = $request->price_sale;
$data->status = $request->status;
if ($data->isDirty()) {
$data->update($request->all());
return response()->json([
'color' => 'green',
'message' => 'CATEGORY EDIT'
]);
} else {
return response()->json([
'color' => 'red',
'message' => 'NO CHANGE DETECTED'
]);
}
}
You can use fill() method to fill the model with data without committing to database. Do the dirty check and then save. Eg:
public function update(ProductUpdateRequest $request, Product $product)
{
$product->fill($request->all()); //no need to use product->find since $product with the id is already injected
if ($product->isDirty()) {
$product->update($request->all()); //or use $product->save(); since model is alraedy filled with new data
return response()->json([
'color' => 'green',
'message' => 'CATEGORY EDIT'
]);
} else {
return response()->json([
'color' => 'red',
'message' => 'NO CHANGE DETECTED'
]);
}
}
Do note that save method actually checks if the model is dirty. So, if you do not want to send custom messages based on whether the model was changed or not, you could just call save() instead of update() without the dirty check.

Laravel insert array to DB and associate another array with it's id's

I am looping through an array and generate 3 arrays. One that goes to Event table, one for address table and another for geoloc table. Problem is that geoloc + address table needs event_id which is a foreign key linked to id in event table. I am doing a bulk insert because there are a lot of records in the array, roughly about 1500. Is it possible to associate address and geoloc with event id when $event is a bulk insert?
foreach ($facebookEvents as $facebookEvent) {
if (!empty($facebookEvent['event_times'][0]['start_time'])) {
foreach ($facebookEvent['event_times'] as $recurrence) {
$eventsArray[] = [
'type' => 'Facebook Event',
'startdate' => date('Y-m-d', strtotime($recurrence['start_time'])),
'endate' => date('Y-m-d', strtotime($recurrence['end_time'])),
'startime' => date('H:i:s', strtotime($facebookEvent['start_time'])),
'endtime' => date('H:i:s', strtotime($facebookEvent['end_time'])),
'title' => $facebookEvent['name'],
'description' => $facebookEvent['description'],
'entity_id' => $event,
];
$addressArray[] = [
'town' => $facebookEvent['place']['location']['city'],
'address' => $facebookEvent['place']['location']['street'],
'postcode' => $facebookEvent['place']['location']['zip'],
// also event id from each $eventsarray
];
$geolocArray[] = [
'lat' => $facebookEvent['place']['location']['latitude'],
'lng' => $facebookEvent['place']['location']['longitude'],
// also event id from each $eventsarray saved
];
}
}
}
} catch (Exception $e) {
$error = $e->getMessage();
$env = config('app.name');
$command = 'Facebook Recalculate';
Notification::route('slack', 'https://hooks.slack.com/services/T30BGA1EW/B7A9TEC3F/N0FqRyzdsdsdsDN5SVxiN')
->notify(new JobErrorNotification($error, $env, $command));
}
}
$event = Event::insert($eventsArray);
//save address array and add $event->id for each one
// same for geoloc
$algolia = Event::all()->searchable();
}

Laravel 5.3 DB:transaction is committing even some queries failed

I have a User model for basic user info, then a Role model and RoleUser model to associate roles with user. On user edit form, additional role can be added to that user. So, here two DB operations are done within a DB::transaction,
1) Update User info into User model
2) Add role to user
The issue is, if "Add role to user" fails, it doesn't Rollback changes in "User" model which already updated successfully.
Here is my sample code-
In Controller:
$response =
DB::transaction(function() use($user_data, $input) {
//Update changes in basic user info using "User" Model
$response = User::updateUser($user_data['user']);
if ($response->status===FALSE) {//not updated
return $response;
}
if (!empty($user_data['roles'])) {
$roles = [];
foreach ($user_data['roles'] as $role) {
$roles[] = ['role_id' => $role, 'user_id' => $user_data['user']['id'], 'created_by' => $this->curr_user->id, 'updated_by' => $this->curr_user->id];
}
//Add new roles to the user using "RoleUser" Model
$response3 = RoleUser::createRoleUser($roles);
if ($response3->status===FALSE) {//failed to add
return $response3;
}
}
return $response;
}, 5);
//source of createRoleUser method in RoleUser model
try {
DB::table($table)->where('id', $id)->update($changes);
} catch (\Illuminate\Database\QueryException $qe) {
return (object) ['status' => FALSE, 'error' => $qe->errorInfo];
} catch (\Exception $e) {
return (object) ['status' => FALSE, 'error' => [$e->getCode(), 'non-DB', $e->getMessage()]];
}
return (object) ['status' => TRUE, 'data' => $changes + ['id' => $id]];
//source of createRoleUser method in RoleUser model
try {
$new_rec_id = DB::table('role_users)->insertGetId($new_data);
$new_rec = FALSE;
if ($new_rec_id) {
$new_rec = DB::table($table)->where('id', $new_rec_id)->first();
}
} catch (\Illuminate\Database\QueryException $qe) {
return (object) ['status' => FALSE, 'error' => $qe->errorInfo];
} catch (\Exception $e) {
return (object) ['status' => FALSE, 'error' => [$e->getCode(), 'non-DB', $e->getMessage()]];
}
return (object) ['status' => TRUE, 'data' => $new_rec];
You have to throw an exception from within the transaction closure in order for the transaction to trigger the rollback. If no exception is thrown, the transaction will commit.
Keeping this in mind, that means the call to the transaction function needs to be wrapped in a try/catch, as the code that handles the rollback will rethrow the exception after the rollback for your application code to handle.
So, your code would look something like:
try {
$response = DB::transaction(function() use($user_data, $input) {
//Update changes in basic user info using "User" Model
$response = User::updateUser($user_data['user']);
if ($response->status===FALSE) {//not updated
// throw exception to trigger rollback
throw new \Exception($response->error);
}
if (!empty($user_data['roles'])) {
$roles = [];
foreach ($user_data['roles'] as $role) {
$roles[] = ['role_id' => $role, 'user_id' => $user_data['user']['id'], 'created_by' => $this->curr_user->id, 'updated_by' => $this->curr_user->id];
}
//Add new roles to the user using "RoleUser" Model
$response3 = RoleUser::createRoleUser($roles);
if ($response3->status===FALSE) {//failed to add
// throw exception to trigger rollback
throw new \Exception($response3->error);
}
}
// return without exception to trigger commit
return $response;
}, 5);
} catch (\Exception $e) {
echo 'uh oh: '.$e->getMessage();
}

Resources