1
votes

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]
4
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?ka_lin
@ka_lin, I have to map specific fields from my request. For example, $request->formatted_date is set to $document->dateoliverbj

4 Answers

1
votes
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.

0
votes

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.

0
votes

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())
    );
0
votes

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");