Forget late static binding, I need late static __FILE__
Asked Answered
P

5

5

I'm looking for the get_called_class() equivalent for __FILE__ ... Maybe something like get_included_file()?

I have a set of classes which would like to know what directory they exist in. Something like this:

<?php

class A {

    protected $baseDir;

    public function __construct() {
        $this->baseDir = dirname(__FILE__);
    }

    public function getBaseDir() {
        return $this->baseDir;
    }
}

?>

And in some other file, in some other folder...

<?php

class B extends A {
    // ...
}

class C extends B {
    // ...
}

$a = new A;
echo $a->getBaseDir();

$b = new B;
echo $b->getBaseDir();

$c = new C;
echo $c->getBaseDir();

// Annnd... all three return the same base directory.

?>

Now, I could do something ghetto, like adding $this->baseDir = dirname(__FILE__) to each and every extending class, but that seems a bit... ghetto. After all, we're talking about PHP 5.3, right? Isn't this supposed to be the future?

Is there another way to get the path to the file where a class was declared?

Pasteurization answered 27/4, 2010 at 4:53 Comment(2)
I think the only way is the 'ghetto', but why are you doing this, perhaps there is another approach to the problem?Phung
@Phung This is for the view layer of an application. Each view object (usually) consists of a view class and a view template file. In the example above A, B and C are view classes. Each would have, in their parent directory, a matching template file. It would be great to define said directory once, though, instead of every time...Pasteurization
A
1

what if you don't use __FILE__ but a separate variable and set the variable to __FILE__ in each class

class A {

    protected static $baseDir;
    protected $filename = __FILE__; // put this in every file

    public function __construct() {

    }

    public function getBaseDir() {
        return dirname($this->filename) . '<br>'; // use $filename instead of __FILE__
    }   

}

require('bdir/b.php');
require('cdir/c.php');

class B extends A {
    protected $filename = __FILE__; // put this in every file
}

$a = new A;
echo $a->getBaseDir();

$b = new B;
echo $b->getBaseDir();

$c = new C;
echo $c->getBaseDir();

you still have to redeclare the property in each class, but not the method

Adige answered 27/4, 2010 at 6:15 Comment(1)
Yeah, I was worried that it would come down to an answer like this. Note that if you can require PHP 5.3, you can store the equivalent of dirname(__FILE__) by declaring this in every extending class: protected $dirName = DIR;Pasteurization
N
5

ReflectionClass::getFileName

Nerty answered 2/11, 2011 at 19:17 Comment(0)
F
3

Have you tried assigning it as a static member of the class?

<?php
class Blah extends A {
    protected static $filename = __FILE__;
}

(Untested, and statics plus class inheritance becomes very fun...)

Firth answered 27/4, 2010 at 4:55 Comment(0)
A
1

what if you don't use __FILE__ but a separate variable and set the variable to __FILE__ in each class

class A {

    protected static $baseDir;
    protected $filename = __FILE__; // put this in every file

    public function __construct() {

    }

    public function getBaseDir() {
        return dirname($this->filename) . '<br>'; // use $filename instead of __FILE__
    }   

}

require('bdir/b.php');
require('cdir/c.php');

class B extends A {
    protected $filename = __FILE__; // put this in every file
}

$a = new A;
echo $a->getBaseDir();

$b = new B;
echo $b->getBaseDir();

$c = new C;
echo $c->getBaseDir();

you still have to redeclare the property in each class, but not the method

Adige answered 27/4, 2010 at 6:15 Comment(1)
Yeah, I was worried that it would come down to an answer like this. Note that if you can require PHP 5.3, you can store the equivalent of dirname(__FILE__) by declaring this in every extending class: protected $dirName = DIR;Pasteurization
R
0

You could use debug_backtrace(). You probably don't want to, though.

Renewal answered 17/2, 2011 at 17:21 Comment(0)
H
0

Tested:

    protected static $filename = __FILE__; 
    static::$filename 

Doesn't work.

It looks like the constant is registered when the class is loaded which is not "late".

Not sure it was possible before, but what was best for me today is using reflection :

    $basePath = new \ReflectionObject($this);
    $dir = dirname($basePath->getFileName());
Higa answered 30/1, 2017 at 15:21 Comment(1)
Almost there! You can also avoid $this (in case of static methods) by using late-static-binding + ReflectionClass, eg (new \ReflectionClass(static::class))->getFileName().Byssinosis

© 2022 - 2024 — McMap. All rights reserved.