Using Enum classes in Laravel 5 project - php

I want to use some enum classes in my laravel 5 app.
They are modeled after this PHP man page example: http://php.net/manual/en/class.splenum.php
The file app\Enums.php looks like this:
<?php
namespace MyApp\Enums;
class ItemStates extends SplEnum
{
const __default = self::Active;
const Active = 1;
const Pending = 2;
}
class ItemVisibility extends SplEnum
{
const __default = self::Community;
const Community = 1;
const Personal = 2;
}
I want to use these from a controller.
I put a use statement at the top of my controller:
use MyApp\Enums;
When I try to use the class like this:
if ($category['Family'] == CategoryFamily::General)
I get an error:
Class 'MyApp\Http\Controllers\Quiz\CategoryFamily' not found
I have run compose dump-autoload in case that matters.
How can I use my Enum classes from inside controllers (multiple controllers)?

Please correct me if I'm wrong, but Laravel uses a PSR-4 compliant autoloader. In the documentation of psr-4 it is mentioned:
The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.
You can check if it uses this standard in your composer.json file to be sure:
"psr-4": {
"MyApp\\": "app/"
}
This means it won't be able to find your class. I suggest you put each class into a separate file with the same name as the class and put that in a MyApp\Enum namespace for example.
The other options you have are to include your app using the psr-0 standard in your composer.json, or to manually include your Enum file wherever you want it.
UPDATE
Once you've done this, you should be able to use SplEnum by putting use SplEnum; under the namespace .. in top of your file, if and only when you have SplTypes installed. If you're on Windows or do not want to install this PECL Extension, then I suggest this answer: https://stackoverflow.com/a/254543/2433843 with an elegant solution.

I think you have to import the enum class :
namespace MyApp\Enums;
use SplEnum; // specify correct path if needed

Related

Class Not Found using PSR-4

I have a PSR-4 specification in my composer.json file as below
"autoload" : {
"psr-4" : {
"MyMVC\\" : "app/"
}
},
Above is my directory structure. In my Core/Config.php file i have class Config that is under namespace MyMVC\Core. (Just taking Config class as example in question, this is same for all classes).
Now in my Config/config.php file i am using below code
<?php
use MyMVC\Core;
Config::$config['base_url'] = 'http://localhost/mymvc';
But this gives me error of Class Config Not Found. The problem can be fixed if i use MyMVC\Core\Config;. But it should work without using Config explicitly. Since there can be files added by the framework user which are supposed to be autoloaded.
Thanks
The use primitive imports or aliases a namespace or class. As the manual states:
PHP supports three kinds of aliasing or importing: aliasing a class name, aliasing an interface name, and aliasing a namespace name. PHP 5.6+ also allows aliasing or importing function and constant names.
Your use statement is "aliasing a namespace". So
use MyMVC\Core;
Is the same as:
use MyMVC\Core as Core;
Thus in your code:
Config::$config['base_url'] = 'http://localhost/mymvc';
Should be:
Core\Config::$config['base_url'] = 'http://localhost/mymvc';

Attempted to load class "ClassName" from namespace (...). Even though namespace is imported

I have a Symfony project to which I added some non-symfony php files containing various classes. But for some reason the classes are not loaded when loading the website, even though the IDE sees them properly.
So, I have a class that needs other classes:
namespace rootspace\FrontBundle\Controller;
use rootspace\FrontBundle\Networks\TwitterOAuth;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class TwitterController extends Controller
{
public function connectAction(){
// The TwitterOAuth instance
$connection = new TwitterOAuth('abc', '123');
}
}
And then the class which fails to load (that needs yet another file)
namespace rootspace\FrontBundle\Networks;
/* Load OAuth lib. You can find it at http://oauth.net */
//require_once('OAuth.php'); -- should this be commented out?
/**
* Twitter OAuth class
*/
class TwitterOAuth {
/* Contains the last HTTP status code returned. */
}
Lastly, the third file
namespace rootspace\FrontBundle\Networks;
use Symfony\Component\Config\Definition\Exception\Exception;
class OAuthConsumer
{
public $key;
public $secret;
}
(...)
I assume the actual filenames don't matter, right? Nor their structure? PhpStorm sees all the classes properly, I can right-click through them, but it fails when deployed.
Thanks for help
Edit - the whole error message says
Attempted to load class "TwitterOAuth" from namespace "rootspace\FrontBundle\Networks" in D:\Dropbox\project\src\rootspace\FrontBundle\Controller\TwitterController.php line 15. Do you need to "use" it from another namespace?
This is because Symfony's autoloader follows PSR standards (PSR-0, PSR-4) which says that fully qualified (with namespace) class name translates to file location and name. So in fact file names does matter.
So in your case rootspace\FrontBundle\Networks\TwitterOAuth class should be located in rootspace/FrontBundle/Networks directory in file called TwitterOAuth.php
If classes you are using does not follow PSR standards you can also register them manually in app/autoloader.php file
Check these for more info:
How can I add a namespace to Symfony 2.1?:
How to autoload class
And check this answer
I forgot to add a .php extension to my filename

