Why can't I use 'require' with 'array_map'? - php

I've tried to include the contents from a list of files:
$files = [
'a.php',
'b.php',
];
$contents = array_map('require', $files);
But this didn't work. The error I get is:
Warning: array_map() expects parameter 1 to be a valid callback, function 'require' not found or invalid function name
Why is this and is there a way to make it work?

Because require isn't a function, it's a language construct.
You'll need to create a valid callback function to do the actual require, or use an autoloader

As everyone already noticed - it is a language construct.
You can try this
$includes = array('a.php', 'b.php');
array_map(function($file){
require $file;
}, $includes);

Agree with Mark Baker as it's not function , You can use _autoload() in case you are including class files.

use autoload or spl_autoload_register
to comfort work use namespaces
or you may use array_wallk without return value and anonunys function
`$files` = [
'a.php',
'b.php',
];
`$contents` = array_map(`$files`, function(`$el`){
require(`$el`);
});
//but foreach working faster:
foreach(`$files` as `$item`){
require(`$item`
);}`

Related

Automatically loading the classes

I've built "core" class that loads another classes, and I want to load automatically all the classes in spesific folder named "class", I've started to build something, but I have no idea if it's good.
In the construct function at the core class, I'm getting an array with the class names to load.
The construct function calls to function named _loadClasses, and in the _loadClasses function, I'm loading the classes by using require_once() fucntion.
Then at the top of the page, i'm adding public variable with the name of the class.
For example, "public $example;"
Now, what left is to create the ocject of the class, so that's what I did.
Example of the _loadClasses method:
require_once("class/user.class.php");
self::$user = new User();
Here comes the "automat" part.
I want the function _loadClasses to get an array, for example:
private function _loadClasses( $classesToLoad = array('security', 'is') );
and now, I'm using glob to load the classes from the folder "class", the name syntax of the classes files in the folder "class" is classname.class.php.
$classesArray = array(); // initialize the variable of all the web classes
$classesFiles = glob("class/*.php"); // gets all the web classes from the folder 'class'
foreach($classesFiles as $file) { // loop on the classes in the folder 'class'
$filename = explode('class/', $file);
$filename = $filename[1];
$className = explode('.class.php', $filename);
$className = $className[0];
if($className != 'index.php' || $className != 'database') {
array_push( $classesArray, $className ); // adds the class name into the array 'classesArray'
}
}
foreach( $classesArray as $className ) {
if( in_array($className, $classesToLoad) ) {
require_once("class/$className.class.php");
$classLines = file( "class/$className.class.php" );
$classNameLine = $classLines[1];
$classNameLine = explode(' ', $classNameLine);
$classObjectName = $classNameLine[1];
$classObjectName = explode(" ", $classObjectName);
self::$$classObjectName = new $classObjectName();
}
}
I need something like that, of curse it doesn't work, it's just to show you what I wanna do with an example. Thanks in advance.
For this particular approach I'd suggest something like:
// Your custom class dir
define('CLASS_DIR', 'class/')
// Add your class dir to include path
set_include_path(get_include_path().PATH_SEPARATOR.CLASS_DIR);
// You can use this trick to make autoloader look for commonly used "My.class.php" type filenames
spl_autoload_extensions('.class.php');
// Use default autoload implementation
spl_autoload_register();
To get started there's no need to implement a parent class autoloading functionality for "core" objects since they should only be aware of their role functionality. Use php standard library.
For this purposes you can use the __autoload() function. It will be called when you create a new object.
__autoload($class)
{
require 'dir/to/your/classes/'. $class. '.php'
}
You have to use one class per file and name the files the same as the class they describe.
"it doesn't work" is not a useful diagnostic. What doesn't work? What's the error message? Which line does it fail at? Looking at the code, the first loop, though a little messy (why do you have a file named index.php in this directory? Why don't you just glob for *.class.php?) should probably work OK. But the second loop is horrible.
To start with, why load all the filenames into an array in one loop, then use a second loop to load some of them? As for reading the class file to determine the object name....words fail me. Simply name it as the filename without the .class.php
$classesFiles = glob("class/*.class.php"); // gets all the web classes from the folder 'class'
foreach($classesFiles as $file) {
$prefix=array_shift(explode('.', basename($file)));
if (in_array($prefix, $classestoload)
&& !isset($this->$prefix)) {
if (!class_exists($prefix)) {
require($file);
}
$this->$prefix=new $prefix();
}
}
You could use the autoloader, but this will get messy if you integrate with other code which also uses the autoloader, but in a different way.

Class not found when creating a class with class name being a string

I need to create classes based on the parameter passed to a function. I do it this way:
public function index($source)
{
if(in_array($source, ModuleManager::getAllModules()))
{
$provider = new $source();
if($image)
{
return $provider->getAll(true);
}
else
{
return $provider->getAll(false);
}
}
}
Notice that on line 5 I'm trying to create an object of class $source which will definitely be available. I understand that the above code is actually an eval call. I'm using Laravel 5.2 and the above code returns:
FatalThrowableError in ProcReqController.php line 19:
Fatal error: Class 'Example' not found
In the above error Example can be any class that I made. Now if I hard code the value of $source then it works just fine.
What am I getting that error?
I believe what's happening is PHP gets confused when you try to instantiate a class whose class name is in a variable and it has to do with imports.
Solution 1
Set your $class variable to the fully qualified class name including the namespace and it should work.
In this way, new $class() should work even while including parenthesis.
Solution 2
After further testing, it seems when you instantiate a variable class, it always assumes global namespace.
With this in mind, you can use class_alias to alias each of your classes. In config/app.php, you can add each class to the aliases array.
'aliases' => [
....
'Example' => App\Example::class
]
The autoloader allows you to use classes without fully qualifying them... in the php interactive shell you'll have to manually include classes AND fully qualify them.
if you have a composer project, go to it's directory and do the following to load the Primal color classes:
set_include_path(getcwd().'/vendor/primal/color/lib/Primal/Color/');
include 'Color.php';
include 'Parser.php';
include 'RGBColor.php';
include 'HSVColor.php';
$hello = Primal\Color\Parser::parse('#666');
var_export($hello->toHSV());
/*
returns
Primal\Color\HSVColor::__set_state(array(
'hue' => 0,
'saturation' => 0,
'value' => 37.647058823529413,
'alpha' => 1,
))
*/
Remove the parentheses at the end of the instantiation call, I think.
Check out this php interactive shell session:
php > class Foo { };
php > $fooname = 'Foo';
php > $bar = new $fooname;
php > var_dump($bar);
object(Foo)#2 (0) {
}
src: https://stackoverflow.com/a/4578350/2694851

Laravel Mail - PathToFile variable not found

I am writing this simple code to send a mail with attachment, however, I am not able to pass the path to the file variable.
$pathToFile = "Sale-".$id.".csv";
Mail::send(array('html' => 'sales.invoice_template'), $data, function($message)
{
$message->to('test#test.com'); // dummy email
$message->attach($pathToFile);
});
The above code throws:
Undefined variable: pathToFile
Also, I tried passing a variable (added $pathToVariable with $message in above closure) to the closure but it throws following error:
Missing argument 2 for SaleController::{closure}()
It basically doesn't identify any variable outside the closure. Can anyone please help me out here?
You can try this:
$pathToFile = "Sale-".$id.".csv";
Mail::send(array('html' => 'sales.invoice_template'), $data, function($message) use ($pathToFile)
{
$message->to('test#test.com'); // dummy email
$message->attach($pathToFile);
});
The instruction:
use ($pathToFile)
...allows you to use your variable in the closure.
When referencing $pathToFile within your closure, the script is looking for $pathToFile to be declared within the closure. As no declaration exists, you see the undefined variable error.
Any variable used inside a function is by default limited to the local function scope.
Source: http://www.php.net/manual/en/language.variables.scope.php
To fix it you should be able to pass $pathToFile into your closure, e.g.:
Mail::send(array('html' => 'sales.invoice_template'), $data, function($message, $pathToFile)
{
$message->to('test#test.com'); // dummy email
$message->attach($pathToFile);
});

Mustache php gettext()

I am experimenting with kostache, "mustache for kohana framework".
Is there any way I can use simple PHP functions in mustache template files.
I know logic and therefore methods are against logic-less design principle, but I'm talking about very simple functionality.
For example:
gettext('some text') or __('some text')
get the base url; in kohana -> Url::site('controller/action')
Bobthecow is working on an experimental feature that will allow you to call a function as a callback.
Check out the higher-order-sections branch of the repository and the ticket to go with it.
You could use "ICanHaz" http://icanhazjs.com/
and then you can declare your mustache templates as
<script id="welcome" type="text/html">
<p>Welcome, {{<?php echo __('some text') ?>}}! </p>
</script>
Well, you can do this now with Bobthecow's implementation of Mustache Engine. We need anonymous functions here, which are passed to the Template Object along with other data.
Have a look at the following example:
<?php
$mustache = new Mustache_Engine;
# setting data for our template
$template_data = [
'fullname' => 'HULK',
'bold_it' => function($text){
return "<b>{$text}</b>";
}
];
# preparing and outputting
echo $mustache->render("{{#bold_it}}{{fullname}}{{/bold_it}} !", $template_data);
In the above example, 'bold_it' points to our function which is pasalong withwith other data to our template. The value of 'fullname' is being passed as a parameter to this function.
Please note that passing parameters is not mandatory in Mustache. You can even call the php function wothout any parameters, as follows:
<?php
# setting data for our template
$template_data = [
'my_name' => function(){
return 'Joe';
}
];
# preparing and outputting
echo $mustache->render("{{my_name}} is a great guy!", $template_data); # outputs: Joe is a great guy!
Credits: http://dwellupper.io/post/24/calling-php-functions-for-data-in-mustache-php

PHP Hook Function

Can I basically do something like:
register_function_hook('myFunctionHook');
so then when any function is run:
functionA(); //The hook runs myFunctionHook();
anoterFunction(); //The hook runs myFunctionHook();
Class::functionA(); //The hook runs myFunctionHook();
Does such a thing exist?
-- Edit --
What I want to do is to get a breakdown of durations of each function. Ie. Performance Tuning. I want to get an idea of what takes all the time without installing xDebug on my Apache server, however I don't know if it is possible.
It's possible with register_tick_function(), also check this comment on the PHP manual:
$script_stats = array();
$time = microtime(true);
function track_stats(){
global $script_stats,$time;
$trace = debug_backtrace();
$exe_time = (microtime(true) - $time) * 1000;
$func_args = implode(", ",$trace[1]["args"]);
$script_stats[] = array(
"current_time" => microtime(true),
"memory" => memory_get_usage(true),
"file" => $trace[1]["file"].': '.$trace[1]["line"],
"function" => $trace[1]["function"].'('.$func_args.')',
"called_by" => $trace[2]["function"].' in '.$trace[2]["file"].': '.$trace[2]["line"],
"ns" => $exe_time
);
$time = microtime(true);
}
declare(ticks = 1);
register_tick_function("track_stats");
// the rest of your project code
// output $script_stats into a html table or something
This "hooks" to everything, not just functions but I think it fits your purpose.
No, its not possible the way you like
But You can achieve something close with inheritance.
class Vehicle {
function __construct() {
$this->hookFunction();
}
function hookFunction() {
//
}
}
class Car extends Vehicle {
}
Class Toyota extends Car {
}
new Toyota(); // will you hook function
// this exclude static call to member functions, or other inline functions.
What you looking for is called profiler. And PQP looks like one, which is standalone.
Instead of polluting the code, you should use a real Profiler, like that one provided by xdebug
Not sure if the Topic Starter needs this anymore, but perhaps others can still benefit from this.
There is a PHP lib, written completely in PHP, that allows you to do exactly what you want.
Here's an article about how it works, including the source code:
http://phpmyweb.net/2012/04/26/write-an-awesome-plugin-system-in-php/
It allows you to register a function from a class to be hooked. So it basically executes your code first, and then you determine wether you want to call the original function too after your code has been executed.

Categories