⚠ In case you've missed it, we have migrated to our new website, with a brand new forum. For more details about the migration you can read our blog post for website migration. This is an archived forum. ⚠

  •     

profile picture

Locale support for number formatting



Adriano Gonçalves
  • profile picture
  • Member

Posted 23 July 2014 - 10:23 AM

Hello,
Firstly I would like to say Grocery CRUD is really something else, and it's helping me a lot.
But there is a issue that I haven't got to find global clue to deal with: I'm not getting to deal with numeric (float) fields when the decimal separator is different than the english. For example, in many countries the decimal separator is the comma, like '18,5'. Is there any global way to deal with this issue without the need of using the callback_field / callback_before_insert approach for each controller?
 
Thank you so much!

 


Amit Shah
  • profile picture
  • Member

Posted 24 July 2014 - 07:37 AM

Hi there and welcome the the GC club.

Well there is no where in GC library i see a formatting for a float point. It is by default.. feature of the language. But still if you want you can lookout in altering the CI library for the same to find if the element is a float, format the same with a certain policy / feature. I will try to workout a solution for the same if time permits. :)


Adriano Gonçalves
  • profile picture
  • Member

Posted 04 August 2014 - 17:07 PM

Well,

For now, I coded a temporary workaround for this issue in my project. As I always work developing a specialization of the Grocery_CRUD class with some improvements, I did it this way:

<?php

require 'Grocery_CRUD.php';

class AppGroceryCRUD extends Grocery_CRUD
{

    protected $_decimal_separator = '.';
    protected $_numeric_fields = array();

    /**
     * Define the fields with the numeric behaviour.
     *
     * @param string $decimal_separator Decimal separator
     * @param string $fields Numeric fields names
     */
    public function setNumericFields($decimal_separator)
    {
        $this->_decimal_separator = $decimal_separator;
        $fields = func_get_args();
        unset($fields[0]);

        foreach ($fields as $curr_f)
        {
            $field_name = $curr_f;
            $field_callback = function($value = '', $primary_key = NULL) use($field_name)
            {
                $formatted_value = strtr($value, '.', $this->_decimal_separator);
                if ($this->getState() == 'add' || $this->getState() == 'edit')
                    $html = '<input type="text" step="any" value="' . $formatted_value . '" name="' . $field_name . '" id="field-' . $field_name . '">';
                else
                    $html = '<span class="numeric_column">' . $formatted_value . '</span>';
                return $html;
            };
            $this->callback_field($curr_f, $field_callback);
            $this->callback_column($curr_f, $field_callback);
            $this->_numeric_fields[] = $curr_f;
        }
    }

    protected function db_insert($state_info)
    {
        $state_info->unwrapped_data = $this->_convertNumericFields($state_info->unwrapped_data);
        return parent::db_insert($state_info);
    }

    protected function db_update($state_info)
    {
        $state_info->unwrapped_data = $this->_convertNumericFields($state_info->unwrapped_data);
        return parent::db_update($state_info);
    }

    /**
     * Convert the locate numbers to DB
     *
     * @param array $post_data Array with POST data
     * @return array POST data with converted numbers
     */
    protected function _convertNumericFields($post_data)
    {
        foreach ($this->_numeric_fields as $curr_f)
        {
            if (array_key_exists($curr_f, $post_data))
            {
                $post_data[$curr_f] = preg_replace('/[^0-9' . $this->_decimal_separator . ']/i', '', $post_data[$curr_f]);
                $post_data[$curr_f] = strtr($post_data[$curr_f], $this->_decimal_separator, '.');
            }
        } return $post_data;
    }

}

And I call it this way in controller:

$crud->setNumericFields(',', 'number_field1', 'number_field2', 'number_field2', '...', 'number_fieldn');

I hope to develop a better solution later, but I hope that may this approach help anyone with the same problem...

 

UPDATE: I made a fix in the code to solve a columns problem.


Adriano Gonçalves
  • profile picture
  • Member

Posted 26 October 2015 - 08:17 AM

Now, a workaround for PHP versions that doesn't supports anonymous functions with "use":

    /**
     * Define the fields with the numeric behaviour.
     *
     * @param string $decimal_separator Decimal separator
     * @param int $decimals [optional] Number of decimals
     * @param string $fields Numeric fields names
     */
    public function setNumericFields($decimal_separator, $decimals)
    {
        $this->_decimal_separator = $decimal_separator;
        $crud_state = $this->getState();
        $fields = func_get_args();
        array_shift($fields);

        if (is_int($decimals))
        {
            array_shift($fields);
        }

        foreach ($fields as $curr_f)
        {
            $field_name = $curr_f;
            $campo_readonly = $this->_checkReadOnlyField($field_name);

            // Solução para versões do PHP < 5.5
            $field_callback = create_function('$value = \'\', $primary_key = NULL', '
                if (is_numeric("' . $decimals . '"))
                {
                    $formatted_value = number_format($value, "' . $decimals . '", "' . $decimal_separator . '", \'\');
                }
                else
                {
                    $formatted_value = strtr($value, \'.\', "' . $decimal_separator . '");
                }

                if (("' . $crud_state . '" == \'add\' || "' . $crud_state . '" == \'edit\') && !(' . ($campo_readonly ? '1' : '0') . '))
                {
                    $html = \'<input type="text" step="any" value="\' . $formatted_value . \'" name="' . $field_name . '" id="field-' . $field_name . '">\';
                }
                else
                {
                    $html = \'<span class="numeric_column">\' . $formatted_value . \'</span > \';
                }

                return $html;
             ');

            $this->callback_field($curr_f, $field_callback);
            $this->callback_column($curr_f, $field_callback);
            $this->_numeric_fields[] = $curr_f;
        }
    }

PLaXToR
  • profile picture
  • Member

Posted 13 February 2020 - 04:41 AM

Hello, 

Could you please give more details about install?

 

1-) i made php in same folder with Grocery_CRUD.php (library)

2-) i changed setNumericFields function with second you gave,

3-) $crud->setNumericFields(',',...);

 

all of then it doesnt work.

 

Have you got another resolve for locale numaric money formats

 

For example i need to replacing

-10000.00 to 10.000,00

or

-3400 to 3.400

 

Thank you for interesting.