Usando array numerici o array associativi, la ricerca e il recupero dei dati? [percorsi del file di una pagina]

0

Sto costruendo su un CMS in cui le dipendenze e i file necessari per una pagina vengono memorizzati nel database. Poiché questo può essere molto dinamico, serializzo questi percorsi in un campo Database nella mia tabella pages .

Sto cercando di memorizzare questi percorsi di file sul recupero in una matrice per usarlo in un interruttore e analizzarlo in una pagina web. Ho difficoltà a provare a decidere come ordinare i dati nell'array.

Ho alcune categorie in cui i file possono cadere:

  • CSS
  • JavaScript in testa
  • JavaScript prima del tag finale del corpo
  • Meta tag
  • PHP include
  • Etc ...

Diciamo che ho alcuni file:

CSS

  1. style.css
  2. custom.css

JavaScript-top

  • jQuery.min.js
  • Bootstrap.min.js

PHP include

  • pages.php

Qui ci sono due scelte:

Opzione 1. Usa un array numerico con un sub-array come valore per contenere un tipo di inclusione e il percorso del file:

array( 0 => [
          type => "css",
          file => "/path/to/file"
       ],
       1 => [
          type => "css",
          file => "/path/to/file"
       ],
       2 => [
          type => "js-top",
          file => "/path/to/file"
       ],
       4 => [
          type => "js-top",
          file => "/path/to/file"
       ],
       etc.. );

Opzione 2. Un array associato con un sub-array numerico:

array( css => [ 
           0 => "/path/to/file",
           1 => "/path/to/file"
         ],
       js-top => [ 
           0 => "/path/to/file",
           1 => "/path/to/file"
         ],
       php-include => [ 
           0 => "/path/to/file"
         ],
       etc...);

Vorrei andare per l'opzione 2, perché non devo iterare sull'array ogni volta che arrivo a un caso e devo cercare un possibile valore. Mentre con l'opzione 2, posso facilmente controllare se questo tipo isset () e passare attraverso l'interruttore molto più veloce!

Sto facendo questa domanda non a causa del possibile aumento delle prestazioni. Sto facendo questa domanda perché sto cercando di progettare i migliori sistemi e sono sempre alla ricerca di una ragione per cui farei una (semplice) scelta come questa.

Quale opzione sceglieresti e perché?

    
posta Abayob 23.05.2016 - 20:54
fonte

1 risposta

1

PHP è un linguaggio orientato agli oggetti, o almeno in qualche modo supporta ragionevolmente la programmazione orientata agli oggetti.

L'idea principale di OOP è che gli oggetti inviano messaggi ad altri oggetti e tali oggetti rispondono a tali messaggi. La metafora di "messaggistica" è azzeccata: quando invii a qualcuno un messaggio, tutto ciò che puoi vedere è la loro risposta. Non puoi vedere cosa fanno con il messaggio. Potrebbero leggerlo, pensarci bene e rispedirci una risposta (eseguendo una funzione). Potrebbero leggerlo e inviarti una risposta pre-inscatolata (leggendo una proprietà). Possono arruolare l'aiuto di altre persone (inviare messaggi stessi). Possono anche consegnare il messaggio a qualcun altro per rispondere (proxy). Non lo sai Spetta interamente al destinatario del messaggio che cosa fare con quel messaggio.

E questo è ciò che vogliamo fare qui. Vogliamo semplicemente inviare al frammento in questione un messaggio che dice "renditi!" e non ci interessa come il frammento lo fa. Il frammento PHP farà qualcosa di diverso dal frammento <meta> .

Nel tuo codice, hai "tipi" (o "classi") diversi di "cose" (o "oggetti"): hai frammenti CSS, frammenti JavaScript e così via. E tu switch tra l'esecuzione di diversi pezzi di codice a seconda della "classe" della cosa con cui hai a che fare. Per i CSS, fai una cosa, per JS, fai una cosa diversa.

Tuttavia, tale funzionalità è già integrata in PHP stesso! Quando scrivi:

$foo->bar();

Quindi PHP eseguirà diverse varianti di bar a seconda di quale sia la classe di $foo . Stai duplicando il lavoro che PHP già fa per te.

Potresti fare qualcosa di simile a questo: avere un'interfaccia comune per i diversi tipi di oggetto, che fondamentalmente significa solo che decidi su un nome e una firma per il metodo che vuoi usare. In PHP hai persino la possibilità di documentare questa decisione utilizzando interface :

interface PageFragment {
  public function render();
}

In realtà non hai bisogno di questo, potresti semplicemente avere un gruppo di classi con lo stesso nome di metodo, e funzionerebbe a prescindere, ma documentare la tua interfaccia comune con interface è bello, perché ti permette di usare digita il suggerimento più avanti, cioè documenta che un metodo richiede un oggetto di tipo PageFragment e ti dà un posto centrale in cui inserire la documentazione, in modo che tu possa dire agli utenti di interface quale sia il metodo render() dovrebbe fare.

Opzionalmente, possiamo aggiungere alcune classi base comuni che contengono alcune funzionalità comuni per tutti i tipi di frammenti di pagina:

abstract class FragmentBase implements PageFragment {
  protected $path;

  function __construct($path) {
    $this->path = $path;
  }

  // Just as an example
  public function __toString() {
    return "Page fragment from file {$this->path}";
  }
}

Il vero lavoro viene quindi eseguito in sottoclassi / implementazioni diverse di PageFragment , una classe per ogni tipo di frammento:

