How to organize your own classes in FuelPHP? - php

I put all my classes in "fuel/app/classes/" folder, for a simple call to MyClass::MyMethod()
Start to store classes in "fuel/app/classes/lib/" with the given "namespace lib".
Calling the lib\MyClass::MyMethod() or prescribing "use lib" much more comfortable than proposed Folder_MyClass::MyMethod() see http://docs.fuelphp.com/general/classes.html
Is there any way to load a specific namespace is in "bootstrap.php", that would not have to write any "use lib" at the beginning of the file (controller, model), or not add everytime to call like "lib\"?

FuelPHP uses a cascading filesystem for classes that doesn't favor class name segments over namespaces. The only requirement is that you classes are somewhere in the classes folder.
For example, say you have a file called app/classes/some/sub/system/name/myclass.php.
You can define this class as:
class Some_Sub_System_Name_Myclass {}
But also as
namespace Some\Sub\System\Name;
class Myclass {}
Or anything in between. The common rule is : glue your namespace and class name together, convert it to lower case, replace all underscores and backslashes by DIRECTORY_SEPARATOR, and stick a ".php" extension on it, and you have your filename.

You could probably add lib as a Core Namespace. In bootstrap.php:
Autoloader::add_core_namespace('lib');
http://docs.fuelphp.com/classes/autoloader.html#/method_add_core_namespace
You should then just be able to use \MyClass::MyMethod(); without having to prefix it with the namespace or without having to Use lib;

Related

How and where should I use the keyword "use" in php

