2014-06-17 25 views
8

Abbiamo familiarità con Componenti e Helpers in CakePHP.come utilizzare la funzione comune in helper e componente In Cakephp

Ho un componente ABC e un helper XYZ ed entrambi hanno la stessa funzione (circa 2000 linee per un totale di 4000 linee). c'è un modo per usare la stessa funzione nei file Controller e .CTP. non è bene usare la stessa funzione 2 volte.

qualsiasi metodo in modo che sia possibile utilizzare la funzione Componente/Assistente in Helper/Component senza riscrivere?

stesso metodo nel componente e aiutante >>

Componente

classe DATAComponent estende Component {

public $components = array('Session', 'THmail'); 

public function UsaStateList() 
{ /********/} 

Helper

class LabHelper extends AppHelper { 
    public function UsaStateList() 
    { /********/} 
} 

risposta

7

Bene, dovrai riscrivere lo qualcosa di, non si risolverà da solo.

CakePHP è ancora PHP, quindi è possibile applicare facilmente modelli comuni per mantenere le cose ASCIUTTE. Il modo più diretto sarebbe probabilmente quello di spostare la funzionalità condivisa in una classe di utilità che sia il componente che l'helper possono utilizzare internamente lasciando invariata la loro API pubblica.

Alcuni degli helper di CakePHP fanno qualcosa di simile, controllare ad esempio l'helper del tempo.

Traits potrebbe essere un'opzione anche, a seconda della quantità di funzionalità essere condiviso e quanto è legato all'uso di un componente/helper .

+0

ho notato upvotes in arrivo per la mia piuttosto vecchio risposta e macchiato la generosità. Potrebbe non essere ovvio, ma questa risposta è stata aggiunta molto prima della ricompensa, cioè non è quella dettagliata, canonica che @trante sta cercando (non sono sicuro di cosa esattamente stia cercando). – ndm

2

Volevo utilizzare un componente all'interno di un helper. Quindi sono uscito con la seguente soluzione.

<?php 

App::uses('AppHelper', 'View/Helper'); 
App::import('Component', 'MyComponent'); 

class MyHelperHelper extends AppHelper { 

    private $MyComponent = null; 

    public function __construct(View $View, $settings = array()) { 
     $collection = new ComponentCollection(); 
     $this->MyComponent = new MyComponentComponent($collection); 
     parent::__construct($View, $settings); 
    } 

    public function myCustomFunction() { 
     return $this->MyComponent->myCustomFunction(); 
    } 

} 
+3

Se si utilizzano componenti in helper, si sta facendo torto Cake MVC. I componenti sono per i controller e gli helper sono per le viste. – BadHorsie

1

ok si desidera utilizzare una singola funzione di componente e il suo assistente, mi vengono in mente 3 cose che puoi fare:

  1. chiamare una funzione dal componente nel vostro aiutante.
  2. Chiamare una funzione da un helper nel componente.
  3. Creare un modello o utilizzare un modello esistente in cui si inserisce la funzione ed è possibile utilizzare questa funzione nel componente o nell'aiuto.

Opzione numbre 3: Nel vostro aiuto e dei componenti, è necessario importare un modello, partendo dal presupposto che la funzione sia in un modello "StateList":

come si chiama il funcion del modello "StateList" nel vostro aiutante, in modo da:

App::import("Model", "StateList"); 
$model = new StateList(); 
$model->UsaStateList(); 

come si chiama il funcion del modello "StateList" nel componente, in modo da:

$model = ClassRegistry::init('StateList'); 
$model->UsaStateList(); 

ans se si desidera utilizzare la stessa funzione in un controller solo:

$this->loadModel('StateList'); 
$this->StateList->UsaStateList(); 
+1

'$ model = new StateList();' non è corretto. '$ model = ClassRegistry :: init ('StateList');' è valido da qualsiasi luogo. – bancer

2

vorrei andare con una classe nella cartella Lib. È abbastanza chiaro come gestire una classe di libreria che ha solo metodi statici. Quindi, ometto questo caso. Una soluzione praticabile per creare un'istanza della classe potrebbe essere quella di crearla nel controller e inserirla nel registro. Se hai davvero bisogno di accedere a CakeRequest, CakeResponse e CakeSession (prendi nota che CakeSession ha molti metodi statici, quindi spesso non hai bisogno di un'istanza di quella classe) da quella classe puoi impostarlo dal controller:

$MyLib = new MyLib(); 
$MyLib->setRequest($this->request); // optional 
ClassRegistry::addObject('MyLib', $MyLib); 

Poi dalla vista o qualsiasi altro luogo si sarebbe solo ottenere un'istanza di MyLib dal registro di sistema:

ClassRegistry::getObject('MyLib'); 

o semplicemente

$list = ClassRegistry::getObject('MyLib')->UsaStateList(); 

Quindi, la classe sarebbe qualcosa di simile:

// /Lib/MyLib.php 
class MyLib { 
    public function setRequest(CakeRequest request) {...} 
    public function UsaStateList() {...} 
} 
1

semplice risposta

per le funzioni comuni in tutta l'applicazione, aggiungere un Lib o di classe Utility.

app/lib/MyClass.php

class MyClass { 

    public static function usaStateList() { 
     // ... 
    } 
} 

Quindi aggiungere questo nella parte superiore di qualsiasi file che si desidera l'accesso alla funzione:

App::uses('MyClass', 'Lib'); 

E chiamare la funzione di dove si vuole :

$myClass = new MyClass(); 
$states = $myClass::usaStateList(); 

migliore risposta

Sembra a me come il vostro problema specifico è che si vuole essere in grado di ottenere un elenco di stati degli Stati Uniti, sia il controller e il vostro punto di vista. Il modo migliore per farlo è avere una tabella di database degli Stati Uniti.

  1. Creare una tabella nel database denominato us_states.

    Esempio SQL:

    CREATE TABLE `us_states` (
        `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
        `name` VARCHAR(20) NOT NULL, 
        `abbreviation` CHAR(2) NOT NULL 
    ) ENGINE = MYISAM 
    
  2. Inserire tutti gli stati come dati in quella tabella. È possibile trovare dump SQL su Internet che già hanno quello per voi (ad esempio Like this one).

  3. Creare un modello UsState in CakePHP.

    /** 
    * Model for US States 
    * 
    * @package app.Model 
    */ 
    class UsState extends AppModel { 
    
        /** 
        * Default sort order 
        * 
        * @var string|array 
        */ 
        public $order = 'UsState.name'; 
    } 
    

Che cosa si può poi fare è accedere gli stati dal controller semplicemente utilizzando il modello.

/** 
    * Your Controller 
    * 
    * @package app.Controller 
    */ 
    class YourController extends AppController { 

     public function index() { 

      // Get a list of US states 
      $this->loadModel('UsState'); 
      $states = $this->UsState->find('all'); 
     } 

    } 

E se si desidera accedere quegli stati in vista, allora si dovrebbe passare lungo che i dati come si farebbe normalmente tutte le altre variabili.

Immagino che vorresti farlo in modo da poter avere un menu di selezione degli stati degli Stati Uniti, forse.

 public function index() { 

      // Get a list of US states 
      $this->loadModel('UsState'); 
      $states = $this->UsState->find('all'); 

      // Make the states into an array we can use for a select menu 
      $stateOptions = array(); 
      foreach ($states as $state) { 
       $stateOptions[$state['id']] = $state['name']; 
      } 

      // Send the options to the View 
      $this->set(compact('stateOptions')); 
     } 

E secondo lei è possibile visualizzare un menu di selezione per questo come questo:

echo $this->Form->select('us_state_id', $stateOptions);