プログラミング

プログラミング初心者のPHP修羅の道#1〜簡単な計算機アプリ〜

今回から新しく「PHP修羅の道シリーズ」の記事を上げていくことにいたしました。というのも、新しく参画する現場がPHPを使用することと個人的に元々知識をつけていきたかった言語であったことからしっかりと学習していこうという経緯になります。

今後はPHP資格「PHP技術者検定試験」に関する記事や、自己学習として作成したアプリに関する記事などPHP関連の記事をシリーズとして投稿していこうと思います。

普段学習に使用している教材はこちらになります。

まずは今回はシリーズの第一弾として「簡易電卓アプリ」に関する記事となります。

アプリの作成

作成したアプリ

操作映像

完成イメージ

簡易電卓アプリ」の作成に伴いまず初めにiPhoneの電卓をイメージしてみました。

横画面表示ではより多機能な電卓となります。

今回目指す電卓ではデザインは無視して、単純に電卓として機能するものを完成イメージとしました。

【基本機能】

・数字:0〜9

・記号:四則演算記号、符号の切り替え、百分率、オールクリア、小数点

・ディスプレイ表示

【追加機能】

・指数計算

・ネイピア数(e)

・クリア

ざっくりこんな感じで作成イメージを考えました。追加機能に関しては基本機能が完成した後から追加した機能になります。

画面側のコード

まずは見た目の作成に取り掛かりました。といっても見た目は簡易的なものなので複雑なコードはありません。

<?php require_once("CalculatorApp.php")?>

<!DOCTYPE html>
<html>
    <head>
        <title>電卓アプリケーション</title>
    </head>
    <body>
        <h2>電卓アプリケーション</h2>
            <p><?php if(empty($displayNum)){echo 0;}else{echo $displayNum;} ?></p>
        <form action="?" method="post">
            <input type="hidden" name="displayNum" value="<?php echo $displayNum;?>"/>
            <input type="hidden" name="pre_button" value="<?php echo $pre_button;?>"/>
            <input type="hidden" name="ope" value="<?php echo $ope;?>"/>
            <input type="hidden" name="pre_num" value="<?php echo $pre_num;?>"/>
            <input type="hidden" name="input_num" value="<?php echo $input_num;?>"/>


            <table>
                <tr align="center">
                    <td><button type="submit" name="button" value="e^x">e^x</button></td>
                    <td><button type="submit" name="button" value="x^y">x^y</button></td>
                    <td><button type="submit" name="button" value="10^x">10^x</button></td>
                    <td><button type="submit" name="button" value="x^2">x^2</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="AC">AC</button></td>
                    <td><button type="submit" name="button" value="C">C</button></td>
                    <td><button type="submit" name="button" value="%">%</button></td>
                    <td><button type="submit" name="button" value="÷">÷</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="7">7</button></td>
                    <td><button type="submit" name="button" value="8">8</button></td>
                    <td><button type="submit" name="button" value="9">9</button></td>
                    <td><button type="submit" name="button" value="×">×</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="4">4</button></td>
                    <td><button type="submit" name="button" value="5">5</button></td>
                    <td><button type="submit" name="button" value="6">6</button></td>
                    <td><button type="submit" name="button" value="-">-</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="1">1</button></td>
                    <td><button type="submit" name="button" value="2">2</button></td>
                    <td><button type="submit" name="button" value="3">3</button></td>
                    <td><button type="submit" name="button" value="+">+</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="0">0</button></td>
                    <td><button type="submit" name="button" value="+/-">+/-</button></td>
                    <td><button type="submit" name="button" value="e">e</button></td>
                    <td><button type="submit" name="button" value="=">=</button></td>
                </tr>
            </table>
        </form>
    </body>
</html>

画面側コード説明

・ディスプレイ表示

<p><?php if(empty($displayNum)){echo 0;}else{echo $displayNum;} ?></p>

ディスプレイに表示するための変数「$displayNum」が空、つまりボタンを押してないかクリアした状態なら0を表示しておき、それ以外は変数に格納された値を表示します。

・hidden

