I am using these require statements in my root folder of project directory (in index.php).
require("./models/college/collegeModel.php");
require("./routes/routes.php");
require("./controllers/college/collegeController.php");
require("./controllers/home/homeController.php");
require("./controllers/login/loginController.php");
require("./controllers/logout/logoutController.php");
require("./controllers/public/publicController.php");
require("./lib/util.php");
and now I am trying to use composer autoload to load on demand by using composer.json file to remove all above require with single one :
require("./vendor/autoload.php");
My composer.json file is as follows
{
"name": "vermajnv/web",
"authors": [
{
"name": "vermajnv",
"email": "nayanrahul.jnv#gmail.com"
}
],
"require": {},
"autoload": {
"classmap": ["models/college", "controllers/college",
"controllers/home", "controllers/login", "controllers/logout",
"controllers/public", "lib/", "routes/"]
}
}
It works fine if I remove "lib/" and "routes/"
please provide me proper solution for this problem I'll be thankful to all.
oho.. I got what I was doing wrong
actually the util.php and routes.php does not contains a class to initialize the autoload_classmap.php
my util.php was before like this :
<?php
public function baseUrl($url) {
$contaxtPath = "/" . explode("/", $_SERVER['REQUEST_URI'])[1];
return $contaxtPath . $url;
}
public function redirect($to) {
$url = baseUrl($to);
header("Location:" . $url, 302);
}
Now I just make it wrapped with a class with static methods and these methods can be access through HTMLutill::
<?php
class HTMLutil {
// static method inside a class are visible every where without creating instance of class (HTMLutil) we can access it by HTML::baseUrl();
public static function baseUrl($url) {
$contaxtPath = "/" . explode("/", $_SERVER['REQUEST_URI'])[1];
return $contaxtPath . $url;
}
public static function redirect($to) {
$url = self::baseUrl($to);
header("Location:" . $url, 302);
}
}
Now my app is working fine.
happy coding guys..
Related
I am trying to make my own mock MVC framework as a project. This is my first time using composer outside of using it for requiring dependencies for Laravel. The actual autoloading works well, but when I try to autoload the helpers.php something weird happens. The file is autoloaded(if I change the path of the file I get the file not found error) but the contents inside it are not. In another file I try to call any function from the helpers.php file and I get
Fatal error: Uncaught Error: Call to undefined function
This is the file structure of the example
composer.json
App
Utils
helpers.php
public
index.php
This is my composer.json file:
{
"name": "admin/projecttest",
"autoload": {
"psr-4": {
"Admin\\Projecttest\\": "src/",
"App\\": "App/"
},
"files": [
"App/Utils/helpers.php"
]
},
"minimum-stability": "dev"
}
The helpers.php
<?php
namespace App\Utils;
use Leonlav77\Frejmcore\helpers\DotEnv;
function config($config){
$config = explode(".", $config);
$file = $config[0];
$configFile = require "../config/$file.php";
return $configFile[$config[1]];
}
function env($key, $default = null){
(new DotEnv(__DIR__ . '../../.env'))->load();
return getenv($key) ? getenv($key) : $default;
}
function baseDir(){
return __DIR__ . "/../";
}
index.php (where I call the function from the helper)
<?php
require "../vendor/autoload.php";
var_dump(function_exists('baseDir'));
var_dump(baseDir());
from the function_exists I get false
As the user Foobar suggested the the problem was in the namespace of the helpers.php . Since it had a namespace the functions also had a namespace, so insted of baseDir() I needed to use App/Utils/baseDir().
The solution was to simply remove the namespace from helpers.php
How can I autoload helper functions (outside of any class)? Can I specify in composer.json some kind of bootstrap file that should be loaded first?
You can autoload specific files by editing your composer.json file like this:
"autoload": {
"files": ["src/helpers.php"]
}
(thanks Kint)
After some tests, I have came to the conclusions that adding a namespace to a file that contains functions, and setting up composer to autoload this file seems to not load this function across all the files that require the autoload path.
To synthesize, this will autoload your function everywhere:
composer.json
"autoload": {
"files": [
"src/greetings.php"
]
}
src/greetings.php
<?php
if( ! function_exists('greetings') ) {
function greetings(string $firstname): string {
return "Howdy $firstname!";
}
}
?>
...
But this will not load your function in every require of autoload:
composer.json
"autoload": {
"files": [
"src/greetings.php"
]
}
src/greetings.php
<?php
namespace You;
if( ! function_exists('greetings') ) {
function greetings(string $firstname): string {
return "Howdy $firstname!";
}
}
?>
And you would call your function using use function ...; like following:
example/example-1.php
<?php
require( __DIR__ . '/../vendor/autoload.php' );
use function You\greetings;
greetings('Mark'); // "Howdy Mark!"
?>
Class not found, apparently. I've tried various things but nothing works.
Composer:
"autoload": {
"psr-4": {
"App\\": "application/"
}
}
File structure:
https://i.imgur.com/h9wOEqI.png
<?php
namespace App\Library\Classes;
defined('START') or exit('We couldn\'t process your request right now.');
class Application
{
private static $libraries = array();
public static function get($library) {
if (isset(self::$libraries[$library]) && isset(self::$classes[$library])) {
return self::$libraries[$library];
}
$fixedLibrary = str_replace('.', '/', $library);
$file = ROOT . '/application/library/classes/' . strtolower($fixedLibrary) . '.php';
self::$libraries[$library] = $library;
$declared = get_declared_classes();
$workingClass = end($declared);
self::$libraries[$library] = new $workingClass();
return self::$libraries[$library];
}
}
?>
Error is on this line:
Application::get('test')->test();
Yet, if I change it to this, it works:
include ROOT . '/application/Library/Application.php';
App\Library\Classes\Application::get('test')->test();
The PSR4 is not built-in part or PHP, you need an implementation of autoloader to use this standard such as provided by the Composer.
When you install or update depedencies, composer generates the relevant code of autoloading, but you can directly update it by the command dump-autoload, as #jibsteroos said. Next you should explicitly include the file vendor/autoload.php in the entry point of your application.
Also, error message says about class Application, but you should add the use statement at first:
use App\Library\Classes\Application;
Application::get('test')->test();
Or use the fully qualified class name (class name with namespace prefix):
\App\Library\Classes\Application::get('test')->test();
I'm new to PHP and not really familiar with using git.
I got this library:
https://github.com/CKOTech/checkout-php-library
and I wanna run the sample code here:
https://github.com/CKOTech/checkout-php-library/wiki/Tokens
I know the code may not work perfectly for you cuz you would need a secret key from the provider, however, I don't need general errors like " cannot find class ApiClient"
what I did is simply including the autoloader in my index.php file, is that all what I have to do to use an Autoloader? does it have to do anything with composer.json?
Thanks a ton for the help in advance.
Autoloader.php:
<?php
function autoload($className)
{
$baseDir = __DIR__;
$realClassName = ltrim($className, '\\');
$realClassName = str_replace('\\',DIRECTORY_SEPARATOR,$realClassName );
$fileName = '';
$includePaths = $baseDir.DIRECTORY_SEPARATOR.$realClassName. '.php';
if ( $file = stream_resolve_include_path($includePaths) ) {
if (file_exists($file)) {
require $file;
}
}elseif(preg_match('/^\\\?test/', $className)) {
$fileName = preg_replace('/^\\\?test\\\/', '', $fileName);
$fileName = 'test' . DIRECTORY_SEPARATOR . $fileName;
include $fileName;
} else {
$classNameArray = explode('_', $className);
$includePath = get_include_path();
set_include_path($includePath);
if (!empty($classNameArray) && sizeof($classNameArray) > 1) {
if (!class_exists('com\checkout\packages\Autoloader')) {
include 'com'.DIRECTORY_SEPARATOR.'checkout'.DIRECTORY_SEPARATOR.'packages'.DIRECTORY_SEPARATOR.'Autoloader.php';
}
}
}
}
spl_autoload_register('autoload');
If you want to use an autoloader to make your life measurably better:
Use namespaces/PSR4.
Use Composer.
So let's say I'm working on project foo, within my working directory [let's just say it's /] I make a folder named /src/ and inside is /src/FooClient.php. It contains:
<?php
namespace sammitch\foo;
class FooClient {}
While in / I run composer init and accept all of the defaults, because typing out the simple JSON config file that that generates is tedious. Now I have a composer.json that looks like:
{
"name": "Sammitch/foo",
"authors": [
{
"name": "Sammitch",
"email": "sammitch#sam.mitch"
}
],
"require": {}
}
All we need to do now is add a section to the end:
"autoload": {
"psr-4": {
"sammitch\\foo\\": "src/"
}
}
Now to make Composer do it's magic and make the autoloader just run composer dumpautoload. When this runs Composer will create the /vendor/ folder and the autoloader.
Now all we need to do is:
<?php
require('vendor/autoload.php');
use \sammitch\foo\Client as FooClient()
$c = new FooClient();
Now not only do you have a top-tier autoloader, but you're also set up to start using Composer packages and leveraging all that good stuff from Packagist.
I'm using composer in my latest project and mapping my function like this
"require": {
...
},
"require-dev": {
...
},
"autoload": {
"psr-4": {
...
},
"files": [
"src/function/test-function.php"
]
}
I imagine there will be a lot of files in a folder function, ex : real-function-1.php, real-function-2.php, etc. So, can composer call all the files in the folder function ? i lazy to use
"files": [
"src/function/real-function-1.php",
"src/function/real-function-2.php",
..,
"src/function/real-function-100.php",
]
Is there any lazy like me...
If you can't namespace your functions (because it will break a bunch of code, or because you can't use PSR-4), and you don't want to make static classes that hold your functions (which could then be autoloaded), you could make your own global include file and then tell composer to include it.
composer.json
{
"autoload": {
"files": [
"src/function/include.php"
]
}
}
include.php
$files = glob(__DIR__ . '/real-function-*.php');
if ($files === false) {
throw new RuntimeException("Failed to glob for function files");
}
foreach ($files as $file) {
require_once $file;
}
unset($file);
unset($files);
This is non-ideal since it will load every file for each request, regardless of whether or not the functions in it get used, but it will work.
Note: Make sure to keep the include file outside of your /real-function or similar directory. Or it will also include itself and turn out to be recursive function and eventually throw a memory exception.
There's actually a better way to do this now without any custom code. You can use Composer's classmap feature if you're working with classes. If you're working with individual files that contain functions then you will have to use the files[] array.
{
"autoload": {
"classmap": ["src/", "lib/", "Something.php"]
}
}
This whole process can be completely automated while still performing relatively well.
With the following package.json (note the absence of an autoload entry, you could however add others)
{
"scripts": {
"pre-autoload-dump": "\\MyComponentAutoloader::preAutoloadDump"
}
}
And then...
<?php
class MyComponentAutoloader
{
public static function preAutoloadDump($event): void
{
$optimize = $event->getFlags()['optimize'] ?? false;
$rootPackage = $event->getComposer()->getPackage();
$dir = __DIR__ . '/../lib'; // for example
$autoloadDefinition = $rootPackage->getAutoload();
$optimize
? self::writeStaticAutoloader($dir)
: self::writeDynamicAutoloader($dir);
$autoloadDefinition['files'][] = "$dir/autoload.php";
$rootPackage->setAutoload($autoloadDefinition);
}
/**
* Here we generate a relatively efficient file directly loading all
* the php files we want/found. glob() could be replaced with a better
* performing alternative or a recursive one.
*/
private static function writeStaticAutoloader($dir): void
{
file_put_content(
"$dir/autoload.php",
"<?php\n" .
implode("\n", array_map(static function ($file) {
return 'include_once(' . var_export($file, true) . ');';
}, glob("$dir/*.php"))
);
}
/**
* Here we generate an always-up-to-date, but slightly slower version.
*/
private static function writeDynamicAutoloader($dir): void
{
file_put_content(
"$dir/autoload.php",
"<?php\n\nforeach (glob(__DIR__ . '/*.php') as \$file)\n
include_once(\$file);"
);
}
}
Things to note:
preAutoloadDump takes care of adding the autoload.php entrypoint to composer.
autoload.php is generated every time the autoloader is dumped (e.g. composer install / composer update / composer dump-autoload)
when dumping an optimised autoloader (composer dump-autoload --optimize), only the files found at that point will be loaded.
you should also add autoload.php to .gitignore