Today im asking for something, that i cant believe to find on the web.
Im trying to make a javascript function, which allows me to give a filename/pathname as a parameter and the function returns javascript code which will be executed/initialized immediatly - just like PHP's include or require.
Now i tried several technics to realize my approach but i just dont hit the right spot so i might be asking: is it even possible to do that in JS?
Thanks in advance
There are many libraries and standards that exist merely for this purpose. In Node.js, there is a CommonJS implementation built-in. If you want to export a piece of code from a file, or the entire contents of a file, you can attach it to the module.exports or simply exports object. You may then use require('./path/to/file'); to require it in a separate piece of code.
Some libraries try to borrow this approach and implement it on the client side, browserify being one of them.
However, it would do you better to have a look at the best client-side library of them all: RequireJS
RequireJS implements what is called the Asynchronous Module Definition pattern, which loads in all the project dependencies in a top-level file. It gives you access to two functions, require() and define() that take a number of paramaters. The first function simply requires dependencies, while the second one defines a module and name's that modules dependencies, like so:
A top-level file that defines no modules, only uses them:
require(['jquery', 'underscore', 'backbone'], // dependencies
function($, _, Backbone) { // dependencies are passed into callback
$('div').append('Test'); // dependencies are available to this file
}
);
A module:
define(['jquery', 'underscore', 'backbone'], // this module's dependencies
function($, _, Backbone) { // dependencies are made available
var MyModule = {};
return MyModule; // this return statement essentially defines the module
}
);
The great thing about this approach is that by having a top level file and several modules that all define their own dependencies, you only ever need to reference a module if it actually is a dependency of that file, so your top-level stuff is always neat and uncluttered and usually consists of no more than an initialize function.
RequireJS also comes with an optimizer called R.js that can minify and concatenate your scripts in the right order using UglifyJS or Google's Closure Compiler. It's worth checking out.
Related
How to include a specific function based on requirement from a php file containing various function definitions.
eg. PHP file functions.php contains 3 functions a(), b() and c()
I have to use require_once('/f/functions.php') in other.php file to use function c.
What could i do to only include the function c in file other.php file using require_once() function and avoid other functions not to be included ?
There is no built in way to do it. Although there are ways to go around it if you do it for the sport.
While this is highly not recommended. Really, just dont do it... here's how:
1) Read the file as text.
2) find the function block and extract it
3) run it through eval.
This will cause any global state set up in the file to not be run. Which you may or may not want.
SuperClosure does something similar I believe to serialize closures, which by default php does not support.
One could leverage the PHP7 abstract syntax tree to also includes related functions. For example, if there are three functions defined - A, B and C. A uses B internally. If you include A, you would want to also include B.
This wont be more performant than just including the whole file, but feel free to prove me wrong with benchmarks.
You might be interested in namespaces. Both classes and functions support it.
You cannot, period. PHP doesn't have any sort of module system. To "include functions", all you can do is execute a source code file (what include will do), which will by the act of executing the code in the file define those additional functions, or anything else that's in the file. You cannot selectively pick only certain parts of the code to run.
I'm trying to create a composer package & i understand the basic workflow like of creating composer.json, auto loading and creating classes under src directory.
There is one small programming misunderstanding i have is that almost all the other packages i'm reading has interfaces and a class implementing them. I don't understand need of interfaces in this context and why we need them. I have never used interface or i'm not sure if i understand its general use case. It would be nice if someone can help me understand it.
Beside the other question i had in context to composer is how do i test / run a composer project whilst i create it?
Beside this projects that i'm referring has a command directory inside src i don't understand significance of this or its use case too. I guess it has something to do with symfony php console command.
Also there is a bin directory at source, now how is that useful.
Sorry if i'm being naive here but i'm just trying to understand which components fall where and why is it like that. I couldn't find a composer tutorial online past creating composer.json
You are asking a lot of questions at once, but I'll try to at least address interfaces, since I believe that's the most important one.
Interfaces are mostly used with Dependency Injection. They define methods without actually caring how the methods are actually implemented. A class may depend on an interface instead of an actual (concrete) class, which allows an easy way to swap components. Below is an example of how one might use interfaces.
interface PostsInterface {
public function getPosts();
}
class JsonPostFetcher implements PostsInterface {
public function getPosts() {
// Load posts from JSON files here
}
}
class MySqlPostFetcher implement PostsInterface {
public function getPosts {
// Load posts from a MySQL database
}
}
class Blog {
public function __construct(PostsInterface $fetcher) {
// Load posts from either JSON or a database
// depending on which fetcher is provided
$posts = $fetcher->getPosts();
}
}
Using this method anyone can now write their own code to provide posts from an external API ApiPostFetcher, SQLite Database SqlitePostFetcher, Serialized PHP files SerializedPostFetcher etc. One could even write a DymmyPostFetcher that simply returns a pretermined array of posts that could be used for testing purposes. You can then use any implementation of PostsInterface in your blog like in the following example.
$fetcher = new JsonPostFetcher(); // You can provide different fetchers here.
$blog = new Blog($fetcher);
If you're unfamiliar with dependency injection, I highly recommend learning it, since it will be especially useful in writing modular code.
GOAL:
I'm interested in generating a DOT Format description of the class dependencies in a PHP program.
IDEA:
It shouldn't be hard to write a CodeSniffer "sniff" that can detect (and emit DOT records for) the following patterns in PHP source:
class SomeClassName extends BasicClassName { // SomeClassName refers to BasicClassName
...
new OtherClassName(); // SomeClassName refers to OtherClassName
ThisClassName::some_method(); // SomeClassName refers to ThisClassName
ThatClassName::$some_member; // SomeClassName refers to ThatClassName
RandomClassName::some_constant; // SomeClassName refers to RandomClassName
...
}
But I haven't found any published sniffs to emit this information (and any other patterns indicating a "real" class dependency relationship that I may have missed).
NOTE:
I specifically do not care about PHP's include() and require() statements (whose behavior I'm not convinced is even well-defined). For the purposes of this question let's assume that all PHP class resolution is handled via autoloading, and that we're looking to use only static code analysis to build the class dependency diagram.
EDIT:
Unfortunately, I see no general way to deal with the following:
class ThatClassName {
...
function generateClassName() {
// something too complicated to analyze statically...
}
function foo() {
$name = $this->generateClassName();
$instance = new $name; // ThatClassName refers to ... what?
...
}
...
}
But of course it would be possible to represent this scenario in a dependency graph by showing ThatClassName with a dependency on the generateClassName() method - perhaps shown with parens to make the method name easily distinguishable from a class name. And it probably wouldn't be a bad idea to establish a convention whereby any method which generates a class name dynamically must contain an annotation (in the associated comment) which indicates every class name which might possibly be generated - these "documented dynamic dependencies" could then be automatically included in the dependency graph.
This isn't really what PHP_CodeSniffer is designed to do; specifically because the sniffs are not supposed to output data or write to files. But, there is certainly nothing stopping you from doing this inside a sniff. It's just PHP code after all and it doesn't need to report any errors or warnings.
I haven't come across any sniffs that are doing anything like you describe, so I think you'd have to write a new one.
If you want to create a new sniff, I'd recommend starting with an abstract scope sniff. This allows you to look for T_NEW and T_DOUBLE_COLON tokens inside T_CLASS tokens. Here is an example.
Or, if you also want to look into global functions and other code outside classes, you can just look for T_NEW and T_DOUBLE_COLON tokens inside a regular sniff
If you're not sure how to get started or you just want some help writing the sniff, contact me and I can help write this with you. I'd just need to know what output you'd want for each case found, or I can just use something basic. If you want a hand, my email is: gsherwood at squiz dot net
I wrote a tool for this: PhpDependencyAnalysis.
This is an extandable static code analysis for object-oriented PHP-Projects (>= 5.3.3) based on namespaces. It creates dependency graphs on customizable levels, e.g. on package-level or on class-level. Thus, it's usable to declare dependencies in general, but it's also usable to perform a detection of violations between layers in a tiered architecture according to compliance with Separation of Concerns, Law of Demeter and Acyclic Dependencies Principle.
You can also change the output format to DOT.
Just check PhpDependencyAnalysis on GitHub.
I have asked a similar question to this one already but I think it was badly worded and confusing so hopefully I can make it a bit clearer.
I am programming in a native Linux file system.
I have a class of HelpTopic:
class HelpTopic extends Help{}
And a class of Help:
class Help{}
Now I go to include HelpTopic:
include('HelpTopic.php');
And even though I do not instantiate HelpTopic with new HelpTopic() PHP (in a Linux file system) still reads the class signature and tries to load Help with HelpTopic.
I do not get this behaviour from a cifs file system shared from a Windows System.
My best guess is that there is some oddity with Linux that causes PHP to react this way but not sure what.
Does anyone have any ideas or solutions to this problem?
EDIT:
I have added my loading function to show what I am doing:
public static function import($cName, $cPath = null){
if(substr($cName, -2) == "/*"){
$d_name = ROOT.'/'.substr($cName, 0, -2);
$d_files = getDirectoryFileList($d_name, array("\.php")); // Currently only accepts .php
foreach($d_files as $file){
glue::import(substr($file, 0, strrpos($file, '.')), substr($cName, 0, -2).'/'.$file);
}
}else{
if(!$cPath) $cPath = self::$_classMapper[$cName];
if(!isset(self::$_classLoaded[$cName])){
self::$_classLoaded[$cName] = true;
if($cPath[0] == "/" || preg_match("/^application/i", $cPath) > 0 || preg_match("/^glue/i", $cPath) > 0){
return include ROOT.'/'.$cPath;
}else{
return include $cPath;
}
}
return true;
}
}
I call this by doing glue::inmport('application/models/*'); and it goes through including all the models in my app. Thing is PHP on a linux based file system (not on cifs) is trying to load the parents of my classes without instantiation.
This is a pretty base function that exists in most frameworks (in fact most of this code is based off of yiis version) so I am confused why others have not run into this problem.
And even though I do not instantiate HelpTopic with new HelpTopic() PHP still reads the class signature and tries to load Help with HelpTopic.
Correct.
In order to know how to properly define a class, PHP needs to resolve any parent classes (all the way up) and any interfaces. This is done when the class is defined, not when the class is used.
You should probably review the PHP documentation on inheritance, which includes a note explaining this behavior:
Unless autoloading is used, then classes must be defined before they are used. If a class extends another, then the parent class must be declared before the child class structure. This rule applies to class that inherit other classes and interfaces.
There are two ways to resolve this problem.
First, add a require_once at the top of the file that defines the child class that includes the file defining the parent class. This is the most simple and straight-forward way, unless you have an autoloader.
The second way is to defione an autoloader. This is also covered in the documentation.
The ... thing ... you're using there is not an autoloader. In fact, it's a horrible abomination that you should purge from your codebase. It's a performance sap and you should not be using it. It also happens to be the thing at fault.
We don't have the definition of getDirectoryFileList() here, so I'll assume it uses either glob() or a DirectoryIterator. This is the source of your problem. You're getting the file list in an undefined order. Or, rather, in whatever order the underlying filesystem wants to give to you. On one machine, the filesystem is probably giving you Help.php before HelpTopic.php, while on the other machine, HelpTopic.php is seen first.
At first glance, you might think this is fixable with a simple sort, but it's not. What happens if you create a Zebra class, and then later need to create an AlbinoZebra that inherits from it? No amount of directory sorting is going to satisfy both the "load ASCIIbetical" and the "I need the Zebra to be first" requirements.
Let's also touch on the performance aspect of the problem. On every single request, you're opening a directory and reading the list of files. That's one hell of a lot of stat calls. This is slow. Very slow. Then, one by one, regardless of whether or not you'll need them, you're including the files. This means that PHP has to compile and interpret every single one of them. If you aren't using a bytecode cache, this is going to utterly destroy performance if the number of files there ever grows to a non-trivial number.
A properly constructed autoloader will entirely mitigate this problem. Autoloaders run on demand, meaning that they'll never attempt to include a file before it's actually needed. Good-performing autoloaders will know where the class file lives based on the name alone. In modern PHP, it's accepted practice to name your classes such that they'll be found easily by an autoloader, using either namespaces or underscores -- or both -- to map directory separators. (Meaning namespace \Models; class Help or class Models_Help would live in Models/Help.php)
Unfortunately most examples won't be useful here, as I don't know what kind of weird things your custom framework does. Take a peek at the Zend Framework autoloader, which uses prefix registration to point class prefixes (Model_) at directories.
PHP's __autoload() (documentation) is pretty interesting to me. Here's how it works:
You try to use a class, like new Toast_Mitten()(footnote1)
The class hasn't been loaded into memory. PHP pulls back its fist to sock you with an error.
It pauses. "Wait," it says. "There's an __autoload() function defined." It runs it.
In that function, you have somehow mapped the string Toast_Mitten to classes/toast_mitten.php and told it to require that file. It does.
Now the class is in memory and your program keeps running.
Memory benefit: you only load the classes you need. Terseness benefit: you can stop including so many files everywhere and just include your autoloader.
Things get particularly interesting if
1) Your __autoload() has an automatic way of determining the file path and name from the class name. For instance, maybe all your classes are in classes/ and Toast_Mitten will be in classes/toast_mitten.php. Or maybe you name classes like Animal_Mammal_Weasel, which will be in classes/animal/mammal/animal_mammal_weasel.php.
2) You use a factory method to get instances of your class.
$Mitten = Mitten::factory('toast');
The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"
Therefore, you can start out using a generic mitten throughout your code, and when the day comes that you need special behavior for toast, you just create that class and bam! - your code is using it.
My question is twofold:
(Fact) Do other languages have similar constructs? I see that Ruby has an autoload, but it seems that you have to specify in a given script which classes you expect to use it on.
(Opinion) Is this too magical? If your favorite language doesn't do this, do you think, "hey nifty, we should have that" or "man I'm glad Language X isn't that sloppy?"
1 My apologies to non-native English speakers. This is a small joke. There is no such thing as a "toast mitten," as far as I know. If there were, it would be a mitten for picking up hot toast. Perhaps you have toast mittens in your own country?
Both Ruby and PHP get it from AUTOLOAD in Perl.
http://perldoc.perl.org/perltoot.html#AUTOLOAD:-Proxy-Methods
http://perldoc.perl.org/AutoLoader.html
Note that the AutoLoader module is a set of helpers for common tasks using the AUTOLOAD functionality.
Do not use __autoload(). It's a global thing so, by definition, it's somewhat evil. Instead, use spl_autoload_register() to register yet another autoloader to your system. This allows you to use several autoloaders, what is pretty common practice.
Respect existing conventions. Every part of namespaced class name is a directory, so new MyProject\IO\FileReader(); should be in MyProject/IO/FileReader.php file.
Magic is evil!
The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"
Rather such tricky code, use simple and verbose one:
try {
$mitten = new ToastMitten();
// or $mitten = Mitten::factory('toast');
} catch (ClassNotFoundException $cnfe) {
$mitten = new BaseMitten();
}
I think this feature comes in very handy, and I have not seen any features like it else where. Nor have I needed these features else where.
Java has something similar. It's called a ClassLoader. Probably other languages too, but they stick with some default implementation.
And, while we're at this. It would have been nice if __autoload loaded any type of symbols, not just classes: constants, functions and classes.
See Ruby's Module#const_missing
I just learned this: Ruby has a method on Module called const_missing that gets called if you call Foo::Bar and Bar isn't in memory yet (although I suppose that Foo has to be in memory).
This example in ruby-doc.org shows a way to use that to implement an autoloader for that module. This is in fact what Rails uses to load new ActiveRecord model classes, according to "Eloquent Ruby" by Russ Olsen (Chapter 21, "Use method_missing for flexible error handling", which also covers const_missing).
It's able to do this because of the "convention over configuration" mindset: if you reference a model called ToastMitten, if it exists, it will be in app/models/toast_mitten.rb. If you could put that model any place you wanted, Rails wouldn't know where to look for it. Even if you're not using Rails, this example, and point #1 in my question, shows how useful it can be to follow conventions, even if you create them yourself.