<input type="hidden" name="displayNum" value="<?php echo $displayNum;?>"/>
<input type="hidden" name="pre_button" value="<?php echo $pre_button;?>"/>
<input type="hidden" name="ope" value="<?php echo $ope;?>"/>
<input type="hidden" name="pre_num" value="<?php echo $pre_num;?>"/>
<input type="hidden" name="input_num" value="<?php echo $input_num;?>"/>

各変数の値を表示せず保持させます。

・table

<table>
                <tr align="center">
                    <td><button type="submit" name="button" value="e^x">e^x</button></td>
                    <td><button type="submit" name="button" value="x^y">x^y</button></td>
                    <td><button type="submit" name="button" value="10^x">10^x</button></td>
                    <td><button type="submit" name="button" value="x^2">x^2</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="AC">AC</button></td>
                    <td><button type="submit" name="button" value="C">C</button></td>
                    <td><button type="submit" name="button" value="%">%</button></td>
                    <td><button type="submit" name="button" value="÷">÷</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="7">7</button></td>
                    <td><button type="submit" name="button" value="8">8</button></td>
                    <td><button type="submit" name="button" value="9">9</button></td>
                    <td><button type="submit" name="button" value="×">×</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="4">4</button></td>
                    <td><button type="submit" name="button" value="5">5</button></td>
                    <td><button type="submit" name="button" value="6">6</button></td>
                    <td><button type="submit" name="button" value="-">-</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="1">1</button></td>
                    <td><button type="submit" name="button" value="2">2</button></td>
                    <td><button type="submit" name="button" value="3">3</button></td>
                    <td><button type="submit" name="button" value="+">+</button></td>
                </tr>
                <tr align="center">
                    <td><button type="submit" name="button" value="0">0</button></td>
                    <td><button type="submit" name="button" value="+/-">+/-</button></td>
                    <td><button type="submit" name="button" value="e">e</button></td>
                    <td><button type="submit" name="button" value="=">=</button></td>
                </tr>
            </table>

tableタグを利用してボタンを等間隔に配置しています。

画像の引用元:サルワカ

処理プログラムのコード

<?php
//------------------------変数の定義-------------------------

$displayNum = $_POST['displayNum'];
$pre_num = $_POST['pre_num'];
$ope = $_POST['ope']; 
$pre_button = $_POST['pre_button']; 
$button = $_POST['button']; 
$input_num = $_POST['input_num']; 

//----------------------------------------------------------

//------------------------処理の内容--------------------------

//<<<<<<<<<<<<数字ボタンが押された場合>>>>>>>>>>>>>
if(isNumBtn($button)||empty($button)){
    //次に記号を押した場合
    if(isSymBtn($pre_button)){
        $pre_num = $displayNum;
        $displayNum = $button; //次に押した数字が表示される
    }else{ //連続で数字が押された場合
            
            //01や02と表示されないようにする
            if(($displayNum == '0') && (isNumBtn($button) != '0')){ 
                $displayNum = '';
            }

            $displayNum = $displayNum.$button;
    }


}else{

//<<<<<<<<<<<<記号ボタンが押された場合>>>>>>>>>>>>>>
    switch($button){
        case 'AC': //オールクリア
            $displayNum = '';
            $pre_num = '';
            $input_num = '';
            break;

        case '+/-': //符号反転
            $displayNum = -$displayNum;
            break;

        case '%': //百分率
            $displayNum = $displayNum / 100;
            break;

        case 'x^2': //二乗
            $displayNum *= $displayNum;
            break;

        case 'e': //ネイピア数
            $displayNum = $displayNum * 2.718281828459045;
            break;    

        case 'e^x': //ネイピア数の累乗
            $displayNum = 2.718281828459045 ** $displayNum;
            break;

        case '10^x': //10の累乗
            $displayNum = 10 ** $displayNum;
            break;
            default: //次の処理へ

            //すでに数字ボタンが押されており、次に押すボタンが記号ボタンまたは「=」の場合
        if(!empty($pre_num)&&(preg_match('/=/', $button)||(isNumBtn($pre_button)&&isSymBtn($button)))){
            switch($ope){
                case '+':
                    $displayNum = $pre_num + $displayNum;
                    break;
                case '-':
                    $displayNum = $pre_num - $displayNum;
                    break;
                case '×':
                    $displayNum = $pre_num * $displayNum;
                    break;
                case '÷':
                    $displayNum = $pre_num / $displayNum;
                    break;

                case 'x^y':
                    $displayNum = $pre_num ** $displayNum;
                    break;
                    default:
                    break;
            }

            //現在入力中の値をクリア
            if($button == "C"){
                $displayNum = $pre_num;
                $ope = '';
                $pre_button = $pre_num;
                break;
            }
        }
        //「=」を押さない場合
        if ($button != '='){
            $ope = $button;  
        }      
    break;
    }
}
//押したボタンの数字を表示
$pre_button = $button;
//----------------------------------------------------------

