Aiuto nella scrittura di codice più generico

4

Sto facendo un progetto PHP MVC usando il codice di accensione. Ho due modelli, a e b.

Ogni classe contiene quattro funzioni (inserisci, elimina, aggiorna e visualizza) e le loro implementazioni sono quasi le stesse una con l'altra. Un amico ha suggerito di inserire versioni generiche delle quattro funzioni all'interno di una classe di utilità ei due modelli possono accedere alla loro funzione. Ad esempio, ecco l'implementazione generica di insert.

public function insert($tableName, $columns, $preds = null)
{
    // call code igniter's insert function
}
// do the same with delete, update and view

Tuttavia, essendo stato introdotto per programmazione diretta dei dati prima e dopo di recente ho scoperto che php può avere array di funzioni, penso che possiamo migliorarlo.

Quello che vorrei fare è: su ogni classe, creerò un array globale che contiene le quattro funzioni CRUD di accensione del codice specifiche per la classe con i tasti "insert", "add", "delete", "update".

Invece di creare quattro funzioni per ogni operazione CRUD, creerò una funzione di utilità e una funzione di esecuzione generale per ogni classe.

Nota: sono estremamente nuovo su php, alcuni dei codici php potrebbero non funzionare. Non l'ho ancora implementato direttamente.

// in the utility class
public function execute($dataFunctions, $op, $tableName, $columns)
{
    // this will not work, I am not yet familiar with putting functions inside an array
    $dataFunctions['op']($tableName,$columns);
}

// on class a
public function execute($op, $columns)
{
    // dataFunctions is the name of the global array
    utils->execute($dataFunctions,$op,"a",$colums)
}
// same with class b

Il fatto è che non sono completamente sicuro che questa sia una buona idea. Non l'ho mai fatto prima. Potrei non essere a conoscenza di eventuali inconvenienti. Dovrei preferire il modo con la gamma di funzioni? O dovrei limitarmi a implementare le quattro funzioni crude?

    
posta morbidCode 21.04.2016 - 15:43
fonte

1 risposta

4

Avere una classe base astratta e due classi derivate concrete. Non ci hai detto cosa è diverso, ma hai solo detto che "le loro implementazioni sono quasi le stesse tra loro". Supponiamo che il nome del database sia l'unica differenza:

abstract class Model_base {
    public function insert($tableName, $columns, $preds = null) {
        $db = $this->getDB();
        // call code igniter's insert function on $db
    }

    // Gets the database to operate on
    abstract function getDB();
}

class a extends Model_base {
    function getDB() {
        return $this->load->database('db_a', TRUE);
    }
}

class b extends Model_base {
    function getDB() {
        return $this->load->database('db_b', TRUE);
    }
}

Vedi anche:

link   Connessione a più database

link   Configurazione del database

Modifica: esempio di utilizzo:

Potresti creare due istanze:

$modelA = new a():
$modelB = new b():

$modelA->insert(...);

$modelB->insert(...);

Oppure potresti avere un selettore di modelli:

$model = $useA ? new a() : new b();

$model->insert(...);

Btw, se in realtà differiscono solo nel database selezionato, puoi anche solo passare il nome del database (db_a o db_b) o l'oggetto del database Code Igniter a un costruttore di una singola classe, non sono richieste classi astratte / derivate. Tutto dipende da cosa è diverso tra le classi.

Modifica 2: "in realtà l'unica differenza è il nome delle tabelle e delle colonne, entrambi sono all'interno di un database"

Dato che cambiano solo i nomi delle tabelle e delle colonne:

class Model_base {
    private $tableName1;
    private $tableName2;
    private $colName1;
    private $colName2;
    function __construct(
        $tableName1,
        $tableName2,
        $colName1,
        $colName2
    ) {
        $this->tableName1 = $tableName1;
        $this->tableName2 = $tableName2;
        $this->colName1 = $colName1;
        $this->colName2 = $colName2;
    }

    public function insert($preds = null) {
        // call code igniter's insert function using table and column names given in constructor
        // ...($this->tableName1, $this->colName2, ...);
    }
}

class Model_a extends Model_base {
    function __construct() {
        parent::__construct(
            'table1_a',
            'table2_a',
            'col1_a',
            'col2_a'
        );
    }
}

class Model_b extends Model_base {
    function __construct() {
        parent::__construct(
            'table1_b',
            'table2_b',
            'col1_b',
            'col2_b'
        );
    }
}

L'utilizzo è simile a prima.

Modifica 3: Più breve se molti nomi di tabelle, ma meno "compilatori" aiutano:

class Model_base {
    private $tableNames;
    private $colNames;
    function __construct(array $tableNames, array $colNames) {
        $this->tableNames = $tableNames;
        $this->colNames = $colNames;
    }

    public function insert($preds = null) {
        // call code igniter's insert function using table and column names given in constructor
        // ...($this->tableNames['table_1'], $this->colNames['col_2'], ...);
    }
}

class Model_a extends Model_base {
    function __construct() {
        parent::__construct(
            array(
                'table_1' => 'table_1a',
                'table_2' => 'table_2a'
            ),
            array(
                'col_1' => 'col_1a',
                'col_2' => 'col_2a'
            )
        );
    }
}

class Model_b extends Model_base {
    function __construct() {
        parent::__construct(
            array(
                'table_1' => 'table_1b',
                'table_2' => 'table_2b'
            ),
            array(
                'col_1' => 'col_1b',
                'col_2' => 'col_2b'
            )
        );
    }
}

L'utilizzo è simile a prima.

    
risposta data 22.04.2016 - 07:23
fonte

Leggi altre domande sui tag