PHP prepend class names with sub-space for autoloading

I'm just wrapping my head around PHP namespaces and autoloading with composer. I have a question about the following code:
namespace APP\Controllers;
use APP;
use APP\Interfaces;
use APP\Lib;
class PageController
extends Lib\ActionController
implements Interfaces\ControllerInterface
{
//stuff
}
Why do I have to prepend the extends class with the sub-space with 'Lib\' when I already use the line 'use APP\Lib;'? Same goes for the interface. When I don't prepend I get an autoload error. I'm using composer to autoload and have this in my composer.json:
"autoload": {
"psr-4": {
"APP": "app/"
}
}
In app/ I have subfolders Lib, Interfaces and Controllers like so:
/app
/Controllers
/Interfaces
/Lib
I noticed that in other devs code they don't have to do this. I'm confused as to what I am doing wrong.
Thanks for the help.
You are including three namespaces:
use APP;
use APP\Interfaces;
use APP\Lib;
Now if you say just:
extends ActionController
PHP would not know if it is:
APP\ActionController or
APP\Interfaces\ActionController or
APP\Lib\ActionController
If you still wanted to extend it without Lib subspace you would need to do:
use APP\Lib\ActionController; first
use is only there to alias namespaces or class names to shorter names. It's there to avoid having to repeatedly address all classes by their fully qualified name all the time:
$a = new \Foo\Bar\Baz\Quurx();
$b = new \Foo\Bar\Baz\Quurx();
// shorter:
use Foo\Bar\Baz\Quurx;
$a = new Quurx();
$b = new Quurx();
use Foo\Bar is shorthand for use Foo\Bar as Bar. So, you're creating an alias Bar which really resolves to the full name \Foo\Bar. Since APP\Interfaces doesn't resolve to any particular interface in your case, just using implements Interfaces wouldn't mean anything. And if you just used implements ControllerInterface, it would be ambiguous which namespace that resolves to. \APP\Controllers\ControllerInterface? \APP\ControllerInterface? \APP\Lib\ControllerInterface? It's just not clear and cannot be resolved automatically.
So, what you're doing is you're shortening APP\Interfaces to just Interfaces, and then refer to APP\Interfaces\ControllerInterface by just using the shorter Interfaces\ControllerInterface. You could be doing this to make it even shorter:
use APP\Interfaces\ControllerInterface;
.. implements ControllerInterface ..

php psr autoload ambiguity

