phper-framework / phper

The framework that allows us to write PHP extensions using pure and safe Rust whenever possible.
Other
295 stars 17 forks source link

It seems that private methods cannot be called in class methods #147

Closed shijunti19 closed 10 months ago

shijunti19 commented 10 months ago

It seems that private methods cannot be called in class methods

 class
        .add_method("set_code", Visibility::Public, |this, arguments| {
            let code = arguments[0].expect_long().unwrap();
            let items = this.get_mut_property("items").expect_mut_z_obj()?;
            let mut items_mut = items.to_ref_owned();
            items_mut.set_property("code", code);
            this.set_property("items", items_mut);
            let ret = this.call(
                "set_data",
                &mut [ZVal::from("127.0.0.1")],
            );
            Ok::<_, phper::Error>(ret.ok())
        })
        .argument(Argument::by_val("code"));

   class
        .add_method("set_data", Visibility::Private, |this, arguments| {
            let items = this.get_mut_property("items").expect_mut_z_obj()?;
            let mut items_mut = items.to_ref_owned();
            items_mut.set_property("data", ZVal::from(arguments[0].clone()));
            this.set_property("items", items_mut);
            Ok::<_, phper::Error>(this.to_ref_owned())
        })
        .argument(Argument::by_val("data"));

php code:
var_export($a031_result->set_code(501), true)

result:
NULL
shijunti19 commented 10 months ago

Question 2

class
        .add_static_method("__callStatic", Visibility::Public, |arguments| {
            let mut this_class = ClassEntry::from_globals(A031_RESULT_CLASS_NAME)?.init_object()?;
            let method = arguments[0].expect_z_str()?.to_str().unwrap();
            let (_, parameters) = arguments.split_at(1);
            let mut data: Vec<ZVal> = Vec::new(); // 定义一个空的可变 Vec<ZVal>
            for param in parameters {
                data.push(ZVal::from(param.clone()));
            }
            let slice: &mut [ZVal] = &mut data[..];
            let ret = this_class.call(method, slice)?;
            Ok::<_, phper::Error>(ret)
        })
        .arguments([Argument::by_val("method"), Argument::by_val("parameters")]);

How to call non static methods in a class with static methods
jmjoy commented 10 months ago

Question 1:

There is no problem calling private methods within a class. Your problem may be caused by other reasons.

Question 2:

How to call non static methods in a class with static methods

You must call non static methods via object, your demo is OK.

shijunti19 commented 10 months ago

@jmjoy Okay, I'll test it again I hope you can add more similar test codes in the test

shijunti19 commented 10 months ago
__callStatic:
or
   class
        .add_method("__call", Visibility::Public, |this, arguments| {

Fatal error: Uncaught Error: Invalid callback A031Result::set_data, cannot access private method A031Result::set_data() in

The results of my testing are Call and CallStatic cannot return normally

jmjoy commented 10 months ago

You have to understand that even if you are writing an extension, method calls still follow the visibility of the class. This is no different from PHP code.