//------------------------関数の定義--------------------------

//記号ボタンの判別に関する関数
function isSymBtn($btn){
    if($btn=='+'||$btn=='-'||$btn=='×'||$btn=='÷'||$btn=='AC'||$btn=='C'||$btn=='x^2'||$btn=='%'||$btn=='+/-'||$btn=='e'||$btn=='e^x'||$btn=='x^y'||$btn=='10^x'){
        return true;
    }else{
        return false;
    }
}

//数字ボタンの判別に関する関数
function isNumBtn($btn){
    if($btn=='0'||$btn=='1'||$btn=='2'||$btn=='3'||$btn=='4'||$btn=='5'||$btn=='6'||$btn=='7'||$btn=='8'||$btn=='9'){
        return true;
    }else{
        return false;
    }
}

//----------------------------------------------------------
?>

処理プログラムの説明

・変数の定義

$displayNum = $_POST['displayNum'];
$pre_num = $_POST['pre_num'];
$ope = $_POST['ope']; 
$pre_button = $_POST['pre_button']; 
$button = $_POST['button']; 
$input_num = $_POST['input_num']; 

画面側で保持している値を「$_POST」で受け取り、各変数に格納しています。

・関数の定義

順番は前後しますがこちらを先に触れておきます。

//記号ボタンの判別に関する関数
function isSymBtn($btn){
    if($btn=='+'||$btn=='-'||$btn=='×'||$btn=='÷'||$btn=='AC'||$btn=='C'||$btn=='x^2'||$btn=='%'||$btn=='+/-'||$btn=='e'||$btn=='e^x'||$btn=='x^y'||$btn=='10^x'){
        return true;
    }else{
        return false;
    }
}

//数字ボタンの判別に関する関数
function isNumBtn($btn){
    if($btn=='1'||$btn=='2'||$btn=='3'||$btn=='4'||$btn=='5'||$btn=='6'||$btn=='7'||$btn=='8'||$btn=='9'){
        return true;
    }else{
        return false;
    }
}

「関数isSymBtn()」では記号ボタンが押されたときにtrueを返します。

「関数isNumBtn()」では数字ボタンが押されたときにtrueを返します。

・数字ボタンが押された時の処理

