Is there way to pass Symfony variables to translation without keys - php

we are now using custom translations for our project in PHP and I want to migrate them to Symfony ones. Everything looks great, but my only concern is that variable placeholders needs key to bind successfully, can I somehow change the code to accept translation variables in sequence (without keys)?
Let me show an example:
Our code now:
$translator->translate('For the period %date%, %data%', [$dateInterval, $additionalData]);
But this is how Symfony wants it:
return $this->symfonyTranslator->trans('For the period %date%, %data%', ['%date%' => $dateInterval, '%data%' => $additionalData]);
This is what I want:
return $this->symfonyTranslator->trans('For the period %date%, %data%', [$dateInterval, $additionalData]);
Is this somehow possible? I didn't find it anywhere in the documentation and Google didn't help either.

I have solved it by myself this is the code (in case anyone needs it):
Basically, it gets all %variables% and sets them as array keys with corresponding array values from $parameters variable.
public function translate(string $gettextString, array $parameters = []): string
{
$gettextString = $this->newlinesNormalizer->normalize($gettextString);
preg_match_all('~\%(\S+)\%~m', $gettextString, $matches);
$variables = $matches[array_key_last($matches)];
$finalParameters = [];
foreach ($variables as $index => $variable) {
if (substr($variable, 0, 1) === '%' && substr($variable, -1) === '%') {
continue;
}
$finalParameters['%' . $variable . '%'] = $parameters[$index];
}
return $this->symfonyTranslator->trans($gettextString, $finalParameters);
}

Related

(PHP) Search for parts of a string in a vector and return the value

I'm facing the following dilemma, I have a vector that is returned from the bank in the following format:
$vetor = array(0 => 'CR:9090909090909', 1 => 'TR:9090909090909', 2 => 'CP:9090909090909', 3 => 'TP:9090909090909');
I would like to know how to check if in an indeterminate index it contains one of the example codes "CR:" if it has, remove the "CR:" from the value leaving only the value after this code in the case "9090909090909", remembering that this interaction will be in one foreach for each index of the vector.
You can choose from two variants.
a) Finding and extracting the single CR code value from $vector array.
function getCode($vector, $type) {
foreach ($vector as $typeAndCode) {
list($type1, $code1) = explode(":", $typeAndCode);
if ($type1 === $type) return $code1;
}
return false;
}
$code = getCode($vector, "CR");
b) Writing the extracted CR code value directly into the existing $vector array. (I don't suppose you will need this variant, but your question wasn't very clear about it.)
$vector = array_map(function ($typeAndCode) {
list($type, $code) = explode(":", $typeAndCode);
return $type === "CR" ? $code : $typeAndCode;
}, $vector);

Variable Variables for Array Key

