We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Using controllers in a micro application

Hi.

I have a couple of GET routes definition using controller class as the action to execute, tow of this controllers inherit from a parent controller which has an Initialize method.

I'm noticing this Initialize method is not getting fire when the instance is created.

Can you guys confirm this behavior is ok?

Using phalcon 0.8.0



98.9k

Since your controllers aren't running within Phalcon\Mvc\Application, you can use the __construct method instead of initialize



12.1k

I'm afraid I can't do that since __construct has been defined as final.

Fatal error: Cannot override final method Phalcon\Mvc\Controller::__construct()



98.9k

ok, then instead of inheriting Phalcon\Mvc\Controller, you can use Phalcon\DI\Injectable that offers the same behavior as Phalcon\Mvc\Controller and it doesn't have a final constructor



12.1k

Yes that will work, but then I'm gonna loose all the Controller services access.

I think I will just call Initialize method manually where I need it.



98.9k

"but then I'm gonna loose all the Controller services access" ? why?



12.1k

I already tried.

If I define my parent class as Phalcon\DI\Injectable I can't do thinks like $this->request or $this->response.

D



98.9k

why? The goal of Phalcon\DI\Injectable is allow you to access services using $this->request or $this->response, also Phalcon\Mvc\Controller is a subclass of Phalcon\DI\Injectable



12.1k

Ah, sorry, you are completed right, I was inheriting from a wrong class in my code, thats why it didn't work.

Thanks you very much.



12.1k

Well, here is something else, if I define the __construct method in the parent class I got this exception:

exception 'Phalcon\DI\Exception' with message 'A dependency injection object is required to access the application services

in any place I tried to access the services, I'm doing $obj->setDI($di); when I create the obj.



12.1k

No answer for this?



98.9k
edited Oct '14
class MyController extends Phalcon\DI\Injectable
{
         public function __construct($di)
         {
              $this->setDI($di);
         }    
}
$my = new MyController($di);

or

class MyController extends Phalcon\DI\Injectable
{

}
$my = new MyController();
$my->setDI($di);


80

Hi there, I'm having problems with autoloading controllers in micro application, and cant find what exactly i'm doing wrong. Can someone pls share code for the bootstrap file that will work?



12.1k

Can you share your code?

What I did is way crazy, don't know if is a good solution yet, have to test more scenarios.



80

I'm trying to use router but i keep getting the same error: Phalcon\Mvc\Micro\Exception: Matched route doesn't have an associate handler



12.1k
edited Oct '14

That sounds to me, like you are requesting a url that have an associated action, you can define a notFound request action like this

$app->notFound(function () use ($app) {
    $app->response->setStatusCode(404, "Not Found")->sendHeaders();
    echo 'This is crazy, but this page was not found!';
});

for more info: https://docs.phalcon.io/en/0.9.0/reference/micro.html



80

already have that.. this is the router code $router->add( "/:controller/:action/:params", array( "controller" => 1, "action" => 2, "params" => 3, ) );



12.1k

mmm, I'm not sure how you can use that definition in micro applications, make no sense for me, but the experts have the last word in that case.



98.9k

@prekoc Usually, using a router directly would not work in Micro applications, this kind of application requires each route mapped to a valid handler (callable function/method)

This is how a micro application could work with controllers: https://gist.github.com/phalcon/4961874



80

Hi Phalcon, thanks for that, i have done that and it works, but cant that be done with using wildcards so that ti wont have to manually type each route? The API I want to build can become quite large with lots of methods so having to manually add each one of them is a bit pain in the a**



12.1k

In that case, maybe what I have done can help you, I also did something to avoid creating every controller before use it, I will post the code asap.



12.1k

Hey @prekoc you can take a look to:

https://github.com/odiel/phalcon_micro_controllers

The application is not finished yet and I'm pretty sure there should be some errors with the RequestHandler class, hope that help you.



80

Hi @odiel thanks for that.. looks quite good, i made something like that but placed it in the bootstrap instead of new class (requestHandler). Anyway I'm just starting out with this so it's good to know that there are ppl to talk to if i get stuck somewhere :) cheers



80

One other question, is there a way to catch the returned value from executed method? example: in the bootstrap file: $app->get("/robots/show", array($robotsController, showAction)); and in the controller class robotsController extends \Phalcon\Mvc\Controller { public function showAction() { return 'sample"; } }

simple echo 'sample' will print out the text, but i want to format it before sending it to the client. Any way i can do this?



12.1k

Hi @prekoc, make not sense for me to capture what the controller is returning, instead that, you can create a view an render the view, also you can create your own \Responser object and format the response as you like.

I have made some changes for the [phalcon_micro_controllers] code example that make the life easier. I will commit the changes soon.



80

the API i'm building should return responses in 2 formats, json and xml. So what i want to do is create different controllers and actions in them, and all the actions return array response. In the index file i'll catch that array response, and depending on what type of response the user wants, i will either return json_encode, or create a function that will return xml format of the array instead of formating the response in every controller action and outputting it there. Hope this makes some sense :)



12.1k

Here is a solution:

Create a base controller class that can render the data, based on the requested response format (json/xml), this controller also can know from where to read the format parameter, inherit from this base controllers all the controllers that need this feature, your child controller need to assign in some way the data you want to output, then you can call from the base controller the function [render] outputting the data in the desired format.

Hope this make sense to you.

Sorry about my English grammar.



98.9k
edited Oct '14

As @odiel says the BaseController is a good option:

<?php

class BaseController extends Phalcon\Mvc\Model
{
    protected function render($format, $response)
    {
        if ($format == 'json') {
            echo json_encode($response);
        } else {
            if ($format == 'xml') {
                //
            }
        }
    }
}

Then in the controller:

<?php

class RobotsController extends BaseController
{
    public function showAction()
    {
        echo $this->render('json', array(1, 2, 3));
    }
}


12.1k

There you have a more graphic example from @Phalcon.

I have updated the github repo with new small changes, we actually don't need an extra class to handle the request, I putted everything in the Application class.

I think this approach is more clean an smooth to follow.

https://github.com/odiel/phalcon_micro_controllers



80

Perfect, thanks a lot guys, this is really helpful :) I don't know why i didn't think of this any sooner, cause it also solves some other issues that i had. thanks again.



98.9k
Accepted
answer

Starting from Phalcon 1.1.0, the framework supports controllers in micro application out of the box: https://docs.phalcon.io/en/latest/reference/micro.html#using-controllers-as-handlers

hi, sorry, Im still dont know about my situation. Sorry about my grammar first..

I want my controller use service from micro, like response, request etc, but I cant do that in my controller.

I define loader Micro Apps like this :

<?php

$loader = new \Phalcon\Loader();

use Phalcon\Mvc\Micro;

/**

  • We're a registering a set of directories taken from the configuration file */ $loader->registerDirs( [ $config->{APP_ENV}->application->controllersDir, $config->{APP_ENV}->application->modelsDir, $config->{APP_ENV}->application->libraryDir, ] )->register();

/**

  • Handle the request */ $app = new Micro($di); // micro API

$app->get('/', function () use ($app) { $app->response->setContentType('application/json', 'UTF-8');

$app->response->setJsonContent(array(
    "status" => "OK",
    'message' => "Welcome to CNN APIS",
));

$app->response->send();

});

My problem is here $app->get("/newsfeed/{kanal}", ['NewsfeedController', "indexAction"]); . When I want to use :

$app->response->setJsonContent(array( "status" => "OK", 'message' => "Welcome to CNN APIS", ));

My controller said, I can't find object like response, request etc. How to use $app object in my controller ?

thx ...