Using Doctrine in Joomla 1.5 - doctrine

I'm trying to use Doctrine in Joomla 1.5 but have not been able to get anything running.
According to this article: http://magazine.joomla.org/issues/issue-may-2011/item/447-using-doctrine-ORM-in-joomla
I immediately get Fatal error: Class 'Fatal error: Call to undefined method JController::getInstance() in /var/www/html/hosts/joomla/public_html/components/com_bugs/bugs.php on line 13
The bugs.php looks like this:
// no direct access
defined('_JEXEC') or die; // Include dependancies
jimport('joomla.application.component.controller');
//require_once(JPATH_LIBRARIES . '/doctrine/vendor/autoload.php');
require_once(JPATH_LIBRARIES . '/doctrine/bootstrap.php');
require_once(JPATH_LIBRARIES . '/doctrine/JoomlaDoctrineBootstrapper.php');
require_once(JPATH_COMPONENT.DS.'controller.php');
//$controller = new BugsController(JRequest::getVar('task', ''));
$controller = JController::getInstance('Bugs');
Not sure how to implement this, when trying to use the $controller = new BugsController the error is: Fatal error: Class 'JController' not found in
This because I have the autoload on in bugs.php and have /public_html/components/com_bugs/controller.php extend /public_html/libraries/doctrine/JoomlaDoctrineBootstrapper.php the JoomlaDoctrineBootstrapper exends JController but JController cannot be found anymore after composer and the autoload did something.
I'm starting to think that it's not possible to use Joomla with Doctrine since Doctrine has to be installed with composer (didn't find any other documentation on how to download and configure it) and composer seems to want everything in vendor so have to put all the Joomla classes in vendor too?
[UPDATE]
It looks like whatever composer does in /public_html/libraries/doctrine/vendor/autoload.php completely breaks jimport('joomla.application.component.controller')
Not including the autoload however gives me another problem, like none of the Doctrine classes are found: Class 'Doctrine\Common\Cache\ArrayCache' not found
Maybe I'll try and hack /public_html/libraries/doctrine/vendor/composer/autoload_real.php to try and see if that one can load Joomla classes for me.

Either jimport or composer won't work because jimport defines __autoload. Instead of __autoload I'm using spl_autoload_register that only seems to work with PHP version starting from 5.1.2.
Changed loader:
/public_html/libraries/loader.php
class JLoader
{
public static function autoload($class)
{
if(JLoader::load($class)) {
return true;
}
return false;
}
//... other code and comments
function import( $filePath, $base = null, $key = 'libraries.' )
{
static $paths;
if (!isset($paths)) {
$paths = array();
//assuming PHP 5 >= 5.1.2
spl_autoload_register(array('JLoader', 'autoload'), true, true);
}
//remove the __autoload function
The bugs.php looks like this:
/public_html/components/com_bugs/bugs.php
<?php
// no direct access
defined('_JEXEC') or die; // Include dependancies
require_once(JPATH_LIBRARIES . '/doctrine/vendor/autoload.php');
require_once(JPATH_LIBRARIES . '/doctrine/bootstrap.php');
require_once(JPATH_LIBRARIES . '/doctrine/JoomlaDoctrineBootstrapper.php');
require_once(JPATH_COMPONENT.DS.'controller.php');
//using links like /index.php?option=com_bugs&format=text&task=save
// defaults to link so above is same as: http://joomla/index.php?option=com_bugs&format=text&task=save&router=link
$route=JRequest::getVar('router', 'Link');
$controllerName = 'bugsController'.$route;
//include the controller
include_once(dirname(__FILE__) . '/controllers/'.$route.".php");
$controller = new bugsControllerlink(JRequest::getVar('task', ''));
$controller->setEntityManager(bootstrapDoctrine());
$controller->execute(JRequest::getVar('task', ''));
$controller->redirect();
/**
* Initialize doctrine by setting the entities and proxies locaties. Also define
* a default namespace for the proxies.
*/
function bootstrapDoctrine() {
$doctrineProxy = new JoomlaDoctrineBootstrapper(JoomlaDoctrineBootstrapper::APP_MODE_DEVELOPMENT);
$doctrineProxy->setEntityLibrary(dirname(__FILE__) . '/models');
$doctrineProxy->setProxyLibrary(dirname(__FILE__) . '/proxies');
$doctrineProxy->setProxyNamespace('Joomla\Proxies');
$doctrineProxy->setConnectionOptions(getConfigurationOptions());
$doctrineProxy->bootstrap();
return $doctrineProxy->getEntityManager();
}
function getConfigurationOptions() { // Define database configuration options
$joomlaConfig = JFactory::getConfig();
return array('driver' => 'pdo_mysql', 'path' => 'database.mysql'
, 'dbname' => $joomlaConfig->getValue("config.data.db")
, 'user' => $joomlaConfig->getValue("config.data.user")
, 'password' => $joomlaConfig->getValue("config.data.password"));
}
?>
The link controller looks like: (file name has start with a capital L)
/public_html/components/com_bugs/controllers/Link.php
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla controller library (done by composer)
//jimport('joomla.application.component.controller');
class bugsControllerlink extends JoomlaDoctrineBootstrapper{
function __construct()
{
parent::__construct();
$this->registerTask( 'show','show' );
$this->registerTask( 'save','save' );
}
function save(){
$model=$this->getModel('link');
$view = $this->getView('show','text');
$view->setLayout('save');
$model->em=$this->getEntityManager();
$view->data = $model->save();
$view->display();
}
}
Didn't change the boodtrap, that still looks like this:
/public_html/libraries/doctrine/bootstrap.php
<?php
interface JoomlaDoctrineController {
public function setEntityManager(Doctrine\ORM\EntityManager $entityManager);
}
?>
The /public_html/libraries/doctrine/JoomlaDoctrineBootstrapper.php looks like:
<?php
/** * Configuration class to integrate Doctrine into Joomla. *
* #author pderaaij <removed email, check link in question> */
use Composer\Autoload\ClassLoader,
Doctrine\ORM\EntityManager,
Doctrine\ORM\Configuration,
Doctrine\Common\Cache\ArrayCache;
jimport( 'joomla.application.component.controller' );
class JoomlaDoctrineBootstrapper extends JController{
const APP_MODE_DEVELOPMENT = 1;
const APP_MODE_PRODUCTION = 2;
private $applicationMode;
private $cache;
private $entityLibrary;
private $proxyLibrary;
private $proxyNamespace;
private $entityManager;
private $connectionOptions;
public function __construct($applicationMode=1) {
$this->applicationMode = $applicationMode;
$this->_name="bugs";
parent::__construct();
}
public function getConnectionOptions() {
return $this->connectionOptions;
}
public function setConnectionOptions($connectionOptions) {
$this->connectionOptions = $connectionOptions;
}
public function getProxyLibrary() {
return $this->proxyLibrary;
}
public function setProxyLibrary($proxyLibrary) {
$this->proxyLibrary = $proxyLibrary;
}
public function getProxyNamespace() {
return $this->proxyNamespace;
}
public function setProxyNamespace($proxyNamespace) {
$this->proxyNamespace = $proxyNamespace;
}
public function getCache() {
return $this->cache;
}
public function setCache($cache) {
$this->cache = $cache;
}
public function getEntityLibrary() {
return $this->entityLibrary;
}
public function setEntityLibrary($entityLibrary) {
$this->entityLibrary = $entityLibrary;
}
public function getApplicationMode() {
return $this->applicationMode;
}
public function setApplicationMode($applicationMode) {
$this->applicationMode = $applicationMode;
}
public function getEntityManager() {
return $this->entityManager;
}
public function setEntityManager($entityManager) {
$this->entityManager = $entityManager;
}
/** * Bootstrap Doctrine, setting the libraries and namespaces and creating * the entitymanager */
public function bootstrap() {
$this->registerClassLoader(); // Load cache
if ($this->getApplicationMode() == self::APP_MODE_DEVELOPMENT) {
$this->cache = new ArrayCache;
} else {
$this->cache = new ApcCache;
} /** #var $config Doctrine\ORM\Configuration */ $config = new Configuration;
$config->setMetadataCacheImpl($this->cache);
$driverImpl = $config->newDefaultAnnotationDriver($this->getEntityLibrary());
$config->setMetadataDriverImpl($driverImpl);
$config->setQueryCacheImpl($this->cache);
$config->setProxyDir($this->getProxyLibrary());
$config->setProxyNamespace($this->getProxyNamespace());
if ($this->applicationMode == self::APP_MODE_DEVELOPMENT) {
$config->setAutoGenerateProxyClasses(true);
} else {
$config->setAutoGenerateProxyClasses(false);
} $this->entityManager = EntityManager::create($this->getConnectionOptions(), $config);
}
/** * Register the different classloaders for each type. */
private function registerClassLoader() { // Autoloader for all the Doctrine library files
//Doctrine was done by public_html/libraries/doctrine/vendor/autoload.php
// $classLoader = new ClassLoader('Doctrine', dirname(__FILE__) . '/');
// $classLoader->register(); // Autoloader for all Entities
//name of ComposerAutoloader is defined in /public_html/libraries/doctrine/vendor/composer/autoload_real.php
$modelLoader = ComposerAutoloaderInit825f56ea1383e6b7fef7ea99c51fea36::getLoader();
$modelLoader->set("Entities\\",dirname(__FILE__)."/../../components/com_"
//not sure how to do the proxies yet, have to check this with production settings
// $proxiesClassLoader = new ClassLoader('Proxies', $this->getProxyLibrary());
// $proxiesClassLoader->register();
}
}
?>
The Joomla model save function looks something like this (checking received JSON should be done in a controller or helper function):
public function save() {
//a textbox having the name 'json' or xhr post
$link = JRequest::getVar('json',false,'post');
if($link==false){
return;
}
$link = json_decode($link);
$newLink = new Link();
$newLink->setId($link->id);
$newLink->setName($link->name);
foreach($link->categories as $category){
$cat = new Category();
$cat->setId($category->id);
$cat->setName($category->name);
$newLink->addCategorie($cat);
}
$this->em->persist($newLink);
$this->em->flush();
return $link;
}
I guess the code as is will break when using APP_MODE_PRODUCTION in /public_html/components/com_bugs/bugs.php

Related

Laravel - Instantiate object and keep it within all controller's methods

I'm working with this case where I need to instantiate an object after a form is submitted in a controller. Everything's working fine until I call this object (as a property) from another method. It appears to be null.
If I intentiate the object from constructor method, I have no problem at all.
I can't keep this object in session because of closure.
Here's what i got so far.
// Version with the object iniate within the constructor that's working
class SearchConsoleController extends Controller
{
private $console;
protected function __construct() {
$callback = route('searchconsole.callback') ;
$this->console = $this->setConsole(env('CLIENT_ID'), env('CLIENT_SECRET'), $callback);
}
private function setConsole($cliendId, $cliendSecret, $callback){
$console = new Console(new Google_Client(), $cliendId, $cliendSecret, $callback);
return $console;
}
public function index(Request $request) {
return view('searchconsole.index')->with('authUrl', $this->console->getAuthUrl());
}
public function callback(Request $request){
if ($request->has('code')) {
$this->console->acceptCode($request->get('code'));
return redirect()->action('SearchConsoleController#listSites', [$request]);
}
else{
die('error');
}
}
Now the version which i'm stucked wih
class SearchConsoleController extends Controller
{
private $console;
private $callback;
protected function __construct() {
$this->callback = route('searchconsole.callback') ;
}
private function setConsole($cliendId, $cliendSecret, $callback){
$console = new Console(new Google_Client(), $cliendId, $cliendSecret, $this->callback);
return $console;
}
public function index(Request $request) {
// VIEW WITH A FORM FROM WHICH I GET CLIENT_SECRET & CLIENT_ID var
return view('searchconsole.index');
}
public function getAuthUrl(Request $request) {
// FORM FROM INDEX IS SUBMITTED
$clientId = ($request->has('google-client-id')) ?
$request->get('google-client-id') :
null
;
$clientSecret = ($request->has('google-client-secret')) ?
$request->get('google-client-secret') :
null
;
$this->console = $this->setConsole($clientId, $clientSecret, $this->callback);
return $this->console->getAuthUrl();
}
public function callback(Request $request){
if ($request->has('code')) {
// ***** MY PROBLEM *********
$this->console->acceptCode($request->get('code')); // HERE $this->console IS NULL;
// *******************
return redirect()->action('SearchConsoleController#listSites', [$request]);
}
else{
die('error');
}
}
I just can't figure out how I can do this so console is still available
UPDATE :
following #iamab.in advice, i looked into Service Provider but i just dont know how i can instante the Console Object within the service provider.
Here's what i've done.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Helpers\Console;
use Google_Client;
use Illuminate\Support\Facades\Route;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(Console::class, function() {
$request = app(\Illuminate\Http\Request::class);
$clientId = ($request->has('google-client-id')) ?
$request->get('google-client-id') :
null
;
$clientSecret = ($request->has('google-client-secret')) ?
$request->get('google-client-secret') :
null
;
$callback = Route::get()->name('searchconsole.callback');
return new Console(new Google_Client(), $clientId, $clientSecret, $callback);
});
}
public function boot(){}
....
I just dont know how and where to implement it.
Thanks again
Update#2 :
okay my solution was working, I just didnt launch the correct app ..... 😅

Store config in database in Laravel

I am currently using Laravel 5.2. I want to be able to store config properties (key-value pairs) in database, that I am willing to access from both my application on runtime and the console (either php artisan command or Tinker).
What is my best option?
.env is one way, but it is not stored in the database, but in a file.
Config::get is another way, but it also writes in files. Can it be configured to write in database?
Cache::get is setup to work with the database, but is temporary, not permanent, so it is out of question.
The reason I am interested in database config, is because we often replace/delete files during deployment. Also it would be nice to store values encrypted. Also important feature here is to be able to easily get values via either php artisan or tinker
Make a migration: php artisan make:migration CreateSettingsTable
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSettingsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->id();
$table->string('key');
$table->string('value');
$table->timestamps();
$table->unique([
'key', //I add a unique to prevent double keys
]);
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('settings');
}
}
Make the model: php artisan make:model Setting
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
protected $fillable = [
'key',
'value'
];
//I would normally do this in a repository,
// but for simplicity sake, i've put it in here :)
static public $settings = null;
static function get($key, $default = null)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
$model = self
::$settings
->where('key', $key)
->first();
if (empty($model)) {
if (empty($default)) {
//Throw an exception, you cannot resume without the setting.
throw new \Exception('Cannot find setting: '.$key);
}
else {
return $default;
}
}
else {
return $model->value;
}
}
static function set(string $key, $value)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
if (is_string($value) || is_int($value)) {
$model = self
::$settings
->where('key', $key)
->first();
if (empty($model)) {
$model = self::create([
'key' => $key,
'value' => $value
]);
self::$settings->push($model);
}
else {
$model->update(compact('value'));
}
return true;
}
else {
return false;
}
}
}
Please note here, that I added the get and set functions, together with a static $settings variable directly to the model, to keep the example small. Usually I would opt to making a repository or service(not serviceprovider) to handle these functions. This way you only query db once(per request) for all the settings. You could stick this in cache, but that is not part of this answer of now.
Run php artisan migrate to ge the table in the db.
Run composer dump-autoload to make sure tinker can find the Setting class.
Use someting like php artisan tinker(https://laravel.com/docs/7.x/artisan#tinker) to test it, in this case you can do:
Setting::set('someKey', 'someValue'); //Set someKey to someValue
Setting::get('someKey'); //Get someKey, throws exception if not found
Setting::get('somekey2', 'someDefault'); //Shows someDefault because somekey2 is not set yet.
I hope it helps! :)
I extended Rob Biermann approach to handling json data
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
class Setting extends Model
{
use HasFactory;
protected $casts = [
'value' => 'array'
];
protected $fillable = [
'key',
'value'
];
/**
* #var Setting[]|\Illuminate\Database\Eloquent\Collection|null
*/
static public $settings = null;
static function getAll(string $key, $default = null){
if (empty(self::$settings)) {
self::$settings = self::all();
}
$keys = explode('.', $key);
$databaseKey = $keys[0];
unset($keys[0]);
$model = self
::$settings
->where('key', $databaseKey)
->first();
if (empty($model)) {
if (empty($default)) {
//Throw an exception, you cannot resume without the setting.
throw new \Exception('Cannot find setting: ' . $key);
} else {
return $default;
}
} else {
return $model->value;
}
}
static function get(string $key, $default = null)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
$keys = explode('.', $key);
$databaseKey = $keys[0];
unset($keys[0]);
$model = self
::$settings
->where('key', $databaseKey)
->first();
if (empty($model)) {
if (empty($default)) {
//Throw an exception, you cannot resume without the setting.
throw new \Exception('Cannot find setting: ' . $key);
} else {
return $default;
}
} else {
if(!empty( $keys)){
return Arr::get($model->value, implode('.',$keys));
}
if(is_string( $model->value)){
return $model->value;
}
if(Arr::has($model->value, 'default')){
return $model->value['default'];
}
return $model->value;
}
}
static function set(string $key, $value)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
$keys = explode('.', $key);
$databaseKey = $keys[0];
unset($keys[0]);
$model = self
::$settings
->where('key', $databaseKey)
->first();
if (empty($model)) {
if(!empty($keys)){
$array = [];
$model = self::create([
'key' => $key,
'value' => Arr::set($array, implode('.',$keys), $value)
]);
}
else{
$model = self::create([
'key' => $key,
'value' => $value
]);
}
self::$settings->push($model);
} else {
if(!empty($keys)){
$old = $model->value;
if(is_string($old)){
$old = ["default" => $old] ;
}
if(Arr::has($old, implode('.',$keys))){
$old = Arr::set($old, implode('.',$keys), $value);
}
else{
$old = Arr::add($old, implode('.',$keys), $value);
}
$model->update(['value' => $old]);
}
else{
if(is_array($model->value)){
$new = $model->value;
$new['default'] = $value;
$value = $new;
}
$model->update(['value' => $value]);
}
}
return true;
}
}
now u can use
Setting::get('someKey.key');
Setting::get('someKey.key.key1');
Setting::set('someKey.key', 'test');
Setting::set('someKey.key.key1', 'test');
I'm using laravel 9, and using package from spatie: spatie/laravel-settings.
If you follow the docs you may set the setting class, for example I want to store payment gateway settings into the database, namely Securepay in Malaysia.
In settings folder, App\Settings will have a new file PaymentGatewaySettings.php:
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class PaymentGatewaySettings extends Settings
{
public string $env;
public string $uid;
public string $auth_token;
public string $checksum_token;
public static function group() : string
{
return 'payment_gateway';
}
}
In AppSeviceProvider.php we add new line under boot method:
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
/**
* Payment Gateway settings
*
*/
if(DB::table('settings')->where('group', 'payment_gateway')->exists()) {
config()->set('services', array_merge(config('services'), [
'securepay' => [
'env' => app(SecurepaySettings::class)->env,
'uid' => app(SecurepaySettings::class)->uid,
'auth_token' => app(SecurepaySettings::class)->auth_token,
'checksum_token' => app(SecurepaySettings::class)->checksum_token,
]
]));
}
}
If we do not put the if statement, it would be an error while want to run php artisan command.
In other cases you may extend the Illuminate\Foundation\Application class, and you may use something like this app()->getSecurePayEnv() in everywhere in you application, but to set the config I'm still using boot method in AppSeviceProvider.php.
Hope it helps.

