How to create a new instance of a class from string? - php-extension

In my PHP Extension (Written in C) I have a string with the class name. To be more precise, I have the namespace + class name. For example: Dumb\Factory
This class implements an interface defined in my extension which has a class entry
zend_class_entry *garlic_servicemanager_factoryinterface_ce;
and implements a public method named createService
Inside another class I have a method named get and I check to see if the parameter is a string. When it is a String I would like to instantiate the class and call that method, however I don't know how to instantiate the PHP class from within my C code.
How may I instantiate a class from a string so I can call the method defined by the interface?

You have to find the class_entry from the string and you can do it like below...
zend_class_entry *ce = NULL;
char *className = "Dumb\Factory";
zend_class_entry **pce;
if (zend_lookup_class(className, strlen(className ), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Class %s does not exist", className);
return;
}
ce = *pce;
// Now you have got "zend_class_entry" and
// now you can create N number of objects out of it.
// Check the Reflection API for more info.

Related

Difference between "def" and "static def" in Gradle

As the title, what is exactly the difference of these two defs in Groovy?
Maybe it's a documentation problem, I can't find anything...
A method declaration without static marks a method as an instance method. Whereas a declaration with static will make this method static - can be called without creating an instance of that class - see https://www.geeksforgeeks.org/static-methods-vs-instance-methods-java/
def in groovy defines a value as duck typed. The capabilities of the value are not determined by its type, they are checked at runtime. The question if you can call a method on that value is answered at runtime - see optional typing.
static def means that the method will return a duck typed value and can be called without having instance of the class.
Example:
Suppose you have these two classes:
class StaticMethodClass {
static def test(def aValue) {
if (aValue) {
return 1
}
return "0"
}
}
class InstanceMethodClass {
def test(def aValue) {
if (aValue) {
return 1
}
return "0"
}
}
You are allowed to call StaticMethodClass.test("1"), but you have to create an instance of InstanceMethodClass before you can call test - like new InstanceMethodClass().test(true).

How to detect if JavaScript (ES6) class has a non-default constructor?

I would like to know by some form of reflection or other means if a given ES6 class has a user-written non-default constructor, or not.
Assuming that user-provided constructor has one argument or more, you can do that by checking the length property of the function(class). But if the constructor takes no argument, there is simply no way as far as I know
function Person(fName, lName) {
this.firstName = fName;
this.lastName = lName
}
console.log(Person.length);
function Person2() {}
console.log(Person2.length);
class Person3 {
constructor(f,l) {}
}
console.log(Person3.length);
class Person4 {
}
console.log(Person4.length);
You can invoke the Classname.prototype.constructor.toString() (where Classname is the inspected class name) and get the source string for the class. Which you can then parse and see if it was a constructor declared or not.
Presumably, you need a decent parser for that, but it's another story.
References:
http://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.tostring

How to pass arguments from resolve() to callback specified in give()?

Constructor of class A requires an instance of class B, whose constructor in turn takes an optional string argument.
I want to be able to specify the value of that string argument to class B constructor when resolving class A. I want to do something like this in my service provider:
$this->app
->when(A::class)
->needs(B::class)
->give(function($argument_for_b /* <-- LOOK HERE */){
return new B($argument_for_b);
})
and then obtain instance of A like this (assuming A has been bound to AInterface in the container):
$aInstance = resolve(AInterface::class /* HOW TO PASS ARGUMENT FOR B? */);

missing reference for kendo.data.ObservableObject when extending typescript class

export class MyClass extends kendo.data.ObservableObject {
constructor() {
super();
super.init(this);
}
.
.
.
.
}
I get compilation error:
Error 599 Build: Type name 'kendo.data.ObservableObject' in extends clause does not reference constructor function for 'kendo.data.ObservableObject'.
What am I missing here ?
Type name 'kendo.data.ObservableObject' in extends clause does not reference constructor function for 'kendo.data.ObservableObject'.
Based on http://docs.telerik.com/kendo-ui/api/framework/observableobject the constructor needs as least one argument (the object to observe) So you need to call the constructor with an argument as shown:
export class MyClass extends kendo.data.ObservableObject {
constructor(objToObserve) {
super(objToObserve);
}
.
.
.
.
}
This error, perhaps the most confusing issued by the compiler, means that when the compiler looked up the value indicated by the type in the extends clause, it didn't resolve to a value that was a constructor function for that type.
A smaller example:
class C { }
module M {
var C = 3;
class D extends C { } // <-- Error
}
Here, the type name C inside M means class C, but the value name C means the var declared in the module.
It sounds like you might have a var kendo or var data somewhere in your program. To diagnose this, above the line you write extends kendo.data.ObservableObject, write var foo: kendo.data.ObservableObject and see what error you get.

Convert String into Class for TitleWindow

I don't know if this is possible, I am pulling the names for TitleWindows from my database as strings.
Then from my main application I have to launch the TitleWindow. So in my function I need to convert the name of the TitleWindow which is a String to a Class, because the PopUpManager accepts a Class. Below is my code.
When launching my application and trying to launch the TitleWindow I am getting the error:
Implicit coercion of a value of type String to an unrelated type Class.
I don't want to hard code the name of my popUp in the PopUpManager, that is why I am doing it like this. Any way to work around this?
public function getScreen(screenName:String):void
{
var screen_Name:Class = new Class();
screen_Name = screenName;
var popUpWindow:TitleWindow = PopUpManager.createPopUp(this, screen_Name, false) as TitleWindow;
PopUpManager.centerPopUp(popUpWindow);
}
I have had to do something very similar recently. Here is the function I wrote to do it:
//You have to provice the package signature
private var viewPackage:String = "org.bishop";
//In my case, event.type is the name of a class
var className: String = viewPackage + "." + event.type;
try{
var classRef:Class = getDefinitionByName(className) as Class;
viewNavigator.pushView(classRef);
}
catch(e:ViewError){
trace(e.message);
logger.debug(e.message);
}
Note: for the class to be created correctly, you will need to include both an import statement:
import org.bishop.Login;
and also declare a variable of the class in the code as follows:
Login;
otherwise the classes will not be available to be created.

Resources