I would go for the first option, mostly because I believe that less columns are better.
First of all, the first option would only require an insert when a student is absent, while the second would, first, have an insert for each student at each month, and then for each student that is absent, it would require to update the row each time the student is absent.
The second option would however give a good matrix directly in the database which days a student is absent, but that would be easily achieved through PHP.
Also, having one row per day a student is absent, allows for better statistics when it comes to reporting.
For instance, check how many students that were absent during one month:
select month(date), count(*) from attendance where is_absent = 1 group by month(date);
compared to (here I assume that d1..d31 is an integer with either 1 or 0)
select month(date), sum(d1+d2+d3+d4+d5..+d31) from attendance group by month(date);
Or, if you have a
student table as well (which I assume you will have) and you want to see which students were not absent:
where student_id not in (select student_id from attendance)
from students s
join attendance a on s.student_id = a.student_id
where (d1+d2+d3+d4+d5..+d31) = 0
Finally, since you wanted to store the reason for the student to be absent, it means for option 2 you would either, have one more row for each reason or have one more column for each day which stores the reason, since otherwise you could only store one reason per month, unless you store the reason as a concatenated string in the column which would require a separator and thus limit the characters you put in as reason.
However, in the end it is more of a personal preference, since with correctly created indexes, I doubt that you would have to worry about the performance, but depending on the amount of absent students, option 2 would be using more storage than option 1 (number of columns * rows * size of the data types)