I try to learn oop but in my first class it gives me this error.
Database class
<?php
namespace App;
class Database
{
...
}
in my functions.php
<?php
require 'helpers.php';
require 'connection.php';
use App\Database;
...
Class under the "app" folder and it's namespace is "App". Why I'm getting this error ?
You either need to include the file, or use an AutoLoader. AutoLoaders tell PHP where a class can be found, as PHP needs to know the file.
Autoloaders are fully explained in the PHP documentation:
https://secure.php.net/manual/en/language.oop5.autoload.php
Example from the mentioned documentation:
<?php
spl_autoload_register(function ($class_name) {
include $class_name . '.php';
});
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
In this case spl_autoload_register is used to register the autoloader. The autoloader is a function which takes the class name, and includes the necessary class. For example you can use the autoloader function as used above, in which case the class name needs to be identical to the filename.
This is a quite simple example, but a more advanced autoloader could check if files exist, check multiple locations, etc...
Examples are mentioned in the comments on your original question.
note: You will find other sources mentioning the __autoload($class) function. This function does exactly the same, but will be removed from PHP in future updates. Therefore, you are better off using spl_autoload_register
Because I posted my Autoloader in the comments.
https://github.com/ArtisticPhoenix/MISC/blob/master/Autoloader.php
You can find the code at the bottom of this post:
The basic usage is as follows:
require_once 'Autoloader.php';
AutoLoader::getInstance()->regesterPath('\\', __DIR__);
This assumes it's in the directory that is the root of you namespace. So if you have a class.
namespace App;
class Database{ ... }
And this class is in
www
|- Autoloader.php
|- App
| --Database.php
Then it will look for __DIR__ + Namespace or __DIR__/APP/. You can register paths because if you have this setup.
www
|- Autoloader.php
|- includes
|-- App
| ---Database.php
Where the class is located in includes/App and Autoloader is in / the root folder you can do it this way.
require_once 'Autoloader.php';
AutoLoader::getInstance()->regesterPath('\\', __DIR__.'/includes/');
Also if you have it setup like this.
www
|- Autoloader.php
|- includes
| --Database.php
Where there is no actual App folder then you can do it like this.
require_once 'Autoloader.php';
AutoLoader::getInstance()->regesterPath('\\App\\', __DIR__.'/includes/');
Or any combination of the above.
It will account for the differences between \\App. App and \\App\\ for the most part. But you can also turn on debugging with this.
require_once 'Autoloader.php';
$AutoLoader = AutoLoader::getInstance();
$AutoLoader->setDebug(true);
$AutoLoader>regesterPath('\\App\\', __DIR__.'/includes/');
And it will spit out a bunch of stuff telling you where it is looking. You may have to use <pre> to keep the whitespace format, if your working in HTML. Conveniently you can also turn off Debugging, because you may be autoloading a bunch of classes.
$AutoLoader->setDebug(false);
You can also assign multiple paths, and give them a priority and it will look in them in the order of the priority. But that is not really important in this case.
So for example:
I have a folder
www
|-MISC
|--index.php
|--Autoloader.php
|---IMAP
|----GmailClient.php
Which is also in the same Git Repo. It has the namespace of Lib\Email\IMAP of which only the IMAP exists.
And to load It if I do this in index.php, which is inside the MISC file and at the same level as the AutoLoader.php file:
//include the Autoloader
require_once __DIR__.'/Autoloader.php';
//get an instance of it (Singleton pattern)
$Autoloader = Autoloader::getInstance();
//regester a namespace, path pair
$Autoloader->regesterPath('Lib\Email', __DIR__.'/IMAP/');
//preserve whitespace
echo "<pre>";
//turn on debugging before a problem class
$Autoloader->setDebug(true);
//Attempt to load the class as normal
$G = new GmailClient($hostname, $username, $password);
//turn off debugging after trying to load a problem class.
$AutoLoader->setDebug(false);
This is what it Outputs for debugging
================================= Autoloader::debugMode ==================================
Autoloader::splAutoload Lib\Email\IMAP\GmailClient
Checking class: GmailClient
Checking namespace: Lib/Email/IMAP
checking pathname:C:/Server/www/MISC/IMAP/IMAP/GmailClient.php
==========================================================================================
Right away we can see C:/Server/www/MISC/IMAP/IMAP/GmailClient.php That IMAP is in there 2x. This is because I included that in the path, So it starts looking in C:/Server/www/MISC/IMAP/ and then adds the namespace that wasn't given in the namespace arg IMAP from Lib/Email/IMAP. We gave it Lib/Email as the first argument. So essentially, because this was part of the path it's already in that folder when it looks for that.
So If I just remove that IMAP from the path:
$Autoloader->regesterPath('Lib\Email', __DIR__);
It will output this:
================================= Autoloader::debugMode ==================================
Autoloader::splAutoload Lib\Email\IMAP\GmailClient
Checking class: GmailClient
Checking namespace: Lib/Email/IMAP
checking pathname:C:/Server/www/MISC/IMAP/GmailClient.php
Found: C:/Server/www/MISC/IMAP/GmailClient.php
==========================================================================================
With the most important line being this
Found: C:/Server/www/MISC/IMAP/GmailClient.php
Which obviously means that it found the class file and loaded it.
Hope that makes sense.
Following is the full code for the autoloader, that way the answer wont break if anything changes with the Repo I linked.
<?php
/**
*
* (c) 2016 ArtisticPhoenix
*
* For license information please view the LICENSE file included with this source code. GPL-3
*
* PSR4 compatible Autoloader
*
* #author ArtisticPhoenix
* #see http://www.php-fig.org/psr/psr-4/
*
* #example
* $Autoloader = Autoloader::getInstance();
* //looks in includes for folder named /includes/Lib/Auth/User/
* $Autoloader->regesterPath('Lib\\Auth\\User', __DIR__.'/includes/');
*
*/
final class Autoloader
{
/**
*
* #var int
*/
const DEFAULT_PRIORITY = 10;
/**
* namespace / class path storage
* #var array
*/
private $paths = array();
/**
* cashe the loaded files
* #var array
*/
private $files = array();
/**
* namespace / class path storage
* #var array
*/
private $debugMode = false;
/**
*
* #var Self
*/
private static $instance;
/**
* No public construction allowed - Singleton
*/
private function __construct($throw, $prepend)
{
spl_autoload_register(array( $this,'splAutoload'), $throw, $prepend);
}
/**
* No cloning of allowed
*/
private function __clone()
{
}
/**
*
* Get an instance of the Autoloader Singleton
* #param boolean $throw
* #param boolean $prepend
* #return self
*/
public static function getInstance($throw = false, $prepend = false)
{
if (!self::$instance) {
self::$instance = new self($throw, $prepend);
}
return self::$instance;
}
/**
* set debug output
* #param boolean $debug
* #return self
*/
public function setDebug($debug = false)
{
$this->debugMode = $debug;
return $this;
}
/**
* Autoload
* #param string $class
*/
public function splAutoload($class)
{
$this->debugMode('_START_');
$this->debugMode(__METHOD__.' '.$class);
//keep the orignal class name
$_class = str_replace('\\', '/', $class);
$namespace = '';
if (false !== ($pos = strrpos($_class, '/'))) {
$namespace = substr($_class, 0, ($pos));
$_class = substr($_class, ($pos + 1));
}
//replace _ in class name only
if (false !== ($pos = strrpos($_class, '/'))) {
if (strlen($namespace)) {
$namespace .= '/'.substr($_class, 0, ($pos));
} else {
$namespace = substr($_class, 0, ($pos));
}
$_class = substr($_class, ($pos + 1));
}
$this->debugMode("Checking class: $_class");
$this->debugMode("Checking namespace: $namespace");
do {
if (isset($this->paths[ $namespace ])) {
foreach ($this->paths[ $namespace ] as $registered) {
$filepath = $registered['path'] . $_class . '.php';
$this->debugMode("checking pathname:{$filepath}");
if (file_exists($filepath)) {
$this->debugMode("Found: $filepath");
$this->debugMode('_END_');
require_once $filepath;
$this->files[$class] = $filepath;
}
}
}
if (strlen($namespace) == 0) {
//if the namespace is empty and we couldn't find the class we are done.
break;
}
if (false !== ($pos = strrpos($namespace, '/'))) {
$_class = substr($namespace, ($pos + 1)) . '/' . $_class;
$namespace = substr($namespace, 0, ($pos));
} else {
$_class = (strlen($namespace) ? $namespace : '') . '/' . $_class;
$namespace = '';
}
} while (true);
$this->debugMode('_END_');
}
/**
* get the paths regestered for a namespace, leave null go get all paths
* #param string $namespace
* #return array or false on falure
*/
public function getRegisteredPaths($namespace = null)
{
if (is_null($namespace)) {
return $this->paths;
} else {
return (isset($this->paths[$namespace])) ? array($namespace => $this->paths[$namespace]) : false;
}
}
/**
*
* #param string $namespace
* #param string $path
* #param int $priority
* #return self
*/
public function regesterPath($namespace, $path, $priority = self::DEFAULT_PRIORITY)
{
$namespace = str_replace('\\', '/', $namespace); //convert to directory seperator
$path = ($this->normalizePath($path));
$this->paths[$namespace][sha1($path)] = array(
'path' => $path,
'priority' => $priority
);
$this->sortByPriority($namespace);
return $this;
}
/**
* un-regester a path
* #param string $namespace
* #param string $path
*/
public function unloadPath($namespace, $path = null)
{
if ($path) {
$path = $this->normalizePath($path);
unset($this->paths[$namespace][sha1($path)]);
} else {
unset($this->paths[$namespace]);
}
}
/**
* check if a namespace is regestered
* #param string $namespace
* #param string $path
* #return bool
*/
public function isRegistered($namespace, $path = null)
{
if ($path) {
$path = $this->normalizePath($path);
return isset($this->paths[$namespace][sha1($path)]) ? true : false;
} else {
return isset($this->paths[$namespace]) ? true : false;
}
}
/**
* get the file pathname of a loaded class
* #param string $class
* #return mixed
*/
public function getLoadedFile($class = null)
{
if (!$class) {
return $this->files;
}
if (isset($this->files[$class])) {
return $this->files[$class];
}
}
/**
* output debug message
* #param string $message
*/
protected function debugMode($message)
{
if (!$this->debugMode) {
return;
}
switch ($message) {
case '_START_':
echo str_pad("= ".__METHOD__." =", 90, "=", STR_PAD_BOTH) . PHP_EOL;
break;
case '_END_':
echo str_pad("", 90, "=", STR_PAD_BOTH) . PHP_EOL . PHP_EOL;
break;
default:
echo $message . PHP_EOL;
}
}
/**
* sort namespaces by priority
* #param string $namespace
*/
protected function sortByPriority($namespace)
{
uasort($this->paths[$namespace], function ($a, $b) {
return ($a['priority'] > $b['priority']) ? true : false;
});
}
/**
* convert a path to unix seperators and make sure it has a trailing slash
* #param string $path
* #return string
*/
protected function normalizePath($path)
{
if (false !== strpos($path, '\\')) {
$path = str_replace("\\", "/", $path);
}
return rtrim($path, '/') . '/';
}
}
P.S. the GmailClient class I used in this example, I wrote to parse incoming Emails in a Gmail account. It's not 100% fleshed out as we needed it for a specific purpose. But it is in the same GitHub repository.
Related
I have this function:
public function __construct()
{
$config = include APPPATH."email_config.php";
$driver = "Email_".ucfirst(strtolower($config['driver'])); echo $driver.RT; //gives Email_Smtp
// return new $driver($config); //do not work
return new Email_Smtp($config); //works
}
new $driver($config) gives the error message:
Fatal error: Uncaught Error: Class 'Email_Smtp' not found
$driver is the string "Email_Smtp".
return new Email_Smtp($config) works like a charm.
Whats wrong here?
the config file:
return array(
/**
* Mail useragent string wird in Header als X-Mailer: gesetzt
*/
'useragent' => 'my agent',
/**
* Mail driver (mail, smtp, sendmail, noop, php)
*/
'driver' => 'smtp',
...
here is my autoload:
class Autoloader {
/**
* #type string
*/
protected $namespacePrefix = '';
/**
* #type string
*/
protected $baseDir = '';
/**
* Sets the namespace's prefix.
* Only classes with this namespace will be autoloaded.
*
* #param string $prefix
* #return \Autoloader
*/
public function setNamespacePrefix($prefix) {
$this->namespacePrefix = $prefix;
return $this;
}
/**
* Sets the base directory, where we can find our php files.
*
* #param string $dir
* #return \Autoloader
*/
public function setBaseDir($dir) {
$this->baseDir = $dir;
return $this;
}
/**
* Register our autoloader.
*
* #return void
*/
public function register() {
spl_autoload_register(function($class) {
if (!preg_match('/^' . preg_quote($this->namespacePrefix) . '/', $class)) {
// Don't register a class without our namespace's prefix
return;
}
$relativeClass = substr($class, strlen($this->namespacePrefix));
$file = $this->baseDir . str_replace('\\', DIRECTORY_SEPARATOR, $relativeClass) . '.php';
if (file_exists($file)) {
require_once($file);
// if the loaded file contains a class...
if (class_exists($class, false))
{
if (method_exists($class, '_init') and is_callable($class.'::_init'))
{
call_user_func($class.'::_init');
}
}
}
});
}
}
I'm trying to get my app working, Its a vanilla php, I have 2 services with one dependent on other. I'm running service from the bootstrap, which requires simple SplClassLoader.
The directory structure (Slightly simplified):
-src
-logic
-Service
-CustomService.php
-DataProviderService.php
-SplClassLoader.php
-test
-bootstrap.php
Bootstrap:
<?php
require __DIR__ . '/../src/SplClassLoader.php';
$oClassLoader = new \SplClassLoader('logic', __DIR__ . '/../src');
$oClassLoader->register();
$service = new logic\Service\CustomService;
$service->execute();
SplClassLoader:
<?php
/**
* SplClassLoader implementation that implements the technical interoperability
* standards for PHP 5.3 namespaces and class names.
*
* http://groups.google.com/group/php-standards/web/final-proposal
*
* // Example which loads classes for the Doctrine Common package in the
* // Doctrine\Common namespace.
* $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
* $classLoader->register();
*
* #author Jonathan H. Wage <jonwage#gmail.com>
* #author Roman S. Borschel <roman#code-factory.org>
* #author Matthew Weier O'Phinney <matthew#zend.com>
* #author Kris Wallsmith <kris.wallsmith#gmail.com>
* #author Fabien Potencier <fabien.potencier#symfony-project.org>
*/
class SplClassLoader
{
private $_fileExtension = '.php';
private $_namespace;
private $_includePath;
private $_namespaceSeparator = '\\';
/**
* Creates a new <tt>SplClassLoader</tt> that loads classes of the
* specified namespace.
*
* #param string $ns The namespace to use.
*/
public function __construct($ns = null, $includePath = null)
{
$this->_namespace = $ns;
$this->_includePath = $includePath;
}
/**
* Sets the namespace separator used by classes in the namespace of this class loader.
*
* #param string $sep The separator to use.
*/
public function setNamespaceSeparator($sep)
{
$this->_namespaceSeparator = $sep;
}
/**
* Gets the namespace seperator used by classes in the namespace of this class loader.
*
* #return void
*/
public function getNamespaceSeparator()
{
return $this->_namespaceSeparator;
}
/**
* Sets the base include path for all class files in the namespace of this class loader.
*
* #param string $includePath
*/
public function setIncludePath($includePath)
{
$this->_includePath = $includePath;
}
/**
* Gets the base include path for all class files in the namespace of this class loader.
*
* #return string $includePath
*/
public function getIncludePath()
{
return $this->_includePath;
}
/**
* Sets the file extension of class files in the namespace of this class loader.
*
* #param string $fileExtension
*/
public function setFileExtension($fileExtension)
{
$this->_fileExtension = $fileExtension;
}
/**
* Gets the file extension of class files in the namespace of this class loader.
*
* #return string $fileExtension
*/
public function getFileExtension()
{
return $this->_fileExtension;
}
/**
* Installs this class loader on the SPL autoload stack.
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
}
/**
* Uninstalls this class loader from the SPL autoloader stack.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* #param string $className The name of the class to load.
* #return void
*/
public function loadClass($className)
{
if (null === $this->_namespace || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) {
$fileName = '';
$namespace = '';
if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;
require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName;
}
}
}
So yeah, Im running php php bootstrap.php and getting error that too few arguments passed into contructor. How to make bootstrap load dependency injections? How I should make it work? Can I use some kind of service container of phpunit maybe? Its a clue I have been given. No idea if I did explain problem well enough, but hope I did! :)
Error message:
PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function logic\Service\CustomService::execute(), 0 passed in /.../test/bootstrap.php on line 12 and exactly 1 expected in /.../Service/CustomService.php:23
Stack trace:
#0 /.../test/bootstrap.php(12): logic\Service\CustomService->execute()
#1 {main}
thrown in /.../logic/Service/CustomService.php on line 23
I'm struggling with fixing this class exception error. If anyone could help it would be greatly appreciated, Thanks!
BACKGROUND INFO:
After installing a Dashnex plugin on my wordpress site & then uninstalling WP Quick cache I am getting this error message. Please note that quick cache is fully uninstalled & the wp-config.php file includes no quick cache instructions.
ERROR MESSAGE:
Fatal error: Uncaught exception 'ReflectionException' with message 'Class \quick_cache does not exist' in /home/cal108/public_html/wp-content/plugins/dashnex-plugin/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php:246 Stack trace: #0 /home/cal108/public_html/wp-content/plugins/dashnex-plugin/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php(246): ReflectionClass->__construct('\quick_cache') #1 /home/cal108/public_html/wp-content/plugins/dashnex-plugin/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(113): Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver->getAllClassNames() #2 /home/cal108/public_html/wp-content/plugins/dashnex-plugin/DashNex/Doctrine/MagicSchema.php(18): Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getAllMetadata() #3 /home/cal108/public_html/wp-content/plugins/dashnex-plugin/DashNex/Doctrine/MagicSchema.php(37): DashNex\Doctrine\MagicSchema->Get in /home/cal108/public_html/wp-content/plugins/dashnex-plugin/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php on line 246
AnnotationDriver.php Line 246
$rc = new \ReflectionClass($className);
AnnotationDriver.php File
<?php
abstract class AnnotationDriver implements MappingDriver
{
/**
* The AnnotationReader.
*
* #var AnnotationReader
*/
protected $reader;
/**
* The paths where to look for mapping files.
*
* #var array
*/
protected $paths = array();
/**
* The paths excluded from path where to look for mapping files.
*
* #var array
*/
protected $excludePaths = array();
/**
* The file extension of mapping documents.
*
* #var string
*/
protected $fileExtension = '.php';
/**
* Cache for AnnotationDriver#getAllClassNames().
*
* #var array|null
*/
protected $classNames;
/**
* Name of the entity annotations as keys.
*
* #var array
*/
protected $entityAnnotationClasses = array();
/**
* Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
* docblock annotations.
*
* #param AnnotationReader $reader The AnnotationReader to use, duck-typed.
* #param string|array|null $paths One or multiple paths where mapping classes can be found.
*/
public function __construct($reader, $paths = null)
{
$this->reader = $reader;
if ($paths) {
$this->addPaths((array) $paths);
}
}
/**
* Appends lookup paths to metadata driver.
*
* #param array $paths
*
* #return void
*/
public function addPaths(array $paths)
{
$this->paths = array_unique(array_merge($this->paths, $paths));
}
/**
* Retrieves the defined metadata lookup paths.
*
* #return array
*/
public function getPaths()
{
return $this->paths;
}
/**
* Append exclude lookup paths to metadata driver.
*
* #param array $paths
*/
public function addExcludePaths(array $paths)
{
$this->excludePaths = array_unique(array_merge($this->excludePaths, $paths));
}
/**
* Retrieve the defined metadata lookup exclude paths.
*
* #return array
*/
public function getExcludePaths()
{
return $this->excludePaths;
}
/**
* Retrieve the current annotation reader
*
* #return AnnotationReader
*/
public function getReader()
{
return $this->reader;
}
/**
* Gets the file extension used to look for mapping files under.
*
* #return string
*/
public function getFileExtension()
{
return $this->fileExtension;
}
/**
* Sets the file extension used to look for mapping files under.
*
* #param string $fileExtension The file extension to set.
*
* #return void
*/
public function setFileExtension($fileExtension)
{
$this->fileExtension = $fileExtension;
}
/**
* Returns whether the class with the specified name is transient. Only non-transient
* classes, that is entities and mapped superclasses, should have their metadata loaded.
*
* A class is non-transient if it is annotated with an annotation
* from the {#see AnnotationDriver::entityAnnotationClasses}.
*
* #param string $className
*
* #return boolean
*/
public function isTransient($className)
{
$classAnnotations = $this->reader->getClassAnnotations(new \ReflectionClass($className));
foreach ($classAnnotations as $annot) {
if (isset($this->entityAnnotationClasses[get_class($annot)])) {
return false;
}
}
return true;
}
/**
* {#inheritDoc}
*/
public function getAllClassNames()
{
if ($this->classNames !== null) {
return $this->classNames;
}
if (!$this->paths) {
throw MappingException::pathRequired();
}
$classes = array();
$includedFiles = array();
foreach ($this->paths as $path) {
if ( ! is_dir($path)) {
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
}
$iterator = new \RegexIterator(
new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS),
\RecursiveIteratorIterator::LEAVES_ONLY
),
'/^.+' . preg_quote($this->fileExtension) . '$/i',
\RecursiveRegexIterator::GET_MATCH
);
foreach ($iterator as $file) {
$sourceFile = $file[0];
if ( ! preg_match('(^phar:)i', $sourceFile)) {
$sourceFile = realpath($sourceFile);
}
foreach ($this->excludePaths as $excludePath) {
$exclude = str_replace('\\', '/', realpath($excludePath));
$current = str_replace('\\', '/', $sourceFile);
if (strpos($current, $exclude) !== false) {
continue 2;
}
}
require_once $sourceFile;
$includedFiles[] = $sourceFile;
}
}
$declared = get_declared_classes();
foreach ($declared as $className) {
$rc = new \ReflectionClass($className);
$sourceFile = $rc->getFileName();
if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) {
$classes[] = $className;
}
}
$this->classNames = $classes;
return $classes;
}
}
I WAS ABLE TO SOLVE MY PROBLEM. HELP NOT NEEDED ANYMORE :)
FOR ANYONE THIS MAY STILL HELP:
I DISABLED ALL OF MY PLUGINS BY RENAMING THEM IT IN CPANEL, THEN BROUGHT EACH ONE ONLINE AGAIN TO KNOW IF THE DASHNEX PLUGIN WAS THE CULPRIT. IT WAS. THEN RENAMED ALL PLUGINS AGAIN & ALL WORKING FINE.
I DON'T THINK THE DASHNEX PLUGIN LIKED MY UNINSTALLING WP QUICK CACHE. BUT REINSTALLING IT AFTER WP QUCIK CACHE HAD ALREADY BEEN UNINSTALLED WORKED FINE. THIS IS THE 2ND TIME I'VE HAD PROBLEMS WHEN QUICK CACHE HAS BEEN UNINSTALLED SO BE WARY OF IT. MAYBE BEST TO JUST DEACTIVATE IT & ONLY UNINSTALL IT ON A BRAND NEW SITE BEFORE INSTALLING ANY OTHER PLUGINS.
DIDN'T END UP NEEDING TO TWEAK THE PHP CODE.
I'm relatively new to PHPUnit and TDD, and I was wondering how I might test the following code:
class File
{
/**
* Write data to a given file
*
* #param string $file
* #param string $content
* #return mixed
*/
public function put($path, $content)
{
return file_put_contents($path, $content);
}
}
How can I test if the file was created WITHOUT actually creating the file (with PHPUnit obviously).
Thanks.
You can mock the file system for your unit tests by using a virtual file system like vfsStream with documentation here
EDIT
An example would be something like:
class FileTest extends \PHPUnit_Framework_TestCase
{
/**
* #var vfsStreamDirectory
*/
private $root;
/**
* set up test environmemt
*/
public function setUp()
{
$this->root = vfsStream::setup('exampleDir');
}
/**
* test that the file is created
*/
public function testFileIsCreated()
{
$example = new File();
$filename = 'hello.txt';
$content = 'Hello world';
$this->assertFalse($this->root->hasChild($filename));
$example->put(vfsStream::url('exampleDir/' . $filename), $content);
$this->assertTrue($this->root->hasChild($filename));
}
}
<?php
require_once BLOCKS_ROOT_ENGINE . "Zend/Loader/StandardAutoloader.php";
//require_once BLOCKS_ROOT_ENGINE."library/Zend/Config/Reader/Xml.php";
class Engine {
static public function start() {
$autoLoader = new Zend\Loader\StandardAutoloader(array(
'fallback_autoloader' => true,
));
// register our StandardAutoloader with the SPL autoloader
$autoLoader->register();
$config = new Engine_Zend_Config_Reader_Xml();
//echo $config->config->layout->default->head;
$root = new Core_Root_Blocks_Root();
}
}
The above is located in Engine/Engine.php
The Zend library is located in Engine/Zend/* The autoloader successfully finds the Xml class. But for some strange reason it can not find the interface it implements. what am i doing wrong.
Directory Structure
XML.php
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* #link http://github.com/zendframework/zf2 for the canonical source repository
* #copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Config\Reader;
use XMLReader;
use Zend\Config\Exception;
/**
* XML config reader.
*/
class Xml implements ReaderInterface
{
/**
* XML Reader instance.
*
* #var XMLReader
*/
protected $reader;
/**
* Directory of the file to process.
*
* #var string
*/
protected $directory;
/**
* Nodes to handle as plain text.
*
* #var array
*/
protected $textNodes = array(
XMLReader::TEXT,
XMLReader::CDATA,
XMLReader::WHITESPACE,
XMLReader::SIGNIFICANT_WHITESPACE
);
/**
* fromFile(): defined by Reader interface.
*
* #see ReaderInterface::fromFile()
* #param string $filename
* #return array
* #throws Exception\RuntimeException
*/
public function fromFile($filename)
{
if (!is_file($filename) || !is_readable($filename)) {
throw new Exception\RuntimeException(sprintf(
"File '%s' doesn't exist or not readable",
$filename
));
}
$this->reader = new XMLReader();
$this->reader->open($filename, null, LIBXML_XINCLUDE);
$this->directory = dirname($filename);
set_error_handler(
function ($error, $message = '', $file = '', $line = 0) use ($filename) {
throw new Exception\RuntimeException(sprintf(
'Error reading XML file "%s": %s',
$filename, $message
), $error);
}, E_WARNING
);
$return = $this->process();
restore_error_handler();
return $return;
}
/**
* fromString(): defined by Reader interface.
*
* #see ReaderInterface::fromString()
* #param string $string
* #return array|bool
* #throws Exception\RuntimeException
*/
public function fromString($string)
{
if (empty($string)) {
return array();
}
$this->reader = new XMLReader();
$this->reader->xml($string, null, LIBXML_XINCLUDE);
$this->directory = null;
set_error_handler(
function ($error, $message = '', $file = '', $line = 0) {
throw new Exception\RuntimeException(sprintf(
'Error reading XML string: %s',
$message
), $error);
}, E_WARNING
);
$return = $this->process();
restore_error_handler();
return $return;
}
/**
* Process data from the created XMLReader.
*
* #return array
*/
protected function process()
{
return $this->processNextElement();
}
/**
* Process the next inner element.
*
* #return mixed
*/
protected function processNextElement()
{
$children = array();
$text = '';
while ($this->reader->read()) {
if ($this->reader->nodeType === XMLReader::ELEMENT) {
if ($this->reader->depth === 0) {
return $this->processNextElement();
}
$attributes = $this->getAttributes();
$name = $this->reader->name;
if ($this->reader->isEmptyElement) {
$child = array();
} else {
$child = $this->processNextElement();
}
if ($attributes) {
if (!is_array($child)) {
$child = array();
}
$child = array_merge($child, $attributes);
}
if (isset($children[$name])) {
if (!is_array($children[$name]) || !array_key_exists(0, $children[$name])) {
$children[$name] = array($children[$name]);
}
$children[$name][] = $child;
} else {
$children[$name] = $child;
}
} elseif ($this->reader->nodeType === XMLReader::END_ELEMENT) {
break;
} elseif (in_array($this->reader->nodeType, $this->textNodes)) {
$text .= $this->reader->value;
}
}
return $children ?: $text;
}
/**
* Get all attributes on the current node.
*
* #return array
*/
protected function getAttributes()
{
$attributes = array();
if ($this->reader->hasAttributes) {
while ($this->reader->moveToNextAttribute()) {
$attributes[$this->reader->localName] = $this->reader->value;
}
$this->reader->moveToElement();
}
return $attributes;
}
}
ERROR
I think that you missed to set the include paths to Zend Framework library in your index.php file.
The autoloader class loads because you add require_once to the exact file with autoloader class definition. As I understand BLOCKS_ROOT_ENGINE constant is defined in your index.php.
Also I guess that you add somehow /opt/local/apache2/htdocs/blocks path to include paths in index.php - that is because autoloader is able to load Engine_Zend_Config_Reader_Xml class.
It is necessary to add BLOCKS_ROOT_ENGINE in your index.php to include paths list to allow autoloader find Zend\Config\Reader\ReaderInterface.
Not sure if this is your case, but once I ran into strange issues with my students with permission.
One student (with root permission) did something with folder permissions and we were not able to find out what - but files in that folder couldn't be accessible by php any more.
Even file_exists() returned false.
We finnaly resolve issue by copying whole folder, removing original one and renaming copied folder with original name.
Please check if your permissions are ok.
Well the issue had to do with out I set up my autoloader. I downloaded the skeleton ZF2 and found this file that was quite helpful for setting up
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* #link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
* #copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* This autoloading setup is really more complicated than it needs to be for most
* applications. The added complexity is simply to reduce the time it takes for
* new developers to be productive with a fresh skeleton. It allows autoloading
* to be correctly configured, regardless of the installation method and keeps
* the use of composer completely optional. This setup should work fine for
* most users, however, feel free to configure autoloading however you'd like.
*/
// Composer autoloading
if (file_exists('vendor/autoload.php')) {
$loader = include 'vendor/autoload.php';
}
$zf2Path = false;
if (is_dir('vendor/ZF2/library')) {
$zf2Path = 'vendor/ZF2/library';
} elseif (getenv('ZF2_PATH')) { // Support for ZF2_PATH environment variable or git submodule
$zf2Path = getenv('ZF2_PATH');
} elseif (get_cfg_var('zf2_path')) { // Support for zf2_path directive value
$zf2Path = get_cfg_var('zf2_path');
}
if ($zf2Path) {
if (isset($loader)) {
$loader->add('Zend', $zf2Path);
} else {
include $zf2Path . '/Zend/Loader/AutoloaderFactory.php';
Zend\Loader\AutoloaderFactory::factory(array(
'Zend\Loader\StandardAutoloader' => array(
'autoregister_zf' => true
)
));
}
}
if (!class_exists('Zend\Loader\AutoloaderFactory')) {
throw new RuntimeException('Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.');
}