I used use the keyword "use" generally above the class definition. Like this:
<?php
namespace suites\plugins\content\agpaypal;
use \Codeception\Util\Fixtures;
use \Codeception\Verify;
use \Codeception\Specify;
class agpaypalTest extends \Codeception\Test\Unit
{
protected $tester;
...
But now I realised, that I have to put the line for the trait Specify into the class definition. Like this:
<?php
namespace suites\plugins\content\agpaypal;
use \Codeception\Util\Fixtures;
use \Codeception\Verify;
class agpaypalTest extends \Codeception\Test\Unit
{
use \Codeception\Specify;
protected $tester;
...
I think it is because the package \Codeception\Specify; is a trait. But I do not understand why I couldn't reuse this trait when I set the line
use \Codeception\Specify;
before the class definition?
I would be happy if someone could point me to a hint or an explanaiton that explains to me where I should use the keyword "use" the best.
In PHP, the keyword use is used in 3 cases:
As class name alias - simply declares short name for a class (must be declared outside of the class definition)
(manual: Using namespaces: Aliasing/Importing )
To add a trait to a class (must be declared inside (at the top) of the class definition)
(manual: Traits)
In anonymous function definition to pass variables inside the function
(manual: Anonymous functions)
You can not import class with use keyword. You have to use include/require statement. Even if you use some php auto loader, still autoloader will have to use either include or require internally.
The Purpose of use keyword:
Consider a case where you have two classes with same name; you'll find it strange, but when you are working with big MVC structure, this happens. So if you have two classes with same name, put them in different name spaces. Now consider when your auto loader is loading both classes (does by require), and you are about to use object of class. In this case, the compiler will get confused which class object to load among two. To help the compiler make a decision, you can use the use statement so that it can make a decision which one is going to be used on.
Here refer this
How does the keyword 'use' work
use is basically including a class in the file to use it.
There are two ways to include a class file in another file.
The most general is require or include method. Another method is using composer. Assume this Directory Structure
Project
|
|--- Folder A
| |
| |---UserRegistration.php
|
|---Example
|
|--TestUserRegistration.php
In Folder A there is UserRegistartion.php and you want to use the code in TestUserRegistration.php In UserRegistration.php It can be class, trait or Interface
Method 1.
In TestUserRegisteration.php you can include or require file UserRegistartion.php
and use it
Method 2
Using Composer. In UserRegistration.php you define namespace FolderA; as the first line of code. Then write your code as you do. So Now you want to use this file in TestUserRegistration.php you do
include vendor/autoload.php;
use FolderA\UserRegistration;
Which one is better and why?
Method 2 using composer is the best method. In method 1 wherever you want to include UserRegistration you have to find the relative path to UserRegistration file. So lets assume some day you need to change the directory structure your application will break as the relative path you had provided now it does'nt exist.
But in Method 2 you always use the namespace you provided \ The filename instead of where you want to use. So even you change the directory structure you don't have to got all codes and modify the path. It will work as it was.
To know more study about how to use namespace and composer.

Am I using namespaces, autoload, and aliasing correctly?

I've been reading a lot of posts on StackOverflow but I'm not really sure I'm using namespaces, autoloading, and aliasing correctly. This is functioning fine, but I'm not sure I'm properly using these concepts. I've listed some reasons why I think this setup is incorrect at the bottom of the post.
Imagine the following directory structure:
\public_html
- index.php
\Classes
\A
- One.php
\B
- Two.php
One.php is structured like:
<?php
namespace Classes\A;
class A { ....
Two.php is structured like:
<?php
namespace Classes\B;
class B { ....
Then, in index.php I do something like:
<?php
use Classes\A\One as One;
use Classes\B\Two as Two;
spl_autoload_register(function ($className) {
...
});
... ?>
So, a couple things that bug me about this:
If I am doing aliasing (the "use" statements) I still need to list out all of the files. Aren't we trying to avoid doing this by using autoload?
If I want to use internal classes, I need to add a line such as "use \mysqli;" into the class that uses this and do things like "new \mysqli()". Seems kind of messy?
If a class extends a class from another namespace (say Two.php extends One.php for example) then I need to include "use \Classes\A\One as One;" in One.php which seems to be what we want to avoid in the first place
You don't have to reference all of your namespaced classes via a use statement. You can use partial namespaces.
use Classes\A;
new A\One();
So you can see if you had another class in the A namespace it could be instantiated with
new A\Three();
There are many things in the global namespace, you don't need to define them with use. You can just call them \mysqli(). Yes it's a bit unsightly but it allows you to make a function called mysqli in your own code without worrying about collisions with globally namespaced functions.
I'm not sure I follow you on this one. You don't need to do a use in the base class which references itself.
Ultimately it kinda seems like you view use almost like include when they are very different, use, in this context, is a convenience thing so you don't have to type out full namespaces every time.
Your Autoloader also doesn't need to know about your namespaces. The autoloader just tells PHP how to load a class. So if it sees a class come in with the name Classes\A\One you can make it look in the directory /Classes/A for a file called One.php and include it. PHP will make sure that the class is allocated in the proper namespace. The autoloader is just a convenience thing to keep you from having to do includes and requires in each of your PHP files.

Laravel 5 Class extend

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.

Is it possible use multiple classes under the same namespace, in the same file

Is it possible use multiple classes under the same namespace, in the same file? I want to do something like this:
<?php
namespace MyNamespace\Helpers\Exceptions
use Exception;
class CustomException1 extends Exception{}
class CustomException2 extends Exception{}
class CustomException3 extends Exception{}
to avoid using one single file for each custom exception class.
The problem is, when I try to use, in another class, one of the custom exceptions,
use MyNamespace\Helpers\Exceptions\CustomException1;
the CustomException1 class is not found. Any ideas?
I don't think there's anything syntactically wrong with doing this, but I don't think any PSR-4 compliant auotloaders will be able to find a class that is not in it's own dedicated file since the standard is that the name of a file a class belongs in is the same as the name of the class itself:
The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.
Because of this, if you want to use this approach you will have to ensure to include that class file manually whenever you will need those classes to be defined (basically, anytime you want to throw / catch any of those exceptions).
An alternative is to define the classes you want to inside of another class' file that you are absolutely certain will always be autoloaded prior to any invocation of any new CustomExceptionN statements. You will probably find in the majority of cases it is a lot more trouble trying to remember to first be sure to autoload Class1 before using Class2 than it is to just follow the standard and include each class in it's own file located at the proper namespace path.

How should I organise my files according to PSR-0?

I'm a bit confused with the guidelines and how to name the files.
1.) What does Vendor mean in \<Vendor Name>\(<Namespace>\)*<Class Name>
2.) If I name the namespace AnimalsApp and have an abstract class Dog, do I put concrete classes such as GermanShepherd in their own folder?
ie. AnimalsApp\Dog\GermanShepherd\GermanShepherd.php or AnimalsApp\Dog\GermanShepherd.php?
Further, do I include Dog.php in the GermanShepherd.php file, or is that up to the autoloader to load everything for me?
3.) Do all subclasses of the namespace need to have the namespace at the top of each file?
4.) Is <Class Name> synonymous to <Interface> here? What about when you have something like class MyClass extends MyAbstract implements MyInterface. Where do you put the files?
What does Vendor mean in \<Vendor Name>\(<Namespace>\)*<Class Name>
Nothing in particular. Its importance is that all the other parts of the relative path are fully specified by the source code, and therefore "somewhat outside your control". The vendor prefix is there to allow you to have a class Vendor1\Animals\Dog and me to have a class Vendor2\Animals\Dog and for those two classes to not conflict if they ever happen to be used in the same application.
In practice: choose something that identifies yourself or your organization. It can be whatever you like, but since the idea is "something extremely unlikely to be picked by anyone else" decide accordingly.
If I name the namespace AnimalsApp and have an abstract class Dog, do I put concrete classes such as GermanShepherd in their own folder?
You put concrete classes where their namespace dictates. If the fully qualified class name is AnimalsApp\Dog\GermanShepherd then you put it inside the directory AnimalsApp\Dog. If the FQCN is AnimalsApp\GermanShepherd then you put it inside AnimalsApp.
I should mention that both of the above examples seem unlikely and/or indicative of bad choices; the FQCN should probably be something like AnimalsApp\Animals\GermanShepherd.
Further, do I include Dog.php in the GermanShepherd.php file, or is that up to the autoloader to load everything for me?
It's up to the autoloader.
Do all subclasses of the namespace need to have the namespace at the top of each file?
A namespace does not have subclasses, it contains classes. Assuming that's what you meant then the answer is yes, because if the namespace is not there then by definition the classes are not contained inside it.
Is <Class Name> synonymous to <Interface> here? What about when you have something like class MyClass extends MyAbstract implements MyInterface. Where do you put the files?
Treat interfaces and classes in the exact same way.

Categories