I am working on a php sdk rewrite project and the client wants to get PSR standards done. I am looking at the standards page here
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
One thing what i am not able to understand, if i use name spaces in my class do i still need to use include or require or use. I mean the whole reason of autoload beats the purpose right ?
For example, say i have a class this way,
namespace Employee\Department;
Class Department
{
//code
}
and i have another class which uses this class by extending it,
namespace Employee\community;
Class Community extends Department
{
//code
}
so does the above code make it to psr-0 standard considering that i have an autoload function exactly thats on the link above.
The second example is going to assume Department is in the Community namespace so in this case you would need a use statement. Also both of your examples would use the namespace Employee not Employee\Whatever for example lets assume the following layout:
Employee/
Community.php
Community/
Manager.php
Department.php
Department/
Manager.php
Then we would see the class/namespaces like the following
namespace Employee;
class Department {
}
///////////
namespace Employee;
class Community extends Department {
}
/////////////
namespace Employee\Department;
class Manager {
}
/////////////
namespace Employee\Community;
use Employee\Department\Manager as BaseManager;
Class Manager extends BaseManager {
}
For your understanding, autoloading works by registering the autoload function in the autoload stack via spl_autoload_register; this allows the function to be invoked whenever a new Class() statement is executed (more info).
On the other hand, the FIG standard for autoloading, PSR-0, defines how a namespace will be translated into a filename by a PSR-0 autoloader function. For example, given the namespace Vendor\Foo, the autoloader will look for the file Vendor/Foo.php having the following code
namespace Vendor;
class Foo
{
public function do()
{
echo "Foo";
}
}
Therefore, following the mandatory requirements, a PSR-0 compliant namespace resolves to the correct PHP file which could otherwise have been included using a require or include.
If I read your intentions correctly, you just need the following namespace in both code snippets:
namespace Employee;
Of course, this is not a PSR-0 namespace because there is no vendor name (unless your vendor name is 'Employee'). Anyway, using this namespace in your two code snippets will work fine.
However, if you intended to keep them in separate namespaces, then the autoloader won't figure out Department in extends Department in the second snippet. You will have to either import the namespace or explicitly specify it as so:
namespace Employee\community;
class Community extends Employee\Department\Department
{
//code
}
I imagine that you did not expect the full class names from your snippets to be Employee\Department\Department, and that is why I first suggested keeping the same namespace for your purposes.

Using namespaces in Laravel 4

I'm new to Laravel and using PHP namespaces in general. I didn't run into any problems until I decided to make a model named File. How would I go about namespacing correctly so I can use my File model class?
The files are app/controllers/FilesController.php and app/models/File.php. I am trying to make a new File in FilesController.php.
Namespacing is pretty easy once you get that hang of it.
Take the following example:
app/models/File.php
namespace App\Models;
class File {
public function someMethodThatGetsFiles()
{
}
}
app/controllers/FileController.php
namespace App\Controllers;
use App\Models\File;
class FileController {
public function someMethod()
{
$file = new File();
}
}
Declare the Namespace:
namespace App\Controllers;
Remember, once you've put a class in a Namespace to access any of PHP's built in classes you need to call them from the Root Namespace. e.g: $stdClass = new stdClass(); will become $stdClass = new \stdClass(); (see the \)
"Import" other Namespaces:
use App\Models\File;
This Allows you to then use the File class without the Namespace prefix.
Alternatively you can just call:
$file = new App\Models\File();
But it's best practice to put it at the top in a use statement as you can then see all the file's dependencies without having to scan the code.
Once that's done you need to them run composer dump-autoload to update Composer's autoload function to take into account your newly added Classes.
Remember, if you want to access the FileController via a URL then you'll need to define a route and specify the full namespace like so:
Route::get('file', 'App\\Controllers\\FileController#someMethod');
Which will direct all GET /file requests to the controller's someMethod()
Take a look at the PHP documentation on Namespaces and Nettut's is always a good resource with this article
first, load your class with:
$ composer dump-autoload
then
$file = new File;
// your stuff like:
$file->name = 'thename';
$file->active = true;
$file->save();
Section: Insert, Update, Delete on Laravel 4 Eloquent's doc
To namespace your model, at the top of your model class right after the opening
Then when you call from controllers you will call new Whatever\Model;
You probably have to do a dump-autoload with composer the first time around.
have a look to it.. hopefully will clear your query....
<?php
namespace app\controllers;
use yii\web\Controller;
use app\models\users;
class UserController extends Controller{
public function actionIndex()
{
echo "working on .....";
}
}
Namespaces are defined at the top of PHP classes right after the opening php script tag like this:
<?php
namespace MyNameSpace;
When you then want to use the namespaced class in some other class, you define it like this:
new MyNameSpace\PhpClass;
or import it at the top of the file (after namespaces if present) like this:
<?php
//namespace
use MyNameSpace\MyPHPClass;
//then later on the code you can instantiate the class normally
$myphpclass = new MyPHPClass();
In Laravel namespaces can be defined anywhere composer can autoload them, I'd recommend defining namespaces within the app directory. So you can define a namespace like Utils for holding Utility classes by creating a Utils directory in the app directory, creating our utility classes and defining the namespace as we did above.
Afterwards you have run the command to ask composer to autoload classes:
$ composer dump-autoload

Categories