@@ -51,12 +51,16 @@ extern crate proc_macro;
5151/// publicly with the same name as the field. Property types must implement
5252/// `IntoZval` and `FromZval`.
5353///
54- /// You can rename the property with options:
54+ /// You can customize properties with these options:
5555///
56- /// - `name` - Allows you to rename the property, e.g. `#[php(name =
56+ /// - `name` - Allows you to rename the property, e.g. `#[php(prop, name =
5757/// "new_name")]`
5858/// - `change_case` - Allows you to rename the property using rename rules, e.g.
59- /// `#[php(change_case = PascalCase)]`
59+ /// `#[php(prop, change_case = PascalCase)]`
60+ /// - `static` - Makes the property static (shared across all instances), e.g.
61+ /// `#[php(prop, static)]`
62+ /// - `flags` - Sets property visibility flags, e.g. `#[php(prop, flags =
63+ /// ext_php_rs::flags::PropertyFlags::Private)]`
6064///
6165/// ## Restrictions
6266///
@@ -204,6 +208,70 @@ extern crate proc_macro;
204208/// }
205209/// # fn main() {}
206210/// ````
211+ ///
212+ /// ## Static Properties
213+ ///
214+ /// Static properties are shared across all instances of a class. Use
215+ /// `#[php(prop, static)]` to declare a static property. Unlike instance
216+ /// properties, static properties are managed entirely by PHP and do not use
217+ /// Rust property handlers.
218+ ///
219+ /// ```rust,no_run,ignore
220+ /// # #![cfg_attr(windows, feature(abi_vectorcall))]
221+ /// # extern crate ext_php_rs;
222+ /// use ext_php_rs::prelude::*;
223+ /// use ext_php_rs::class::RegisteredClass;
224+ ///
225+ /// #[php_class]
226+ /// pub struct Counter {
227+ /// #[php(prop)]
228+ /// pub instance_value: i32,
229+ /// #[php(prop, static)]
230+ /// pub count: i32,
231+ /// #[php(prop, static, flags = ext_php_rs::flags::PropertyFlags::Private)]
232+ /// pub internal_state: String,
233+ /// }
234+ ///
235+ /// #[php_impl]
236+ /// impl Counter {
237+ /// pub fn __construct(value: i32) -> Self {
238+ /// Self {
239+ /// instance_value: value,
240+ /// count: 0,
241+ /// internal_state: String::new(),
242+ /// }
243+ /// }
244+ ///
245+ /// /// Increment the static counter from Rust
246+ /// pub fn increment() {
247+ /// let ce = Self::get_metadata().ce();
248+ /// let current: i64 = ce.get_static_property("count").unwrap_or(0);
249+ /// ce.set_static_property("count", current + 1).unwrap();
250+ /// }
251+ ///
252+ /// /// Get the current count
253+ /// pub fn get_count() -> i64 {
254+ /// let ce = Self::get_metadata().ce();
255+ /// ce.get_static_property("count").unwrap_or(0)
256+ /// }
257+ /// }
258+ ///
259+ /// #[php_module]
260+ /// pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
261+ /// module.class::<Counter>()
262+ /// }
263+ /// # fn main() {}
264+ /// ```
265+ ///
266+ /// From PHP, you can access static properties directly on the class:
267+ ///
268+ /// ```php
269+ /// Counter::$count = 0;
270+ /// Counter::increment();
271+ /// Counter::increment();
272+ /// echo Counter::$count; // 2
273+ /// echo Counter::getCount(); // 2
274+ /// ```
207275// END DOCS FROM classes.md
208276#[ proc_macro_attribute]
209277pub fn php_class ( args : TokenStream , input : TokenStream ) -> TokenStream {
@@ -812,6 +880,34 @@ fn php_module_internal(args: TokenStream2, input: TokenStream2) -> TokenStream2
812880/// The `#[php(defaults)]` and `#[php(optional)]` attributes operate the same as
813881/// the equivalent function attribute parameters.
814882///
883+ /// ### Static Methods
884+ ///
885+ /// Methods that do not take a `&self` or `&mut self` parameter are
886+ /// automatically exported as static methods. These can be called on the class
887+ /// itself without creating an instance.
888+ ///
889+ /// ```rust,ignore
890+ /// #[php_impl]
891+ /// impl MyClass {
892+ /// // Static method - no self parameter
893+ /// pub fn create_default() -> Self {
894+ /// Self { /* ... */ }
895+ /// }
896+ ///
897+ /// // Instance method - takes &self
898+ /// pub fn get_value(&self) -> i32 {
899+ /// self.value
900+ /// }
901+ /// }
902+ /// ```
903+ ///
904+ /// From PHP:
905+ ///
906+ /// ```php
907+ /// $obj = MyClass::createDefault(); // Static call
908+ /// $val = $obj->getValue(); // Instance call
909+ /// ```
910+ ///
815911/// ### Constructors
816912///
817913/// By default, if a class does not have a constructor, it is not constructable
0 commit comments