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

New Controller, New Project, Error

I created a new "test1" phalcon project with devtools in C:\xampp\htdocs. When I tried to access localhost/test1 I got the same error from a previous post (https://forum.phalcon.io/discussion/20291/phalcon-4-new-project-error#C62007).

So I applied the recommended fix and it worked. localhost/test1 is loading and I get the You're now flying with Phalcon message.

Now I created a new Con1Controller and the correct folder and phtml file in views. But when I tried to access localhost/con1 I get the error 404 Object not found! message.

While trying to find a solution I set up a virtual host:

 <VirtualHost *:80>

    ServerAdmin    [email protected]
     DocumentRoot   "C:\xampp\htdocs\test1"
    DirectoryIndex index.php
     ServerName     localhost
     ServerAlias    localhost

     <Directory "C:\xampp\htdocs\test1">
        Options       All
         AllowOverride All
         Require       all granted
     </Directory>

 </VirtualHost>

When I did that I was able to access the controller at localhost/con1 but test1 could now be accessed only at localhost and not on localhost/test1.

What am I doing wrong?

These are my settings: config.php

<?php

/*
 * Modified: prepend directory path of current file, because of this file own different ENV under between Apache and command line.
 * NOTE: please remove this comment.
 */
defined('BASE_PATH') || define('BASE_PATH', getenv('BASE_PATH') ?: realpath(dirname(__FILE__) . '/../..'));
defined('APP_PATH') || define('APP_PATH', BASE_PATH . '/app');

return new \Phalcon\Config([
    'database' => [
        'adapter'     => 'Mysql',
        'host'        => 'localhost',
        'username'    => 'root',
        'password'    => '',
        'dbname'      => 'test',
        'charset'     => 'utf8',
    ],
    'application' => [
        'appDir'         => APP_PATH . '/',
        'controllersDir' => APP_PATH . '/controllers/',
        'modelsDir'      => APP_PATH . '/models/',
        'migrationsDir'  => APP_PATH . '/migrations/',
        'viewsDir'       => APP_PATH . '/views/',
        'pluginsDir'     => APP_PATH . '/plugins/',
        'libraryDir'     => APP_PATH . '/library/',
        'cacheDir'       => BASE_PATH . '/cache/',
        'baseUri'        => preg_replace('/public([\/\\\\])index.php$/', '', $_SERVER["PHP_SELF"]),
    ]
]);

loader.php

<?php

$loader = new \Phalcon\Loader();

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

router.php

<?php

$router = $di->getRouter();

// Define your routes here

$router->handle($_SERVER['REQUEST_URI']);

services.php

<?php
declare(strict_types=1);

use Phalcon\Escaper;
use Phalcon\Flash\Direct as Flash;
use Phalcon\Mvc\Model\Metadata\Memory as MetaDataAdapter;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Php as PhpEngine;
use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
use Phalcon\Session\Adapter\Stream as SessionAdapter;
use Phalcon\Session\Manager as SessionManager;
use Phalcon\Url as UrlResolver;

/**
 * Shared configuration service
 */
$di->setShared('config', function () {
    return include APP_PATH . "/config/config.php";
});

/**
 * The URL component is used to generate all kind of urls in the application
 */
$di->setShared('url', function () {
    $config = $this->getConfig();

    $url = new UrlResolver();
    $url->setBaseUri($config->application->baseUri);

    return $url;
});

/**
 * Setting up the view component
 */
$di->setShared('view', function () {
    $config = $this->getConfig();

    $view = new View();
    $view->setDI($this);
    $view->setViewsDir($config->application->viewsDir);

    $view->registerEngines([
        '.volt' => function ($view) {
            $config = $this->getConfig();

            $volt = new VoltEngine($view, $this);

            $volt->setOptions([
                'path' => $config->application->cacheDir,
                'separator' => '_'
            ]);

            return $volt;
        },
        '.phtml' => PhpEngine::class

    ]);

    return $view;
});

/**
 * Database connection is created based in the parameters defined in the configuration file
 */
$di->setShared('db', function () {
    $config = $this->getConfig();

    $class = 'Phalcon\Db\Adapter\Pdo\\' . $config->database->adapter;
    $params = [
        'host'     => $config->database->host,
        'username' => $config->database->username,
        'password' => $config->database->password,
        'dbname'   => $config->database->dbname,
        'charset'  => $config->database->charset
    ];

    if ($config->database->adapter == 'Postgresql') {
        unset($params['charset']);
    }

    return new $class($params);
});

/**
 * If the configuration specify the use of metadata adapter use it or use memory otherwise
 */
$di->setShared('modelsMetadata', function () {
    return new MetaDataAdapter();
});

/**
 * Register the session flash service with the Twitter Bootstrap classes
 */
$di->set('flash', function () {
    $escaper = new Escaper();
    $flash = new Flash($escaper);
    $flash->setImplicitFlush(false);
    $flash->setCssClasses([
        'error'   => 'alert alert-danger',
        'success' => 'alert alert-success',
        'notice'  => 'alert alert-info',
        'warning' => 'alert alert-warning'
    ]);

    return $flash;
});

/**
 * Start the session the first time some component request the session service
 */
$di->setShared('session', function () {
    $session = new SessionManager();
    $files = new SessionAdapter([
        'savePath' => sys_get_temp_dir(),
    ]);
    $session->setAdapter($files);
    $session->start();

    return $session;
});

index.php

<?php
declare(strict_types=1);

use Phalcon\Di\FactoryDefault;

error_reporting(E_ALL);

define('BASE_PATH', dirname(__DIR__));
define('APP_PATH', BASE_PATH . '/app');

try {
    /**
     * The FactoryDefault Dependency Injector automatically registers
     * the services that provide a full stack framework.
     */
    $di = new FactoryDefault();

    /**
     * Read services
     */
    include APP_PATH . '/config/services.php';

    /**
     * Handle routes
     */
    include APP_PATH . '/config/router.php';

    /**
     * Get config service for use in inline setup below
     */
    $config = $di->getConfig();

    /**
     * Include Autoloader
     */
    include APP_PATH . '/config/loader.php';

    /**
     * Handle the request
     */
    $application = new \Phalcon\Mvc\Application($di);

    echo $application->handle($_GET['_url'] ?? '/')->getContent();
} catch (\Exception $e) {
    echo $e->getMessage() . '<br>';
    echo '<pre>' . $e->getTraceAsString() . '</pre>';
}

Phalcon DevTools (4.0.3)

Environment: OS: Windows NT DESKTOP-P2K7MSM 10.0 build 18363 (Windows 10) AMD64 PHP Version: 7.4.6 PHP SAPI: cli PHP Bin: C:\xampp\php\php.exe PHP Extension Dir: C:\php\ext PHP Bin Dir: C:\php Loaded PHP config: C:\xampp\php\php.ini Versions: Phalcon DevTools Version: 4.0.3 Phalcon Version: 4.0.6 AdminLTE Version: 2.3.6

and the new controller:

<?php
declare(strict_types=1);

class Con1Controller extends \Phalcon\Mvc\Controller
{

    public function indexAction()
    {

    }

}

Do you have your .htaccess file set up to redirect from localhost/ to localhost/public? And another .htaccess file to redirect any 404s to index.php?



131

Hi, I had the same problem now (created a sample project on Xampp with almost exact same config as you). The only changes I have made to the default setup was:

  1. in public/index.php I changed l.43

    echo $application->handle($_SERVER['REQUEST_URI'])->getContent();

    to

    echo $application->handle($_GET['_url'] ?? '/')->getContent();

  2. in app/config/config.php I changed baseUri to '/test1/'
  3. I use also namespace, that is set up in app/config/loader.php by adding

    $loader->registerNamespaces( [ "test1" => $config->application->modelsDir ] );

    just after new Loader() instantiation, but the namespace should not affect this.

With this I can access /localhost/test1 and also /localhost/test1/con1