benanamen Posted October 6, 2016 Share Posted October 6, 2016 So now I have some classes that need to be used by the application. From what I can gather, now I need to know several things to "include" them in the app such as Namespaces, spl_autoload_register, and PSR-4. Could someone please put these things in perspective and when/how to implement. I have read up on each of these items. I am not grasping it as of now. It also seems to be that their is a particular directory structure for the class files and not just a single directory with all the class files in it. Quote Link to comment https://forums.phpfreaks.com/topic/302287-oop-namespace-spl_autoload_register-psr-4/ Share on other sites More sharing options...
requinix Posted October 6, 2016 Share Posted October 6, 2016 - I could write out an explanation of namespaces, but it would be easier to just point you to the documentation. Namespaces are optional but more "professional" than continuing to name classes with underscores. - spl_autoload_register is about autoloading. It means you don't have to do a require_once for every single class file you need. If you're familiar with __autoload, spl_autoload_register is a better alternative. - PSR-4 is a recommendation about how to use namespaces. It's pretty basic, one of the least controversial PSRs, and almost universally accepted. <?php // root/code/MyWebsite/Core/User.php namespace MyWebsite\Core; use MyWebsite\Model; class User { public static function get($username) { $user = Model\User::get($username); // MyWebsite\Model\User return $user ? new self($user) : null; } } ?> <?php // root/code/MyWebsite/Model/User.php namespace MyWebsite\Model; use MyWebsite\Db; use MyWebsite\ModelBase; class User extends ModelBase { public static function get($username) { $db = new Db(); // MyWebsite\Db $row = $db->get("users", "username", $username); return $row ? new self($row) : null; } } ?> <?php // root/bootstrap.php // this autoloader only applies to MyWebsite\* classes spl_autoload_register(function($class) { if (strncmp($class, "MyWebsite\\", 10) == 0) { $file = __DIR__ . strtr($class, "\\", DIRECTORY_SEPARATOR) . ".php"; is_file($file) && require_once($file); } }); ?> <?php // root/public/login.do.php require_once("/path/to/root/bootstrap.php"); $user = MyWebsite\Core\User::get($_POST["username"]); if ($user->login($_POST["password"])) { header("Location: /"); } else { header("Location: /login?invalid"); } ?>Can you ask more specific questions than just "please explain everything"? 1 Quote Link to comment https://forums.phpfreaks.com/topic/302287-oop-namespace-spl_autoload_register-psr-4/#findComment-1538072 Share on other sites More sharing options...
benanamen Posted October 13, 2016 Author Share Posted October 13, 2016 RE: spl_autoload_register I am using the example code from the manual and it works. spl_autoload_register(function ($class) { include 'classes/' . $class . '.class.php'; }); $valid_login = new LoginAttemptsLog($pdo); $valid_login->logSuccessfulAttempt('new_goodusername'); Through testing I see that it somehow reads new LoginAttemptsLog into $class and thinks it is a filename to look for in the classes directory. Do I need to understand anything more than this? What else is there to know about this? Quote Link to comment https://forums.phpfreaks.com/topic/302287-oop-namespace-spl_autoload_register-psr-4/#findComment-1538234 Share on other sites More sharing options...
requinix Posted October 13, 2016 Share Posted October 13, 2016 When PHP encounters a class that hasn't been loaded, it triggers autoloaders. If you called spl_autoload_register then all of those will be called in order until one of them causes the class to be defined (like through an include/require). Since your autoloader indiscriminately tries to include "classes/*.class.php", and $class is set to "LoginAttemptsLog", then it will try to include "classes/LoginAttemptsLog.class.php" using the normal rules for including a file with a relative path. If you tried to instantiate a "Site\LoginAttemptsLog" then the code would try to include "classes/Site\LoginAttemptsLog.class.php". What else is there to know... about the code you posted? About autoloading in general? PSR-4? Namespaces? Quote Link to comment https://forums.phpfreaks.com/topic/302287-oop-namespace-spl_autoload_register-psr-4/#findComment-1538238 Share on other sites More sharing options...
benanamen Posted October 13, 2016 Author Share Posted October 13, 2016 (edited) Since your autoloader indiscriminately tries to include "classes/*.class.php", Is the manual example a bad usage? What else is there to know... about the code you posted? About autoloading in general? PSR-4? Namespaces? Question was regarding the autoloader. I want to know it inside and out before I go on the the next item. Edited October 13, 2016 by benanamen Quote Link to comment https://forums.phpfreaks.com/topic/302287-oop-namespace-spl_autoload_register-psr-4/#findComment-1538250 Share on other sites More sharing options...
maxxd Posted October 13, 2016 Share Posted October 13, 2016 In my experience, using namespaces requires a bit more work than that in the autoloader. For instance, to use requinix's example of "Site\LoginAttemptsLog" converting to "classes/Site\LoginAttemptsLog.class.php", that's not going to be a valid path due to the backslash. So you'd want to explode the class string on a backslash, then implode the resulting array using the directory separator as the glue. This'll give you an include path like "classes/Site/LoginAttemptsLog.class.php", which of course you'll want to test to make sure exists and is a readable file, plus other security checks and stops that Jacques1 can explain far better than I. As long as you follow the directory structure conventions, you should be golden. It's like the days of PEAR naming conventions where file names were long and words separated by underscores, except now the underscores are backslashes and you've got the ability to use the 'use' directive in your code to cut down on the amount of typing you have to do. Quote Link to comment https://forums.phpfreaks.com/topic/302287-oop-namespace-spl_autoload_register-psr-4/#findComment-1538267 Share on other sites More sharing options...
requinix Posted October 14, 2016 Share Posted October 14, 2016 Is the manual example a bad usage?It's fine for smaller projects, but like maxxd said it should do things like fix backslashes and test that the file exists. So you'd want to explode the class string on a backslash, then implode the resulting array using the directory separator as the glue.strtr() is much simpler. $fixed_class_path = strtr($class, "\\", DIRECTORY_SEPARATOR); plus other security checks and stops that Jacques1 can explain far better than I.I'm not going to argue with him if he comes in and says something, but "security checks" implies someone is able to craft an arbitrary class name and cause your code to execute it, and possibly also got an unauthorized file onto the server. But I'm not even sure it's possible to trigger autoloading on an invalid class in the first place. spl_autoload_register(function($class) { var_dump($class); }); $c = "!@#$%^&*()\\Abc"; class_exists($c); // no output new $c(); // no output Quote Link to comment https://forums.phpfreaks.com/topic/302287-oop-namespace-spl_autoload_register-psr-4/#findComment-1538271 Share on other sites More sharing options...
Jacques1 Posted October 14, 2016 Share Posted October 14, 2016 I'm not going to argue with him if he comes in and says something No nervous breakdown this time? I'm disappointed. Quote Link to comment https://forums.phpfreaks.com/topic/302287-oop-namespace-spl_autoload_register-psr-4/#findComment-1538275 Share on other sites More sharing options...
requinix Posted October 14, 2016 Share Posted October 14, 2016 Nervous breakdown? Nah, you're just not worth the time and aggravation. Quote Link to comment https://forums.phpfreaks.com/topic/302287-oop-namespace-spl_autoload_register-psr-4/#findComment-1538280 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.