Income & Expense Calculator With PHP [+Source Code]

Share your learning

This is a simple PHP based income and expense calculator without the use of the database.

Are you looking for interesting budget calculator with PHP?

Today, we are going to build an amazing income and expense calculator with PHP only. It’s just for real-time fun, no need to store anywhere.

But If you want then this might be an assignment for you. Isn’t it?

One bonus point is that we also going to learn some interesting jQuery here. Why jQuery?

jQuery helps us to add some extra fun Like add more field, remove field etc.

So, let’s roll-out,

What we are going to build?

Final output screen

What we are going to use?

  1. PHP
  2. Bootstrap
  3. jQuery
  4. HTML 5 Table

let’s dive into it,

Create layout files

We are going to add the following files:

  1. header.php
  2. footer.php

The header file is to link external CSS and Js. Footer file is to link and trigger Js.

You can read about the best position of Js file in HTML document, here.

Header

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    
    <!-- Add page icon -->
    <link rel="icon" href="assets/icon/sb.png" type="image/png" sizes="16x16" /> 
    <title>Income & Expense calculator</title>
    
    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
    
    
    <!-- Latest compiled and minified JavaScript -->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    
    <!-- Add external css  -->
    <link rel="stylesheet" href="assets/css/theme.css" />
</head>
<body>

Footer

    <script src="./assets/js/main.js"></script>
</body>
</html>

Budget calculator

In this file, we will get all the added incomes and expenses. Then calculate the final balance and balance may be positive or negative.

We will also count max records to process max rows of the table, talk about it later.

<?php

$total_income = $total_exp = $balance = $count_inc = $count_exp = $row_length = 0;


if(isset($_POST['inc'])){
    $count_inc = count($_POST['inc']);
    foreach($_POST['inc_amt'] as $amt) {
        $total_income += intval($amt);
    }
}

if(isset($_POST['exp'])){
    $count_exp = count($_POST['exp']);
    foreach($_POST['exp_amt'] as $amt) {
        $total_exp += intval($amt);
    }
}

$row_length = $count_inc > $count_exp ? $count_inc : $count_exp ;

$balance = $total_income - $total_exp;

Create Index file

This file helps us to connect all the other files like layout and budget calculator file.

Let’s look at the code,

<?php
   include_once('layout/header.php');
   include_once('budget_calculator.php');
?>

<div class="container">
    <div class="page-header">
        <h1>Income & Expenses <small>Calculator</small></h1>
    </div>

    <div class="row">
        <div class="col-md-12">
            <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="post">
                <table class="table table-bordered">

                    <thead>
                        <tr>
                            <th colspan="2">Receipients</th>
                            <th colspan="2">Expenditures</th>
                        </tr>
                        <tr>
                            <th>Item</th>
                            <th>Amount</th>
                            <th>Item</th>
                            <th>Amount</th>   
                        </tr>
                    </thead>
                    <tbody>
                        <tr class="head-inputs">
                            <td>
                                <i class="glyphicon glyphicon-plus i-btn add-income-btn"></i> 
                                <input class="inpt" name="income" type="text">
                            </td>
                            <td>
                                <i class="glyphicon glyphicon-piggy-bank i-btn inc-amt"></i>
                                <input class="inpt"  name="income_amt" type="text">
                            </td>
                            <td>
                                <i class="glyphicon glyphicon-plus i-btn add-expense-btn"></i> 
                                <input class="inpt"  name="expense" type="text">
                            </td>
                            <td>
                                <i class="glyphicon glyphicon-piggy-bank i-btn exp-amt"></i>
                                <input class="inpt"  name="expense_amt" type="text">
                            </td>
                        </tr>

                        <?php 
                           
                                for ($i = 0; $i < $row_length; $i++) {        
                        ?>
                            <tr>
                                <td><?php echo isset($_POST['inc'][$i]) ? "<i class='glyphicon glyphicon-minus i-btn remove-income-btn'></i> <input type='text' class='td-inpt' readonly name='inc[]' value='".$_POST['inc'][$i]."' />" : ''; ?></td>
                                <td><?php echo isset($_POST['inc_amt'][$i]) ? "<input type='text' class='td-inpt' readonly name='inc_amt[]' value='".$_POST['inc_amt'][$i]."' />" : ''; ?></td>
                                
                                <td><?php echo isset($_POST['exp'][$i]) ? "<i class='glyphicon glyphicon-minus i-btn remove-expense-btn'></i> <input type='text' class='td-inpt' readonly name='exp[]' value='".$_POST['exp'][$i]."' />" : ''; ?></td>
                                <td><?php echo isset($_POST['exp_amt'][$i]) ? "<input type='text' class='td-inpt' readonly name='exp_amt[]' value='".$_POST['exp_amt'][$i]."' />" : ''; ?></td>
                            </tr>
                        <?php }
                         ?>

                    </tbody>
                </table>
                <div class="well">
                    <button type="submit" class="btn btn-success">Calculate</button>
                    <hr />
                    <p><strong>Income : </strong> <?= $total_income; ?></p>
                    <p><strong>Expenses : </strong> <?= $total_exp; ?></p>
                    <p><strong>Balance : </strong> <?= $balance; ?></p>
                </div>
            </form>
        </div>
    </div>
