Input dates with text box - php

What's the standard way to get rid of the three <select> elements and allow users to just type dates in a regular <input type="text"> control?
Requirements include:
Date format must be D/M/Y
Existing dates must be printed correctly
Cannot break date validation
I cannot find any reasonable documentation on this, just hacks in forum threads written by users as clueless as me xD
Clarification: Please note the CakePHP tag. I already know how to handle dates in regular PHP. I need help about the precise CakePHP mechanism I can use to adjust the framework's default functionality (and I really mean adjust rather than override).
So far, I've added this to the model:
public $validate = array(
'fecha' => array(
array(
'rule' => 'notEmpty',
'required' => true,
),
array(
'rule' => array('date', 'dmy'),
),
)
);
... and I've composed the field like this inside the view:
echo $this->Form->input(
'Foo.fecha',
array(
'type' => 'text',
)
);
... but all I can do with this is reading and validating user input: it won't print previous date properly and it won't store new date properly.

Here's a summary of my findings. It seems that the appropriate mechanism is using Model Callback Methods to switch between two date formats:
Database format, e.g.: 2012-08-28
Display format, e.g.: 28/08/2012
Steps:
Add two utility methods to AppModel to convert between my custom format (aka "display format") and MySQL's default format (aka "DB format").
Add an afterFind() filter to my model that converts to display format when read from DB.
Render the form control as 'type' => 'text'.
Add a 'rule' => array('date', 'dmy') validation rule to the field inside the model.
Add a beforeSave() filter to my model that converts to DB format right before saving.
These steps can be encapsulated with a behaviour that implements the afterFind() and beforeSave() callbacks and possibly some others like beforeFind(). The behaviour can be applied directly to AppModel and will take care of traversing data arrays to convert dates between both formats (if the model has an attached table). The code is not trivial but can be done and it makes it all transparent.
Drawbacks:
Makes code MySQL-only (but, isn't it MySQL-only already?)
Makes it difficult to localize.
If you need to do date math, you find yourself with human-readable strings.
It would be more rock-solid to be able to use three formats:
Database format, e.g.: 2012-08-28
Display format, e.g.: 28/08/2012
PHP internal format, e.g. Unix timestamps or DateTime objects
Sadly, the CakePHP core is not designed for that and it all starts getting too complicate if you attemp to implement it this way.

The only possible way looks like letting the user typing whatever he wants do, then checking for its validity when he wants to submit the form or something. Or better, go for jQuery datepicker.

In case you'll write the input fields using the helper,
There's a type option for the input method of formhelper.
Try this , for instance:
<?php
echo $this->Form->input('birth_dt', array(
'type' => 'text',
'label' => 'Date of birth',
));
EDIT: (after reading your comment)
The solution if so , can be to validate the input value after the submit of the form
or using ajax vaildation.

Related

Efficient way to capture "variations" or "combinations" ore "aliases" for switch-case argument(s) in PHP

I am pretty sure this challenge has been solved by someone already but even searching with different words, I could not find a solution for this problem:
I try to give users the possibility to run certain functions of a class based on an argument like
service_class::do_this( "selection-argument" );
but the user shall be able to use "clear words" as well as "aliases" and even "well known" abbreviations or synonyms.
I use switch-case construction to call the "real" function.
Example: To get the contens of a folder, The user can use "getdir", "dir", "Directory", "getfolder", "getcontent", "content", "d-cont" and a number of more other "matching words" to start the function(s) underlaying and getting back the very same result.
Capture-ing lowercase/uppercase is simple. What I search for is an efficient way to capture all possible "variations" - that are, of course different number of variations for different functions called.
At the moment I use multiple "case "": lines after each other, but that makes the code quite long, and further I would like the user to be able to "enahnce" the recognition set for a certain function.
That's why I thought about "stripos" to determine first what "internal word" to use and only then run into the switch-case construction.
Anyone had that issue and can direct me to a "good and efficient" solution?
Seems that Stck-exchange itself had a similar challenge (https://codereview.stackexchange.com/tags/php/synonyms) ... maybe I can simply re-use the underlying code?
Thanks in advance and sorry if I overlooked a solution already posted.
You could use a database or array. Let's do the latter. So to determine whether an user wants to get a directory you would define an array like this:
$getDirVariants = ['getdir',
'dir',
'directory',
'getfolder',
'getcontent',
'content',
'd-cont'];
It is easy to add more of these arrays. To test the query word you would do:
$queryWord = strtolower($queryWord);
if (in_array($queryWord, $getDirVariants)) service_class::getDir(<arguments>);
elseif (in_array($queryWord, $deleteVariants)) service_class::delete(<arguments>);
You can easily add to the arrays or make it a 2D array to contain more commands. That array could also be placed in a database.
Especially when there are many commands, with many variants, a database will be the better solution, because you can find the query word with one database query.
There's a variation I can think of that will also simplify the code when there are many commands. You could use an associative array to find the command:
$commandVariants = ['getdir' => 'getdir',
'dir' => 'getdir',
'directory' => 'getdir',
'getfolder' => 'getdir',
'getcontent' => 'getdir',
'content' => 'getdir',
'd-cont' => 'getdir',
'delete' => 'delete',
'del' => 'delete',
'remove' => 'delete',
'unlink' => 'delete'];
$queryWord = strtolower($queryWord);
if (isset($commandVariants[$queryWord])) {
$command = $commandVariants[$queryWord];
service_class::$command(<arguments>);
}
else echo "I don't recognize that command.";
This uses a variable identifier.

Does Zend2 frame work allow for phone numbers as low as two digits?

I have done testing work and min 4 digits are required for phone numbers..
How (if posible) to allow the application based on Zend2 to validate phone numbers as low as 2 digits, like: ‘11’?
If your app is already doing validation via a Zend\Validator chain then you probably want to do it via one of the existing validators. This will keep the validation in one place and prevent you from having to write any custom code. If Zend\I18n\Validator\PhoneNumber is already in your chain then you can check to see if there's a supported type for your country that matches your desired pattern. See the files in zend-i18n/src/Validator/PhoneNumber. (This is probably not likely for a two-digit number, that seems pretty custom.) If not, you can probably inject a Zend\Validator\Between or a Zend\Validator\StringLength object into your validator chain via a config file change.
Thank you for your help, I have decided in the end to remove validation from Zend2 (back end);
'validators' => array(
0 => array(
'name' => 'Zend\\I18n\\Validator\\PhoneNumber',
'options' => array(
'country' => 'DE',
),
),
),
Replacing this with: 'validators' => array(),
And I have added validation on the front end (angular.js);
minlength="2" maxlength="255"
ng-pattern= "/[0-9][0-9]/

Zend Framework 2 DateSelect/MonthSelect formatting

With the newly released version of Zend Framework 2, two new form elements were added; DateSelect and MonthSelect. I want to use the former, which adds three selects; day, month and year. However, I have a problem formatting the output how I want - and, there is no documentation for this!
I am adding the form element to my form like this (taken from this page):
$this->add(array(
'type' => 'Zend\Form\Element\DateSelect',
'name' => 'birthDate',
'options' => array(
'label' => 'Date',
'create_empty_option' => true,
'day_attributes' => array(
'data-placeholder' => 'Day',
'style' => 'width: 20%',
),
'month_attributes' => array(
'data-placeholder' => 'Month',
'style' => 'width: 20%',
),
'year_attributes' => array(
'data-placeholder' => 'Year',
'style' => 'width: 20%',
)
)
));
For outputting, I am doing like this:
echo $this->formDateSelect($form->get('birthDate'));
The thing is that I don't know how to control the way the selects are formatted. For instance, they are currently outputted in this form: [month] [day], [year]. I want to change two things; first, I want to switch the day and month, and secondly, I want to get rid of the comma.
The helpers use the IntlDateFormatter class to format the selects. In the source code, I noticed that you can use the predefined constants for the date type when calling __invoke() [link to source code], like this:
echo $this->formDateSelect($form->get('birthDate'), IntlDateFormatter::SHORT);
Having tried all of the constants, I still cannot get the format I want.
I noticed that there are getters for the three selects, but using the formSelect view helper with each of them, empty selects are rendered because the data population is within the new view helpers. So that pretty much defeats the purpose of even using the selects individually; then I might as well just use regular selects.
Does anyone have any idea how I can gain more control on how my selects are formatted? Is it even possible without too much hassle, or should I just use three regular selects for maximum flexibility?
The format of the ViewHelper is $this->formDateSelect($element, $intlFormat, $locale).
With this being said, you should be able to create the output you want by accessing your current locale setting and insert int into the ViewHelpers __invoke(). Seeing the getLocale() of the ViewHelper implies, that the default translator from configuration is not used, so you have to set a locale explicitly for this ViewHelper, but then it should work out just fine ;)
If that doesn't work as expected for you, i may advise you to hit Bakura a message on his Blog about the new Form Features
I have no idea whatsoever why anyone would want to put a random comma in between Select DOM elements when outputting a date... what can you do with it exactly?
To remove the comma and any other delimiter you can pass in via options:
"render_delimiters": false
Which I think should be false by default
As Sam mentions you can just update the locale settings in your php.ini
For example I have this in my php.ini
intl.default_locale = en_Gb
This formats the DateSelect element in the Day / Month / Year format required for my UK projects.

change order of array elements in php file

Not sure about how to title this post.
I just inherited a set of internationalization documents, each containing an array of key value pairs. I recognize the methodology is not ideal, it is however, what I'm stuck with given my role, the time and resources I have available. These lists were created by hand and items were constantly being added haphazardly to keep up with demand. The examples below are simplified, there are ~21 language files, each with 100+ entries.
The array from one file will have elements something like the below:
'download_high' => 'Vysoké',
'download_low' => 'Nízké',
'download_med' => 'Strední',
'download_video' => 'Stáhnout video',
While another file will have something like the following:
'download_video' => 'Descargar Video',
'download_high' => 'Alta',
'download_med' => 'Media',
'download_low' => 'Baja',
For the most part, the elements are ordered consistently, but there are plenty of exceptions and it complicates maintaining the files. I was wondering if there's a way to make the order / formatting of these arrays consistent either via an IDE or notepad++ plugin, etc. I don't want to order them alphabetically necessarily as there are logical groupings that won't translate well to alphabetical sorting since only some of the variables are namespaced. Doing it by hand is almost out of the question, but it would be nice if there were some way to specify an order and have some kind of text manipulation tool batch process the files. I'm not all that familiar with php, so I don't know that it would be worth it for me to do this via code unless it's very simple.
PHP has a function called var_export. You could run the code and then print it with the function.
Personally, I would run some regex in notepad++ to do it.
Edit: In notepad++, you can do a find/replace with regex.
In the "Find what" field, put \s*'(.+?)'\s*=>\s*'(.+?)'\s*(?:(,)|\s*$)\s*
In the "Replace with" field, put '$1' => '$2'$3\n
This will turn something like:
'download_high' =>  'Vysoké',
'download_low'=>
'Nízké',
'download_med'
=>
'Strední'
,
'download_video' => 'Stáhnout video',
'filter_by' => 'Filtrovat podle'
,
'footer_contact' => 'Kontakt'
into
'download_high' => 'Vysoké',
'download_low' => 'Nízké',
'download_med' => 'Strední',
'download_video' => 'Stáhnout video',
'filter_by' => 'Filtrovat podle',
'footer_contact' => 'Kontakt'
*note: This is written with the assumption that all keys and values use single quotes and that neither keys nor values have any escaped single quotes inside.
Given the situation I'd do it semi-automatically on an as-needed basis. That is, it sounds to me like you're charged with maintaining these files, and it's in the maintenance that the sorting becomes an issue.
For each language file formatted like:
<?php
$something = array(
'download_video' => 'Descargar Video',
'download_high' => 'Alta',
...
'download_med' => 'Media',
'download_low' => 'Baja',
);
Issue a sort lang.es.php command in bash, or via however you prefer to sort something.
Open the file for editing.
Delete the array declaration.
Copy/paste the sorted lines from #1.
Honestly, it was a super bad idea for your predecessor to effectively hard-code something like this. It would be much better if this were stored via CSV, XML, pg/mySQL, etc where you could at least invoke an editor that understands the data format.
i wouldn't suggest using arrays and php files etc if you are going to have a continuously growing list. take the couple minutes now to set up mysql and pull from a database with your desired parameters. NEAT, FAST, EFFECIENT AND SCALABLE.
My suggestion would be to simply build a script to load all those arrays into a database where they can be maintained more easily. Of course you would need to make sure you database table/fields were set up for UTF-8 character sets and collations.
Am I correct in understanding that you have already gotten your data into PHP arrays? At this point you could just do this to sort the keys. This would make the ordering consistent:
ksort($array);

Zend Framework: How to filter input, turning zero to null, then validate null?

So I've determined that my validator does not get called when I filter the input value and turn zero into null.
$this->addElement('select', 'State_ID', array('label' => 'State', 'multiOptions' => $this->getStates(), 'validators' => array($requiredBasedOnCountry), 'filters' => array($makeZeroNull)));
The reason I am doing this is because I don't want to insert 0 into the database. When I call getValues() on the form, I don't want to have to change each one manually. But I want to also validate the input. How can I filter the value, and also validate it?
I'm not really sure what your validators or filters are, since you've only shared that they're two variables, without saying what they are.
That said, Zend_Filter_Null will probably be what you're looking for.
http://framework.zend.com/manual/en/zend.filter.set.html

Categories