2

I have installed https://packagist.org/packages/pusher/pusher-php-server using composer and am PSR-4 autoloading all of the packages in my app.

I was able to successfully connect to Pusher API using basic code called from a page that had no "use namespace" mentioned:

$pusher = new Pusher(
            $app->config->get('pusher.api-key'), 
            $app->config->get('pusher.api-secret'),
            $app->config->get('pusher.app-id'),
            array('encrypted' => true)
        );

I decided that I wanted all of the Pusher connection code within its own class, so I created the class below within its own namespace, and saved it as PusherConnect.php in the Smawt/Helpers directory:

<?php

namespace Smawt\Helpers;

class PusherConnect
{
    protected $app;

    public function __construct($app)
    {
        $this->app = $app;

        $pusher = new Pusher(
            $this->app->config->get('pusher.api-key'), 
            $this->app->config->get('pusher.api-secret'),
            $this->app->config->get('pusher.app-id'),
            array('encrypted' => true)
        );

        $results = $pusher->get_channels( array( 'filter_by_prefix' => 'user_') );
        $channel_count = count($results->channels);

        $this->app->view->appendData([
            'channels_count' => $channel_count
        ]);

        $pusher->channel_count = $channel_count;

        return $pusher;
    }

    public function check()
    {
        if (!$this->app->config->get('pusher.api-key')) {
            $this->app->flash('global', 'No Pusher account has been set up.');
            return $this->app->response->redirect($this->app->urlFor('home'));
        }
    }
}

I then instantiated the object with

<?php

use Smawt\Helpers\PusherConnect;

$pusher = new PusherConnect($app);

but I was met with

Fatal error: Class 'Smawt\Helpers\Pusher' not found in C:\Users\...\PusherConnect.php on line 13

So, I realised that the pusher-php-server classes were not namespaced, as no Pusher namespaces were mentioned in the Composer generated autoload_psr4.php file. So, I edited the vendor supplied Pusher.php file:

namespace Pusher;

class PusherException extends \Exception
{
}

class Pusher
{ ...

and my own PusherConnect class

public function __construct($app)
    {
        $this->app = $app;

        $pusher = new \Pusher\Pusher(

and all started working.

The problem appears to be related to instantiating the non-namespaced Pusher class from within my own class, which is namespaced. So, my question is "How do I prevent Composer over-writing my changes, next time I composer update, and also, why am I not able to avoid this editing of the Composer installed package by referring to the global namespace from within my own class?" such as in my own PusherConnect class

public function __construct($app)
    {
        $this->app = $app;

        $pusher = new \Pusher(

Incidentally, it appears that the Pusher Library was namespaced at one time, but is no longer: https://github.com/pusher/pusher-http-php/commit/fea385ade9aede97b37267d5be2fce59d0f1b09d

Thanks in advance

Ian N
  • 55
  • 7

3 Answers3

2

The problem appears to be related to instantiating the non-namespaced Pusher class from within my own class, which is namespaced.

Seems you solved it already by requiring a namespaced branch, but anyway:

If you use new Pusher in a namespaced class, then PHP will try to find the class under this namespace: Smawt\Helpers\ and will fail with "Class not found", because Smawt\Helpers\Pusher doesn't exist inside this namespace - there is no mapping.

By prefixing with the leading backslash new \Pusher you are referring to the global namespace from within your namespaced class. The alternative would be to add a use statement to the top use \Pusher; and then just $obj = new Pusher.

Both will work, because Composer generates the autoloading files, after the package is fetched and the package you are fetching defines a classmap based autoloading: "classmap": [ "lib/" ]. So, the class Pusher maps to /vendor/pusher/pusher-php-server/lib/Pusher.php.

a) prefix with leading backslash

namespace Smawt\Helpers;

class PusherConnect
{
    protected $app;

    public function __construct($app)
    {
        $this->app = $app;

        $pusher = new \Pusher(

a) use-statment

namespace Smawt\Helpers;

use \Pusher;

class PusherConnect
{
    protected $app;

    public function __construct($app)
    {
        $this->app = $app;

        $pusher = new Pusher(
Jens A. Koch
  • 39,862
  • 13
  • 113
  • 141
1

If you want to modify a library brought in with Composer and keep the changes (but not submit a pull request to that package), move it outside your vendor directory and start tracking it with your version control system. The down side (and why people don't often do this) is now any bugfixes or improvements made to that package will have to be handled manually by you.

wogsland
  • 9,106
  • 19
  • 57
  • 93
1

It seems that PSR-4 Autoloading and Namespaces are to be in the next release of Pusher Library. In the meantime I followed the advice at How to require a fork with composer and created my own fork of the Pusher Library, then updated my composer.json to require this branched version from github, which I had namespaced.

Community
  • 1
  • 1
Ian N
  • 55
  • 7