</div>

<?php
   include_once('layout/footer.php');
?>


Create Js file

This is the bonus point here, we are using some jQuery which will help us to build add a record and remove record system for income and expenses in the table.

We will also use the recursive function concept. Read about recursive function here.

$(document).ready(()=>{
        

    $('.add-expense-btn').click(()=>{
        add_new_record('expense');
    })
    $('.add-income-btn').click(()=>{
        add_new_record('income');
    })

    $(document).on('click', '.remove-income-btn', function(){
        remove_record(this, 'input[name="exp[]"]', [0, 1]);
    })

    $(document).on('click', '.remove-expense-btn', function(){
        remove_record(this, 'input[name="inc[]"]', [2, 3]);
    })
    
})

function remove_parent_row(element) {
    element.remove();
}

function empty_parent_row(element, inx) {
    element.children().map((i, el)=>{
        if(i == inx[0] || i == inx[1]) {
            $(el).html('');
        } 
    })
}

function remove_record(element, search_input, indexes) {
    var parent_row = $(element).closest('tr');
    parent_row.find(search_input).length > 0 ? empty_parent_row(parent_row, indexes) : remove_parent_row(parent_row);    
}


function add_new_record(type) {
    var short_form = type === 'income' ? 'inc' : 'exp';
    var inx = type === 'income' ? [0, 1] : [2, 3];

    var item = $('input[name="'+type+'"]').val();
    var item_amt = $('input[name="'+type+'_amt"]').val();

    
    if(item.length > 0 && item_amt.length > 0 && /^[0-9]*$/.test(item_amt)) {

        var last_row = $('tbody tr:not(.head-inputs)').last();

        var row = last_row.length > 0 ? find_child(last_row, short_form) ? false 
                    : check_prev(last_row, short_form)
                    : false;
    
        var remove_btn = '<i class="glyphicon glyphicon-minus i-btn remove-'+type+'-btn"></i>';

        if(!row) {
            var tr = "<tr><td></td><td></td><td></td><td></td></tr>";
            $('tbody').append(tr);
            row = $('tbody tr').last();
        }
        

        var itm = "<input type='text' class='td-inpt' readonly name='"+short_form+"[]' value=' "+item+" '> ";
        var itm_amt = "<input type='text' class='td-inpt' readonly name='"+short_form+"_amt[]' value=' "+item_amt+" '> ";

        
        row.children().map((i, el)=>{
            if(i == inx[0]) {
                $(el).html(remove_btn+itm);
            } else if(i == inx[1]) {
                $(el).html(itm_amt);
            }
        })

        $('input[name="'+type+'"]').val('');
        $('input[name="'+type+'_amt"]').val('');
    } else {
        alert('Please enter the valid '+type+' source and amount');
    }
}

function check_prev(element, input_name) {
    var prev_input = $(element).prev().not('.head-inputs'); 

    if (prev_input.length > 0) {
        if (!find_child(prev_input, input_name)) {
            return check_prev(prev_input, input_name);
        } 
    } 
    return element;                  
}

function find_child(element, name) {
    return element.children().find("input[name='"+name+"[]']").length > 0;
}

Assignment for you

Here is your assignment, add edit record feature in this project. If you face any kind of issue then please write in the comment section below.

Sum-up

What will learn from the above project?

  1. jQuery to use element traverse system like children, prev and closest etc.
  2. Recursive function system. Sometimes it’s not enough to use loop then we need to use a recursive function approach.
  3. Dynamic element adds and removes through Js.
  4. PHP loops and use of inline conditions like we have used to fill the entered record after calculation.

Done!

Get the source code

Click on the below button to clone code from git-hub repository.

Satpal

View Comments

Recent Posts

How to Switch PHP Versions in XAMPP Easily: Managing Multiple PHP Versions on Ubuntu

Today we are going to learn about managing multiple PHP versions on ubuntu with xampp.…

1 year ago

How to Use Coding to Improve Your Website’s SEO Ranking?

Let's understand about how to use coding to improve your website's SEO. In today’s computerized…

1 year ago

Most Important Linux Commands for Web Developers

Let's understand the most important linux commands for web developers. Linux, as an open-source and…

1 year ago

Top 75+ Laravel Interview Questions Asked by Top MNCs

Today we are going to discuss top 75+ Laravel interview questions asked by top MNCs.Laravel,…

1 year ago

Mailtrap Integration for Email Testing with Laravel 10

Today we will discuss about the Mailtrap integration with laravel 10 .Sending and receiving emails…

1 year ago

Firebase Cloud Messaging (FCM) with Ionic 6: Push Notifications

Today we are going to integrate FCM (Firebase Cloud Messaging) push notifications with ionic application.Firebase…

1 year ago