Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract trait't method not allowed to be static in PHP?

Tags:

oop

php

traits

Here is my example:

trait FileConfig {
    public static function getPathForUploads() {
        $paths = static::getPaths();
        //etc.
    }

    abstract public static function getPaths(); //doesn't work. Error: "Static function SharedDefaultConfig::getPaths() should not be abstract"

    abstract public function getPaths(); //OK
    public static function getPaths() {} //OK
}

Class:

class AppConfig {
    use FileConfig;

    public static function getPaths() {
        return array(...);  
    }
}

Call:

AppConfig::getPathForUploads();

It's nessessary to make it static and abstract (to force classes using FileConfig to implement getPaths).

I wonder how is it possible to implement method changing it's static property? Is it a good practice or there are better solutions? Will it one day become illegal?

Thank you

like image 625
VladRia Avatar asked Jan 13 '15 13:01

VladRia


2 Answers

This is fixed in php 7, so the following code works:

<?php

error_reporting(-1);

trait FileConfig {
    public static function getPathForUploads() {
        echo static::getPaths();
    }

    abstract static function getPaths();
}

class AppConfig {
    use FileConfig;

    protected static function getPaths() {
        return "hello world";
    }
}

AppConfig::getPathForUploads();

http://sandbox.onlinephpfunctions.com/code/610f3140b056f3c3e8defb84e6b57ae61fbafbc9

But it does not actually check if the method in AppConfig is static or not during compilation. You will only get a warning when you try to call the non-static method statically: http://sandbox.onlinephpfunctions.com/code/1252f81af34f71e901994af2531104d70024a685

like image 173
user1431317 Avatar answered Sep 21 '22 04:09

user1431317


You do not need to make the method static to force classes using it to implement the method. You can simply use interfaces alongside.

trait FileUploadConfig {
    public static function getPathForUploads() {
        $paths = static::getPaths();
        //etc.
    }
}

The trait was left as is. I just took away the functions for the interface.

interface PathConfiguration {
    public static function getPaths();
}

The interface forces the class to implement the function. I left the static in there to correspond with the trait's specification.

class AppConfig implements PathConfiguration {
    use FileUploadConfig;
    public static function getPaths() {
        return [];
    }
}
like image 34
Igbanam Avatar answered Sep 19 '22 04:09

Igbanam