When you add 1 month to 2019-03-31, PHP will internally just increment the month value 03 to 04. The result is 2019-04-31.
As April has only 30 days, 2019-04-31 has the same meaning as 2019-05-01 has. And that's the reason, why you get one month and zero days as the result.
The DateInterval class has another handy property: days instead of m and d. It will contain the total number of days between the two dates, which equals to 31 (you have to add 31 days to 2019-03-31 to get to the 2019-05-01.
On this value you can implement your own logic, what "one month" is. If you define it as "one month = 30 days", this could be your whished result:
$start_date = new DateTime('31-03-2019');
$end_date = new DateTime('01-05-2019');
$diff = $start_date->diff($end_date);
$months = floor($diff->days / 30);
$days = $diff->days % 30;
echo "day: " . $days . " month: " . $months . "\n";