1

I am trying to get Laravel to update a database record, if it's already exists. This is my table:

id        |    booking_reference | description | date
------------------------------------------------------
PRI KEY   |    UNIQUE            | MEDIUM TEXT | DATE
AUTO INC  |                      |

My model looks like this:

Document.php:

class Document extends Model
{
    protected $fillable = [
        'booking_reference', 'description', 'date'
    ];

}

And my controller, looks like this - please note that it's webhook() that's being called.

DocumentController.php:

class DocparserController extends Controller
{
    //This is the function to capture the webhook
    public function webhook(Request $request)
    {
        $document = new Document();

        $document->fill($request->all());
        //Grab the date_formatted field from our request.
        $document->date = $request->input('date_formatted');

        $document->updateOrCreate(
            ['booking_reference' => $document->booking_reference],
            //How can I do so it updates all fields?

        );

        return response()->json("OK");
    }
}

So my problem is, that I cannot figure out how to update my entire row, where the booking_reference is already present.

I want to update all fields (description, date), without having to enter them all like:

 ['booking_reference' => $document->booking_reference],
 ['description' => $document->comments, 'date' => $document->date]
2
  • Why not use $request->all() directly or make a method which maps/translates values from the input to a given array (having the appropriate keys: 'booking_reference', 'description', 'date') since you are sending date_formatted instead of date? Commented Aug 20, 2018 at 12:47
  • @ka_lin, I have to map specific fields from my request. For example, $request->formatted_date is set to $document->date Commented Aug 20, 2018 at 12:48

4 Answers 4

1
Document::updateOrCreate(
    ['booking_reference' => $request->input('booking_reference')],
    $request->all() + ['date' => $request->input('date_formatted')]
);

If you wanted to adjust the request inputs before calling that you could do that mapping and slim this down.

$request->merge(['date' => $request->input('date_formatted')]);
// now $request->all() has `date`

...updateOrcreate(
    [...],
    $request->all(),
)

That particular field has to be mapped at some point ... if you really really wanted to you could actually have a middleware do this mapping, which would slim this down to just $request->all() as the second array.

Or even set up a mutator for date_formatted that sets date.

Basically this has to happen somewhere, it just depends where.

Sign up to request clarification or add additional context in comments.

1 Comment

This is very clean and just what I was looking for! Didn't know about the merge() function - definitely helpful!
0

You can use any one of the following to check if the records exists and run the update query if the data already exists.

$user = Document::where('booking_reference', '=', $request->booking_reference)->first();
if ($user === null) {
   // user doesn't exist
}

OR

if (Document::where('booking_reference', '=', $request->booking_reference)->count() > 0) {
   // user found
}

Or even nicer

if (Document::where('booking_reference', '=', $request->booking_reference)->exists()) {
   // user found
}

And i do not think you can update an entire row of data at once. You have to point which attribute to update to which one.

1 Comment

"So my problem is, that I cannot figure out how to update my entire row", have you read the question?
0

I would have a private function to normalize the input data:

private static function transformRequestInput($requestArray)
{
    $map = ['date_formatted'=>'date'];
    foreach($map as $key=>$newKey){
        if(isset($requestArray[$key])) {
            $requestArray[$newKey] = $requestArray[$key];
            unset($requestArray[$key]);
        }
    }
    return $requestArray;
}

And I would use it like so:

    $document->updateOrCreate(
        ['booking_reference' => $document->booking_reference],
        self::transformRequestInput($request->all())
    );

Comments

0

If you want a class or object to associative array (properties must be public):

$updateArr = (array) $document;
$document->updateOrCreate($updateArr);

However, you use a protected property ($fillable) so you must:

$document = new Document();
$document->fill($request->all());
//Grab the date_formatted field from our request.
$document->date = $request->input('date_formatted');

$reflection = new ReflectionClass($document);
$property = $reflection->getProperty('fillable');
$property->setAccessible(true);
$updateArr = (array) $property->getValue($document);
$property->setAccessible(false);

$document->updateOrCreate($updateArr);
return response()->json("OK");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.