So everything works fine if i use $loader->registerDirs() function, but if i use registerNamespaces function i get dispatcher error, that says: "IndexController handler class cannot be loaded". here is code for index.php file
<?php
use Phalcon\Di\FactoryDefault;
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Application;
use Phalcon\Url;
use Phalcon\Db\Adapter\Pdo\Mysql;
// Define some absolute path constants to aid in locating resources
define('BASE_PATH', dirname(__DIR__));
define('APP_PATH', BASE_PATH . '/app');
// Register an autoloader
$loader = new Loader();
//$loader->registerDirs(
// [
// APP_PATH . '/controllers/',
// APP_PATH . '/models/',
// APP_PATH . '/modules/'
// ]
//);
$loader->registerNamespaces(
[
'App\Controllers' => APP_PATH . '/controllers/'
]
);
$loader->register();
$container = new FactoryDefault();
$container->set(
'view',
function () {
$view = new View();
$view->setViewsDir(APP_PATH . '/views/');
return $view;
}
);
$container->set(
'db',
function () {
return new Mysql(
[
'host' => 'localhost',
'username' => 'sammy',
'password' => 'password',
'dbname' => 'learning',
]
);
}
);
$container->set(
'url',
function () {
$url = new Url();
$url->setBaseUri('/');
return $url;
}
);
$application = new Application($container);
// Handle the request
$response = $application->handle(
$_SERVER["REQUEST_URI"]
);
$response->send();
That my IndexController.php file.
<?php
declare(strict_types=1);
namespace App\Controllers;
use Phalcon\Http\Request;
use \Phalcon\Mvc\Controller;
use Phalcon\Http\Message\Uri;
class IndexController extends Controller
{
public function indexAction()
{
return 'hi';
}
}
so as you can see the path for registerDirs and registerNamespaces functions are the same, but it doesn't seem to work. Because of it i tried many ways of changing paths but it didn't help.
Here's my directory structure:
in short you need to change the default namespace in Phalcon\Mvc\Router
$router = $container->getRouter();
$router->setDefaultNamespace('App\Controllers');
$router->handle();
you may want to read this answer https://stackoverflow.com/a/22673713/2640796
Related
Using symfony / routing, need to implement routing for the MVC application. Using the whole Symfony is prohibited, only the library.
Controller class:
namespace App\Controllers;
use App\Core\Controller;
class IndexController extends Controller {
public function IndexAction(){
$this->View->render('index');
}
}
view class:
namespace App\Core;
namespace App\Core;
class View{
public function render($viewName) {
$viewAry = explode('/', $viewName);
$viewString = implode(DS, $viewAry);
if(file_exists('View/site' . $viewString . '.php')) {
require 'View/site' . $viewString . '.php';
} else {
die('The view \"' . $viewName . '\" does not exist.');
}
}
}
and Index.php itself from which it all starts:
use App\Controllers\IndexController;
use App\Core\Routing;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
use App\Core\Application;
use Symfony\Component\Routing\Router;
require __DIR__ . '/vendor/autoload.php';
$collection = new RouteCollection();
$collection->add('index', new Route('/', array(
'_controller' => [IndexController::class, 'IndexAction']
)));
return $collection;
As a result of a request to the application through the postman, I get nothing, what's the problem?
In your front controller you are just defining the routes, but not actually processing the request, matching it to a controller or invoking it.
There is a section on this topic in the manual, it uses more symfony components, but can be of help.
You'd have to determine the requested route directly from PATH_INFO instead of using the HttpFoundation component, and then try to match the request to a route.
Here is a very crude implementation:
$collection = new RouteCollection();
$collection->add('index', new Route('/', array(
'_controller' => [IndexController::class, 'IndexAction']
)));
$matcher = new UrlMatcher($collection, new RequestContext());
// Matcher will throw an exception if no route found
$match = $matcher->match($_SERVER['PATH_INFO']);
// If the code reaches this point, a route was found, extract the corresponding controller
$controllerClass = $match['_controller'][0];
$controllerAction = $match['_controller'][1];
// Instance the controller
$controller = new $controllerClass();
// Execute it
call_user_func([$controller, $controllerAction]);
I'm New in Phalcon framework. I'm testing my first multi module phalcon project with : Phalcon-4.0.3, i have install psr and i'm following example from phalcon documentation. everything is normal without volt engine but my backend module or controller not responding and i didnt get any error & the problem is i cant redirect to beckend module or controller if any expert please solve my issue!!
[index.php]
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Router;
use Phalcon\Mvc\Application;
$di = new FactoryDefault();
$di->set('router',function () {
$router = new Router(false);
$router->setDefaultModule('frontend');
$router->add('/backend',
[
'module' => 'backend',
'controller' => 'index',
'action' => 'index',
]
);
return $router;
}
);
$application = new Application($di);
$application->registerModules(
[
'frontend' => [
'className' => 'Multiple\Frontend\Module',//\Multiple\Frontend\Module::class,
'path' => '../apps/frontend/Module.php',
],
'backend' => [
'className' => 'Multiple\Backend\Module',//\Multiple\Backend\Module::class,
'path' => '../apps/backend/Module.php',
],
]
);
try{
$response = $application->handle($_SERVER["REQUEST_URI"]);
$response->send();
}catch (\Throwable $e) {
echo $e->getMessage();
}
[Backend Module]
namespace Multiple\Backend;
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Volt;
use Phalcon\Di\DiInterface;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\ModuleDefinitionInterface;
class Module implements ModuleDefinitionInterface
{
public function registerAutoloaders(DiInterface $di = null)
{
$loader = new Loader();
$loader->registerClasses([
'Multiple\Backend\Module' =>'../apps/backend/Module.php',
]);
$loader->registerNamespaces(
[
'Multiple\Backend\Controllers' => '../apps/backend/controllers/',
'Multiple\Backend\Models' => '../apps/backend/models/',
]
);
$loader->register();
}
public function registerServices(DiInterface $di)
{
$di->set('dispatcher',function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('Multiple\Backend\Controllers');
return $dispatcher;
}
);
$di->set('view',function () {
$view = new View();
$view->setViewsDir('../apps/backend/views/');
return $view;
}
);
}
}
[Frontend Module]
namespace Multiple\Frontend;
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Volt;
use Phalcon\Di\DiInterface;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\ModuleDefinitionInterface;
class Module implements ModuleDefinitionInterface
{
/**
* Register a specific autoloader for the module
*/
public function registerAutoloaders(DiInterface $di = null)
{
$loader = new Loader();
$loader->registerClasses([
'Multiple\Frontend\Module' =>'../apps/frontend/Module.php',
]);
$loader->registerNamespaces([
'Multiple\Frontend\Controllers' => '../apps/frontend/controllers/',
'Multiple\Frontend\Models' => '../apps/frontend/models/',
]);
$loader->register();
}
/**
* Register specific services for the module
*/
public function registerServices(DiInterface $di)
{
// Registering a dispatcher
$di->set('dispatcher',function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('Multiple\Frontend\Controllers');
return $dispatcher;
}
);
// Registering the view component
$di->set('view',function () {
$view = new View();
$view->setViewsDir('../apps/frontend/views/');
return $view;
}
);
}
}
I am getting an Catchable fatal error with Slim 3 on my Models, i have a similar set up on my Controllers and it works just fine. When i implement the same on my Modal class i get the following error.
Catchable fatal error: Argument 1 passed to Base\Models\BaseModel::__construct() must implement interface Interop\Container\ContainerInterface, none given, called in \bootstrap\app.php on line 111 and defined in \Models\BaseModel.php on line 11
This is my bootstrap file
use Noodlehaus\Config;
session_start();
require __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'determineRouteBeforeAppMiddleware' => true,
'displayErrorDetails' => true,
'addContentLengthHeader' => false
],
]);
$container = $app->getContainer();
$container['config'] = function() {
return new Config(__DIR__ . '/../config/' . file_get_contents(__DIR__ . '/../env.php') . '.php');
};
$container['mailer'] = function($container) {
return new MailgunEmail; ///LINE 110
};
require __DIR__ . '/../app/routes.php';
This is the env.php
return [
'mailgun' => [
'apikey' => 'key-123456',
'domain' => 'sandbox123456.mailgun.org',
'from' => 'noreply#anydomain.com',
],
];
My Base Model
namespace Base\Models;
use Interop\Container\ContainerInterface;
abstract class BaseModel {
protected $container;
public function __construct(ContainerInterface $container) { /// LINE 11
$this->container = $container;
}
public function __get($property) {
if($this->container->{$property}) {
return $this->container->{$property};
}
}
}
My Email Model
namespace Base\Models;
use Base\Models\BaseModel;
use Http\Adapter\Guzzle6\Client;
use Mailgun\Mailgun;
class MailgunEmail extends BaseModel {
public function sendWithApi($to, $subject, $html) {
$client = new Client();
/// INSTEAD OF HARD CODING LIKE THIS
$mailgun = new Mailgun('key-123456', $client);
/// I WANT TO DO SOMETHING LIKE THIS
$mailgun = new Mailgun($this->config->get('mailgun.apikey'), $client);
$domain = 'sandbox123456.mailgun.org';
$builder = $mailgun->MessageBuilder();
$builder->setFromAddress('noreply#anydomain.com');
$builder->addToRecipient($to);
$builder->setSubject($subject);
$builder->setHtmlBody($html);
return $mailgun->post("{$domain}/messages", $builder->getMessage());
}
}
I am not sure why i am getting this error or how i can fix it.
Just pass the $container variable to your MailgunEmail constructor in your bootstrap file.
$container['mailer'] = function($container) {
return new MailgunEmail($container); ///LINE 110
};
I'm trying to set up unittests, but I'm having no luck at all. I created TestHelper.php in a tests folder. This file looks like this:
<?php
use Phalcon\Di;
use Phalcon\Di\FactoryDefault;
ini_set('display_errors',1);
error_reporting(E_ALL);
define('ROOT_PATH', __DIR__);
define('PATH_LIBRARY', __DIR__ . '/../app/library/');
define('PATH_SERVICES', __DIR__ . '/../app/services/');
define('PATH_RESOURCES', __DIR__ . '/../app/resources/');
define('BASE_DIR', dirname(__DIR__));
define('APP_DIR', BASE_DIR . '/app');
set_include_path(
ROOT_PATH . PATH_SEPARATOR . get_include_path()
);
// Required for phalcon/incubator
include __DIR__ . "/../vendor/autoload.php";
// Use the application autoloader to autoload the classes
// Autoload the dependencies found in composer
$loader = new \Phalcon\Loader();
$loader->registerDirs(
array(
ROOT_PATH
)
);
$config = include APP_DIR . '/config/config.php';
$loader->registerNamespaces(array(
'MyApp\Models' => $config->application->modelsDir,
'MyApp\Controllers' => $config->application->controllersDir,
'MyApp\Forms' => $config->application->formsDir,
'MyApp\Classes' => $config->application->classesDir,
'MyApp' => $config->application->libraryDir
));
$loader->register();
I also created UnitTestCase.php:
<?php
use Phalcon\Di;
use Phalcon\DI\FactoryDefault;
use Phalcon\Test\UnitTestCase as PhalconTestCase;
use Phalcon\Mvc\View;
use Phalcon\Crypt;
use Phalcon\Mvc\Dispatcher;
use \Phalcon\Mvc\Dispatcher as PhDispatcher;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
use Phalcon\Mvc\Model\Metadata\Files as MetaDataAdapter;
use Phalcon\Session\Adapter\Files as SessionAdapter;
use Phalcon\Flash\Direct as Flash;
use Phalcon\Logger;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Logger\Adapter\File as LoggerFile;
use MyApp\Auth\Auth;
use MyApp\AuthPublic\AuthPublic;
use MyApp\Acl\Acl;
use MyApp\CacheData\CacheData;
use MyApp\Mail\Mail;
use MyApp\PHPExcel\PHPExcel;
abstract class UnitTestCase extends PhalconTestCase
{
/**
* #var \Voice\Cache
*/
protected $_cache;
/**
* #var \Phalcon\Config
*/
protected $_config;
/**
* #var bool
*/
private $_loaded = false;
public function setUp(Phalcon\DiInterface $di = NULL, Phalcon\Config $config = NULL)
{
// Load any additional services that might be required during testing
$di = new FactoryDefault();
$config = include APP_DIR . '/config/config.php';
/**
* The URL component is used to generate all kind of urls in the application
*/
$di->set('url', function () use ($config) {
$url = new UrlResolver();
$url->setBaseUri($config->application->baseUri);
return $url;
}, true);
/**
* Setting up the view component
*/
$di->set('view', function () use ($config) {
$view = new View();
$view->setViewsDir($config->application->viewsDir);
$view->registerEngines(array(
'.volt' => function ($view, $di) use ($config) {
$volt = new VoltEngine($view, $di);
$volt->setOptions(array(
'compiledPath' => $config->application->cacheDir . 'volt/',
'compiledSeparator' => '_'
));
return $volt;
}
));
return $view;
}, true);
/**
* Database connection is created based in the parameters defined in the configuration file
*/
$di->set('db', function () use ($config) {
$eventsManager = new EventsManager();
// Debug sql logging //
$is_debug_sql_logging = true;
if ( $is_debug_sql_logging )
{
$logger = new LoggerFile( $config->application->logsDir ."debug_sql.log" );
$logger->log( "\n------\n" );
// Listen all the database events //
$eventsManager->attach( 'db', function( $event, $connection ) use ($logger) {
if ( $event->getType() == 'beforeQuery' ) {
$log_message = $connection->getRealSQLStatement()."\n".print_r( $connection->getSQLVariables(), true );
$logger->log( $log_message, Logger::DEBUG );
}
if ($event->getType() == 'afterQuery') {
//...//
}
});
}
// Database connection //
$dbAdapter = new DbAdapter(array(
'host' => 'localhost',
'username' => 'root',
'password' => 'root',
'dbname' => 'database'
));
//Assign the eventsManager to the db adapter instance
$dbAdapter->setEventsManager( $eventsManager );
return $dbAdapter;
});
/**
* If the configuration specify the use of metadata adapter use it or use memory otherwise
*/
$di->set('modelsMetadata', function () use ($config) {
return new MetaDataAdapter(array(
'metaDataDir' => $config->application->cacheDir . 'metaData/'
));
});
$di->set('modelsManager', function() {
return new \Phalcon\Mvc\Model\Manager();
});
/**
* Start the session the first time some component request the session service
*/
$di->set('session', function () {
$session = new SessionAdapter();
$session->start();
return $session;
});
/**
* Cache of models
*/
$di->set('cache', function () {
$cacheData = new CacheData();
return $cacheData;
});
/**
* Crypt service
*/
$di->set('crypt', function () use ($config) {
$crypt = new Crypt();
$crypt->setKey($config->application->cryptSalt);
return $crypt;
});
/**
* Set a 404 redirect AND use a default namespace
*/
$di->set('dispatcher', function() use ($di) {
$evManager = $di->getShared('eventsManager');
$evManager->attach(
"dispatch:beforeException",
function($event, $dispatcher, $exception)
{
switch ($exception->getCode()) {
case PhDispatcher::EXCEPTION_HANDLER_NOT_FOUND:
case PhDispatcher::EXCEPTION_ACTION_NOT_FOUND:
$dispatcher->forward(
array(
'controller' => 'error',
'action' => 'show404',
)
);
return false;
}
}
);
$dispatcher = new PhDispatcher();
$dispatcher->setEventsManager($evManager);
/* Dispatcher use a default namespace */
$dispatcher->setDefaultNamespace('MyApp\Controllers');
return $dispatcher;
},
true
);
/**
* Loading routes from the routes.php file
*/
$di->set('router', function () {
return require __DIR__ . '/routes.php';
});
/**
* Flash service with custom CSS classes
*/
$di->set('flash', function () {
return new Flash(array(
'error' => 'notification notification--error',
'success' => 'notification notification--success',
'notice' => 'notification notification--neutral',
'general' => 'notification notification--general',
'warning' => 'notification notification--warning'
));
});
/**
* Authentication component
*/
$di->set('auth', function () {
return new Auth();
});
/**
* Self test authentication component
*/
$di->set('authPublic', function () {
return new AuthPublic();
});
/**
* Mail service uses AmazonSES
*/
$di->set('mail', function () {
return new Mail();
});
/**
* Access Control List
*/
$di->set('acl', function () {
return new Acl();
});
/**
* PHPExcel
*/
$di->set('phpexcel', function () {
return new PHPExcel();
});
parent::setUp($di, $config);
$this->_loaded = true;
}
/**
* Check if the test case is setup properly
*
* #throws \PHPUnit_Framework_IncompleteTestError;
*/
public function __destruct()
{
if (!$this->_loaded) {
throw new \PHPUnit_Framework_IncompleteTestError('Please run parent::setUp().');
}
}
}
And also phpunit.xml:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="TestHelper.php"
backupGlobals="false"
backupStaticAttributes="false"
verbose="true"
colors="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="true">
<testsuite name="Phalcon - Testsuite">
<directory>./</directory>
</testsuite>
</phpunit>
All this together, should make me able to run some unittests. However, when I go to the tests folder in terminal and run ../vendor/bin/phpunit it throws an error. The error is Phalcon\Di\Exception: Service 'modelsManager' wasn't found in the dependency injection container. I have been struggling for some hours with this and I hope someone will be able to help me. What am I doing wrong here?
Add DI::setDefault($di); before parent::setUp($di, $config); in UnitTestCase.php
This way you can access DI components globally, not only in local scope.
My setUp() function in UnitTestCase.php looks like this:
public function setUp()
{
parent::setUp();
$di = new FactoryDefault();
// load all services.
include APP_PATH . "/config/services.php";
DI::setDefault($di);
$this->setDi($di);
$this->_loaded = true;
}
This way I have access to DI via $this->di (eg: $this->di->get('config') and all other related libraries which need DI can get it globally.
So I am working on a sample database project.
I have a LoginController.php, a Faculty database, and a login page (phtml).
I get the error Fatal error: Class 'Faculty_DB' not found in /usr/local/zend/apache2/htdocs/InternProject1/application/controllers/LoginController.php on line 25
In the LoginController.php I have the following (plus some more):
public function indexAction()
{
$login = new Form_Login();
//$this->view->login = $login;
$request = $this->getRequest();
if($request->isPost())
{
$data = $request->getPost();
//$this->isValid(
if($this->getRequest()->getPost())
{
$username = $request->getParam('username');
$password = $request->getParam('password');
// echo " What you entered is: $username and $password";
//line 24
$faculty = new Faculty_DB();
//then conditions for validation.
This references
class Faculty_DB extends Zend_Db_Table_Abstract
which is located in application/models/ directory
I have the following in Bootstrap.php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initAutoload()
{
$autoLoader = Zend_Loader_Autoloader::getInstance();
$autoLoader->registerNamespace(array('App_'));
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH,
'namespace' => '',
'resourceTypes' =>
array('form'=>
array('path' => 'forms/',
'namespace' => 'Form_'
),
),
));
return $autoLoader;
}
}
Any clue on how to fix this?
I tried the following:
protected function _initResourceAutoloader()
{
$autoloader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH,
'namespace' => 'Application',
));
$autoloader->addResourceType( 'model', 'models', 'Model');
return $autoloader;
}
but when I do that, it tells me it can't find my Login_Form;
Given that your application namespace is Application, try:
Put your faculty DB class in application/models/Faculty.php
Name it Application_Model_Faculty
Extend it from Application_Model_DbTable_Faculty
Put the DbTable class in application/models/DbTable/Faculty.php
Since you are using Zend_Application, it will take care of setting up the autoloader and special prefixes like Form_, Model_, Plugin_ etc for you, so you can safely remove the _initAutoload and _initResourceAutoloader from your Bootstrap.