# Sage 9 PSR-4 - Not loading or instantiating classes

**URL:** https://discourse.roots.io/t/sage-9-psr-4-not-loading-or-instantiating-classes/10809
**Category:** sage
**Created:** 2017-11-02T21:38:45Z
**Posts:** 11

## Post 1 by @codepuncher — 2017-11-02T21:38:45Z

Hi all,

Have searched the net and forums prior to posting this but can’t seem to find an answer.

I see that with PSR-4 autoloading (based on code within Sage/its dependencies) we only need to “use” a namespace to require the file we need.

However, I can’t seem to load my files or even instantiate them.

I can see that in Sage composer.json we have

```
"psr-4": {
  "App\\": "app/"
}
```

So, naturally, I have added a file called ‘post-types.php’ inside of ‘app/’ which is a basic class to load other post types. The problem is that nothing in this file is being executed - unless I manually instantiate the class at the end of the file.

app/themes/fabric/app/post-types.php

```
<?php

namespace App;

var_dump('outside class scope');

//use App\PostTypes\Event;

class PostTypes
{
    public function __construct()
    {
        // new Event();
        var_dump('inside class constructor');
    }
}
```

Neither var\_dumps work even though the first is outside of the class scope.  
I know I could simply add ‘new PostTypes();’ at the bottom of this file, but surely I should have to do that with the autoloading? Seems to be the case when I look at other classes within vendor/  
Can anyone point out what I’m doing wrong here? Feel like it must be something very simple that I’m missing.

Any help appreciated.  
Thanks

---

## Post 2 by @kalenjohnson — 2017-11-02T21:46:50Z

