Incomplete json response in a large eloquent-collection's ajax request - laravel
I'm having an error in my Laravel 8 app which uses yajra/laravel-datatables-oracle with server-side rendering, and I can't figure it out so far. What makes it frustating is the fact that this have been working just fine for the last couple of months, and suddenly I got a report about this error just this morning.
So I have a page which shows a table. The table itself is pretty large, with more than 25 columns shown, thousands of total records, and with some nested relationships as well. For this, I use the yajra/laravel-datatables-oracle package with ajax/server-side rendering as I mentioned above. The page has pagination option enabled, and is set to show 50 records by default. The page is functioning correctly when opened in its default condition.
However, an error will happen when user changes the table's page-length to "All". After checking the the route that handles the table's ajax rendering, turns out the error happened because the returned json is not a valid json. So instead of getting a valid json like these:
"data": [
{"id": 1, "name": "Foo"},
// ....
{"id": 999, "name": "Bar"}
]
I get:
"data": [
{"id": 1, "name": "Foo"},
// ....
{"id": 500,
]
// or...
"data": [
{"id": 1, "name": "Foo"},
// ....
{"id": 500, "name": "Ja
]
The point is that the returned response is incomplete, which makes it invalid as a json, which makes the datatables throws a json bad parsing error.
These are the things for you to know:
Remember, this thing have been working fine for the last couple of months.
Just like the example above, the json response (which is incomplete) is always changing everytime I refresh the url. Meaning that it's likely not related to "abnormal" record.
The error occurs only if the selected page-lenght pass a certain amount of number:
It's working when just being selected (up to) 180 items per page (each item has a total of >100 fields).
More than 180 and the error will occur. However, the incompleteness could be anywhere, not in the 181'th item. It could be in the 70th-ish, 90th-ish, etc. In fact, It never returns more than 100 records when the error occur.
I had thought that this might be caused by PHP's memory exhaustion. I tried to set the memory_limit of the PHP to -1 or 999999M, but nothing changes.
This is actually not just happening in one page, but many.
However, there are another pages, that's working totally fine without the error above. The size of the data that it has is roughly the same.
I really have no idea what's the cause of this. Is this because of the server's PHP config, the database (mysql), the ajax request, or what?
Please help. You're much appreciated.
Additional Info
This is one of the method's controller where the error appears.
use App\Models\Instansi;
use App\Models\InstrukturKelasPeriodeTahapan;
use App\Models\Tahapan;
use App\Models\Tahun;
use Illuminate\Http\Request;
use Yajra\DataTables\Facades\DataTables;
public function datatable(Request $request) {
// validate request etc...
$jadwals = InstrukturKelasPeriodeTahapan::query()
->withInstruktur()->withKelasPeriodeTahapan()
->withTarifInTahunAndPeriodeOf($tahun, $periode)
->withPphInTahunAndPeriodeOf($tahun, $periode)
->withCount([
'pamongDalamKelasPeriodeTahapan as jumlah_pamong_yg_mengajar'
])
->whereHasTahunOf($tahun)
->whereHasPeriodeOf($periode)
->whereHasTahapanOf(Tahapan::PPP);
if ($request->instansi) {
if ($request->instansi == Instansi::NON_FOO) {
$jadwals->whereHasInstansiOfNonFoo();
} else {
$jadwals->whereHasInstansiOf($request->instansi);
}
}
return DataTables::of($jadwals)
->addIndexColumn()
->make(true);
}
This should get a total of 1134 records and used to be working just fine. Now, when the error occurs, I get less than 100 records, and the last returned record is incomplete.
These different return syntaxes still giving me incomplete result.
return response()->json(
DataTables::of($jadwals)
->addIndexColumn()
->make(true)
);
return DataTables::of($jadwals)
->addIndexColumn()
->toJson();
return $jadwals->get();
return response()->json($jadwals->get());
However, these sintaxes is returning the complete 1134 records. But I can't use it as it's not using datatable's response format.
return dd($jadwals->get());
return $jadwals->get()->toJson();
And this is a data example of how an item/record should look like when returned completely, with 120 lines in total:
{
"id": 9999,
"kelas_periode_tahapan_id": 999,
"instruktur_id": 999,
"jumlah_pamong_yg_mengajar": 9,
"instruktur": {
"id": 9999,
"id_ref": 9999,
"nama": "Dr. Xxxxx",
"email": "xxxxxxxx#gmail.com",
"tgl_lahir": "95-09-9977",
"nip": "999999999999999999",
"nik": "99999999999999999",
"npwp": "99999999999999999",
"golongan_id": 9,
"jab_fungsional_id": 9,
"instansi_id": 9,
"no_rek": "99999999999",
"nama_bank": "BANK XXXXXXXX",
"bank_cabang": "XXX",
"nama_rek": "Xxxxxxxx Xxxxx Xxxxxxxxx",
"is_active": 9,
"golongan": {
"id": 9,
"description": "XXXXX",
"periodes": [
{
"id": 9,
"tahun_id": 9,
"periode": 9,
"pivot": {
"golongan_id": 9,
"periode_id": 9,
"pph_npwp": 9,
"pph_non_npwp": 9
}
}
]
},
"jab_fungsional": {
"id": 9,
"description": "Xxxxxxxx",
"periodes": [
{
"id": 9,
"tahun_id": 9,
"periode": 9,
"pivot": {
"jab_fungsional_id": 9,
"periode_id": 9,
"tarif": 99999999
}
}
]
},
"instansi": {
"id": 9,
"description": "Xxxxxxxxxxx Xxxxxxxxxxxxx Xxxxxxxxxxxx"
}
},
"kelas_periode_tahapan": {
"id": 999,
"kelas_id": 99,
"periode_tahapan_id": 99,
"is_verified": 9,
"is_locked": 9,
"kelas": {
"id": 99,
"periode_prodi_id": 9,
"description": "Xxxxxxxxxxx Xxxxxxxxxxxxx Xxxxxxxxxxxx",
"nama_grup_wa": "Xxxxxxxx Xxxxxxxxxxx",
"link_grup_wa": "https://xxxxxxxxxxxxxxxxxxxxxxxxx",
"periode_prodi": {
"id": 9,
"prodi_id": 9,
"periode_id": 9,
"prodi": {
"id": 9,
"nama": "Xxxxxxxxxxxxx Xxxxxxxxxxxxx",
"kode": "999",
"is_active": 9
}
}
},
"periode_tahapan": {
"id": 99,
"periode_id": 9,
"tahapan_id": 9,
"ket_hari_ke": 99,
"jadwal": "09-08-9099",
"materi": "Xxxxxxxxxxx Xxxxxxxx Xxxxxxxxxxxxxxxxxxxxx",
"jp_full": 9,
"jp_pamong": 9,
"tahapan": {
"id": 9,
"description": "Xxxxxxxxxxx Xxxxxxxxxxxxx Xxxxxxxxxxxx",
"akronim": "XXX",
"satuan": "XXX"
},
"periode": {
"id": 9,
"tahun_id": 9,
"periode": 9,
"tahun": {
"id": 9,
"tahun": 9099
},
"persentase_honor": {
"id": 9,
"periode_id": 9,
"full_dosen": 900,
"full_gpamong": 900,
"persentase_dosen": 99,
"persentase_gpamong": 99
}
}
}
},
"DT_RowIndex": 1
}
Related
Retrieving data from REST API
I am trying to implement my first project in Laravel that will contain APIs, more specifically the Sportmonks API. What is the best way to get the data and display it in my view? I have managed to display some of the data, but I do not know the correct way to display the data from the "standings", as well as from the tables that it has in it (overall, home, away, total) API returns { "data": [{ "id": 77447501, "name": "1st Phase", "league_id": 501, "season_id": 17141, "round_id": 195000, "round_name": 33, "type": "Group Stage", "stage_id": 77447501, "stage_name": "1st Phase", "resource": "stage", "standings": { "data": [{ "position": 1, "team_id": 62, "team_name": "Rangers", "round_id": 195000, "round_name": 33, "group_id": null, "group_name": null, "overall": { "games_played": 33, "won": 28, "draw": 5, "lost": 0, "goals_scored": 78, "goals_against": 10, "points": 89 }, "home": { "games_played": 16, "won": 16, "draw": 0, "lost": 0, "goals_scored": 47, "goals_against": 2, "points": 48 }, "away": { "games_played": 17, "won": 12, "draw": 5, "lost": 0, "goals_scored": 31, "goals_against": 8, "points": 41 }, "total": { "goal_difference": "68", "points": 89 }, "result": "Championship Round", "points": 89, "recent_form": "WWWWD", "status": null }],.... } }] } Controller public function index() { $response = Http::get('apiurl'); $response->json(); $result = json_decode($response, true); $matches = $result['data']; return view('/api', compact('matches')); }
Instead of returning json you can return object $response = Http::get('apiurl'); $result=$response->object(); $matches=$result->data; return view('/api', compact('matches')); then in your view #foreach($matches as $match) #foeach($match->standings->data as $standing) {{$standing->team_name??null}} #endforeach #endforeach
Any limitation on ORDS post API data volume?
I am trying to send a POST request of huge block of JSON to ORDS but always getting 500 - Internal server error. If I reduce the value to around 2000 the POST API works successfully. I am using a CLOB variable to handle at JSON data inside PL/SQL proc. What could be wrong ? [ { "id": 1382, "name": "PROD_4", "description": "Prod_Smart_Name", "comments": "", "entity": { "id": 14, "entity_name": "data_code" }, "is_active": 1, "is_editable": 1, "is_visible": 1, "is_used": 4, "version": 4, "is_deleted": 0, "guid": "99044d05f0c74df1ad10c8a6a7b035bc", "created_by": "swankhad", "created_date": "04-OCT-17 11.24.08.569000 AM", "last_modified_by": "runigawa", "last_modified_date": "25-JUN-19 09.32.54.000000 AM", "value": [ "23594333089", "496151500740", "881996810051", "5358843633", "213671772739", "5348779195", "5353301001", "2482690600", "23599643375", "23590876041", "5351247103", "5358844706", "23590871124", "61296679111", "23590871127", "23590871128", "23599103268", "4930889250", "213672200260", "23590876040", "213672229060", "53589209680", "23590876043", ..... ] }]
Get the total no of records returned from the API
I'm getting the data for the grid using an API. The api is returning the data in the below format { "current": 1, "rowCount": 10, "rows": [ { "id": 19, "sender": "123#test.de", "received": "2014-05-30T22:15:00" }, { "id": 14, "sender": "123#test.de", "received": "2014-05-30T20:15:00" }, ... ], "total": 1123 } My question is, is it possible the to send back the "total" to the API when the user clicks on next page or search or any other operation?. Basically I want to send the total after the first time data loaded to the grid. ajax: true, post: function () { /* To accumulate custom parameter with the request object */ return { ReportID: "[ReportID]" ,Parameters:"[ReportParameters:Json]" ,RecordsPerPage:ReportOption.pageSize ,Key:drillThroughKey **,Total:{total}** }; } In the above code {total} needs to be the total received at the first time. Thanks
Microsoft LUIS builtin.number
I used builtin.number in my LUIS app trying to collect a 4 digit pin number. The following is what's returned from LUIS when my input is "one two three four". "entities": [ { "entity": "one", "type": "builtin.number", "startIndex": 0, "endIndex": 2, "resolution": { "value": "1" } }, { "entity": "two", "type": "builtin.number", "startIndex": 4, "endIndex": 6, "resolution": { "value": "2" } }, { "entity": "three", "type": "builtin.number", "startIndex": 8, "endIndex": 12, "resolution": { "value": "3" } }, { "entity": "four", "type": "builtin.number", "startIndex": 14, "endIndex": 17, "resolution": { "value": "4" } }, As you can see, it's returning individual digits in both text and digit format. Seems to me that it's more important to return the whole digit than the individual ones. Is there a way to do it so that I get '1234' as result for builtin.number? Thanks!
It's not possible to do what you're asking for by only using LUIS. The way LUIS does its tokenization is that it recognizes each word/number individually due to the whitespace. It goes without saying that 'onetwothreefour' will also not return 1234. Additionally, users are unable to modify the recognition of the prebuilt entities on an individual model level. The recognizers for certain languages are open-source, and contributions from the community are welcome. All of that said, a way you could achieve what you're asking for is by concatenating the numbers. A JavaScript example might be something like the following: var pin = ''; entities.forEach(entity => { if (entity.type == 'builtin.number') { pin += entity.resolution.value; } } console.log(pin); // '1234' After that you would need to perform your own handling/regexp, but I'll leave that to you. (after all, what if someone provides "seven eight nine ten"? Or "twenty seventeen"?)
Laravel - pivot data not available in email
I have the relations in the models as follows: class HotelBooking extends Model { public function rooms(){ return $this->belongsToMany('App\Room', 'hotelbooking_room', 'hotelbooking_id')->withPivot(['quantity', 'addon_id']); } } When I call $booking->rooms()->get();, I should get the following data: "rooms": [ { "id": 28, "hotel_id": 89, "type": "Double", "quantity": 4, "adults": 2, "children": 1, "description": null, "created_at": "2016-05-15 12:24:39", "updated_at": "2016-05-15 15:29:58", "pivot": { "hotelbooking_id": 30, "room_id": 28, "quantity": 1, "addon_id": 386 } } ] Which is normally correct. What's weird is that when I send $rooms to the email data, the pivot attribute is not sent. It works well along the website but in case of sending it in the email it does not. Any idea why?!