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

how to change urls in the routing file

Hi,

I'm trying to change the url for the user, for expample: www.site.com/user/username. and this is my code:

$router->add( '/user/:param', array( 'controller' => 'user', 'action' => 'username', 'param' => 1, ) );

it shows me the page is not found, but when I change the code to the following:

$router->add( '/user/:params', array( 'controller' => 'user', 'action' => 'username', 'params' => 1, ) );

it works but all the methods for user controller doesn't work. I would like also to add some more urls like this: www.site.com/user/username/settings

how to solve this? Thanks



43.9k

hi

it works but all the methods for user controller doesn't work

??

hi

it works but all the methods for user controller doesn't work

??

I mean all the other functions of the controller (user) not working any more. Functions like register and log in ..etc. It show me page not found. This happened only if I use the second code in my topic.



5.7k
edited May '15

Is there a specific reason you're using :param instead of giving your variable a descriptive name such as "username"?

Take a look here for more info on supported placeholders https://docs.phalcon.io/en/latest/reference/routing.html#defining-routes

In any case, have you tried this syntax?

$router->add( '/user/{username}', array( 'controller' => 'user', 'action' => 'username') ); // Option 1
//or
$router->add( '/user/{param}', array( 'controller' => 'user', 'action' => 'username') ); // Option 2

Then in the controller just reference the username like so:

$username = $this->dispatcher->getParam('username'); // Use with Option 1 from above
// or - Depending on the method above
$username = $this->dispatcher->getParam('param'); // Use with Option 2 from above

For adding more URLs, you should be able to do so like this:

$router->add( '/user/{username}/settings', array( 'controller' => 'user', 'action' => 'settings') );
/**
 * The in the controller get the param values like so:
 * $username = $this->dispatcher->getParam('username');
 */

// And for specific settings
$router->add( '/user/{username}/settings/{setting_name}', array( 'controller' => 'user', 'action' => 'specificSetting') );
/**
 * The in the controller get the param values like so:
 * $username = $this->dispatcher->getParam('username');
 * $setting_name = $this->dispatcher->getParam('setting_name');
 */

Also, as your application grows, it would be a good idea to start naming your routes:

$router->add( '/user/{username}/settings', 
    array(
        'controller' => 'user',
        'action' => 'settings'
    )
)->setName('user_settings');

Then in your views you can use the url function (Volt Example):

<a href="{{ url(['for' : 'user_settings','username' : user.getUsername() ]) }}">{{ user.getUsername() }}</a> 

If you pass the user object/model from the controller to the view, this will render <a href="/user/my_username/settings">my_username</a>

So later on if you change your URL for that route, your application will automatically render the new URL without you having to update anything else.



43.9k

// After experiencig some issues with

$router->add( '/user/:param', array( 'controller' => 'user', 'action' => 'username', 'param' => 1, ) );

// I prefer 

$router->add( '/user/{username}', array( 'controller' => 'user', 'action' => 'username') ); // Option 1

// In UserController

public function usernameAction($username)

// So there is no need of $username = $this->dispatcher->getParam('username');
edited May '15

Hi, I have tried the both options and it works, but all the other functions of user controller not working. It keep showing page not found.

here is my route

<?php

$router = new Phalcon\Mvc\Router();

$router->add(
     '/user/{username}',
     array(
         'controller' => 'user',
         'action'     => 'username',
     )
 );

$router->add(
     '/user/{username}/information',
     array(
        'controller' => 'user',
        'action'     => 'information'
     )
 );

 return $router;

here is my action

<?php

public function usernameAction($username)
{
      $username = $this->dispatcher->getParam('username');

      $user = User::findFirstByUsername($username);

      if(!$user)
      {
          $this->dispatcher->forward(array(
          'controller' => 'Error',
          'action' => '_404'
          ));
          return false;
      } 

      $this->tag->setTitle($username .' profile');

      if($this->session->has('usersession'))
      {
          $session = $this->session->get('usersession');

          $user_follow = User_follow::findFirstByid($session->id);
      }

      $this->view->setVar('user', $user);
      $this->view->setVar('user_follow', $user_follow);
      $this->view->setVar('count_followers', count(User_follow::find("follower = ".$user->id."")));
      $this->view->setVar('count_following', count(User_follow::find("following = ".$user->id."")));
}

