Aiuto per la creazione di una funzione PHP riutilizzabile che 'dinamico' chiamare altre funzioni

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

Domanda

Questa è la mia prima volta che sto cercando di fare qualcosa di serio con db relazionale MySQL e un qualche tipo di CMS realizzato in PHP con CodeIgniter.
Sono venuto alla parte in cui devo inserire alcuni dati in pochi molti-a-molti tabelle correlate.
Nel mio codice tutto funziona bene (bene, con pochi minuti di prove), ma ho bisogno di aiuto con la funzione di creazione riutilizzabile, che mi aiuterà molto a fare tutte le relazioni tra le mie tabelle ...

Ho cercato di commentare tutto ciò che nel mio codice, in modo da tutte le spiegazioni sono lì ...

<?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.
  }
 }

}
?>

Bene, guardando questo codice ora, vedo che ho potuto mettere quella parte formattazione anche in quella funzione, ma non è tanto importante in questo momento ...

Grazie molto per qualsiasi aiuto con questo !!

È stato utile?

Soluzione

Il modo migliore per farlo è quello di utilizzare un rel="nofollow Tabella Gateway . Invece di

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

si crea classi per ogni tabella nel database. Ogni tabella incapsula logica CRUD nella classe, per esempio.

class Countries
{
    $protected $_db;

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

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

    // ... other methods
}

In aggiunta, vi suggerisco di utilizzare per questo tipo di lavoro, perché tutta quella roba appartenga insieme e probabilmente non si desidera inserire tutti i dati, se una delle query fallisce. Non so come CodeIgnitor gestisce le transazioni, ma in fondo, si dovrebbe fare in questo modo, allora:

$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
}

Anche se questo non risponde alla tua domanda come chiamare dinamicamente una funzione ( call_user_func() potrebbe fare questo), facendo come suggerito sopra rende il codice molto più gestibile.

La tua domanda è un po 'vago, come per se si desidera eseguire tutte le funzioni in una sequenza o semplicemente si vuole scambiare seconda di ciò che l'utente ha inviato. Per il primo caso, utilizzare il metodo di transazione. Per il secondo caso, si sarebbe semplicemente un'istanza della classe appropriata e chiamare il metodo di salvataggio.

Altri suggerimenti

Non del tutto sicuri delle vostre esigenze, ma penso che potrebbe essere dopo call_user_func:

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

$function_name = 'process';

call_user_func($function_name, $countries);

In questo modo, è possibile assegnare dinamicamente una funzione di base di, per esempio, l'elenco dei paesi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top