Is in_array() function in php multibyte safe?
If not ,how can i make it so?
The php.net multibyte reference lists mb_stristr() but it accepts a string , not an array as haystack .
My haystack = array of strings and needle = string.
Since I could not find any built in PHP solution, I did as #FirstOne suggested.
/**
* #return bool true if needle is found in haystack, false otherwise
*/
public function custom_mb_in_array($_needle, array $_hayStack) {
foreach ($_hayStack as $value) {
if (mb_strtolower($value) === mb_strtolower($_needle)) {
return true;
}
}
return false;
}
Related
I am using preg_match to verify an input :
$string = 'test';
if (preg_match ('/[^-a-z\d]/i', $string))
{
return true;
}
else
{
return false;
}
Well I can not understand why it return false here !
Am I missing something ?
Shouldn't it return true ?
The solution :
(preg_match ('/^[-a-z\d]*$/i', $string))
Tyr this
(preg_match ('/^[-A-Za-z\d]*$/', $string))
So preg_match() can return 0, 1, or false it is probably safer to do a strict check that the result equals 1, i.e.
abstract class Pattern
{
/** #const int */
const TEXT_MATCH = 1;
/**
* #param string $pattern regex pattern to match against
* #param string $string the text string to search
*
* #return bool
*/
public static function match(string $pattern, string $string): bool
{
return preg_match($pattern, $string) === self::TEXT_MATCH;
}
}
Primarily the bit you're interested in is this
preg_match($pattern, $string) === 1;
If you then use it:
$result = Pattern::match('/[^-a-z\d]/i', 'test');
var_dump($result); // false
The string doesn't pass the check. If that doesn't resolve your issue we're going to need to see a few examples of strings you are passing through that are always passing. It's probably also worth explaining what you want the regex to match against, because that could be part of the issue also.
I'm using PHP 7.1.12 and I trying to check if values from an array are present in a string to do that I'm doing this:
public function checkWords($word) {
$list = array('extinção','desativação','obrigatório');
foreach($list as $l) {
if (stripos($word, $l) !== false) {
return true;
}
}
return false;
}
and them I call the function
echo($this->checkWords('Físicaem desativação/extinção voluntária:23000.010237/2012-46''); //returns false
Now comes the weird part, if I go to the function and replace $l with let's say: 'hello'.
public function checkWords($word) {
$list = array('extinção','desativação','obrigatório');
foreach($list as $l) {
if (stripos($word, 'extinção') !== false) {
return true;
}
}
}
the function call will return true
echo($this->checkWords('Físicaem desativação/extinção voluntária:23000.010237/2012-46''); //returns true
Any ideas?
Since this question has a bounty, cannot flag it as duplicate, but the issue is with the function used in your case:
stripos($word, 'extinção')
As here is stated, stripos doesn't handle special characters very well and produces this non deterministic results. Use mb_strpos instead.
This seems to be an issue with the string encoding.
1) Check if using mb_stripos works. http://php.net/manual/en/function.mb-stripos.php
2) if (1) fails you may be serving the file with the wrong encoding. Check if your file charset matches your html charset meta header. https://developer.mozilla.org/en/docs/Web/HTML/Element/meta
<meta charset="utf-8">
When you have to deal with multi-byte characters at that time simple string function will not work. You have to use mb functions for it. There is list of mb functions which work with multi-byte characters, Check entire list here:
http://php.net/manual/en/ref.mbstring.php
Now for find position you can use mb_stripos function. Try below code:
function checkWords($word) {
$list = array('extinção','desativação','obrigatório');
foreach($list as $l) {
if (mb_stripos($word, $l) !== false) {
return true;
}
}
return false;
}
var_dump(checkWords('Físicaem desativação/extinção voluntária:23000.010237/2012-46')); // return true
echo PHP_EOL;
var_dump(checkWords('Físicaema dessativação/extsinção voluntária:23000.010237/2012-46')); //return false
DEMO
What is the easiest way to check if a string contains a valid float?
For example
is_string_float("1") = true
is_string_float("1.234") = true
is_string_float("1.2e3") = true
is_string_float("1b2") = false
is_string_float("aldhjsfb") = false
The easiest way would be to use built in function is_float(). To test if a variable is a number or a numeric string you must use is_numeric().
If you really want to know if a string contains a float and ONLY a float you cannot use is_float() (wrong type) or is_numeric() (returns true for a string like "1" too) only. I'd use
<?php
function foo(string $string) : bool {
return is_numeric($string) && strpos($string, '.') !== false;
}
?>
instead.
maybe you can use a couple of functions
out of the box
function is_string_float($string) {
if(is_numeric($string)) {
$val = $string+0;
return is_float($val);
}
return false;
}
This can easily be achieved by double casting.
/**
* #param string $text
* #return bool
*/
function is_string_float(string $text): bool
{
return $text === (string) (float) $text;
}
This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
So I have this (simple) method:
/**
* #param $needle
* #param $haystack
*
* #return array
*/
public function recursiveArraySearch($needle, $haystack)
{
$array = false;
foreach ($haystack as $key => $value) {
if ($key === $needle) {
$array = $value;
} elseif (is_array($value)) {
$this->recursiveArraySearch($needle, $value);
}
}
return $array;
}
Which is called like so:
$result = $this->recursiveArraySearch('some_index', $configArray);
It am having trouble return it once and for all back to $result`.
If the $needle matches the $key then I just want it to return the value but at the moment it's returning to itself.
Something I haven't actually done yet.
Thanks
UPDATE: When I return the method as the answers suggest and it reached the end of an array node (like a binary tree search) it passes a string in as the $haystack and thus return false.
Data Structure:
I may want to get the values of key circled red or I may want the values of the key circled orange?
The function needs to return them of false.
you can do this
public function recursiveArraySearch($needle, $haystack)
{
foreach ($haystack as $key => $value) {
if ($key === $needle) {
return $value;
} elseif (is_array($value)) {
$check = $this->recursiveArraySearch($needle, $value);
if($check)
return $check;
}
}
return false;
}
public function recursiveArraySearch($needle, $haystack)
{
foreach ($haystack as $key => $value) {
if ($key === $needle) {
return $value;
} elseif (is_array($value)) {
$result = $this->recursiveArraySearch($needle, $value);
if ($result !== false){
return $result;
}
}
}
return false;
}
When you recurse down you need to check the result and return only if an item was found. If nothing was found then you need to let the loop continue.
This assumes that your array does not contain any boolean values. If it does, you'll need to use an alternate method to avoid confusing a false value for not found.
I edited this answer to fit your needs.
function findKey($array, $keySearch)
{
foreach ($array as $key => $item) {
if ($key == $keySearch) {
return $item;
}
else {
if (is_array($item)) {
$keyFound = findKey($item, $keySearch);
if( $keyFound != false ) {
return $keyFound;
}
}
}
}
return false;
}
A number of problems here. First and foremost you are not assigning the data returned from the recursive call to any kind of data structure. Also, you should be doing a better job of checking edge conditions. Finally, if your Doc Block says that array is returned, you need to 100% make sure you are returning an array. That is the contract you are making with the caller when they read the documentation on this method, so you should adhere to that.
The example below assumes you are just going to return a numerically indexed array of values to the initial caller. This example includes a merge of recursive results to active array, better handling around input validation, and the consistent return of a numerically-indexed array (with empty array signifying no results).
/**
* #param mixed $needle Integer or string key value used for recursive search.
* #param array $haystack Array to be searched.
*
* #throws InvalidArgumentException
*
* #return array Return numerically-indexed array with empty array if no match.
*/
public function recursiveArraySearch($needle, array $haystack)
{
// validate that we have a proper needle passed
if(!is_int($needle) && !is_string($needle)) {
throw new InvalidArgumentException(
'Invalid search needle type passed as argument. ' .
"Integer or string value expected. Value passed:\n" .
var_export($needle, true)
);
}
$array = [];
foreach ($haystack as $key => $value) {
// recursively search if $value is non-empty array
if(is_array($value) && !empty($value)) {
array_merge($array, $this->recursiveArraySearch($needle, $value));
}
// otherwise, we can make exact string/integer comparison
else if ($key === $needle) {
$array[] = $value;
}
}
return $array;
}
Note here that I am assuming you are looking for all matches in the recursive structure. If you are looking for the first match, you can do something like the following, which is a breadth-first search.
/**
* #param mixed $needle Integer or string key value used for recursive search.
* #param array $haystack Array to be searched.
*
* #throws InvalidArgumentException
*
* #return mixed Return values could be mixed since we have no constraint on
* value types in haystack. Null will be returned on no match, thus
* this function cannot differentiate explicitly defined null values
* from no match.
*/
public function recursiveBreadthFirstSingleMatchArraySearch($needle, array $haystack)
{
// validate that we have a proper needle passed
if(!is_int($needle) && !is_string($needle)) {
throw new InvalidArgumentException(
'Invalid search needle type passed as argument. ' .
"Integer or string value expected. Value passed:\n" .
var_export($needle, true)
);
}
// see if there is key match at first level of array
if(array_key_exists($needle, $haystack)) {
return $haystack[$needle];
}
// iterate through haystack performing recursive search on array until match
foreach ($haystack as $key => $value) {
// recursively search if $value is non-empty array
if(is_array($value) && !empty($value)) {
$result = $this->
recursiveBreadthFirstSingleMatchArraySearch($needle, $value));
if (!is_null($result)) {
return $result;
}
}
}
return null;
}
I was searching here on StackOverflow about converting string to the real value and i didn't found.
I need a function like "gettype" that does something like the result above, but i can't do it all :s
gettypefromstring("1.234"); //returns (doble)1,234;
gettypefromstring("1234"); //returns (int)1234;
gettypefromstring("a"); //returns (char)a;
gettypefromstring("true"); //returns (bool)true;
gettypefromstring("khtdf"); //returns (string)"khtdf";
Thanks to all :)
1+ for Svisstack! ;)
Here is the function if someone want it:
function gettype_fromstring($string){
// (c) José Moreira - Microdual (www.microdual.com)
return gettype(getcorrectvariable($string));
}
function getcorrectvariable($string){
// (c) José Moreira - Microdual (www.microdual.com)
// With the help of Svisstack (http://stackoverflow.com/users/283564/svisstack)
/* FUNCTION FLOW */
// *1. Remove unused spaces
// *2. Check if it is empty, if yes, return blank string
// *3. Check if it is numeric
// *4. If numeric, this may be a integer or double, must compare this values.
// *5. If string, try parse to bool.
// *6. If not, this is string.
$string=trim($string);
if(empty($string)) return "";
if(!preg_match("/[^0-9.]+/",$string)){
if(preg_match("/[.]+/",$string)){
return (double)$string;
}else{
return (int)$string;
}
}
if($string=="true") return true;
if($string=="false") return false;
return (string)$string;
}
I used this function to know if the number X is multiple of Y.
Example:
$number=6;
$multipleof=2;
if(gettype($number/$multipleof)=="integer") echo "The number ".$number." is multiple of ".$multipleoff.".";
But the framework that i work returns always the input vars as strings.
You must try to convert it in specified order:
Check is double
If double, this may be a integer, you must convert and compare this values.
If not, this is char if lenght is == 1.
If not, this is string.
If string, try parse to bool.
You can't use gettype because you may get string type of decimal writed in string.
Here is an updated version of this 9 year old function:
/**
* Converts a form input request field's type to its proper type after values are received stringified.
*
* Function flow:
* 1. Check if it is an array, if yes, return array
* 2. Remove unused spaces
* 3. Check if it is '0', if yes, return 0
* 4. Check if it is empty, if yes, return blank string
* 5. Check if it is 'null', if yes, return null
* 6. Check if it is 'undefined', if yes, return null
* 7. Check if it is '1', if yes, return 1
* 8. Check if it is numeric
* 9. If numeric, this may be a integer or double, must compare this values
* 10. If string, try parse to bool
* 11. If not, this is string
*
* (c) José Moreira - Microdual (www.microdual.com)
* With the help of Svisstack (http://stackoverflow.com/users/283564/svisstack)
*
* Found at: https://stackoverflow.com/questions/2690654/how-to-get-the-real-type-of-a-value-inside-string
*
* #param string $string
* #return mixed
*/
function typeCorrected($string) {
if (gettype($string) === 'array') {
return (array)$string;
}
$string = trim($string);
if ($string === '0') { // we must check this before empty because zero is empty
return 0;
}
if (empty($string)) {
return '';
}
if ($string === 'null') {
return null;
}
if ($string === 'undefined') {
return null;
}
if ($string === '1') {
return 1;
}
if (!preg_match('/[^0-9.]+/', $string)) {
if(preg_match('/[.]+/', $string)) {
return (double)$string;
}else{
return (int)$string;
}
}
if ($string == 'true') {
return true;
}
if ($string == 'false') {
return false;
}
return (string)$string;
}
I am using it in a Laravel middleware to transform form values that were stringified by browser JavaScript's FormData.append() back into their correct PHP types:
public function handle($request, Closure $next)
{
$input = $request->all();
foreach($input as $key => $value) {
$input[$key] = $this->typeCorrected($value);
}
$request->replace($input);
return $next($request);
}
To create that, type in your CLI php artisan make:middleware TransformPayloadTypes.
Then paste in the above handle function.
Don't forget to paste in the typeCorrected function also. I currently recommend making it a private function in your middleware class, but I don't claim to be a super-expert.
You can imagine that $request->all() is an array of key/value pairs, and it comes in with all values stringified, so the goal is to convert them back to their true type. The typeCorrected function does this. I've been running it in an application for a few weeks now, so edge cases could remain, but in practice, it is working as intended.
If you get the above working, you should be able to do something like this in Axios:
// note: `route()` is from Tightenco Ziggy composer package
const post = await axios.post(route('admin.examples.create', {
...this.example,
category: undefined,
category_id: this.example.category.id,
}));
Then, in your Laravel controller, you can do \Log::debug($request->all()); and see something like this:
[2020-10-12 17:52:43] local.DEBUG: array (
'status' => 1,
'slug' => 'asdf',
'name' => 'asdf',
'category_id' => 2,
)
With the key fact being that you see 'status' => 1, and not 'status' => '1',
All of this will allow you to submit JSON payloads via Axios and receive non-nested values in your FormRequest classes and controllers as the actual payload types are mutated. I found other solutions to be too complex. This above solution allows you to submit flat JSON payloads from pure JavaScript easily (so far, haha).