I have yet to find a clear answer on how PHP namespaces work in relation to the file strucutre
If I have some code say
<?PHP
namespace Go/Project
Use Foo/Bar/Dog
class cat extends dog
{
.....
}
?>
What does the file structure for something like this look like and do I need to reflect what I am doing in the namspaces and the imports in the file structure or do I need to add some include()s in there.
It depends on your autoloader.
Some frameworks use standard of PSR-0, some not use. You can write your application without any autoloader and write namespaces independent of your files structure.
For example you can declare namespace Acme/Foo/Bar/Do/For/Me/Some/Thing in index.php of your DocumentRoot and all classes declared in this file will be stored under this namespace.
But if you want to not write in every file require statements for your files you may want to write your autoloader function and make dependence between files structure and namespaces structure.
Related
This is what I have at hand:
//Person.php
namespace Entity;
class Person{
}
User file:
//User.php
use Entity\Person;
$person = new Person;
Here, it fails if I don't include the Person.php file. If I include it, the everything works fine. Do I absolutely require to include the file even when using namespaces? If at all we need to include/require files, then how can namespaces be effectively used? Also, can we maintain folder structure by nesting namespaces?
The answer to your question is "yes and no".
Indeed the code implementing class Person has to be included, otherwise the class is not defined and cannot be used. Where should the definition come from, when the code is not included? The php interpreter cannot guess the classes implementation. That is the same in all programming languages, by the way.
However there is something called Autoloading in php. It allows to automatically include certain files. The mechanism is based on a mapping of class names to file names. So in the end it boils down to php searching through a folder structure to find a file whos name suggests that it implements a class currently required in the code it executes.
But don't get this wrong: that still means the file has to be included. The only difference is: the including is done automatically, so without you specifying an explicit include or require statement.
Yes, you need to include every file.
A very good example can be found here on effective usage of namespaces.
With PSR-0 autoloading, the namespace has to be the same as the folder in which the class is, file the filename has to be the same as the classname. This gives you very simple and effective autoloading with composer for example.
I'm a beginner to L5. I read the documentation about extending classes but i didn't find any information about where to put the file in which i extend the class.
**I have to extend Str.php class. I have read that in L4 it had to be done by putting that file under App/folder but i didn't find that folder in L5.
So please can you tell me how can i do that?
This is the information i have now:
First, you must find where the class file is. We will be extending the Str class, which is under vendor/laravel/framework/src/Illuminate/Support. Note that you can also find this class under the aliases key in app/config/ app.php.
Now create a new folder called lib under app/folder. This folder will hold our class extensions. Because the Str class is grouped under the folder Support, it is suggested that you create a new folder named Support under lib too.
Now create a new file named Str.php under app/lib/Support, which you've just created:
But this is for L4
That's more of a general PHP question and there are two parts: 1) How to extend a class and 2) where to put files.
1) Extending classes isn't something Laravel or anyone else provides. That's right there in the language:
class A {}
class B extends A {}
As long as class A exists and is available, then class B can extend from it.
2) Where the files are is also important here. If you're defining class B and want to extend class A, the php runtime needs to know where to find A. Usually class A isn't defined in the same file as class B.
There are many ways to do this. You could require or include class A when you define class B. That would look something like:
a.php
class A {}
b.php
require "a.php";
class B extends A {}
Now with a lot of files like in the Laravel framework or any worthy library, you're going to have a lot of files to include and have to keep track of how to include those files. That's no fun. So, instead of doing that, PHP has provided a way to autoload the classes. That is, if you define classes in a predictable way, PHP can figure out what classes you're talking about without you having to use require or include statements.
There are also many ways of autoloading php files. In Laravel (and many, many other projects), the composer autoloader is used.
This means that files have to be placed in a pre-defined way in order for the composer autoloader to find them. By reading about the composer autoloader and then digging into the code to see how Laravel's classes are autoloaded, you'll be able to figure out how that happens.
Despite the intricate detail of Peter's answer, I figured I'd write something much more concrete: it doesn't matter.
If you check composer.json, you'll see that we are autoloading everything that is placed inside the app directory anyway. Hence, the choice is really yours. All that matters is that you maintain a sensible and readable structure. For example, you could place it in app/Lib, and namespace all your classes App\Lib (if App is your base namespace of course, which can be changed with php artisan app:name). Of course, you could also have a folder like Helpers/Lib for your extended classes, and keep some form of helpers.php with global helper functions in Helpers.
Why would you do this? Well, you might want to have an easy way to call your new Strfunctions, so instead of having to do Str::yourNewMethod($argument) everywhere, you could add a helper function yourMethod($argument) to easier call the function (if you intend to use it extensively).
One thing you have to remember though, as mentioned by Peter, is that the class you are extending won't automagically be found. It will, however, be autoloaded. Hence, to reference it you have to remember to namespace it, such as in the example below.
<?php namespace App\Helpers\Lib
Class Str extends \Illuminate\Support\Str {}
Also remember to namespace correctly when you call your own class.
This is what I have at hand:
//Person.php
namespace Entity;
class Person{
}
User file:
//User.php
use Entity\Person;
$person = new Person;
Here, it fails if I don't include the Person.php file. If I include it, the everything works fine. Do I absolutely require to include the file even when using namespaces? If at all we need to include/require files, then how can namespaces be effectively used? Also, can we maintain folder structure by nesting namespaces?
The answer to your question is "yes and no".
Indeed the code implementing class Person has to be included, otherwise the class is not defined and cannot be used. Where should the definition come from, when the code is not included? The php interpreter cannot guess the classes implementation. That is the same in all programming languages, by the way.
However there is something called Autoloading in php. It allows to automatically include certain files. The mechanism is based on a mapping of class names to file names. So in the end it boils down to php searching through a folder structure to find a file whos name suggests that it implements a class currently required in the code it executes.
But don't get this wrong: that still means the file has to be included. The only difference is: the including is done automatically, so without you specifying an explicit include or require statement.
Yes, you need to include every file.
A very good example can be found here on effective usage of namespaces.
With PSR-0 autoloading, the namespace has to be the same as the folder in which the class is, file the filename has to be the same as the classname. This gives you very simple and effective autoloading with composer for example.
Im trying to reach a class file where I have defined namespace in the top with the following:
File: config.php
namespace Config;
class Config
{
// Stuffs
}
The file structure is like this
public_html
- admin
-- header.php
-- footer.php
-- file-trying-to-reach-config.php
- config.php
Im trying to reach the config.php -file from the file-trying-to-reach-config.php. In the top of file-trying-to-reach-config.php Im using:
use \Config;
But I have no clue how I, with use move up on folder to reach config.php. Googled and Stacked but didn't find anything about it. Have I misunderstood the concept with namespace and use?
How do I reach config.php with use from file-trying-to-reach-config.php?
The Use operator is used to alias namespaces in PHP, as described in this documentation. This essentially gives you the ability to create short names for classes when you have complex namespaces.
You need to either include or require the config.php file into where you want to call it. e.g.
<?php
include_once('../config.php');
$config = new \Config\Config();
For a more advanced way to handle this, you can look into Autoloading which will do the include bit automagically.
I have a folder structure like so:
index.php
app/
controllers/
folder1/
class.php
There is no namespace definition in class.php. Would it be possible to put class.php in a namespace generated from folder structure relative to index? So it would be loaded like:
new \app\controllers\folder1\classInFile();
Or is there no way to dynamically create namespaces?
A file containing a namespace must declare the namespace at the top of the file before any other code.
http://php.net/manual/en/language.namespaces.definition.php
I.e., you cannot execute any code before the namespace declaration, and afterwards it's too late. Notwithstanding introspective runtime hacks: no, it's not possible. Even if it was, it would depend on runtime information, like what folder the code is executed/included from. The namespace could be var\www\myproject\foo\bar\baz or just foo\bar\baz. How are you going to determine that? That's getting messy.
Really, just make it explicit, even if that means typing a little more. The namespace is part of the class's name. You should not generate names dynamically at runtime.
You shouldn't be dynamically generating namespaces, the namespace cannot be set and read at compile time.
In any case, the namespace is provided/defined before any code is executed.
The namespace needs to be defined inside of class.php if you can create the PHP source file dynamically, you can create the namespace dynamically.