any thing I missed?



43.9k

you say "it works", did you mean "usernameAction" from UserController works, but none of the others UserController actions works ?

In that case, you should have better shown us the code from the others UserController actions ;-)

Yes correct, here is my code


<?php

namespace FC\Controllers;

use Phalcon\Mvc\Controller,
    FC\Controllers\ErrorController as Error,
    FC\Models\User,
    FC\Models\User_follow;

class UserController extends ControllerBase
{
    public function createAction()
    {
        $this->tag->setTitle('Create a user');

        $this->view->setLayout('NoHeaderAside');

        $user = new User();
        $user->username      = $this->request->getPost('username');
        $user->userpass      = $this->security->hash($this->request->getPost('userpass'));
        $user->useremail     = $this->request->getPost('useremail');
        $user->name          = $this->request->getPost('name');
        $user->country       = $this->request->getPost('country');
        $user->avatar        = 1;
        $user->created_at    = date('Y-m-d H:i:s');
        $user->last_activity = date('Y-m-d H:i:s');

        if ($this->request->isPost())
        {
            if($user->save()) 
            {
                $this->session->set('usersession', $user);

                $this->flash->success('The user has been created successfully.');
            }
            else
            {
                foreach($user->getMessages() as $message) 
                {
                    $this->flash->error((string) $message);
                }
            }
        }
    }

    public function loginAction()
    {
        if($this->session->has('usersession'))
        {
            $this->response->redirect('index');
        }

        $this->tag->setTitle('Log in');

        $this->view->setLayout('NoHeaderAside');

        $username  = $this->request->getPost('username');
        $userpass  = $this->request->getPost('userpass');

        $user = User::findFirstByUsername($username);

        if($this->request->isPost())
        {
            if($user)
            {
                if($this->security->checkHash($userpass, $user->userpass))
                {
                    $this->session->set('usersession', $user);
                    $this->response->redirect('index');
                }
                else
                {
                    $this->flash->error('The information is not correct.');
                }
            }
            else
            {
                $this->flash->error('The information is not correct.');
            }
        }
    }

    public function forgotAction()
    {
        if($this->session->has('usersession'))
        {
            $this->response->redirect('index');
        }

        $this->tag->setTitle('Forgot Password');

        $this->view->setLayout('NoHeaderAside');

        $useremail  = $this->request->getPost('useremail');

        $user = User::findFirstByUseremail($useremail);

        if($this->request->isPost())
        {
            if($user)
            {
                $this->flash->success('An email has been sent to '. $useremail);
            }
            else
            {
                $this->flash->error('We cannot find this email.');
            }
        }
    }

    public function usernameAction()
    {
        $username = $this->dispatcher->getParam('username');

        $user = User::findFirstByUsername($username);

        if(!$user)
        {
            $this->dispatcher->forward(array(
                'controller' => 'Error',
                'action' => '_404'
            ));
            return false;
        } 

        $this->tag->setTitle($username .' profile');

        if($this->session->has('usersession'))
        {
             $session = $this->session->get('usersession');

            $user_follow = User_follow::findFirstByFollower($session->id);
        }

        $this->view->setVar('user', $user);
        $this->view->setVar('user_follow', $user_follow);
        $this->view->setVar('count_followers', count(User_follow::find("follower = ".$user->id."")));
        $this->view->setVar('count_following', count(User_follow::find("following = ".$user->id."")));
    }