laravel model event static call issue

Why my static method don´t work with a varible class?
/**
* Events
*/
public static function boot() {
parent::boot();
$class = get_called_class(); // The value os $class is: Product ( string)
// This work
Product::creating(function($model) {
return $model->validate();
});
// Don´t work, the closure never called!
$class::creating(function($model) {
return $model->validate();
});
$class::updating(function($model) {
return $model->validate(true);
});
}
Incredible, this work to:
$class = "Product"; //get_called_class();
Solution ( Not elegant , but ... )
On my Product model i put this, to share class name with Base model.
public static function boot() {
parent::$cls = "Product";
parent::boot();
}
but updating does not work yet!
Actually (since PHP 5.3) it should work to do:
$class = 'Product';
$class::creating(function($model){
return $model->validate();
});
But why not just use static:: to access the current class? This way you don't need get_called_class:
static::creating(function($model){
return $model->validate();
});
There's also call_user_func if everything else fails...

getting class not found error in laravel

I am working on laravel and following the tutorial http://technetlk.blogspot.com.au/2012/09/laravel-backbonejs-coffeescript_3527.html. currently working on 7th part of this tutorial.
in routes.php I have written
Route::any('api/category/(:num?)',
array('as' => 'api.category',
'uses' => 'api.category#index')
);
In api/category.php,
<?php
class Api_Category_Controller extends Base_Controller
{
public $restful = true;
public function get_index($id = null)
{
if (is_null($id ))
{
$allCats = Category::all();
return BaseModel::allToJson($allCats);
}
else
{
$cat = Category::find($id);
return $cat->toJson();
}
}
public function post_index()
{
$cat = Input::json();
$dbCat = new Category();
$dbCat->code = $cat->code;
$dbCat->name = $cat->name;
$dbCat->save();
return $dbCat->toJson();
}
public function put_index()
{
$cat = Input::json();
$dbCat = Category::find($cat->id);
$dbCat->code = $cat->code;
$dbCat->name = $cat->name;
$dbCat->save();
return $dbCat->toJson();
}
public function delete_index($id = null)
{
$dbCat = Category::find($id);
$dbCat->delete();
}
}
?>
and in BaseModel.php
<?php
class Category extends BaseModel
{
public static $table = 'tbl_category';
}
class BaseModel extends Eloquent
{
public function toJson()
{
return json_encode($this->to_array());
}
public static function allToJson($array)
{
$temp = array();
foreach($array as $t)
{
$temp[] = $t->to_array();
}
return json_encode($temp);
}
}
?>
when I am trying to run
curl -X POST http://lbc.dev/api/category -H "Content-Type: application/json" –d '{"code":"cat1", "name":"Category One"}'
I am getting the follwing error
Unhandled Exception
Message:
Class 'Category' not found Location:
C:\xampp\htdocs\NewBlog\application\controllers\api\category.php on
line 9
Your Category Model should be located in /application/models/category.php
Your BaseModel class should be located in /application/models/basemodel.php
The following is if your BaseModel class is not in a defined Autoloader directory:
Another problem you may face is the BaseModel not autoloading
correctly. This can be fixed by appending this line of code to your
start.php file found in your application folder:
// Autoloader::map
'BaseModel' => path('app').'/path/to/basemodel.php',
U have to specify the model in controller file before using it
Add this line above the following line in your controller file
use App\Category;
class Api_Category_Controller extends Base_Controller
{

Routing zend request through a default controller when controller not found

Below is a function defined in my Bootstrap class. I must be missing something fundamental in the way Zend does routing and dispatching. What I am trying to accomplish is simple: For any request /foo/bar/* that is not dispatchable for any reason try /index/foo/bar/. The problem I'm having is when the FooController exists I get Action "foo" does not exist. Basically, the isDispatchable is always false.
public function run() {
$front = Zend_Controller_Front::getInstance();
$request = $front->getRequest();
$dispatcher = $front->getDispatcher();
//$controller = $dispatcher->getControllerClass($request);
if (!$dispatcher->isDispatchable($request)) {
$route = new Zend_Controller_Router_Route(
':action/*',
array('controller' => 'index')
);
$router = $front->getRouter();
$router->addRoute('FallBack', $route);
}
$front->dispatch();
}
So this seems to work, but is not the best answer as it simply drops all the params. I might try shortly doing a forward to /index/[original uri] within the plugin:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initRoute() {
$front = Zend_Controller_Front::getInstance();
$routes = array(
'FallBack' => new Zend_Controller_Router_Route(
':controller/:action/*',
array('controller' => 'index', 'action' => 'index')
)
);
$router = $front->getRouter();
$router->removeDefaultRoutes();
$router->addRoutes($routes);
$front->setRouter($router);
return $router;
}
protected function _initPlugin() {
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new My_Controller_Plugin_FallBack());
}
}
class My_Controller_Plugin_FallBack extends Zend_Controller_Plugin_Abstract {
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$front = Zend_Controller_Front::getInstance();
$dispatcher = $front->getDispatcher();
$router = $front->getRouter();
if (($router->getCurrentRouteName() == 'FallBack') &&
!$dispatcher->isDispatchable($request)) {
$request->setActionName($request->getControllerName());
$request->setControllerName('index');
}
}
}
if i understand your idea right
would you try to use __call magic method ??
then use $this->_redirect(); to your default action for example
more info are here http://php.net/manual/en/language.oop5.overloading.php
UPDATE
if you opened Zend/Controller/Action.php on line 480
public function __call($methodName, $args)
{
require_once 'Zend/Controller/Action/Exception.php';
if ('Action' == substr($methodName, -6)) {
$action = substr($methodName, 0, strlen($methodName) - 6);
throw new Zend_Controller_Action_Exception(sprintf('Action "%s" does not exist and was not trapped in __call()', $action), 404);
}
throw new Zend_Controller_Action_Exception(sprintf('Method "%s" does not exist and was not trapped in __call()', $methodName), 500);
}
what i meant to do is to extend this class and override __call function exactly to be
classs My_Controller_Action extends Zend_Controller_Action{
public function __call($methodName, $args)
{
///// do your magic here ......redirection or logging the request or what ever
}
}
and make sure your controller extend your newly created class
class FooController extends My_Controller_Action
{
public function indexAction()
{
// action body
}
}
so if some how you called inexistent action __call will run
this idea was about inexistent action only
it won't work if the controller doesn't exist

Resources