BrianA's avatar

Record Loss in Database Table/Data Record Not Being Stored in Databaase Table

Hi,

I am currently storing records (data parameters belonging to different devices) in a phpMyAdmin database (devices table). A piece of equipment and an application is being used to obtain the data from each device, and then storing it into the database table via a post request with all the parameters, using an API route.

The API route, defined in the routes file api.php, being used to store the data/add a device to the devices table is the following:

Route::post('/devices/add','Api\DeviceController@store');

The store method, found in the DeviceController is as follows:

public function store(Request $request)
    {
        $validatedData = Validator::make($request->all(), [
            'qr' => 'required|unique:App\Device,qr',
            'fw' => 'required|numeric',

            ... (more data) ...

            'comments' => 'required',
        ], $messages = ['required' => 'Missing :attribute', 
                        'boolean' => 'Not Boolean :attribute', 
                        'numeric' => 'NaN :attribute',
                        'integer' => 'NaN :attribute',
                        'unique' => 'Duplicate :attribute',
                        'between' => 'Invalid :attribute',
                        'in' => 'Failed :attribute']);

        if ($validatedData->fails()) {
            return response()->json([
                'message' => $validatedData->errors()->first()
            ], 400);

        } else {
            // QR code format validation
            $key   = $request->qr;
            $regex = '$[A-Z]{4}[0-9]{9}$';

            if (!preg_match($regex, $key)) {
                return response()->json([
                    'message' => 'Invalid QR Format'
                ], 400);
            }

            // Save data
            $requestData = $request->all();
            $device = Device::make($requestData);
            $saved = $device->save();

            if ($saved) {
                return response()->json([
                    'message' => 'Device Saved'
                ], 200);
            } else {
                return response()->json([
                    'message' => 'Could Not Save Device'
                ], 500);
            }
        }
    }
  • After each successful 'save', a 200 (OK) response is returned and the application beiing used to scan the physical devices and get the data checks for this error before allowing the user to scan the next device (to store it in the table).

After scanning a number of devices, I noticed that one record (entire data belonging to one device) was missing from the devices table. This means that if 300 devices were scanned, only 299 records were present. However, if a 500 error was returned at any time, this would have been detected by the application.

  • I know that there may be various reasons for issues like this, but could someone kindly point out some common reason why this could happen? Could it be that data is saved successfully (and hence a 200 error is returned and interpreted by the user application as a 'go-ahead' for the next post request), and then 'deleted' immediately after?

I am now implementing Laravel Transactions in my code, for example:

// Save data
DB::beginTransaction();
try {
	$requestData = $request->all();
	$device = BleTag::make($requestData);
	$saved = $device->save();
	DB::commit();
} catch (\Exception $e) {
	DB::rollback();
	//throw $e;
	return response()->json([
		'message' => 'Could Not Save Device'
	], 500);
}
  • Could this help prevent something like this from happening, or it is only useful when performing a group of database operations which are different in nature?

Thank you in advance, Brian

0 likes
4 replies
automica's avatar

@briana in this:

	$requestData = $request->all();
	$device = BleTag::make($requestData);
	$saved = $device->save();

only saves to one model, so i'm not sure what benefit you'll get by using a transaction.

I would suggest you validate your request data though, as if the $device doesn't save it'll be to do with the data you are feeding in being invalid.

A side note, you can simplify your code, by removing the 'elses' as you are returning if the 'if' matches.

see

if ($validatedData->fails()) {
    return response()->json([
        'message' => $validatedData->errors()->first()
    ], 400);
}

// QR code format validation
$key = $request->qr;
$regex = '$[A-Z]{4}[0-9]{9}$';

if (!preg_match($regex, $key)) {
    return response()->json([
        'message' => 'Invalid QR Format'
    ], 400);
}

// Save data
$requestData = $request->all();
$device = Device::make($requestData);
$saved = $device->save();

if ($saved) {
    return response()->json([
        'message' => 'Device Saved'
    ], 200);
}
return response()->json([
    'message' => 'Could Not Save Device'
], 500);
BrianA's avatar
BrianA
OP
Best Answer
Level 1

Hi @automica,

Thanks for the tips. I agree with you about transactions. After going through some documentation, that's what I found out too. I'll go through the validation part again to ensure that the request data is valid before being saved in the table.

Regards, Brian

Snapey's avatar

what happens if you get a duplicate? Is the field you are checking for uniqueness in the same format in the database column? Does it correctly identify duplicates?

What happens in the make() function?

BrianA's avatar

Hi @snapey,

Sorry for the late reply, and thanks for your message!

I would have to check again to be sure, however, when testing the project and inserting a duplicate entry, a 500 error, and a 'Could Not Save Device' error were returned, indicating that the device could not be saved. In fact, the device could not be added again to the database from the user's application and a warning message was displayed.

Thanks again, Brian

Please or to participate in this conversation.