2011-05-22 9 views
42

Mam sterownik home z operacją index, która wyświetla zestaw polecanych produktów. Jednak produkty są zarządzane za pomocą kontrolera product, w tym zastrzeżonego modelu i widoków.CodeIgniter: Kontroler obciążenia w kontrolerze

Jak uzyskać dostęp do informacji product z poziomu index w sterowniku home? Instancja product nie będzie działać, ponieważ klasa nie jest ładowana w czasie wykonywania, a funkcja CodeIgniter nie zapewnia sposobu dynamicznego ładowania kontrolerów. Przeniesienie klasy product do pliku biblioteki również nie działa.

Potrzebuję widoków produktu (wypełnionych danymi przetwarzanymi przez kontroler product) wstawionych w widoku indeksu. Używam CodeIgniter 2.0.2.

+4

Wygląda na to, że używasz Kontrolerów do opracowywania danych. Sugeruję, żebyś używał do tego modeli, w ten sposób będziesz musiał tylko wywołać metodę modeli niezależnie od kontrolera, w którym się znajdujesz (chudy kontroler MVC, gruby model). –

+0

Mówię raczej o widżetach lub cząstkach - Chciałbym mieć spójne moduły do ​​umieszczenia w szablonie witryny. W mniejszym lub większym stopniu wymagałoby to utworzenia instancji kontrolerów. – Daniel

Odpowiedz

30

Jeśli jesteś zainteresowany, istnieje ugruntowane pakiet tam, że można dodać do projektu CodeIgniter, które będą obsługiwać ten:

https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/

modułowa Rozszerzenia czyni PHP CodeIgniter ramy modułowe. Moduły to grupy niezależnych komponentów, zazwyczaj modelu, kontrolera i widoku, ułożone w podkatalogu modułów aplikacji, które można przenieść do innych aplikacji CodeIgniter.

OK, więc dużą zmianą jest to, że teraz używałbyś modułowej struktury - ale dla mnie jest to pożądane. Używałem CI od około 3 lat i nie wyobrażam sobie życia bez Modułowych rozszerzeń.

Teraz oto część, która zajmuje się bezpośrednio dzwoniąc kontrolery do renderowania widoku partials:

// Using a Module as a view partial from within a view is as easy as writing: 
<?php echo modules::run('module/controller/method', $param1, $params2); ?> 

To wszystko jest do niego. I zazwyczaj to wykorzystać do ładowania trochę "widgety" jak:

  • kalendarze imprez
  • Lista najnowszych artykułów
  • NEWSLETTER formy
  • ankiet

Zazwyczaj zbudować „widget "kontroler dla każdego modułu i używaj go tylko w tym celu.

Twoje pytanie było również jednym z moich pierwszych pytań, gdy zaczynałem od Codeigniter. Mam nadzieję, że ci to pomoże, mimo że może to być coś więcej niż szukasz. Używam MX od tego czasu i nie oglądałem się za siebie.

Przeczytaj uważnie dokumenty i sprawdź mnóstwo informacji na temat tego pakietu na forach Codeigner. Cieszyć się!

7

W tym przypadku możesz wypróbować oldschoolowy php.

// insert at the beggining of home.php controller require_once(dirname(__FILE__)."/product.php"); // the controller route.

Wtedy będziesz mieć coś takiego:

Class Home extends CI_Controller 
{ 
public function __construct() 
{ 
    parent::__construct(); 
    $this->product = new Product(); 
    ... 
} 

... 
// usage example 
public function addProduct($data) 
{ 
    $this->product->add($data); 
} 
} 

A potem po prostu użyć metody kontrolera, jak chcesz.

0

Za pomocą poniższego kodu można załadować klasy kontrolerów i uruchomić metody.

Kod ten został napisany dla CodeIgniter 2.1

Pierwszy dodać nowy plik MY_Loader.php w application/rdzenia katalogu. Dodaj poniższy kod do nowo utworzonego MY_Loader.php pliku:

