PHP trying to use autoload function to find PDO class - php

This has been bugging me for some time now and I can't seem to make sense of it.
My phpinfo reports that PDO is installed and I can connect to my database on my index.php file. But when I try to open a PDO connection on a namespaced class, php is trying to use my autoload function to find PDO.php which won't work.
My class is as follows:
abstract class {
protected $DB;
public function __construct()
{
try {
$this->DB = new PDO("mysql:host=$host;port=$port;dbname=$dbname", $user, $pass);
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
}
And the error is
Warning: require_once((...)/Model/PDO.php): failed to open stream: No such file or directory in /(...)/Autoloader.php
Fatal error: require_once(): Failed opening required 'vendor/Model/PDO.php' (include_path='.:/Applications/MAMP/bin/php/php5.4.4/lib/php') in /(...)/Autoloader.php
As far I as know the autoloader should be called because PHP PDO extension is installed (yes I'm completely sure).
My autoload is as follows:
spl_autoload_register('apiv2Autoload');
/**
* Autoloader
*
* #param string $classname name of class to load
*
* #return boolean
*/
function apiv2Autoload($classname)
{
if (false !== strpos($classname, '.')) {
// this was a filename, don't bother
exit;
}
if (preg_match('/[a-zA-Z]+Controller$/', $classname)) {
include __DIR__ . '/../controllers/' . $classname . '.php';
return true;
} elseif (preg_match('/[a-zA-Z]+Mapper$/', $classname)) {
include __DIR__ . '/../models/' . $classname . '.php';
return true;
} elseif (preg_match('/[a-zA-Z]+Model$/', $classname)) {
include __DIR__ . '/../models/' . $classname . '.php';
return true;
} elseif (preg_match('/[a-zA-Z]+View$/', $classname)) {
include __DIR__ . '/../views/' . $classname . '.php';
return true;
}
}
Any help please?

It's not really an autoload issue. You are attempting to call a class on the root namespace.
By the looks of it, you are in some 'Model' namespace and calling PDO, you must remember that namespaces are relative by default.
What you want is to either call the the absolute path:
\PDO
or at the top of your file say you're going to use PDO like this:
use PDO;

Related

php dependency injection in method not working

I am trying to get use dependency injection in methods via type hint. its not working for me. calling $container->get(Name::class); works
if (false === file_exists(__DIR__ . '/../vendor/autoload.php')) {
die('Install the composer dependencies');
}
require __DIR__ . '/../vendor/autoload.php';
//(new Dotenv())->bootEnv(dirname(__DIR__) . '/.env');
/* Load external routes file */
require_once dirname(__DIR__) . '/config/routes.php';
$builder = new DI\ContainerBuilder();
$builder->addDefinitions(dirname(__DIR__) . '/config/Definitions.php');
try {
$builder->useAutowiring(true);
$container = $builder->build();
} catch (Exception $e) {
die($e->getMessage());
}
function test(Cache $cache)
{
dd($cache);
}
test();
die;
The Definitions file
<?php
declare(strict_types = 1);
use Psr\Container\ContainerInterface;
require dirname(__DIR__) . '/config/config.php';
return [
Cache::class => DI\create(Cache::class)->constructor(MEMCACHED_SERVERS),
\Twig\Environment::class => function () {
$loader = new \Twig\Loader\FilesystemLoader(dirname(__DIR__) . '/Views/');
$twig = new \Twig\Environment($loader, [
'cache' => dirname(__DIR__) . '/Cache/'
]);
return $twig;
},
];
The error i am getting :
Fatal error: Uncaught ArgumentCountError: Too few arguments to
function test(), 0 passed
That’s because you made the test function require Cache then when you run test() you don’t inject the Cache object here:
function test(Cache $cache)
{
dd($cache);
}
// here you need to pass instance of Cache
test();
I am not familiar with this code base, but you would either need an auto-injection script based on Reflection, or what-have-you, to do that auto-injection or you need to manually pass the Cache object:
test(new Cache);
If the Cache object uses all static methods or class constants, you don't need to create it injectable, you would just use it where it's required as in the script referenced by Cache::class;
One last possibility is that $cache is available in some include in one of those files somewhere, though I don't see that anywhere, but if that is available, you could make a test() a variable function with use():
$test = function() use ($cache)
{
dd($cache);
};
// No injection needed
$test();

Oriented Object PHP autoloader issue

I encounterd a little problem with my classes : they simply do not load through my autoloader.
I get this message error :
Warning:
require(C:\wamp64\www\blog\appAutoloader.php/Table/PostsTable.php):
failed to open stream: No such file or directory in
C:\wamp64\www\blog\app\Autoloader.php on line 23
Fatal error: require(): Failed opening required
'C:\wamp64\www\blog\appAutoloader.php/Table/PostsTable.php'
(include_path='.;C:\php\pear') in
C:\wamp64\www\blog\app\Autoloader.php on line 23
Factory class :
use Core\config;
use Core\Database\MysqlDatabase;
class App {
public $title = "My super site";
private $db_instance;
private static $_instance;
public static function getInstance()
{
if (is_null(self::$_instance))
{
self::$_instance = new App();
}
return self::$_instance;
}
public static function load()
{
session_start();
require ROOT . '/app/Autoloader.php';
App\Autoloader::register();
require ROOT .'/core/Autoloader.php';
Core\Autoloader::register();
}
public function getTable($name)
{
$class_name = '\\App\\Table\\' . ucfirst($name) .'Table';
return new $class_name($this->getDb());
}
public function getDb()
{
$config = Config::getInstance(ROOT . '/config/config.php');
if (is_null($this->db_instance)) {
$this->db_instance = new MysqlDatabase($config->get('db_name'), $config->get('db_user'), $config->get('db_pass'), $config->get('db_host'));
}
return $this->db_instance;
}
}
Namespace App autoloader class :
<?php
namespace App;
class Autoloader {
static function register()
{
spl_autoload_register(array(__CLASS__, 'autoload')); // __CLASS__ load the current class
}
static function autoload($class)
{
if (strpos($class, __NAMESPACE__ .'\\') === 0) {
$class = str_replace(__NAMESPACE__ . '\\', '', $class); // _NAMESPACE_ load the current name_space
$class = str_replace('\\', '/', $class);
require __DIR__ . 'Autoloader.php/' . $class . '.php'; // __DIR__ = the parent folder. Here "app"
}
}
}
Namespace Core autoloader class :
<?php
namespace Core;
class Autoloader {
static function register()
{
spl_autoload_register(array(__CLASS__, 'autoload')); // __CLASS__ load the current class
}
static function autoload($class)
{
if (strpos($class, __NAMESPACE__ .'\\') === 0) {
$class = str_replace(__NAMESPACE__ . '\\', '', $class); // _NAMESPACE_ load the current name_space
$class = str_replace('\\', '/', $class);
require __DIR__ . 'Autoloader.php/' . $class . '.php'; // __DIR__ = the parent folder. Here "app"
}
}
}
Empty PostTable
namespace App\Table;
use Core\Table\Table;
class PostsTable extends Table
{
}
Index page :
define('ROOT', dirname(__DIR__));
require ROOT . '/app/App.php';
App::load();
$app = App::getInstance();
$posts = $app->getTable('Posts');
var_dump($posts->all());
How to make it works please?
AS I said in the comments check this path
require(C:\wamp64\www\blog\appAutoloader.php/Table/PostsTable.php)
Doesn't look right to me
require(C:\wamp64\www\blog\ [appAutoloader.php] /Table/PostsTable.php)
What's that bit doing there....
Also namespace of App is not app for the folder its App because this may work on Windows but you will find it does not work on Linux. Because Linux paths are case sensitive, and windows are not.
Further this makes little to no sense
require __DIR__ . 'Autoloader.php/' . $class . '.php'; // __DIR__ = the parent folder. Here "app"
Require 2 files? Paths don't work that way, not that I am aware of at least.
On top of that your implementation ignores the _ Typically underlines will be part of the class name but are replaced by directory, this allows a shorter namespace. So for example instead of having a namespace like this
Namespace \APP\Table;
class PostsTable ..
You could have a class in the same place Like so
Namespace \APP;
class Table_PostsTable ..
With a shorter namespace but still located in the App/Table/PostsTable.php file. However, that's just how I read the spec for PSR autoloaders.
PRO TIP
Take this path C:\wamp64\www\blog\appAutoloader.php/Table/PostsTable.php open the file browser on you desktop and see if it pulls up the file by pasting it into the navigation bar. It wont, but you can be sure your path is wrong by eliminating the code.

Load External Libraries in Symfony 3

I have Service directory in my symfony application like below
src/SwipeBundle/Service
Inside of this directory I have class called.
RSA.php
This class has
namespace SwipeBundle\Service;
require_once __DIR__ . 'RSA/Crypt/RSA.php';
require_once __DIR__ . 'RSA/File/X509.php';
class RSA
{
public function privateKey() {
require_once __DIR__ . 'RSA/Certificates/private.txt';
}
public function certificates() {
return require_once __DIR__ . 'RSA/Certificates/pinew.cer';
}
}
and the files directory are
src/SwipeBundle/Service/RSA/Certificates/pinew.cer
src/SwipeBundle/Service/RSA/Certificates/private.txt
src/SwipeBundle/Service/RSA/Crypt/RSA.php
src/SwipeBundle/Service/RSA/File/X509.php
I want to load the classes of this service class to my Controller, like so.
Controller
use SwipeBundle\Service;
class BillsPayController extends Controller
{
public function indexAction() {
$rsa = new \Crypt_RSA();
$hash = new \Crypt_Hash('sha1');
$x509 = new \File_X509();
$privatekey = file_get_contents(RSA()->privateKey());
$x509->loadX509(file_get_contents(RSA()->certificates()));
}
}
I tried also using this one.
use SwipeBundle\Service\RSA;
class BillsPayController extends Controller
{
public function indexAction() {
$a = new RSA();
$a->privateKey();
}
}
Error I encountered.
Attempt result 1: Attempted to load class "Crypt_RSA" from the global namespace.
Did you forget a "use" statement?
Attempt result 2: Compile Error: main(): Failed opening required '/Users/jaysonlacson/Sites/contactless/src/SwipeBundle/ServiceRSA/Crypt/RSA.php' (include_path='.:')
I think you are missing a forward slash like this:
require_once __DIR__ . '/RSA/Crypt/RSA.php';
require_once __DIR__ . '/RSA/File/X509.php';
I'm just guessing, but can you try that?

spl_autoload_register loads class twice

I keep trying to know what the problem is with this very simple class loader script.
The class loader looks like this:
#src/vendors/Autoloading/lib/ClassLoader.php
namespace App\Vendors\Autoloading;
class ClassLoader
{
private $path;
function __construct($path)
{
$this->path = $path;
}
public function load($class)
{
if(file_exists( $class = str_replace(array('\\', '_'), DIRECTORY_SEPARATOR, $this->path) . '.php')){
require $class;
return true;
}
}
public function register()
{
return spl_autoload_register([$this, 'load']);
}
}
The initial class loader had more methods and some functions to validate the file names ...
but, in the process of debugging I had to narrow it to that.
So, that class loader is being required inside an autoload.php file, as you can see below.
#src/vendors/autoload.php
namespace App\Vendors;
require 'Autoloading/lib/ClassLoader.php';
$autoload = new Autoloading\ClassLoader('path/Foo/FooClass');
$autoload->register();
The FooClass.php is located in src/Foo/FooClass.php
namespace App\Foo;
class FooClass{}
and there is actually no problem with the autoloading part, the class gets loaded just fine, but it is done twice which shows me the below error. I am calling it from an index.php file
<?php
use \App\Foo\FooClass;
FooClass::somefunction();
Just using that generates this error.
Fatal error: Cannot redeclare class path\foo\FooClass in /path/to/index.php on line 4
Your autoloading function is wrong:
public function load($class)
{
if (
file_exists(
$class = str_replace(
array('\\', '_'),
DIRECTORY_SEPARATOR,
$this->path)
. '.php')
) {
require $class;
return true;
}
}
The function is calles with the name of the class to be loaded (if impossible, the function should do nothing).
What you do is ignoring the class name, and create a new one based on the path the autoloader is created with. This will always load the same file, with the same class, even if there are different classes to be loaded.
And this explains why you get the error, because no matter which class name gets passed, you always include the one file that is related to the path.
You probably want to use a proper PSR-0 or PSR-4 autoloader. I would recommend using the one that comes with Composer, as you are likely to be using Composer sooner or later yourself. Why not starting today?
Check if the class already exists using class_exists before checking for the file
Try using require_once instead of require. Your autoloader won't keep track of what files have been loaded so far.
Here's how I set mine up. I don't use a class. Maybe this will help
function PlatformAutoloader($classname) {
try {
// Change \ to / so namespacing will work
$classname = strtolower(str_replace('\\', DIRECTORY_SEPARATOR, $classname));
if(!#include_once(DIR_CLASSES . DIRECTORY_SEPARATOR . $classname . '.php')) return false;
} catch(Exception $e) {
return false;
}
}
spl_autoload_register('PlatformAutoloader');

PHP spl_autoload_register is doing nothing

i'm updating my code and trying to use spl_autoload_register but IT SIMPLY DOESN'T WORK!!!
I'm using PHP 5.3.8 - Apache 2.22 on Centos / Ubuntu / Win7 and trying to echo something but i get nothing instead... have been trying to make it work for the last 3 hours with no result... this is driving me mad!!!
class ApplicationInit {
// Constructor
public function __construct() {
spl_autoload_register(array($this, 'classesAutoloader'));
echo 'construct working...!';
}
// Autoloading methods
public function classesAutoloader($class) {
include 'library/' . $class . '.php';
echo 'autoload working...!';
}
}
first echo from __construct works but the "classesAutoloader" doesn't work at all, this class is defined in a php file within a folder and i'm calling it from index.php like follows:
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', getcwd() . DS);
define('APP', ROOT . 'application' . DS);
// Initializing application
require(APP.'appInit.php');
$classAuto = new ApplicationInit();
any help is truly appreciated, thanks in advance!
It seems like you're doing the wrong thing. The function that you pass to spl_autoload_register is what's responsible for loading the class file.
Your code is calling
$classAuto = new ApplicationInit();
but by that time, ApplicationInit is already loaded so the autoload function doesn't get called
A more logical way would be for you to to call
spl_autoload_register(function($class){
include 'library/' . $class . '.php';
});
Then when you call
$something = new MyClass();
And the MyClass is not defined, then it will call your function to load that file and define the class.
What is your problem? Your code is working correctly.
class ApplicationInit {
public function __construct() {
spl_autoload_register(array($this, 'classesAutoloader'));
echo 'construct working...!';
}
public function classesAutoloader($class) {
include 'library/' . $class . '.php';
echo 'autoload working...!';
}
}
$classAuto = new ApplicationInit(); //class already loaded so dont run autoload
$newclass = new testClass(); //class not loaded so run autoload

Categories