class CssFragment extends FragmentBase {
  public function render() {
    print("… do stuff to render CSS from file {$this->path}" . PHP_EOL);
  }
}

class MetaFragment extends FragmentBase {
  public function render() {
    print("… do stuff to render <meta> elements from file {$this->path}" . PHP_EOL);
  }
}

class HeaderJsFragment extends FragmentBase {
  public function render() {
    print("… do stuff to render JavaScript in the header from file {$this->path}" . PHP_EOL);
  }
}

class BodyJsFragment extends FragmentBase {
  public function render() {
    print("… do stuff to render JavaScript in the body from file {$this->path}" . PHP_EOL);
  }
}

class PhpFragment extends FragmentBase {
  public function render() {
    print("… do stuff to include PHP from file {$this->path} on the page" . PHP_EOL);
  }
}

Ora, se qualche parte del tuo framework da qualche altra parte nella tua base di codice crea dei frammenti di pagina:

$fragment1 = new PhpFragment("/path/to/foo.php");
$fragment2 = new CssFragment("/path/to/foo.css");

e ne mandi un po 'a te:

$fragments = [$fragment1, $fragment2];

Non hai bisogno di sapere, e non ti importa se sono frammenti CSS o frammenti di PHP o altro. Non hai bisogno di sapere cosa sono, perché loro sanno cosa sono e sanno come gestirsi da soli. Digli semplicemente di fare qualcosa e fanno la cosa giusta, automaticamente:

foreach ($fragments as $fragment) $fragment->render();
// … do stuff to include PHP from file /path/to/foo.php on the page
// … do stuff to render CSS from file /path/to/foo.css

Come puoi vedere, ogni frammento ha fatto la cosa giusta, e ogni frammento ha fatto una diversa cosa, senza che ci fosse un singolo condizionale nell'intero codice sorgente!

Questo tipo di modifica della struttura del codice da un condizionale esplicito rispetto a qualche nozione di "tipo" al dispiegamento del metodo polimorfico su tipi reali è chiamato Sostituisci condizionale con Refilloring polimorfismo :

da

function getSpeed() {
  switch ($type) {
    case EUROPEAN:
      return getBaseSpeed();
    case AFRICAN:
      return getBaseSpeed() - getLoadFactor() * $numberOfCoconuts;
    case NORWEGIAN_BLUE:
      return ($isNailed) ? 0 : getBaseSpeed($voltage);
  }
  throw new RuntimeException("Should be unreachable");
}

a

interface Bird {
  public function getSpeed();
}

class European implements Bird {
  public function getSpeed() {
    return $this->getBaseSpeed();
  }
}

class African implements Bird {
  public function getSpeed() {
    return $this->getBaseSpeed() - $this->getLoadFactor() * $this->numberOfCoconuts;
  }
}

class NorwegianBlue implements Bird {
  public function getSpeed($voltage = 0.0) {
      return ($this->isNailed) ? 0 : $this->getBaseSpeed($voltage);
  }
}

Si noterà che è possibile ridefinire ulteriormente NorwegianBlue in questo modo:

class NorwegianBlue implements Bird {
  public function getSpeed($voltage = 0.0) {
      return $this->getBaseSpeed($voltage);
  }
}

class NailedNorwegianBlue extends NorwegianBlue {
  public function getSpeed($voltage = 0.0) {
      return 0;
  }
}

Esiste una campagna un po 'divertente chiamata Anti- IF Campaign che sostiene la programmazione in questo stile.

Una domanda che potresti porsi è: funziona sempre? Posso sempre sostituire i condizionali con il polimorfismo? E la risposta è: sì, puoi! Il Refactoring Sostituisci condizionale con polimorfismo parla solo di condizionali che attivano una nozione di "tipo", ma in realtà, l'opzione ogni può essere interpretata come un cambio di tipi e quindi refactored allo stesso modo. Ci sono, infatti, lingue che non hanno nemmeno i condizionali, come Smalltalk. E infatti, se PHP non avesse condizionali, potresti implementarli tu stesso usando nient'altro che il dispiegamento del metodo polimorfico:

interface Buul {
  public function ifThenElse(callable $thenBranch, callable $elseBranch);
  public function andand(callable $other);
  public function oror(callable $other);
  public function negate();
}

final class TrueClass implements Buul {
  public function ifThenElse(callable $thenBranch, callable $elseBranch) {
    return $thenBranch();
  }
  public function andand(callable $other) { return other(); }
  public function oror(callable $other) {}
  public function negate() { return FalseClass::instance(); }

  // please excuse the rather crude singleton implementation ;-)
  private static $instance;
  public static function instance() {
    if (isset($instance)) return $instance;
    return $instance = new TrueClass();
  }
}

final class FalseClass implements Buul {
  public function ifThenElse(callable $thenBranch, callable $elseBranch) {
    return $elseBranch();
  }
  public function andand(callable $other) {}
  public function oror(callable $other) { return other(); }
  public function negate() { return TrueClass::instance(); }

  private static $instance;
  public static function instance() {
    if (isset($instance)) return $instance;
    return $instance = new FalseClass();
  }
}

function buul($bool) { return $bool ? TrueClass::instance() : FalseClass::instance(); }

buul(4 < 3)->ifThenElse(function () { print("less" . PHP_EOL); }, function () { print("greater" . PHP_EOL); });
// greater
    
risposta data 20.06.2016 - 16:22
fonte

Leggi altre domande sui tag