Aide à la création d'une fonction PHP réutilisable qui va appeler d'autres fonctions « dynamique »

StackOverflow https://stackoverflow.com/questions/2063691

Question

Ceci est ma première fois que je suis en train de faire quelque chose de sérieux avec db relationnelle MySQL et une sorte de CMS créé en PHP avec CodeIgniter.
Je suis venu à la partie où je dois insérer des données dans quelques nombreux à plusieurs tables connexes.
Dans mon tout code fonctionne bien (bien, avec seulement quelques minutes de test), mais je besoin d'aide à la création de la fonction réutilisable qui me aidera beaucoup à faire toutes les relations dans mes tableaux ...

J'ai essayé de commenter tout mon code, donc toutes les explications sont là-dedans ...

<?php
function add(){

 // This is what user posted in form.
 // There are two input fields:
 // name is always only one record
 // country can be a single record or array separated with " | " characters
 // I use CodeIgniter's $this->input->post instead of $_POST[]
 $name = $this->input->post('name');
 $countries = $this->input->post('country');

 // Inserting data to first table
 $data = array('firstName' => htmlentities($name)); // preparing array for inserting
 $insert_name = $this->db->insert('names', $data); // inserting with CodeIgniter's help
 $last_inserted_ID = $this->db->insert_id(); // getting last inserted ID

 // Inserting data to second table

 // Formatting of posted string of countries
 // Users can post strings similar to this:
 // "Austria"
 // "Austria |"
 // "Austria | "
 // "Austria | Australia"
 // "Austria | Australia |"
 // "Austria | Australia | "
 // and similar variations
 // What I need here is clear array with country names
 $separator = strpos($countries,"|"); // check for "|" character
 if ($separator === FALSE){ // if there is no "|" character in string
  $countries_array[] = $countries; // array is only one value (only one country)
 } else {
  $countries_array = explode(" | ", $countries); // explode my array
  if (end($countries_array) == ""){ // if last item in array is ""
   array_pop($countries_array); // eliminate last (empty) item
  }
 }

 // Now, this is the part I think I will use lots of times.
 // I would like to make this a separate function so I could use it in many places :)
 // I would pass to that function few values and I would use one of them
 // to call different functions in this same class.
 // I guess I should pass data ($countries_array) and function names I wish to call?????? This is problematic part for my brain :))
 // Check the comments below...
 for ($i = 0; $i < sizeof($countries_array); $i++){
  $insertIDS = array(); // this will be an array of IDs of all countries
  $tempdata = $this->get_countries($countries_array[$i]); // query which looks if there is a country with specific name
                // Right here, instead of calling $this->get_countries
                // I would like to call different functions, for example
                // $this->get_links($links_array[$i])
                // or $this->get_categories($categories_array[$i])
                // etc.
  if(sizeof($tempdata) != 0){ // so, if a record already exists
   foreach ($tempdata as $k => $v){
    $insertIDS[] = $k; // insert those IDs in our array
   }
  } else { // and if a record does not exist in db
   $this->add_country($countries_array[$i]); // add it as a new record...
               // This is also one of the places where I would call different functions
               // for example $this->add_link($links_array[$i])
               // or $this->add_categories($categories_array[$i])
               // etc.
   $insertIDS[] = $this->db->insert_id(); // ...get its ID and add it to array
  }

  // Finally, insert all IDs into junction table!
  foreach ($insertIDS as $idKey => $idValue){
   $this->add_names_countries($last_inserted_ID, $idValue); // Another place for calling different functions
                  // example $this->add_names_links($last_inserted_ID, $idValue)
                  // etc.
  }
 }

}
?>

Eh bien, en regardant ce code maintenant, je vois que je pourrais mettre cette partie de formatage aussi dans cette fonction, mais ce n'est pas tellement important maintenant ...

Merci beaucoup pour toute aide à ce !!

Était-ce utile?

La solution

La meilleure façon de le faire est d'utiliser un Table Data Gateway . Au lieu de

$this->db->insert('countries', $data);

vous créez des classes pour chaque table dans votre base de données. Chaque table encapsule logique CRUD dans la classe, par exemple.

class Countries
{
    $protected $_db;

    public function __construct($db)
    {
        $this->_db = $db;
    }

    public function save(array $countries)
    {
        $this->db->insert('countries', $countries);
    }

    // ... other methods
}

En outre, je vous suggère d'utiliser pour ce genre de travail parce que tout ce genre de choses appartient ensemble et vous ne voulez probablement pas d'insérer des données, si l'une des requêtes échoue. Je ne sais pas comment gère les transactions CodeIgnitor, mais au fond, vous devriez le faire de cette façon alors:

$this->db->startTransaction();          // like try/catch for databases
$countries = new Countries($this->db);
$countries->save($countryData);
$links = new Links($this->db);
$links->save($linkData);
// ...
if($this->db->commit() === false) {     // returns true when no errors occured
    $this->db->rollback();              // undos in case something went wrong
}

Bien que cela ne répond pas à votre question comment appeler dynamiquement une fonction ( call_user_func() pourrait le faire), le faire comme suggéré ci-dessus fait votre code beaucoup plus maintenable.

Votre question est un peu vague quant à savoir si vous voulez exécuter toutes les fonctions dans une séquence ou simplement pour échanger en fonction de ce que l'utilisateur a soumis. Pour le premier cas, utilisez l'approche de la transaction. Pour le second cas, vous simplement instancier la classe appropriée et appeler la méthode de sauvegarde.

Autres conseils

Pas tout à fait sûr de vos besoins, mais je pense que vous seriez peut-être après call_user_func:

function process($countries) {
// do stuff
}

$function_name = 'process';

call_user_func($function_name, $countries);

De cette façon, vous pouvez attribuer dynamiquement une fonction basée sur, par exemple, la liste des pays.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top