0

Home page display some information from other controllers, like news, article, etc. What is the best way of using other controller's method in one controller?
Suppose there is one controller called HomeController,is it correct to instantiate a Controller class within home controller?
forexample, if I want to use NewsController,instantiate it!?
The following code is just an example, I want to know that what is the best way to access a method or model in another controller?

class HomeController extends Controller
{
    public function index()
    {
        $news_obj = new NewsController();
        $news = $news_obj->getNews();

        $article_obj = new ArticleController();
        $articles = $article_obj->getArticles();

        return view('template',['news'=>$news,'articles'=>$articles]);
    }
}
  • Possible duplicate of [Access Controller method from another controller in Laravel 5](https://stackoverflow.com/questions/30365169/access-controller-method-from-another-controller-in-laravel-5) – gere Aug 01 '19 at 11:12
  • 1
    Why call the other controllers, why not just access your Eloquent models from that controller? `News::all()` for example. – Peppermintology Aug 01 '19 at 11:16

5 Answers5

4

It's cleaner to not re-use controllers in other controllers. A nicer way would be to extract the logic you want to re-use from the controller into a separate service, which you can then call from both controllers instead.

Example:

class HomeController extends Controller
{
    /**
     * @var NewsService
     */
    private $newsService;

    /**
     * @var ArticleService
     */
    private $articleService;

    public function __construct(NewsService $newsService, ArticleService $articleService)
    {
        $this->newsService = $newsService;
        $this->articleService = $articleService;
    }

    public function index()
    {
        $news = $this->newsService->getNews();
        $articles = $this->articleService->getArticles();

        return view('template',['news'=>$news,'articles'=>$articles]);
    }
}

class NewsController extends Controller
{
    /**
     * @var NewsService
     */
    private $newsService;

    public function __construct(NewsService $newsService)
    {
        $this->newsService = $newsService;
    }

    public function index()
    {
        $news = $this->newsService->getNews();
        return view('template',['news'=>$news]);
    }
}

class ArticleController extends Controller
{
    /**
     * @var ArticleService
     */
    private $articleService;

    public function __construct(ArticleService $articleService)
    {
        $this->articleService = $articleService;
    }

    public function index()
    {
        $articles = $this->articleService->getArticles();
        return view('template',['articles'=>$articles]);
    }
}
PtrTon
  • 3,705
  • 2
  • 14
  • 24
  • can you make an example? –  Aug 01 '19 at 11:24
  • how should i do about news and article? –  Aug 01 '19 at 11:27
  • I added a quick example for you – PtrTon Aug 01 '19 at 11:27
  • Where do you define NewsService and ArticleService ? –  Aug 01 '19 at 11:37
  • Why should i use NewsService instead of News Eloquent model? –  Aug 01 '19 at 11:39
  • I did not define them, because I didn't know what your NewsController and ArticlesController exactly contain. If you can post the contents of those, I can expand my example if that would help you – PtrTon Aug 01 '19 at 11:40
  • @navidlrn - Take a look at [Laravel Service Providers](https://laravel.com/docs/5.8/providers). They provide a great way of abstracting away functionality that can be reused throughout your application, providing a single point of use and configuration. That said, they can also add a level of complexity to your application. – Peppermintology Aug 01 '19 at 11:45
1

I think it is better to define a function inside the model to return the value. And call that function in the controller.

This will be more relevant according to MVC.

MKR
  • 46
  • 3
0

We can't use controller to another controller it is clear.

0

Instantiate the functions that you want to re-use in the correspondent model so you can use them in all controllers.

t00n
  • 395
  • 5
  • 12
0

I agree with @ptrTon on this, I'd suggest adopting a Repository pattern. It may be a bit of a work depending on your app size, but it's defenitely cleaner than instantiating a controller inside another controller.

Basically with this approach you don't manipulate your model directly but you use instead an object which is, in fact, an extra layer. The main advantage of this is that you can extract common operations and perform them from anywhere not inside the controller, but inside an object which the only responsability is to manage the operations on your models, further separating the responsabilities of your app components. With Laravel you can also add a custom route resolution logic which will inject these repositories in your controllers using the IoC container.

If you want to take it further, you could create the repository in a way that it behaves as the model which wraps, and extends its functionalities (PHP's magic methods are your friends). Providing a full example in a single answer can be complicated, but I'll link some intresting resources below.

Repository pattern in Laravel - example

Decorator pattern - concepts

Laravel's explicit model binding (see the "customizing resolution logic" section)

Aranarth
  • 68
  • 6