Zend Framework 2.0 Interface not found - php

Short version
Where does the Client class look for the DispatchableInterface interface?
class Client implements Libraries\Stdlib\DispatchableInterface
I'm trying to add the ZF2 libraries to a CodeIgniter installation. The whole Zend folder sits in:
/Users/stef/Sites/site_name/application/libraries/
In my CI controller I have
public function run()
{
$CI =& get_instance();
$CI->load->library('Zend');
$CI->load->library('Zend/Http/Client');
$client = new Client($url);
//Do stuff
}
When I access the run() method I get a fatal error:
Fatal error: Interface 'Zend\Stdlib\DispatchableInterface' not found in /Users/stef/Sites/site_name/application/libraries/Zend/Http/Client.php on line 27
In libraries/Zend.php (a file I added, not part of the ZF) I have
function __construct($class = NULL)
{
// include path for Zend Framework
// alter it accordingly if you have put the 'Zend' folder elsewhere
ini_set('include_path',ini_get('include_path') . PATH_SEPARATOR . APPPATH . 'libraries/Zend/');
}
It doesn't seem to matter what I set the include_path to be, even when I put bogus values the fatal error stays the same. So it seems that the loading of the interface DispatchableInterface doesn't make use of the include_path.
How can I get Client.php to "find" the interface, which it tries to do so here:
class Client implements Libraries\Stdlib\DispatchableInterface

Least difficult solution is probably:
set_include_path(get_include_path() . PATH_SEPARATOR . '/Users/stef/Sites/site_name/application/libraries/');
require_once 'Zend/Loader/StandardAutoloader.php';
$loader = new Zend\Loader\StandardAutoloader(array('autoregister_zf' => true));
$loader->register();
Then skip the CI->load part. And just use new Zend\Http\Client. Also make sure that the dispatchable interface is in /Users/stef/Sites/site_name/application/libraries/Zend/Stdlib/DispatchableInterface.php
Update:
I noticed just now:
class Client implements Libraries\Stdlib\DispatchableInterface
What class is this? Is it Zend's class? I guess it's some class of yours. And you're adding wrongly namespaced interface. IMO it should be \Zend\Stdlib\DispatchableInterface

Related

Organise custom classes

I'm trying to learn the basics of Slim 3 and I have difficulties trying to figure out the proper way to organise my custom code, esp. custom classes. For instance, I want to create a custom error handler:
<?php
namespace App\Handlers;
// [...]
final class Error extends \Slim\Handlers\Error
{
// [...]
}
... but the documentation I've checked hasn't revealed under which path to save the class definition or how to configure the framework so it can be found in my index.php entry point:
<?php
require __DIR__ . '/../vendor/autoload.php';
// [...]
$app = new \Slim\App(['settings' => ['displayErrorDetails' => true]]);
$container = $app->getContainer();
$container['errorHandler'] = function ($c) {
return new App\Handlers\Error($c['Logger']);
};
Fatal error: Class 'App\Handlers\Error' not found
I'd appreciate any hint.
You're problem is not related to the framework at all.
Slim doesn't tell you where to keep your custom code because it's a matter of your free choice.
Your error:
Fatal error: Class 'App\Handlers\Error' not found
is not generated by Slim, but PHP itself. You need to add an autoloader for your code to let PHP know where to find appropriate classes.
I can see that you utilize Composer, therefore it's the best option to configure composer.json to create autoloader for your code.

Require dynamic class using namespace in PHP

I was studying a couple PHP frameworks and then decided to build my own, of course. But i'm facing one issue. I have a Router class that handles dynamically the HTTP requests and it basically explodes the URL into elements dividing it by the slash and storing it into an array, then a function is called to check if the first element is a valid Controller. If it is valid, the function should require it, but that's where i'm stuck, because it seems that i can't require a file like:
if (file_exists(CONTROLLERS_DIR . $this->url[0] . '.php')) { require \App\Controllers\$this->url[0] }
How can I require a file like that using namespaces?
Thanks.
"How can I require a file like that using namespaces?"
You can't. Namespaces have nothing to do with it.
"PHP Namespaces provide a way in which to group related classes, interfaces, functions and constants." ~ Namespaces overview
require is about file dependancies, regardless the namespace:
if (file_exists(CONTROLLERS_DIR . $this->url[0] . '.php')) {
require(CONTROLLERS_DIR . $this->url[0] . '.php');
}
EDIT: You might want to instantiate a class using a namespace and class name retrieved in run-time though, i.e. something like:
namespace \App\Controllers;
class C {
protected $_i;
public function __construct($i){ $this->_i = $i; }
public function foo(){ echo $this->_i; }
}
and somewhere:
$className = "C"; // or $className = $this->whatever...
$class = "\\App\\Controllers\\".$className;
$instance = new $class(7);
$instance->foo(); // outputs 7
I've built couple of frameworks and I understand what you trying to do...
Basically when you have some path for example "HelloWorld\addComment"
You want to create controller instance
\App\Controllers\HelloWorldController
There are multiple ways to solve it, the one I like is:
Using spl autoloader
http://php.net/manual/en/function.spl-autoload.php
In the link I provided you got the examples you need.
Then you can end up just doing
$controller = new \App\Controllers\HelloWorldController();
You should put the HelloWorldController at the right namespace + maintain directory structure matching the namespace
app
Controllers
HelloWorldController
spl autoloader will do the right including for you, often the default implementation is sufficient - but it is easy to create your own spl autoloader and register it
Later you can test if the $controller has the method you need via method_exist or reflection...