    public function informationAction($username)
    {
        if(!$this->session->has('usersession'))
        {
            $this->response->redirect('index');
        }

        $user = User::findFirstByUsername($username);

        if(!$user)
        {
            $this->dispatcher->forward(array(
                'controller' => 'Error',
                'action' => '_404'
            ));
            return false;
        } 

        $this->tag->setTitle('Information');

        $user = User::findFirstByUsername($username);

        $this->view->setVar('user', $user);
        $this->view->setVar('user_follow', $user_follow);
        $this->view->setVar('count_followers', count(User_follow::find("follower = ".$user->id."")));
        $this->view->setVar('count_following', count(User_follow::find("following = ".$user->id."")));

    }

    public function logoutAction()
    {
        $this->tag->setTitle('Log Out');

        if(!$this->session->has('usersession'))
        {
            $this->flash->error('You need to sign in first.');
        }
        else
        {
            $this->session->remove('usersession');
            $this->session->destroy();
            $this->flash->success('You have logged out successfully.');
        }
    }
}


5.7k

We will also need to see how your routes are defined to find out why the routes are not mapping to the controllers correctly.

We will also need to see how your routes are defined to find out why the routes are not mapping to the controllers correctly.

Okay, I have a file I called it route.php and it's inside folder called config. here is route.php

<?php

$router = new Phalcon\Mvc\Router();

$router->add(
     '/user/{username}',
     array(
         'controller' => 'user',
         'action'     => 'username',
     )
 );

$router->add(
     '/user/{username}/information',
     array(
        'controller' => 'user',
        'action'     => 'information'
     )
 );

 return $router;

config/service.php

 <?php

use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Mvc\View\Engine\Volt;
use Phalcon\Mvc\View;
use Phalcon\Db\Adapter\Pdo\Mysql as DatabaseConnection;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Logger\Adapter\File as FileLogger;
use Phalcon\Session\Adapter\Files as SessionAdapter;
use Phalcon\Cache\Backend\File as FileCache;
use Phalcon\Mvc\Dispatcher as MvcDispatcher;

/**
 * The URL component is used to generate all kind of urls in the application
 */
$di->set(
    'url',
    function () use ($config) {
        $url = new UrlResolver();
        if (!$config->application->debug) {
            $url->setBaseUri($config->application->production->baseUri);
            $url->setStaticBaseUri($config->application->production->staticBaseUri);
        } else {
            $url->setBaseUri($config->application->development->baseUri);
            $url->setStaticBaseUri($config->application->development->staticBaseUri);
        }
        return $url;
    },
    true
);

/**
 * Setting up volt
 */
$di->set(
    'volt',
    function ($view, $di) use ($config) {

        $volt = new Volt($view, $di);

        $volt->setOptions(
            array(
                "compiledPath"      => APP_PATH . "/app/cache/volt/",
                "compiledSeparator" => "_",
                "compileAlways"     => $config->application->debug
            )
        );

        $volt->getCompiler()->addFunction('number_format', function ($resolvedArgs) {
            return 'number_format(' . $resolvedArgs . ')';
        });

        return $volt;
    },
    true
);

/**
 * Setting up the view component
 */
$di->set(
    'view',
    function () use ($config) {

        $view = new View();

        $view->setViewsDir($config->application->viewsDir);

        $view->registerEngines(
            array(
                ".volt" => 'volt'
            )
        );

        return $view;
    },
    true
);

/**
 * Database connection is created based in the parameters defined in the configuration file
 */
$di->set(
    'db',
    function () use ($config) {

        $connection = new DatabaseConnection($config->database->toArray());

        $debug = $config->application->debug;
        if ($debug) {

            $eventsManager = new EventsManager();

            $logger = new FileLogger(APP_PATH . "/app/logs/db.log");

            //Listen all the database events
            $eventsManager->attach(
                'db',
                function ($event, $connection) use ($logger) {
                    /** @var Phalcon\Events\Event $event */
                    if ($event->getType() == 'beforeQuery') {
                        /** @var DatabaseConnection $connection */
                        $variables = $connection->getSQLVariables();
                        if ($variables) {
                            $logger->log($connection->getSQLStatement() . ' [' . join(',', $variables) . ']', \Phalcon\Logger::INFO);
                        } else {
                            $logger->log($connection->getSQLStatement(), \Phalcon\Logger::INFO);
                        }
                    }
                }
            );

            //Assign the eventsManager to the db adapter instance
            $connection->setEventsManager($eventsManager);
        }

        return $connection;
    }
);

