Ayuda con la creación de una función de PHP reutilizable que 'dinámica' llamar a otras funciones

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

Pregunta

Esta es la primera vez que estoy tratando de hacer algo serio con db relacional en MySQL y algún tipo de CMS creada en PHP con CodeIgniter.
Llegué a la parte en la que tengo que insertar algunos datos en pocos-muchos-a-muchos tablas relacionadas.
En mi código todo funciona bien (bueno, con sólo unos minutos de prueba), pero necesito un poco de ayuda con la creación de la función reutilizable que me ayudará mucho para que todas las relaciones en mis cuadros ...

He intentado comenta todo en mi código, por lo que todas las explicaciones están ahí ...

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

}
?>

Bueno, mirando el código ahora, veo que podía poner esa parte de formato también en esa función, pero eso no es tanto importante en este momento ...

Gracias muchísimo para cualquier ayuda con esto !!

¿Fue útil?

Solución

La mejor forma de hacer esto es utilizar un rel="nofollow tabla de datos de puerta de enlace . En lugar de

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

crear clases para cada tabla en su base de datos. Cada tabla encapsula lógica CRUD en la clase, por ejemplo.

class Countries
{
    $protected $_db;

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

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

    // ... other methods
}

Además, sugiero usar para este tipo de trabajo, porque todas esas cosas relacionados entre sí, y es probable que no desea insertar los datos, si una de las consultas falla. No sé cómo CodeIgnitor ocupa de las transacciones, pero básicamente, debe hacerlo de esta manera a continuación:

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

Si bien esto no responde a tu pregunta cómo llamar dinámicamente una función ( call_user_func() podría hacer esto), haciendo como se sugirió anteriormente hace que su código mucho más fácil de mantener.

Su pregunta es un poco vago en cuanto a si se desea ejecutar todas las funciones en una secuencia o simplemente quieres intercambiar dependiendo de lo que el usuario envió. Para el primer caso, utilizar el enfoque transacción. Para el segundo caso, sólo tendría que crear una instancia de la clase apropiada y llame al método guardar.

Otros consejos

No del todo seguro de sus requerimientos, pero creo que es posible que después de call_user_func:

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

$function_name = 'process';

call_user_func($function_name, $countries);

De esta manera, se puede asignar dinámicamente una función basada en, por ejemplo, la lista de países.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top