super3 / IRC-Bot

A very little basic IRCBot that will get improved over the next time.
http://www.wildphp.com
102 stars 47 forks source link

Autoloader: Use a base dir #66

Open NanoSector opened 9 years ago

NanoSector commented 9 years ago

Right now the autoloader freaks out if it doesn't find the file as it expects every class to be loaded from within the phpbot404.php file. If you want to initialise a class from a command, it won't work; the autoloader will try to load an inexisting file and crash.

Solution: Set a 'dir' => dirname(FILE) var in config.php and make the autoloader use that as prefix.

JackBlower commented 9 years ago

Can you give an example? You can easily load classes as long as the structure adheres to the autoloader's folder structure, which is Classes/<namespace>/classname.php.

If you look at line 36 on Autoloader.php (https://github.com/super3/IRC-Bot/blob/master/Classes/Autoloader.php#L36) then you can see it uses the Class directory:

 $filename = __DIR__ . '/' . str_replace( '\\', '/', $class ) . '.php';

Something that needs to change is that the autoloader shouldn't throw an Exception if the file isn't loaded, as that stops other auto-loaders from being registered and used as a lower priority than the one defined here (composer etc)... This is something that I have changed in my new re-write of the bot (soon to have an initial release on my [ElvenSpellmaker's] fork).

If you really can't load the class, then you could always use require and require a new auto-loader and register it within the command.

NanoSector commented 9 years ago

Yes, there's the problem as well. DIR points at the directory the file currently in context resides in. So if you have Bot.php, which is in Classes/Library/IRC, DIR is Classes/Library/IRC.

ETA: DIR = DIR without spaces. I suck at Markdown.

JackBlower commented 9 years ago

The autoloader is perfectly fine, it points to _Classes/_ which is where all classes should be?

It points to where the autoloader.php is,not where the current script is..?

NanoSector commented 9 years ago

Nevermind, wasn't thinking. Either way, if the autoloader is fine, please explain why this doesn't work:

09.01.2015 - 20:57:58     [ LOG ]   :NanoSector!~Yoshi2889@simplemachines/support/NanoSector PRIVMSG #NanoPlayground :!!exec $this->bot->removeCommand('Ping');
09.01.2015 - 20:57:58     [ LOG ]   Requesting privileges for host ~Yoshi2889@simplemachines/support/NanoSector...
09.01.2015 - 20:57:58     [ LOG ]   Success; proceeding with command.
09.01.2015 - 20:57:58     [ LOG ]   Running command "$this->bot->removeCommand('Ping');"
09.01.2015 - 20:57:58     [ INFO ]  The following Command was removed from the Bot: "Ping".
09.01.2015 - 20:58:33     [ LOG ]   :NanoSector!~Yoshi2889@simplemachines/support/NanoSector PRIVMSG #NanoPlayground :!!exec $this->bot->reAddCommand('Ping');
09.01.2015 - 20:58:33     [ LOG ]   Requesting privileges for host ~Yoshi2889@simplemachines/support/NanoSector...
09.01.2015 - 20:58:33     [ LOG ]   Success; proceeding with command.
09.01.2015 - 20:58:33     [ LOG ]   Running command "$this->bot->reAddCommand('Ping');"

Fatal error: Uncaught exception 'Exception' with message 'File: "/mnt/data/IRC Bot/Classes/Library/IRC/ReflectionClass.php" not found.' in /mnt/data/IRC Bot/Classes/Autoloader.php:40
Stack trace:
#0 [internal function]: Autoloader::load('Library\\IRC\\Ref...')
#1 /mnt/data/IRC Bot/Classes/Library/IRC/Bot.php(338): spl_autoload_call('Library\\IRC\\Ref...')
#2 /mnt/data/IRC Bot/Classes/Command/Exec.php(18) : eval()'d code(1): Library\IRC\Bot->reAddCommand('Ping')
#3 /mnt/data/IRC Bot/Classes/Command/Exec.php(18): eval()
#4 /mnt/data/IRC Bot/Classes/Library/IRC/Command/Base.php(159): Command\Exec->command()
#5 /mnt/data/IRC Bot/Classes/Library/IRC/Bot.php(363): Library\IRC\Command\Base->executeCommand(Array, '#NanoPlayground', ':NanoSector!~Yo...')
#6 /mnt/data/IRC Bot/Classes/Library/IRC/Bot.php(283): Library\IRC\Bot->executeCommand('#NanoPlayground', 'Exec', Array, ':NanoSector!~Yo...')
#7 /mnt/data/IRC Bot/Classes/Library/IRC/Bot.php(190): Library\IRC\Bot->main()
#8 /mnt/data/IRC Bot/phpbot404.php(92): Library\IRC\Bot->co in /mnt/data/IRC Bot/Classes/Autoloader.php on line 40
09.01.2015 - 20:58:33     [ LOG ]   Shutdown function called, closing log...
    public function reAddCommand($commandName)
    {
        $reflector = new ReflectionClass($commandName);

        $command = $reflector->newInstanceArgs($args);

        $this->addCommand($command);
    }
ElvenSpellmaker commented 9 years ago

I assume you're trying to use the built in ReflectionClass from PHP. I suggest you go and read about namespaces which explains all about how to use them. In order to access a class in the global namespace you'll need to prepend the class with a backslash to show you're accessing a global class and not in the current namespace. E.g.:

namespace Foo;

// Looks for Foo\Exception
$foo = new Exception;

// Looks for Exception in the global namespace.
$foo = new \Exception;

// If Exception is not defined in Foo\Exception then you can alias it using a `use` statement
// Notice the lack of \ in front of the Exception as use statements always start from the gobal namespace.
use Exception;

// Now looks for \Exception, not \Foo\Exception
$foo = new Exception.

Generally people import/alias classes from different namespaces to make it cleaner code and to be able to switch the class out with just editing the use statement, rather than everywhere it might be in the code.

To fix this then you can do one of two things:

  1. Import the ReflectionClass at the top of your file using a use statement (Recommended).
  2. Put a backslash before the ReflectionClass statement to show the intent to use the global namespace.

Also the bot doesn't use any use statements throughout at the moment and that should be changed before the bot gets any bigger really.

(You can also alias to other class names and more with namespaces).

Check out: http://php.net/manual/en/language.namespaces.php Specifically: http://php.net/manual/en/language.namespaces.importing.php

NanoSector commented 9 years ago

I just copied over the quoted code from the bot, same file; I don't see why it would work once and not twice. On 10 Jan 2015 14:28, "ElvenSpellmaker" notifications@github.com wrote:

I assume you're trying to use the built in ReflectionClass from PHP. I suggest you go and read about namespaces which explains all about how to use them. In order to access a class in the global namespace you'll need to prepend the class with a backslash to show you're accessing a global class and not in the current namespace. E.g.:

namespace Foo;// Looks for Foo\Exception$foo = new Exception;// Looks for Exception in the global namespace.$foo = new \Exception;// If Exception is not defined in Foo\Exception then you can alias it using a use statement// Notice the lack of \ in front of the Exception as use statements always start from the gobal namespace.use Exception;// Now looks for \Exception, not \Foo\Exception$foo = new Exception.

Generally people import/alias classes from different namespaces to make it cleaner code and to be able to switch the class out with just editing the use statement, rather than everywhere it might be in the code.

To fix this then you can do one of two things:

  1. Import the ReflectionClass at the top of your file using a use statement (Recommended).
  2. Put a backslash before the ReflectionClass statement to show the intent to use the global namespace.

Also the bot doesn't use any use statements throughout at the moment and that should be changed before the bot gets any bigger really.

(You can also alias to other class names and more with namespaces).

Check out: http://php.net/manual/en/language.namespaces.php Specifically: http://php.net/manual/en/language.namespaces.importing.php

— Reply to this email directly or view it on GitHub https://github.com/super3/IRC-Bot/issues/66#issuecomment-69455696.