> [@codepuncher](#):
>
> So, naturally, I have added a file called ‘post-types.php’ inside of ‘app/’ which is a basic class to load other post types.

> **[PSR-4: Autoloader - PHP-FIG](https://www.php-fig.org/psr/psr-4/)**
>
> We're a group of established PHP projects whose goal is to talk about commonalities between our projects and find ways we can work better together.

PSR-4 autoloading does not check for dashes. also

> All class names MUST be referenced in a case-sensitive fashion.

---

## Post 3 by @codepuncher — 2017-11-06T18:49:51Z

Thanks for pointing that out Kalen.

I’ve updated ‘post-types.php’ to ‘Post\_Types.php’ and the class name from ‘PostTypes’ to ‘Post\_Types’ based on the examples in the PSR-4 info page - however, the file still doesn’t seem to be loading.

Am I making an incorrect assumption that this file is supposed to be automatically loaded or do I actually have to reference it somewhere like in functions.php alongside the array at the bottom of this snippet?

```
array_map(function ($file) use ($sage_error) {
    $file = "../app/{$file}.php";
    if (!locate_template($file, true, true)) {
        $sage_error(sprintf(__('Error locating <code>%s</code> for inclusion.', 'sage'), $file), 'File not found');
    }
}, ['helpers', 'setup', 'filters', 'admin', 'new/files/here.php]);
```

I am okay with doing that, but was hoping for autoloading.

Thanks again.

---

## Post 4 by @KimH — 2017-11-07T17:48:27Z

I usually add all the files to the import array, only change it to one import per line to make it easier to read.

Have not used autoloading in sage but I don’t believe the files will be automatically loaded, they will be loaded when used/needed. You have to use the class somewhere for it to load. Something like

```
Post_Types::register()
```

or

```
new Post_Types()
```

in setup.php maybe?

The app folder is pretty full of files in many of my projects so I would probably change it to

```
"psr-4": {
  "App\\": "app/classes/"
}
```

---

## Post 5 by @alwaysblank — 2017-11-08T00:29:45Z

@KimH is right that you have to instantiate your class somehow before it actually does anything. Autoloading in PHP basically works like this:

- Your give your script instructions for how to find things based on their namespacing (in this case, those instructions are PSR-4). i.e. “You can find `My\Class` in `./src/my/class.php`.”
- This doesn’t actually “do” anything, or cause anything to be executed on its own: It just tells your script _where it can find things_.
- When, elsewhere in your script, you write, say, `$class = new My\Class($args);`, then PHP says “Oh, you told me I can find `My\Class` in `./src/my/class.php`, I’ll go open that up and use the code in there to instantiate your class!”

The end result is similar to doing `include('./src/my/class.php')` in that it makes your class available for instantiation, but it saves you from having to type all those `include`s, and only loads files you actually use (in addition to probably have other benefits I’m unaware of). `include` will execute the entire file immediately; autoloading only executes the file when the class it contains is requested.

I think the reason you’re running into an issue is that autoloading is usually used to load classes, _which do exactly nothing until they’re instantiated_, and autoloading _won’t even open up those files_ unless you try to instantiate a class. In order to fire the code in your `PostTypes` class, you’d need to do something like what @KimH suggested. Best practice is not to have functions that fire stuff off in files where you define classes, so I’d recommend something like the following:

```
// app/PostTypes.php
namespace App;

class PostTypes
{
    public static function register()
    {
         new static();
         // my memory is a little rusty; you might want to use `new self();` instead.
    }

    // Do your other class stuff
}
```

```
// app/setup.php

PostTypes::register();
```

---

## Post 6 by @codepuncher — 2017-11-13T21:33:57Z

@KimH @alwaysblank thank you for the pointers - I see that my assumptions of how to use this was incorrect. Instantiating the class manually is all I needed and now everything is working as it should :slight_smile:  
I’m not sure why I was thinking autoloading would handle this for me, to be honest, but this makes a lot more sense now.

Thanks!

---

## Post 7 by @marcelo2605 — 2018-08-14T17:56:46Z

@KimH @alwaysblank I’m having the same problem. I need to use a payment class in a function inside controllers/front-page.php. This payment class need to be instantiate, because of it \_\_construct function.

So I did this

Add payment-pagseguro.php inside App

```
namespace App;

class PaymentPagSeguro{

    private $environment;

    public function __construct( $environment ){
		...
	}

	...
}
```

Change Sage required files in functions.php

```
//line 61
['helpers', 'setup', 'filters', 'admin', 'payment-pagseguro']
```

And instantiate the class inside a function:

```
public function foo()
{
   $pagseguro = new PaymentPagSeguro('sandbox');
}
```

I would like to know if this is the right way.

---

## Post 8 by @alwaysblank — 2018-08-14T19:02:55Z

What errors are you seeing?

---

## Post 9 by @marcelo2605 — 2018-08-14T20:05:46Z

No error. I just would like to know if this is the correct way to do.

Before, I tryed this way:

```
// controllers/front-page.php
    
use App\Pagseguro;

        class FrontPage extends Controller
        {

            public function foo()
            {
                $pagseguro = new App/Pagseguro('sandbox');
            }
        }
```

But it’s return a fatal error:

> Uncaught Error: Call to undefined function App\Pagseguro()

---

## Post 10 by @alwaysblank — 2018-08-14T20:44:43Z

If it works, it’s probably the correct way.

I’d recommend reading up on the [PSR-4 loading standard](https://www.php-fig.org/psr/psr-4/) for a deeper understanding of how autoloading works. If you’re using [soberwp/controller](https://github.com/soberwp/controller) I’d recommend reading carefully through the documentation, and then closely examining the [example controllers in sage](https://github.com/roots/sage/tree/master/app/controllers). I promise that if you read through those sources carefully you’ll understand why your initial attempt failed.

---

## Post 11 by @marcelo2605 — 2018-08-15T12:27:21Z

Fixed! I created a folder called payments inside app/controllers, change the namespace of app/controlers/payments/pagseguro.php to

`namespace App\Payments;`

And in front-page.php, I called this class using

`use Payments\Pagseguro;`

And instantiate this like this:

`$pagseguro = new Payments\Pagseguro('sandbox');`

Thanks again @alwaysblank