/**
 * Start the session the first time some component request the session service
 */
$di->set(
    'session',
    function () {
        $session = new SessionAdapter();
        $session->start();
        return $session;
    },
    true
);

/**
 * Router
 */
$di->set(
    'router',
    function () {
        return include APP_PATH . "/app/config/routes.php";
    },
    true
);

/**
 * Register the configuration itself as a service
 */
$di->set('config', $config);

/**
 * Register the flash service with the Twitter Bootstrap classes
 */
$di->set(
    'flash',
    function () {
        return new Phalcon\Flash\Direct(array(
            'error' => 'alert alert-dismissable alert-danger',
            'success' => 'alert alert-dismissable alert-success',
            'notice' => 'alert alert-dismissable alert-info',
        ));
    }
);

/**
 * Register the session flash service with the Twitter Bootstrap classes
 */
$di->set(
    'flashSession',
    function () {
        return new Phalcon\Flash\Session(array(
            'error' => 'alert alert-dismissable alert-danger',
            'success' => 'alert alert-dismissable alert-success',
            'notice' => 'alert alert-dismissable alert-info',
        ));
    }
);

$di->set(
    'dispatcher',
    function () {
        $dispatcher = new MvcDispatcher();

        $eventsManager = new \Phalcon\Events\Manager();

        $eventsManager->attach("dispatch:beforeException", function($event, $dispatcher, $exception) {

        //Handle 404 exceptions
        if ($exception instanceof \Phalcon\Mvc\Dispatcher\Exception) {
            $dispatcher->forward(array(
                'controller' => 'Error',
                'action' => '_404'
            ));
            return false;
        }

        //Handle other exceptions
        $dispatcher->forward(array(
            'controller' => 'Error',
            'action' => '_503'
        ));

            return false;
        });

        //Bind the EventsManager to the dispatcher
        $dispatcher->setEventsManager($eventsManager);

        $dispatcher->setDefaultNamespace('FC\Controllers');

        return $dispatcher;
    },
    true
);


5.7k
edited May '15

Try changing

public function informationAction($username){

to

public function informationAction(){
$username = $this->dispatcher->getParam('username');

I don't see where you're getting the username from the dispatcher in informationAction()

Try changing

public function informationAction($username){

to

public function informationAction(){
$username = $this->dispatcher->getParam('username');

I don't see where you're getting the username from the dispatcher in informationAction()

Same result unless I add the route manually like this:


<?php
$router->add(
    '/user/create',
    array(
       'controller' => 'user',
       'action'     => 'create'
    )
);

anything that I missed?



5.7k

Honestly,

I don't use parameters to determine my modules, controllers, or actions. I know HOW they work. But I don't use the reserved params for dynamic routing, just the variables I need to pass (user_id, account_id, etc..). I create a route for every single possible link within my systems. I'd actually recommend it because it gives you the most control and the least likely way to have your system fo unexplainable things

anything that I missed?

Okay thanks, I will try to solve this problem :)



43.9k

everything looks good in your code (imho;-)

But most of the "non working" methods above (login, create, forgot) have statements with

if($this->request->isPost())

And you've got "not found". So maybe your urls in form views aren't well formed.

I think I know what was the problem, because all the methods is using this url by default: user/{methodName}

so when I add this code,

<?php
$router->add(
    '/user/{username}',
    array(
       'controller' => 'user',
       'action'     => 'username'
    )
);

I changed all the default urls to User controller to be: user/username, so I need to add url for other methods manually and that solved my problem :)