Currently I am attempting to call a multidimensional array, using a string as a key or keys. I would like to use the following code, but I think the key is being interpreted as a string. Any solution?
$data= [];
$data['volvo'] = "nice whip";
$test = "['volvo']";
$data['drivers']['mike'] = "decent";
$test2 = "['drivers']['mike']";
echo $data$test; // should read 'nice whip'
echo $data$test2; // should read 'decent'
You just use the variable (which should just be the string and not PHP syntax) in place of the string literal.
$cars = [];
$cars['volvo'] = 'nice whip';
$test = 'volvo';
echo $cars[$test];
If you need a dynamic array access solution, you could also write a function, which does the actual array access like this:
function path($array, $path) {
$path = is_array($path) ? $path : explode('.', $path);
$current = $array;
while (count($path)) {
$seg = array_shift($path);
if (!isset($current[$seg])) throw new Exception('Invalid path segment: ' . $seg);
$current = $current[$seg];
}
return $current;
}
In your case, this would look like this
echo path($data, 'volvo');
echo path($data, 'drivers.mike');
or
echo path($data, ['volvo']);
echo path($data, ['drivers', 'mike']);
The problem is you can't pass multiple levels in one string like that. (If so, PHP would have to start looking for code fragments inside string array keys. And how would it know whether to interpret them as fragments and then split the string key up, or keep treating it as one string??)
Alt 1
One solution is to change the structure of $data, and make it a single level array. Then you supply keys for all the levels needed to find your data, joined together as a string. You would of course need to find a separator that works in your case. If the keys are plain strings then something simple like underscore should work just fine. Also, this wouldn't change the structure of your database, just the way data is stored.
function getDbItem($keys) {
// Use this to get the "old version" of the key back. (I.e it's the same data)
$joinedKey = "['".implode("'],['", $keys)."']";
$joinedKey = implode('_', $keys);
return $data[$joinedKey];
}
// Example
$data = [
'volvo' => 'nice whip',
'drivers_mike' => 'decent'
];
var_dump(getDbItem(['drivers', 'mike'])); // string(6) "decent"
Alt 2
Another way is to not change number of levels in $data, but simply traverse it using the keys passed in:
$tgt = $data;
foreach($keys as $key) {
if (array_key_exists($key, $tgt)) {
$tgt = $tgt[$key];
}
else {
// Non existing key. Handle properly.
}
}
// Example
$keys = ['drivers', 'mike'];
// run the above code
var_dump($tgt); // string(6) "decent"

How do you iterate through Input::post() data?