<?php if (! defined('BASEPATH')) exit('No direct script access allowed'); 

// written by AJ [email protected] 

class MY_Loader extends CI_Loader 
{ 
    protected $_my_controller_paths  = array(); 

    protected $_my_controllers   = array(); 


    public function __construct() 
    { 
     parent::__construct(); 

     $this->_my_controller_paths = array(APPPATH); 
    } 

    public function controller($controller, $name = '', $db_conn = FALSE) 
    { 
     if (is_array($controller)) 
     { 
      foreach ($controller as $babe) 
      { 
       $this->controller($babe); 
      } 
      return; 
     } 

     if ($controller == '') 
     { 
      return; 
     } 

     $path = ''; 

     // Is the controller in a sub-folder? If so, parse out the filename and path. 
     if (($last_slash = strrpos($controller, '/')) !== FALSE) 
     { 
      // The path is in front of the last slash 
      $path = substr($controller, 0, $last_slash + 1); 

      // And the controller name behind it 
      $controller = substr($controller, $last_slash + 1); 
     } 

     if ($name == '') 
     { 
      $name = $controller; 
     } 

     if (in_array($name, $this->_my_controllers, TRUE)) 
     { 
      return; 
     } 

     $CI =& get_instance(); 
     if (isset($CI->$name)) 
     { 
      show_error('The controller name you are loading is the name of a resource that is already being used: '.$name); 
     } 

     $controller = strtolower($controller); 

     foreach ($this->_my_controller_paths as $mod_path) 
     { 
      if (! file_exists($mod_path.'controllers/'.$path.$controller.'.php')) 
      { 
       continue; 
      } 

      if ($db_conn !== FALSE AND ! class_exists('CI_DB')) 
      { 
       if ($db_conn === TRUE) 
       { 
        $db_conn = ''; 
       } 

       $CI->load->database($db_conn, FALSE, TRUE); 
      } 

      if (! class_exists('CI_Controller')) 
      { 
       load_class('Controller', 'core'); 
      } 

      require_once($mod_path.'controllers/'.$path.$controller.'.php'); 

      $controller = ucfirst($controller); 

      $CI->$name = new $controller(); 

      $this->_my_controllers[] = $name; 
      return; 
     } 

     // couldn't find the controller 
     show_error('Unable to locate the controller you have specified: '.$controller); 
    } 

} 

Teraz można załadować wszystkie kontrolery w katalogu application/controllers. na przykład:

obciążenia Faktura klasa kontrolera i wykonać test funkcji()

$this->load->controller('invoice','invoice_controller'); 

$this->invoice_controller->test(); 

lub gdy klasa jest w reż

$this->load->controller('/dir/invoice','invoice_controller'); 

$this->invoice_controller->test(); 

To po prostu działa tak samo jak załadowania model

62

Załaduj to w ten sposób

$this->load->library('../controllers/instructor'); 

i wywołać następujące metody:

$this->instructor->functioname() 

Działa to dla CodeIgniter 2.x.

+3

najlepsze rozwiązanie tam – Umren

+3

Dzięki za to. Zauważ, że CodeIgniter traktuje kontroler jako singleton, odkryłem więc, że po wczytaniu drugiego kontrolera oryginalny kontroler nie będzie działał normalnie.Po załadowaniu drugiego kontrolera, upewnij się, że nie próbujesz używać '$ this-> load' lub żadnych wczytanych modeli w oryginalnym kontrolerze; zamiast tego użyj '$ ci = get_instance()' i uzyskaj dostęp tylko do modeli za pomocą '$ ci' (np.' $ ci-> user_model'). –

+0

Nawet poza komentarzem oryginalne kontrolery działają dobrze. –

5

podstawie odpowiedzi @Joaquin Astelarra, udało mi się napisać ten mały pomocnika nazwie load_controller_helper.php:

<?php if (! defined('BASEPATH')) exit('No direct script access allowed'); 

if (!function_exists('load_controller')) 
{ 
    function load_controller($controller, $method = 'index') 
    { 
     require_once(FCPATH . APPPATH . 'controllers/' . $controller . '.php'); 

     $controller = new $controller(); 

     return $controller->$method(); 
    } 
} 

Można użyć/nazwać tak:

$this->load->helper('load_controller'); 
load_controller('homepage', 'not_found'); 

Uwaga: Drugi argument nie jest obowiązkowy, ponieważ uruchomi on metodę o nazwie index, podobnie jak CodeIgniter.

Teraz będziesz mógł załadować kontroler wewnątrz innego kontrolera bez użycia HMVC.

Późniejsza edycja: należy pamiętać, że ta metoda może mieć nieoczekiwane wyniki. Zawsze go testuj!

8

Wystarczy dodać więcej informacji, co Zain Abbas powiedział:

Załaduj kontrolera w ten sposób, i używać go jak powiedział:

$this->load->library('../controllers/instructor'); 

$this->instructor->functioname(); 

Lub można utworzyć obiekt i użyj go w następujący sposób:

$this->load->library('../controllers/your_controller'); 

$obj = new $this->your_controller(); 

$obj->your_function(); 

Mam nadzieję, że to pomoże.

+0

CI 3.x nie działa już mawma –

+1

Witam, to rozwiązanie było dla CI 2.x. Wydaje się, że CI 3.x już na to nie zezwala, teraz nie pracuję z CI 3.x, więc nie mogę ci wiele pomóc. Sprawdź to forum http://forum.codeigniter.com/thread-744-page-2.html, możesz tam uzyskać informacje. A tutaj jest problem z Githubem, który być może jest związany z twoim problemem https://github.com/bcit-ci/CodeIgniter/issues/3480. –

0

Wystarczy użyć

..............

self::index();

..............

0

Według tego wpisu na blogu można załadować kontroler w ramach innego kontrolera w kodzie kodów.

http://www.techsirius.com/2013/01/load-controller-within-another.html

Przede wszystkim trzeba rozszerzyć CI_Loader

<?php 

class MY_Loader extends CI_Loader { 

    public function __construct() { 
     parent::__construct(); 
    } 

    public function controller($file_name) { 
     $CI = & get_instance(); 
     $file_path = APPPATH.'controllers/' . $file_name . '.php'; 
     $object_name = $file_name; 
     $class_name = ucfirst($file_name); 

     if (file_exists($file_path)) { 
      require $file_path; 

      $CI->$object_name = new $class_name(); 
     } 
     else { 
      show_error('Unable to load the requested controller class: ' . $class_name); 
     } 
    } 
} 

następnie kontroler obciążenia wewnątrz innego kontrolera.

1

Podano tu wiele dobrych odpowiedzi dotyczących kontrolerów ładujących w kontrolerach, ale dla mnie jest to sprzeczne ze wzorem mvc.

Zdania, które mnie niepokoją;

(wypełnione danych przetwarzanych przez sterownik produktu)

modele są dla przetwarzania i zapis danych. Jeśli umieścisz tę logikę w swoim modelu produktu, możesz wywołać ją z dowolnego kontrolera, który Ci się podoba, bez konieczności próbowania wypaczenia struktury.

Jednym z najbardziej pomocnych cytatów, które przeczytałem, było to, że kontroler był jak "policjant ruchu drogowego", który służył do kierowania żądań i odpowiedzi między modelami i widokami.

0

Wiem, że jest stary, ale jeśli ktokolwiek znajdzie go od niedawna, proponuję utworzyć oddzielny plik klasy w folderze kontrolerów. Przekaż istniejący obiekt kontrolera do konstruktora klasy, a następnie uzyskaj dostęp do funkcji z dowolnego miejsca i nie spowoduje to konfliktu z konfiguracją i obsługą CI.

Powiązane problemy