Class not found error even with autoloading

I'm not a PHP expert; am trying to use this TextRank Library to help with a project.
I seem to be running into a bizarre issue: even after adding the autoload function, executing on the command line still results in "class not found" error. So here's the layout:
Code that calls the other classes (the "main" code):
echo realpath (__DIR__);
function __autoload($class_name) {
if(file_exists(__DIR__ . "/lib/TextRank/" . $class_name . '.php')) {
require_once(__DIR__ . "/lib/TextRank/" . $class_name . '.php');
} else {
throw new Exception("Unable to load $class_name.");
}
}
$config = new Config;
$textrank = new TextRank($config);
$keywords = $textrank->getKeywords("The only asynchronous, one-on-four game in Nintendo’s booth came from the “Wait, they’re still making that?” franchise that is Mario Party, and its buried presence didn’t bode well. Thankfully, Mario Party 10’s demo didn’t waste time with the series’ slowest crawl-around-a-board-game moments, instead jumping straight into four mini-games.");
var_dump($keywords);
Here's my directory structure:
/test.php (the above file)
/lib
/lib/TextRank (contains all the classes referenced by the above code
/lib/TextRank/Config.php
Yet, I still get:
Fatal error: Class 'Config' not found in /path/to/test.php
This means that:
The autoload is working, as no exceptions were thrown.
But somehow, PHP still isn't finding the required classes??
Does this have anything to do with the namespace conventions used in the classes, such as:
(in /lib/TextRank/Config.php)
namespace crodas\TextRank;
class Config
{
....
Yes it does. You need to do
$config = new crodas\TextRank\Config();
But that will not get catched by your autoloader. You need to look for an PSR-0 compatible autoloader.

How to properly use Universal Class Loader?

I'm trying to use Universal Class Loader functionality from Phalcon into my project, however I can't get it working.
Here is how i've implemented into my app (using registerClasses).
index.php:
//...
$loader->registerClasses(
array(
"Commons" => "library/classes/CommonsClass.php"
)
);
$loader->register();
sampleController.php:
public function doAction()
{
$cc = new Commons();
}
And when I execute the controller, it throws me this exception:
Fatal error: Class 'Commons' not found in C:\the\path\to\phalcon_app\app\controllers\SomeController.php on line 63
The Phalcon Documentation just say that you need to register a class and call it in your funcion. There is something I've missed?
Ps.: The library folder is not registered anywhere (don't know if its needed), and it is in the same path as controllers, views, etc (/app/).
You should probably check your directory structure.
given:
mah_app/app/config/loader.php
mah_app/library/classes/Commons.php
I would expect this to work:
// loader.php
$loader->registerClasses(
array(
"Commons" => __DIR__ . "/../../library/classes/Commons.php"
)
)->register();
// works with $loader->registerDirs() for sure
Also, I would also suggest using namespaces and/or matching file name with class name.
Had the same problem. I commented out the namespace declaration inside the class and it worked. Version 2.0.3.

Zend Framework and nested sets

we`re currently developing our own Feedmanager for ShopProducts based on Zend Framework.
In this feedmanager you can manage several feeds, to be created and sent to different locations.
Each feed has n-fields which are in the current version only in one level.
Now we want to change it to a multilevel version, we we have parentfields and childfields.
We dont want to reinvent the wheel, so we would like to use a developed class or helper.
I found the class of F. Pietka.
https://github.com/fpietka/Zend-Nested-Set
I tried to use this helper in our system, but had no success.
I wrote the following line, to use the class:
$oNested = new NestedSet_Model();
I got the following error message:
Fatal error: Call to undefined method NestedSet_Model::getDbTable() in
D:\xampp\htdocs\feedmanager_alpha\application\classes\NestedSet.class.php
on line 75
In the readme of Peitka`s NestedSet helper it says that the ZendLibrary needs to be in the include path.
I think I did this with the following lines:
define("ROOTPATH", realpath("../"));
define("LIBPATH", ROOTPATH . DIRECTORY_SEPARATOR . 'library' . DIRECTORY_SEPARATOR);
// Ensure library/ is on include_path
set_include_path(
implode(PATH_SEPARATOR,
array(
realpath(LIBPATH)
)
)
);
Did I set the include path correctly?
What could be the problem in my case?
Is a nested-set the best way to create the parent-child-model?
I would strongly advise you not to use this class, because it's clearly a WIP. However, if you want to circumvent this error, you can just delete the __construct() method and call the setDb() and setTableName() by hand.
Example:
$model = new NestedSet_Model();
$model->setDb(Zend_Db_Table::getDefaultAdapter());
$model->setTableName('table_name');
class NestedSet extends Zend_Db_Table
{
protected $_name = 't_nested_set_mkb_10';
public function set(){
$model = new NestedSet_Model();
$model->setDb(Zend_Db_Table::getDefaultAdapter());
$model->setTableName('t_nested_set_mkb_10');
}
}
It was long overdue, but I updated https://github.com/fpietka/Zend-Nested-Set (even with unit tests).
Feel free to create issues!

Categories