To my understanding Input::post(); with no parameters returns an array containing all the data from a specific POST..
I am doing this $all_input = Input::post();
But then I am iterating through the array Java-like (is that how you even do it?)
for ($i=0; $i<count($all_input); $i++)
{
if (strpos($all_input[$i], 'something') == true) // ERROR...
but the application crashes with error Undefined offset: 0 which I believe means that the index was not found?
I have also tried adding this to no avail:
if (!isset($all_input))
{
return;
}
If so how can you access the data to iterate through them? I know it contains data cause I can see them when I press the button during the debugging on the browser if I remove that code.
If you didn't already figure it out I am coming from Java developer and I have just started learning php so bear with me please.
According to this: https://fuelphp.com/docs/classes/input.html#/method_post Input::post(); will return $_POST which is an assoc array.
Here is the source code, because the fuelphp's documentation doesn't cover it exactly.
/**
* Fetch an item from the POST array
*
* #param string $index The index key
* #param mixed $default The default value
* #return string|array
*/
public static function post($index = null, $default = null)
{
return (func_num_args() === 0) ? $_POST : \Arr::get($_POST, $index, $default);
}
You need to refer with your input names, so if you have an input which you call 'name', in that case you need to refer $all_input['name']. You can get your keys by using array_keys() function. Also it's better if you use foreach in this situation. Like:
foreach($all_input as $key => $value) {
echo 'Input key: ' . $key . ' value: ' . $value;
}
If you left the $key => you will get only the value, you can left it, if you doesn't use it inside the foreach.
If you don't want to use foreach somewhy:
$all_input = Input::post();
$keys = array_keys($all_input);
for ($i = 0; $i < count($keys); $i++) {
if (strpos($all_input[$keys[$i]], 'something') == true) {
// Do your stuff here.
}
}
But I still recommend foreach if possible, it's less overhead and cleaner code.
This won't work because you are dealing with an Object (Input) not an array.
I recommend using a foreach loop vice a for loop. To verify the contents/structure of the Input Object you can also do a dd() to see the Input Object in its entirety.
Basically,
$input = Input::post();
foreach($input as $i) {
echo $i; //this is a property of the Input Object. if you have arrays or other objects store inside of it, you may need to go deeper into the oject either with a foreach loop again or by calling the property directly ($i->property)
};

Fatal error: Using $this when not in object context using array_walk

I have made a class that should replace data at the hand of an array.
I insert
$data = array(
'bike',
'car',
'pc'
);
And it should translate the array to :
$data = array(
'[#bike]',
'[#car]',
'[#pc]'
);
I have written the following piece of code.
array_walk($PlaceHolders , function(&$value, $key) { $value = $this->Seperators['plcstart'].$value.$this->Seperators['plcend']; });
Which I am using in a class context.
The two sperators have the following value:
$this->Seperators['plcstart'] = '[#';
$this->Seperators['plcend'] = ']';
The problem is. At localhost it works superb!!
Now when I upload the system to a unix environment it stops working!
I have no clue why this is the result.
Would anyone here know what I am doing wrong?
I would recommend you to use array_map() when you want to modify array elements using a callback.
You could end with something like this
class TransformerClass {
private $Seperators = array(
'plcstart' => '[#',
'plcend' => ']'
);
public function transform(array $data) {
return array_map(
function($text) {
return $this->Seperators['plcstart'].$text.$this->Seperators['plcend'];
},
$data
);
}
}
Example:
$transformer = new TransformerClass();
$items = array(
'bike',
'car',
'pc'
);
$result = $transformer->transform($items);
And $result will contain your desired resulting data.
The most bizare thing is... This morning I opened the same page again.
And it worked like the offline environment :-S....
This is quite frustrating though!!
However I would like to make a few small notes:
///######## LOADING ALL PLACEHOLDERS
$PlaceHolders = array_keys($this->TplObjects);
///######## SEPERATOR START
$SeperatorStart = $this->Seperators['plcstart'];
$SeperatorEnd = $this->Seperators['plcend'];
///######## ADDING THE START AND END TAGS TO EACH ARRAY VALUE
array_walk($PlaceHolders , function(&$value, $key) { $value =
$SeperatorStart.$value.$SeperatorEnd; });
This is what I thought to be a solution but it is NOT!!
Why?? Because the way it was worked:
///######## LOADING ALL PLACEHOLDERS
$PlaceHolders = array_keys($this->TplObjects);
///######## ADDING THE START AND END TAGS TO EACH ARRAY VALUE
array_walk($PlaceHolders , function(&$value, $key) { $value = $this->Seperators['plcstart'].$value.$this->Seperators['plcend']; });
Because it got it's data directly out of the class.
By using function I placed the variables into it's own individual scope, hence the variable $SeperatorStart and $SeperatorEnd do not exist in this scope.
I could ofcourse import these two into that function. But I do not know how to do this with array_walk. I have not used this function this often hence I know only a few basic manners to use this function.
The second option as opted for above by #Falc works great! And is the method I was looking for. Hence thanks a million!!

Find if an array value shows up in a string. (Kind of a reverse in_array?)

On a site I'm working on there's a subheadline that only should be shown if the information isn't already shown in the main headline. The main headline is an arbitrary string, while the subheadline is created programatically. The subheadline is generated from the contents of a multi-dimensional array (the contents of which are also used for other parts of the page.)
I used the PHP example of foreach to drill down through the array (only half-understanding how it was working), and then tried strpos to see if the values in the array were in the headline string.
Unfortunately, it doesn't work. There is a high chance that I made a stupid mistake in how I thought it's supposed to work. Or that the variable that tells the site to hide the subhead ("hider") is constantly reset to "no" as a result of the other values in the array.
foreach ($arr_info as $i1 => $n1) {
foreach ($n1 as $i2 => $n2) {
foreach ($n2 as $i3 => $n3) {
$pos = strpos($headline, $n3);
if ($pos === false) {
$hider="no";
} else {
$hider="yes";
}
}
}
Any ideas? Greatly appreciate the help.
Add this:
$hider="yes";
break;
Hope it helps
I think a cleaner approach would be to construct a regex out of the values and see if it matches your string:
$values = array();
array_walk_recursive($arr_info, function($k){$GLOBALS['values'][] = preg_quote($k);});
$hider = preg_match('/(' . implode($values, '|') . ')/', $headline) ? 'yes' : 'no';

Categories