//<<<<<<<<<<<<数字ボタンが押された場合>>>>>>>>>>>>>
if(isNumBtn($button)||empty($button)){
    //次に記号を押した場合
    if(isSymBtn($pre_button)){
        $pre_num = $displayNum;
        $displayNum = $button; //次に押した数字が表示される
    }else{ //連続で数字が押された場合
            
            //01や02と表示されないようにする
            if(($displayNum == '0') && (isNumBtn($button) != '0')){ 
                $displayNum = '';
            }

            $displayNum = $displayNum.$button;
    }

数字ボタンが押された後どのような動作を行うかをif文を用いて処理します。

数字ボタンを押した後に記号ボタンを押した場合、ディスプレイに表示されていた数字が変数「$pre_num」に格納され、次に押したボタンの数字がでディスプレイに表示されます。

例えば「1+2」の場合で考えると、「+」を押した時は画面には「1」が表示されたままですが、「2」を押した時「2」がディスプレイに表示されています。この時画面側ではhidden属性により「$pre_num」には「1」が保持された状態になっています。

次にelseによって「連続で数字が押された場合」の処理を行います。この時、「01」や「00」は電卓における表示では不適切なのでフィルターをかけていきます。

処理は単純で、ディスプレイに「0」が表示されている時に「数字ボタン」が押されると、ディスプレイに表示されていた「0」に空文字が代入され、結果的に目的の押したボタンを表示する処理ができます。

・四則演算以外の記号が押された時

//<<<<<<<<<<<<記号ボタンが押された場合>>>>>>>>>>>>>>
    switch($button){
        case 'AC': //オールクリア
            $displayNum = '';
            $pre_num = '';
            $input_num = '';
            break;

        case '+/-': //符号反転
            $displayNum = -$displayNum;
            break;

        case '%': //百分率
            $displayNum = $displayNum / 100;
            break;

        case 'x^2': //二乗
            $displayNum *= $displayNum;
            break;

        case 'e': //ネイピア数
            $displayNum = $displayNum * 2.718281828459045;
            break;    

        case 'e^x': //ネイピア数の累乗
            $displayNum = 2.718281828459045 ** $displayNum;
            break;

        case '10^x': //10の累乗
            $displayNum = 10 ** $displayNum;
            break;
            default: //次の処理へ

後述しますが、「オールクリア」と「クリア」の区別は明確に分けておく必要があります。「オールクリア」では名前の通り、画面が保持している情報の一切を初期値に戻します。つまり各変数に格納されている値が空文字である必要があります。

その他の処理は説明がなくても見た目通りとなるのでここでは割愛します。

・「数字ボタン」を押下後に「記号ボタン」か「=」を押下

//すでに数字ボタンが押されており、次に押すボタンが記号ボタンまたは「=」の場合
        if(!empty($pre_num)&&(preg_match('/=/', $button)||(isNumBtn($pre_button)&&isSymBtn($button)))){
            switch($ope){
                case '+':
                    $displayNum = $pre_num + $displayNum;
                    break;
                case '-':
                    $displayNum = $pre_num - $displayNum;
                    break;
                case '×':
                    $displayNum = $pre_num * $displayNum;
                    break;
                case '÷':
                    $displayNum = $pre_num / $displayNum;
                    break;

                case 'x^y':
                    $displayNum = $pre_num ** $displayNum;
                    break;
                    default:
                    break;
            }

            //現在入力中の値をクリア
            if($button == "C"){
                $displayNum = $pre_num;
                $ope = '';
                $pre_button = $pre_num;
                break;
            }
        }
        //「=」を押さない場合
        if ($button != '='){
            $ope = $button;  
        }      
    break;
    }

ここでは最初に押されたボタンの数字が格納されている「$pre_num」と後から押されたボタンの数字が格納されている「$displayNum」を使って計算をする処理です。

また、「クリア(C)」は今表示されているボタンの数字を削除して、新しく数字ボタンを押して計算し直すという処理にしたいので、「1+2」という計算の場合,

$pre_num = 1

$displayNum = 2

がそれぞれ格納されているので、ディスプレイに表示される値を前に押した数字「1」に戻して、四則演算の記号ボタンを押す前の処理に戻します。

最後に

単純なプログラムでも0からコーディングしようとすると結構苦労しました。改めて世の中に溢れているアプリに対する畏敬の念が積もるばかりです。

そして今回簡易アプリを作成する中で非常に重要に感じたのは「デバッグ」と「イメージ」でした。デバッグに関しては言わずもがな頻繁に使うので私のような初心者の方は絶対に初めから活用していくべきです。

そして「イメージ」ですが、私のような学習を主として作成するようなアプリは全て既存アプリのマネタイズになると思うので、今回であればiPhoneの電卓アプリの挙動を逐一確認しながらプログラムを書いていきました。

今後も個人学習としてアプリの作成を行っていきたいと思っていますので、その際はまた記事でアップしていこうと思います。

では、また👏

ABOUT ME
ヒロ
社会人4年目/25歳/食品商社で2年間営業した後、IT業界にシステムエンジニアとして転職/Java,PHP言語を扱う開発エンジニア