Checking database value script
You can avoid repeating whole blocks of code by isolating the dynamic components of your function and assign them to an array.  Then as you wish to modify the fields/columns to be checked, you merely need to update the array and not the functional/checking parts.

public function edit_project_master(){
    $no_pro     = 'PRJ-2017-501';
    $check_pro  = $this-&gt;MProject-&gt;get_det_pro($no_pro); //get data form table

    $checklist=[
        ['input'=&gt;'na_pro','column'=&gt;'NAMA_PROJECT','table'=&gt;'PM_REQUIREMENT_PROJECT'],
        ['input'=&gt;'i_metode','column'=&gt;'JADWAL_PROJECT','table'=&gt;'PM_REQUIREMENT_PROJECT']
    ];

    //checking script
    foreach($check_pro as $res_check_pro){
        foreach($checklist as $listrow){
            $pro = $this-&gt;input-&gt;post($listrow['input']); //value for edit
            if($pro != $res_check_pro[$listrow['column']]){  //IF VALUE DIFFERENT
                foreach($res_check_pro as $key_pro =&gt; $val_pro){
                    if($res_check_pro[$listrow['column']] == $val_pro){
                        $col_name = $key_pro;            //GET COLUMN NAME
                        break;  // I assume you want to break as soon as you find a match
                    }
                }
                $data['ACTIVITY']       = "UPDATE";
                $data['OLD_VALUE']      = $res_check_pro[$listrow['column']];
                $data['NEW_VALUE']      = $pro;
                $data['COL_AFFECTED']   = $col_name;
                $data['TABLE_AFFECTED'] = $listrow['table'];  // I'm not sure how you mean "automatically", this is "dynamically"
                $data['ANNOTATION']     = NULL;
                $data['EXECUTOR']       = $this-&gt;session-&gt;userdata('nip');
                $data['CHANGED_ON']     = date("Y-m-d H:i:s");
                $data['CHANGED_BY']     = $_SERVER['REMOTE_ADDR'];
                $data['STATUS']         = 1;
                $this-&gt;MProject-&gt;ins_system_log($data);
            }
        }
    }
}


Also...

I added break; to the innermost foreach() assuming there will only be one match.  This is best practice because it avoids doing pointless iterations.

I made the value for $data['TABLE_AFFECTED'] "dynamic" (modifiable via the $checklist array).  I don't know if this is what you had in mind by "automatic".