PHP namespace behaviour gives FATAL error with spl_autoload_register - namespaces

I want to use namespace and spl_autoload_register together but failed with different error each time.
Please See complete code files on github.
Below are the files
a base file where create a class with namespace class.alpha.php
an include file where I define spl_autoload_register include.php
an example file which instantiate the class object eg.php
Now when I create object from eg.php it gives FATAL error but when I comment namespace line in class.alpha.php then it's working
Please see the code below.
alpha.class.php
<?php
//namespace Alpha; //<< comment and uncomment this to regenerate the error
class Alpha
{
// public static $baseDir_;
public $dir = __DIR__;
public static $baseDir_;
public function __construct()
{
echo __FILE__."=>".__METHOD__;
var_dump(self::$baseDir_, $this->dir);
$firstDir = !empty(self::$baseDir_) ? self::$baseDir_ : $this->dir;
}
}
include.php
<?php //namespace Alpha\config;
spl_autoload_extensions(".php");
spl_autoload_register('loadclass');
function loadclass($class)
{
try {
if (is_readable(strtolower($class).".class.php")) {
include_once strtolower($class).".class.php";
}
} catch (Exception $e) {
print "Exception:". $e;
}
}
//#link http://php.net/manual/en/function.spl-autoload-register.php
// spl_autoload_register(__NAMESPACE__.'Alpha\Alpha()' );
eg.php
<?php
require_once 'include.php';
/** below code works by commenting 1st line on alpha.class.php
if we un comment then below code gives Fatal error: Class 'Alpha' not found */
Alpha::$baseDir_ = '/opt/lampp/archive/';
$obj_ = new Alpha();
var_dump(get_included_files());
var_dump($obj_);
/** now we define namespace Alpha on alpha.class.php */
// $ns_ = new Alpha\Alpha(); // Fatal error: Class 'Alpha\Alpha' not found
// var_dump($ns_);
/** not working even with use statement */
// use Alpha;
// use Alpha;
// $fn = new Alpha\Alpha();
// var_dump($fn);
Please help me out to solve this issue.
Thanks

Your autoloader is receiving a request for a class of "Alpha\Alpha" if you uncomment the namespace in alpha.class.php and place the use Alpha\Alpha in eg. This means that the location it's expecting to find your class in would be alpha\alpha.class.php.
Unless you're on Windows, directory separators are typically forward slash (/). So there's a number of possible solutions.
**Possible Solution #1 - Leave all files in the same place **
If you want to leave everything where it is now, you'll need to remove the namespace from the class names in the autoloader. If you add these lines to the top of your autoloader, that will make it behave that way:
$classParts = explode("\\", $class);
$class = $classParts[count($classParts) - 1];
I would not recommend this solution though since it means that you can no longer provide the same class name in a different namespace.
Possible Solution #2 - Put namespaces in subdirectories
For this solution, you'd create a new directory "alpha" and move "alpha.class.php" into it. For autoloader changes, you can add the following lines to the top of your autoloader:
$class = str_replace("\\", "/", $class);
This will change the namespace separators from backslashes to file path separators with forward slash. This will work on windows as well as mac and linux.
Possible Solution #3 - Follow an established autoloading standard
There are already a number of standard PHP autoloading standards. PSR-0 (now deprecated) works, but PSR-4 would be recommended:
PSR-0: http://www.php-fig.org/psr/psr-0/
PSR-4: http://www.php-fig.org/psr/psr-4/
One big upside of following one of these standards is that there are already plenty of implementations for them and there's been a lot of thought put into how they should work and maintain compatibility with other libraries you may end up wanting to use. Composer (http://getcomposer.org) will allow you to set up and use both PSR-0 and PSR-4 style autoloaders based on a very simple configuration.
Anyway, for the TL;DR crowd, the issue is that the autoloader receives the entire namespaced path in order to know how to load the class. The fatal error was because the autoloader wasn't properly mapping from that namespaced class to a file system location, so the file containing the class was never being loaded.
Hope this helps.

Related

How to create a global function in qml

