I've got this input form: (Using the blade template engine with Laravel, but the html should be easy to understand from this and ultimately trivial)
{{ Form::text('amount[]', Input::old('amount')) }}
<?php echo Form::select('unit[]',
array(
'whole' => _('whole'),
'ml' => _('milliliter'),
'l' => _('liter'),
'dl' => _('deciliter'),
'mg' => _('milligram'),
'g' => _('gram'),
'kg' => _('kilogram'),
'tsp' => _('teaspoon'),
'tbs' => _('tablespoon'),
)) ?>
{{ Form::text('ingredient[]', Input::old('ingredient')) }}
I'm trying to format this to my database to return it in a string like this :
<li><span>1</span> liter red wine</li>
I'm considering making it a simpler form and eliminating the unit measurement forcing my users to type it in instead for flexibility, but I'll still have to cramp it all into one table for my database. The span tag is used in a jQuery to dynamically increase the number so is needed. I've been at this for quite a few days on and off but I can't crack how to do this.
Here is my formatting logic:
$amount = Input::get('amount[]');
$unit = Input::get('unit[]');
$ingredient = Input::get('ingredient[]');
for ( $i = 0, $c = count(Input::get('ingredient[]')); $i < $c; $i++ )
{
$ingredients .= '<li><span>'.$amount[$i].'</span>'.$unit[$i].' '.$ingredient[$i].'</li>';
}
and I send it using
$new = Recipe::create(array(
'title' => Input::get('title'),
'curiousity' => Input::get('curiousity'),
'ingredients' => $ingredients,
'steps' => Input::get('recipe')
));
I've tried numerous ways and I get errors like the $ingredients array not being defined or not being able to use [] in the variable. I tried defining the variable as an '$ingredients = '';' variable but that just produced an empty string. My problem must be in the logic.
Build your select list outside the form for brevity as well as (what I do anyway to keep controllers very slim) send the input to the model all at once.
$input = Input::all();
$new = Recipe::create($input);
Build the array for the ingredients elsewhere. In the model (perhaps?):
$ingredients = array(
'dbname1' => 'displayname1',
'dbname2' => 'displayname2'
);
And display it accordingly, then the form inputs should be sent over with the $input in an array that you can parse and then save to your db.
Other notes about Blade syntax. I'm not aware of a need to define the array brackets [].
{{Form::open()}}
{{Form::label('label1','Display Label 1')}}
{{Form::text('fieldname1',Input::old('fieldname1'))}}
With your ingredients array already built (your current syntax will produce a dropdown and I assume you want checkboxes)
{{Form::select('ingredientsFIELDNAME',$ingredients)}}
{{Form::close()}}
In your Input::all() array your ingredientsFIELDNAME field name will have an array if you've built it as checkbox instead of select. Hope this all makes sense.
Related
We are working on a website based on SilverStripe and this site is connected with a SugarCRM database.
We have created a Form with a CheckboxSet with multiple values and store it a variable called $data['Interessen']
$set_entry_parameters = array(
"session" => $session_id,
"module_name" => "Contacts",
"name_value_list" => array(
array(
"name" => "interessen_c",
"value" => $data['Interessen']['fotografie']
),
array(
"name" => "interessen_c",
"value" => $data['Interessen']['dance']
)
)
);
Now the last array with "interessen_c" overwrites the previous values. We want to add more than one value at one time.
How is this possible?
If the contents of $data['Interessen'] can only have values from a fixed list of possibilities, I'd recommend making the field interessen_c into type multienum ("Multi-Selection Dropdown" field).
For that field create a list of all available items in Sugar (e.g. in Studio or creating the app_list_strings entry manually via code).
Sugar will then support multiple values in this field and display them nicely.
If your program writes the data by communicating with the Sugar REST API you can then just pass the $data['Interessen'] array as the value for interessen_c and Sugar will know what to do with it.
If your program writes the data directly to the interessen_c field in the database, then the field contents must adhere to the following format:
^value1^,^value2^,^value3^
So with ^ around each value and all items being separated by ,
Here an example of how to convert the array values to such a string in PHP:
$interessen = array();
foreach ($data['Interessen'] as $value) {
// add value surrounded by ^ to array
$interessen[] = "^$value^";
}
// transform values in array to string with items being separated by ,
$interessen = implode(',', $interessen);
Side-Note:
From within Sugar one can use encodeMultienumValue($arr) and unencodeMultienum($string) to convert from array to db-string format and back.
Both functions are defined in include/utils.php
Alright so I have an insert query that I would like to run but the issue I am having is with getting object properties/values that I need to insert.
Say I have a query that looks like the one below.
$this->db->insert('tblitems_in', array(
'platform' => $item['Platform'],
'ram' => $item['RAM'],
'qty' => $item['qty'],
'rate' => number_format($item['rate'], 2, '.', ''),
'rel_id' => $insert_id,
'rel_type' => 'estimate',
'item_order' => $item['order'],
'unit' => $item['unit']
));
This works fine when the person chooses RAM on the webpage which sets the $item Objects property 'RAM' to the value that was picked. Now if they choose HardDrive, that properties name is now sent as 'HardDrive' with the value they chose. Is there a way that i Could replace the 'ram' and 'RAM' from the below example with a variable so I could change what the property name is that I would like to insert and insert into the corresponding db column?
EDIT:
I should have added that the options on the webpage are also dynamically created from a database so I do not know at the time of coding what the property names are. They could be RAM, HardDrive, Processor, maybe even Elephant. I was hoping I could use variables so that I could look at the DB used to create the webpage so that I know the property names and then dynamically add those names into the query.
EDIT:
Right now I am using the following code in order to get all the possible options that can be received from the webpage from a DB the webpages uses to create itself.
$plat_options = $this->db->get('tblplatform_options')->row()->name;
In the database right now it is only populated with names RAM and HardDrive to make things known for testing purposes. So this returns $plat_options = {RAM, HardDrive}. I now have to figure out how to test is $item has these(RAM and HardDrive) as properties and if $item does have them then add them into the query previously shown.
You can set an array of key => variable names, then loop over those values to see if they exist in the $item variable and, if so, add that value to the data to be inserted into the db:
//default array of data to insert
$data = [
'platform' => $item['Platform'],
'qty' => $item['qty'],
'rate' => number_format($item['rate'], 2, '.', ''),
'rel_id' => $insert_id,
'rel_type' => 'estimate',
'item_order' => $item['order'],
'unit' => $item['unit']
];
//Get column names from db
$plat_options = $this->db->get('tblplatform_options')->row()->name;
// $plat_options = [RAM, HardDrive]
//Check if $item[$name] exists. If it does, add that to the
// array of data to be inserted
foreach($plat_options as $key) {
if(array_key_exists($key, $item)) {
$data[$key] = $item[$key];
}
}
$this->db->insert('tblitems_in', $data);
edit
I'm not sure this will work (I don't understand the use case).
It is possible, using array_diff_key to get a list of array keys that exist in $item but not in $data. With this array of keys, you can add the missing keys.
I have altered my previous code to demonstrate this.
You could create the array one element at a time based on whatever field data you received. I used a switch statement, but it could be a simple if/then/else as well.
$data_array = array();
$data_array['platform'] = $item['Platform']
switch($item['Object'] {
case 'HardDrive':
$data_array['harddrive'] = $item['HardDrive'];
break;
case 'RAM':
$data_array['ram'] = $item['RAM'];
break;
}
$data_array['qty'] = $item['qty'];
$data_array['rate' = number_format($item['rate'], 2, '.', '');
$data_array['rel_id'] = $insert_id;
$data_array['rel_type' = 'estimate';
$data_array['item_order'] = $item['order'];
$data_array['unit'] = $item['unit'];
$this->db->insert('tblitems_in', $data_array);
If there any way to discover the variables required from a Twig template? Example, if I had:
Hello {{ user }}! You're {{ age }} years old, well done big man!
I'd be able to load this template and then gather each of the required variables, eventually allowing me to have something like:
Array ( [0] => user [1] => age )
The end goal of this is to be able to define a view and then have the system create a form based on the required variables in a template file.
Working Solution
Thanks to morg for pointing me towards tokenize I was able to get what I wanted using the following (I placed it in my controller for testing):
$lexer = new \Twig_Lexer(new \Twig_Environment());
$stream = $lexer->tokenize(new \Twig_Source('{{test|raw}}{{test2|raw|asd}}{{another}}{{help_me}}', null));
$variables = array();
while (!$stream->isEOF()) {
$token = $stream->next();
if($token->getType() === \Twig_Token::NAME_TYPE){
$variables[] = $token->getValue();
while (!$stream->isEOF() && $token->getType() !== \Twig_Token::VAR_END_TYPE) {
$token = $stream->next();
}
}
}
$variables = array_unique($variables);
This returns:
Array
(
[0] => test
[1] => test2
[2] => another
[3] => help_me
)
You'll notice I only get variables and not any of the functions (this is through design), although you could remove the nested while loop if you wish to get both variables and functions.
You can use the twig tokenizer for this.
$stream = $twig->tokenize($source, $identifier);
The tokenizer has a toString() Method, whose resulting string you can parse for
VAR_START_TYPE()
NAME_TYPE(varname)
VAR_END_TYPE()
Look at this for more detailed information.
You can try using preg_match_all('{{\s*(\w+)\s*}}', 'template {{string }} with {{ var}}', $matchesArray);. The $matchArray is structured as following:
Array(
0 => array(0 => '{{string }}', 1 => 'string'),
1 => array(0 => '{{ var}}', 1 => 'var')
)
Another way of doing this from inside PHP code is not elegant, but still more reliable than any regex will be:
$source = "My template string with {{ some }} parameters.";
$stream = $twig->tokenize(new \Twig_Source($source, "source"));
$matches = [];
preg_match_all(
"/NAME_TYPE\((.*)\)/", $stream->__toString(), $matches
);
if (count($matches) > 1) {
$params = array_unique($matches[1]);
} else {
$params = [];
}
This works by using Twig internal mechanisms to tokenize the template string and then extract parameters names with a regex.
Edit: The previous version of my answer used the parse method to create a tree of nodes, but it didn’t seem to work anymore, and matching on NAME_TYPE at the previous step seems more reliable, not sure if I missed something there…
I want to save log entries to my MySQL database from Zend Framework 2. I am using Zend\Log\Logger with a Zend\Log\Writer\Db writer. By supplying the writer with an array, one can choose which columns to save what data to (e.g. timestamp into a "log_date" column) and which data to save. Here is what I am doing:
$logger = new Zend\Log\Logger();
$mapping = array(
'timestamp' => 'timestamp_column',
'priority' => 'priority_column',
'message' => 'message_column',
'extra' => 'extra_column'
);
$logger->addWriter(new Zend\Log\Writer\Db($dbAdapter, 'table_name', $mapping));
$logger->err('some message', array('some extra information'));
The problem I am facing is that the array of column names and their values contain an incorrect column name for the "extra" column. Based on the array above, it should be inserting the value "some extra information" into the "extra_column" column. The problem is that the Zend\Log\Writer\Db class is using the letter "e" as the name of the extra column. This comes from the first letter of "extra_column" in my array above. For some reason, it is taking the first letter of "extra_column" and using it as the column name instead of the entire value.
I took a look at the source code. The mapEventIntoColumn method is being used to get the column names and values as an array. I copied in the relevant part of the method below.
// Example:
// $event = array('extra' => array(0 => 'some extra information'));
// $columnMap = array('extra' => 'extra_column');
// Return: array('e' => 'some extra information')
// Expected (without looking at the code below): array('extra_column' => 'some extra information')
protected function mapEventIntoColumn(array $event, array $columnMap = null) {
$data = array();
foreach ($event as $name => $value) {
if (is_array($value)) {
foreach ($value as $key => $subvalue) {
if (isset($columnMap[$name][$key])) {
$data[$columnMap[$name][$key]] = $subvalue;
}
}
}
}
return $data;
}
The $event parameter is an array containing the same keys as my $mapping array in my first code snippet and the values for the log message. The $columnMap parameter is the $mapping array from my first code snippet (array values are column names).
What actually seems to happen is that because I am passing in extra information as an array (this is required), the inner foreach loop is executed. Here, $key is 0 (the index) so it is actually doing like this: $columnMap['extra'][0]. This gives the letter "e" (the first letter in "extra_column"), which is used as the column name, where it should be the entire column name instead.
I tried to supply my own key in the extra array when calling the log method, but the same happens. The official documentation shows no examples of usage of the extra parameter. I want to insert information that can help me debug errors into my table, so I would like to use it.
Is this a bug or am I missing something? It seems really strange to me! I hope I explained it well enough - it is quite tricky!
Since Daniel M has not yet posted his comment as an answer, I will refer you to his comment which solved the problem.
I want the user to be able to choose a restaurant from a dropdown list. I'm achieving this by the simple:
echo $this->Form->input(
'Restaurant', array('multiple'=>false, array('empty' => true)));
The issue I have is: some restaurants have duplicate names, and I need a way for the user to know which is which. I'd like to have the ID and/or address within the select options like:
<li value='62'>McDonalds (1234 Happy St) - #62</li>
<li value='63'>McDonalds (9876 French Fry Ln) - #63</li>
...etc
Is there a way to do this? I'm obviously capable of doing it w/ normal HTML, but... would be nice to stay in CakePHP.
Thanks ahead of time for any thoughts/suggestions/direction!
When you load your restaurants you're actually getting an array like this
array (
ID => NAME,
ID => NAME
)
Basically, it's an associated array with the ID as the key and the display field as the value. So as long as you modify that array via the find operation or via normal PHP array iteration, you can achieve your goal.
EDIT
So your answer is CakePHP VirtualFields
In your model you define it as
var $virtualFields = array(
'rest_unique_name' => 'CONCAT(Restaurant.first_name, " ", Restaurant.address)'
);
In your controller you do this
$opts = array(
'fields' => array('id', 'rest_unique_name')
);
$restaurants = $this->Restaurant->find('list', $opts);