2016-06-30 1 views
0

Je ne suis pas sûr que j'utilise les bons termes même ici, mais je vais essayer d'expliquer, j'utilise la fonction PHP array_filter pour filtrer les produits et le rappel à une fonction personnalisée que j'ai fait ajouter le (s) filtre (s). Je peux le faire codé en dur très facile, mais je veux évidemment qu'il soit dynamique:Comment puis-je retourner les valeurs littérales d'une chaîne PHP pour qu'elle fonctionne comme du code?

Pour couper une longue histoire courte que la fonction retourne filtre personnalisé à la fonction array_filter() comme ceci:

return ($arr['colour']=='Red' || $arr['colour']=='White'); 

Cela fonctionne bien si codé en dur comme ci-dessus, et filtre le tableau comme prévu pour montrer uniquement les produits qui sont rouges ou blancs, mais j'ai besoin que cela soit dynamique.

Alors, comment puis-je construire une chaîne de valeurs, puis l'utiliser dans l'instruction return?

Par exemple:

$var="$arr['colour']=='Red' || $arr['colour']=='White'"; 
return ($var); 

ne fonctionne pas. J'ai essayé d'utiliser eval() (je ne veux pas l'utiliser de toute façon!) Et cela n'a pas fonctionné.

J'ai une boucle comme suit la construction de la chaîne à partir d'un tableau:

// $value=array of filters e.g colour=Black, colour=Red 

$filterparts=explode("=",$value); 

$filters[]='$arr[\''.$filterparts[0].'\']==\''.$filterparts[1].'\''; 
//creates array e.g $arr['colour']='Red' 

$imploded_filter= implode(" || ", $uniquefilters); 
//creates string e.g $arr['colour']='Red' || $arr['colour']='White' 

Donc, si j'echo $ imploded_filter je reçois la chaîne d'extrait je voudrais revenir

echo $imploded_filter; 
// outputs $arr['colour']='Red' || $arr['colour']='White' 

Toutefois, si je faire

return($imploded_filter); 

il est évidemment pas la chaîne évalue code dur, que puis-je faire, ai-je besoin faire quelque chose à la chaîne ou le retourner d'une manière différente, ou construire le code dont j'ai besoin de revenir d'une manière totalement différente?

Merci pour toute aide!

Répondre

0

clés Array peut être spécifié dynamiquement.Il n'y a pas besoin de eval():

$value = $array[$key]; 

Vous pouvez construire une liste de filtres et correspondent à chacun d'entre eux dans le array_filter() rappel:

$filters = array(
    array('colour', array('white', 'blue')), // multiple accepted values (OR) 
    array('material', 'Fine Bone China'), // single accepted value 
); 

$filtered = array_filter($products, function ($item) use ($filters) { 
    // match all filters 
    foreach ($filters as $filter) { 
     // detect multi-value filter 
     $isArrayFilter = is_array($filter[1]); 

     if (
      // check if multi-value filter doesn't match 
      $isArrayFilter && !in_array($item[$filter[0]], $filter[1]) 
      // check if a single-value filter doesn't match 
      || !$isArrayFilter && $item[$filter[0]] != $filter[1] 
     ) { 
      // filter doesn't match - exclude the item 
      return false; 
     } 
    } 

    // all filters match - include the item 
    return true; 
}); 
+0

Merci, cela semble bien faire le travail, est-il hors de la portée de cette question (ou même de la fonction array_filter!) De demander s'il est possible de travailler ainsi pour toutes les valeurs d'une catégorie (couleur) et puis ET de le combiner avec d'autres catégories? – BenM

+0

Par exemple color = "red" || couleur = "bleu" ET matériau = "métal" || material = "paper" ... pour l'instant, il suffit de vérifier si l'un d'entre eux existe, ce qui est bien, mais soyez gentil d'ajouter cette fonctionnalité. – BenM

+0

Vous pouvez prendre en charge les valeurs de tableau dans '$ filterparts [1]' ('$ filter [1]'). Si c'est un tableau, vous le faites correspondre avec 'in_array ($ arr [$ filter [0]], $ filter [1])' au lieu de simplement le comparer. – ShiraNai7

0
$colors = ['Red', 'White']; 
$products = array_filter($products, function ($product) use ($colors) { 
    return in_array($product['color'], $colors); 
}); 

Il n'y a pratiquement aucune raison ou nécessité de "créer dynamiquement du code source PHP". Il y a toujours une opération qui peut faire ce que vous voulez sur n'importe quel nombre d'éléments sans avoir besoin de concaténer || opérateurs. Ici in_array est une fonction parfaitement fine pour tester une valeur contre plusieurs. Vous pouvez transmettre dynamiquement le tableau de couleurs en utilisant use ($colors).

La solution la plus saine pour les versions PHP anciens est de rapprocher le rappel anonyme avec une classe:

class InArrayFilterCallback { 

    public $data = array(); 
    public $key; 

    public __construct($data, $key) { 
     $this->data = $data; 
     $this->key = $key; 
    } 

    public callback($item) { 
     return in_array($item[$this->key], $this->data); 
    } 

} 

$products = array_filter($products, array(new InArrayFilterCallback($colors, 'color'), 'callback')); 

Bien sûr, vous pourriez aussi utiliser une boucle foreach simple, à la place ...

+0

Bonjour et merci @deceze, savez-vous si cela fonctionne sur PHP <5.5? Je reçois beaucoup d'erreurs en essayant d'utiliser ce code :( – BenM

+0

Cela fonctionne depuis la version 5.3, car les fonctions anonymes ont été introduites.Pour les versions encore plus anciennes (qui sont positivement anciennes maintenant !!) il existe un certain nombre de solutions de contournement possibles. – deceze

+0

Voir mise à jour pour solution de contournement – deceze

0

pourquoi ne pas utiliser in_array fonction, comme ceci:

$filters = [ 
    'colour' => [ 
     'red', 
     'blue', 
    ] 
]; 
array_filter($list, function ($item) use ($filters) { 
    foreach ($filters as $index => $filter) { 
     if (!in_array($item[$index], $filter)) { 
      return false; 
     } 
    } 
    return true; 
}); 

que jamais une bonne idée de faire la chaîne et l'évaluer