I want to create a global function that can be called anywhere in my other qml files. Have tried to put a function inside of a rectangle, but it gives me syntax error in the next object. I don't want to use singleton because the syntax would be like Singleton.foobar. I just want to use foobar at anywhere in other qml.
Rectangle {
function foobar(v) {
return v * 2;
}
}
ApplicationWindow { // syntax error here
}
Define the function in your root-node (ApplicationWindow).
This will be the last place, QML will look for a name, before it resorts to the C++-context properties.
See here to find out, how the names of variables and functions are resolved in QML.
It is not possible however to modify the global object, so true global JS-functions are not possible.
The more efficient approach however would be, to keep it always in one of the moste specific scopes, so referencing it with Identifyer.function() would be faster to look up. The singleton for libraries however is not the way to go. Look here for the usage of JS libraries.
Create C++ class with invokable function:
...
class MyCPPObject : public QObject
{
Q_OBJECT
public:
...
Q_INVOKABLE bool funToCallFromJS(int any, QString args);
...
Create MyCPPObject object in global space (rule is following: it must exist until engine exists (it's some simplification, but enough))
...
MyCPPObject cppobj;
...
Use following code to export it to qml and js:
...
QJSValue wrapobj = engine.newQObject(&cppobj);
engine.globalObject().setProperty("cppFun", wrapobj.property("funToCallFromJS"));
...
wrapobj also must exists while engine exists (again simplification)
4. In qml and JS:
...
if(cppFun(127, "abc"))
console.log("It works!");
...
Note: i used different names in qml space and cpp space just to show it's possible to rename cpp function when it used from js, but you can use same name, of course.

I can't use Autoloader from Symfony2 in Symfony 1.4 for load this namespaced classes

I want to use this php library with namespaced classes in my Symfony 1.4 project: https://github.com/donquixote/cellbrush.
I'm not quite familiar with the namespaces concept. So when i fisrt try the to use the main class of this library, according to its docs, i just did:
$table = \Donquixote\Cellbrush\Table\Table::create();
And i got this fatal error:
Fatal error: Class 'Donquixote\Cellbrush\Table\Table' not found in D:\SF_ROOT_DIR\apps\frontend\modules\home\actions\actions.class.php
So i searched for a solution, and supposedly there is one: stackoverflow sol 1, stackoverflow sol 1 eg, but when i try to implement it i still get the above error.
My case:
Directories and files of interest:
D:\SF_ROOT_DIR\lib\autoload\sfClassLoader.class.php
D:\SF_ROOT_DIR\lib\vendor\ClassLoader (contains:
https://github.com/symfony/ClassLoader/tree/2.6)
D:\SF_ROOT_DIR\lib\vendor\cellbrush-1.0 (contains:
https://github.com/donquixote/cellbrush.)
Code:
SF_ROOT_DIR/config/ProjectConfiguration.class.php
require_once dirname(__FILE__).'/../lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php';
require_once dirname(__FILE__) . '/../lib/autoload/sfClassLoader.class.php';
use Symfony\Component\ClassLoader\UniversalClassLoader;
use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
sfCoreAutoload::register();
class ProjectConfiguration extends sfProjectConfiguration
{
public function setup()
{
$this->namespacesClassLoader();
$this->enableAllPluginsExcept('sfPropelPlugin');
}
public function namespacesClassLoader() {
if (extension_loaded('apc')) {
$loader = new ApcUniversalClassLoader('S2A');
} else {
$loader = new UniversalClassLoader();
}
$loader->registerNamespaces(array(
'Donquixote' => __DIR__ . '/../lib/vendor/cellbrush-1.0/src/Table'));
$loader->register();
}
}
actions.class.php
$table = \Donquixote\Cellbrush\Table\Table::create();
Thanks.
Use composer and its autoloading.
Execute:
composer require donquixote/cellbrush
Now the library is installed in vendor directory and autoloader is generated, you just need to include it. Add this line to the top of config/ProjectConfiguration.class.php:
require_once dirname(__FILE__).'/../vendor/autoload.php';

PHPStorm Intellisense Does Not Recognize Constants Defined in Class

Is there a way to get PhpStorm intellisense to pick up these dynamically defined constants? Given the code below, PhpStorm gives the "Undefined constant SAMPLE_CONSTANT_THAT_WAS_DYNAMICALLY_DEFINED" error message.
class ExampleConfiguration
{
private $configurationMapping;
...
public function DefineConfigConstants()
{
foreach ($this->configurationMapping as $key => $value)
define($key, $value);
}
}
class ExampleClass
{
public function Test()
{
print SAMPLE_CONSTANT_THAT_WAS_DYNAMICALLY_DEFINED;
}
}
This issue can be tracked here: https://youtrack.jetbrains.com/issue/WI-11390, what I'm looking for is suggestions for workarounds.
IDE needs to know about such constants in order to not to complain about them. This means that they have to be defined in "normal" way (actual values do not matter, as long as they are not used for file names/paths in include/require statements).
Suggestion: write custom script that create such myconstants.php file where they will be defined in a normal way (since all such constants defined by users and stored in DB, you have to fetch them from DB yourself) .. and run this script (to update generated file) before working with the code in PhpStorm.

Flex resourceManager working perfect in one file and not at all in another

I'm trying to use resourceManager in Flex for some localization. I'm having a strange problem where it works fine in the first file that I tried it in, but in the second it won't even compile.
Both files have
import mx.resources.ResourceBundle;
at the top and
[ResourceBundle("Hurley")]
above the class definition. The first one compiles fine, and pulls the text from the resources correctly at runtime.
The second file (which is in the same project but a different folder), will not compile, and every mention of resourceManager gives an error of "1120: Access of undefined property resourceManager."
For the two different uses:
In the file that works:
public function SeasonsComboBox() {
this.labelFunction = function(obj:Object):String {
return resourceManager.getString('Hurley','Season_word') + " " + obj.number;
};
}
And the file that doesn't work:
public function getCarousels(seriesId:String, callback:Function):void {
[...]
ExternalInterface.addCallback("getCarouselsFailure", function():void {
Alert.show(resourceManager.getString('Hurley','CarouselsFailure_text'), "Error", Alert.OK);
});
[...]
}
I can't think of anything different I did in either file.
Edit, Solved:
resourceManager is defined in all UIComponent subclasses. The file that worked imported ComboBox. The files that didn't don't. In those files, I can make it work by calling:
ResourceManager.getInstance()
More information here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/resources/IResourceManager.html
The reason that you can't access the reourceManager property, is because it is probably not defined.
It is defined in UIComponent, so any class that extends a UIComponent that will have it defined. But, otherwise you have to define it yourself.
You can do so using something like this:
public var resourceManager:ResourceManager = ResourceManager.getInstance();

Shared Functions in CI2: Helper? Library?

I'm still quite new to OOP, and have been learning-as-I-go with CodeIgniter2+Doctrine2.
I have a couple of shared functions that are handy in various areas of my project, so I'd like to call them. In procedural PHP I'd just stick them in a library file and call them. But that's not working for me now..
include 'function_library.php';
$name = $this -> function_library -> generate_male_name();
Message: Undefined property: Turn::$function_library
I even read somewhere that you needed to use call_function(), but that only got me:
Fatal error: Call to undefined method Turn::call_function()
So I figured maybe I should load it as a helper.
$this->load->helper('character_helper');
echo generate_male_name();
Fatal error: Using $this when not in object context in
/PATH/systemFolder/helpers/character_helper.php
on line 19
Line 19:
$query = $this->doctrine->em->createQuery("select max(u.id) from ORM\Dynasties2\Malenames u");
I considered setting it up as a Library, but honestly that begins to get a little over my head in terms of Classes and such. I have not tried it.
Here is the entirety of that function:
function generate_male_name() {
$query = $this->doctrine->em->createQuery("select max(u.id) from ORM\Dynasties2\Malenames u");
$result = $query->getSingleResult();
//echo $result2[1];
$highval = $result[1];
$random_name = rand(1,$highval);
//echo $random_name;
$name = $this->doctrine->em->find('ORM\Dynasties2\Malenames', $random_name);
return $name->getName();
}
How can I do this?
Edit:
Tried a few additional things, still no success.
I put my function_library in third_party, and did:
$this->load->add_package_path(APPPATH.'third_party/function_library/');
$name = $this -> generate_male_name();
Fatal error: Call to undefined method Turn::generate_male_name()
or $name = $this -> function_library -> generate_male_name();
Message: Undefined property: Turn::$function_library
I'm not crazy about calling it in autoloader, I don't need it everywhere, and that seems less than efficient.
I've read up on libraries, but as I said, Classes are quickly over my head and creating a new library seems more than a little daunting to me.
*What's the best solution here? How do I share a few functions? Is a library the way I need to go, or am I just missing something minor in trying to make a helper or shared_functions thing work?*
May be not an answer, only talking about CodeIgniter
Fatal error: Using $this when not in object context in
/PATH/systemFolder/helpers/character_helper.php on line 19
This happens when you try to use CI instance with $this keyword outside of object context (when CI is not instantiated). Observing the error above I can guess that you are using $this inside the helper character_helper.php that is located inside the helpers folder but outside of CI object context. To use CI object you must instantiate the CI using
$ci = & get_instance();
and use $ci instead of $this in your helper.
If you want to use your helper inside any controller then you can load it normally inside your controller as usual, i.e.
$this->load->helper('character_helper');
and if your helper has a function generate_male_name then you can call it inside your controller as follows
generate_male_name();
$this, however, only works directly within your controllers, your
models, or your views.
Creating CodeIgniter Libraries.