I am developing my own package in Laravel and I am developing a huge number of helper to use with my package so that it can be used this way:
MyPackage::myfunc1();
MyPackage::myfunc2();
MyPackage::myfunc3();
....
The problem is MyPackage class (MyPackage.php) is becoming huge and the code is becoming very long. This bring hard maintainability to the file.
Is there anyway that I can split the class into a few files for easier maintaining? Or, is there any other way to do so?
Thank you.
As per request:
File: MyPackage/Helpers/FooUtil.php
<?PHP
namespace MyPackage\Helpers;
class FooUtil
{
}
File: MyPackage/Helpers/BarUtil.php
<?PHP
namespace MyPackage\Helpers;
class BarUtil
{
}
Example how to use namespaces to seperate classes and how to use different classes in the same namespace. For more information read:
http://www.php.net/manual/en/language.namespaces.php
Using namespaces in Laravel 4
I generally advice you to read about PSR-0, which is used in Symfony/Laravel to properly support autoloading, composer and packagist: http://petermoulding.com/php/psr
PSR in fact defines how to format namespaces in order to be applicable more globally.
In your example a proper namespacing might be:
Author\MyPackage\Helper\FooClass
Related
Here is the example of beginning of my TurnoverController
namespace App\Controllers;
// libraries
use \Turnover\Form;
use \Turnover\StatsByEventNames;
use \Utilities\Utils;
// models
use \Card;
use \GameClient;
use \Gametypes\Dogs;
use \Manager;
// Facades
use \Session;
use \App;
use \URL;
class TurnoverController extends BaseController
Since PSR standard says every class should be in a namespace of at least one level, I added namespace.
But now to load just simple models, without namespace yet, I always have to call use
\ModelName
Plus also same for things like Session, App, Etc.
And also there is a plan to have models in a namespace
App\Models
So to use a model then will have to write
use App\Models\ModelName
. Without namespaces all this was automatic - controllers knew where the models and Facades are. How can I fix that so at least models in default model folder would not required to call use statement?
Same for Facades.
I have a class called Awesome and have used the ServiceProvider and the Facade to register it to the app. Now I can use it as Awesome::Things().
I want to add constants to this class, so I tried
<?php namespace Helper\Awesome;
class Awesome()
{
public static $MOVIE = 'I love the Lego Movie!";
}
but when I call Awesome::$MOVIE, I get Access to undeclared static property: Helper\\Aesome\\Facades\\AwesomeFacade::$MOVIE
Can someone help?
The short version is -- you don't really want to do that. Laravel facades aren't mean to be used like normal classes, and if your application uses them that way you'll likely confuse future developers.
Warning out of the way. When you create a "facade" in Laravel, you're actually creating a class alias. When you added Awesome to the alias list in app/config/app.php, at some point code like the following ran
class_alias('Helper\Aesome\Facades\AwesomeFacade','Awesome');
That means whenever you use a global non-namespaced class Awesome, PHP substitutes Helper\Aesome\Facades\AwesomeFacade. If you wanted to add constants, you'd need to add them to this class.
Laravel's able to pass through methods because of the base Facade class implements a __callStatic method that passes on your call to the actual service implementation object. Facades don't pass on static constant access. Additionally, PHP does not (appear to?) have similar magic methods for passing along requests for constants.
If you're curious about the in depth version of this answer, I'm currently writing a series on Laravel's object system, including some in-depth information about the facade implementation.
I have a Model in my Laravel app called Event. As I just discovered, this creates a conflict between my model and Illuminate\Support\Facades\Event, a built-in facade. The obvious solution here is to either change the name of my Model, which is not ideal because there is really no other name I could give my Model that makes any sense, or to rename the alias in app.php for Illuminate\Support\Facades\Event, which I'd like to avoid for fear of breaking anything that may rely on that alias in the future (I'm afraid I may forget).
It's been suggested that perhaps I could use namespaces, which I attempted as follows:
app/models/Event.php
namespace Models; #<-- I've also tried using "\Models" here
class Event extends \Eloquent{
app/database/seeds/DatabaseSeeder.php
Models\Event::create(); #<-- again, I've also used "\Models\Event"
All 4 combinations above have yielded a Class 'Models\Event' not found error when I run php artisan db:seed.
Perhaps I simply don't understand namespaces properly, but the more pressing issue is how to solve my problem. If it can be solved using namespaces as suggested, great, but I'm open to any other ideas as well.
I made this mistake early on as well, not necessarily understanding the role of namespace throughout the entire app.
The namespace should mark the business logic within the domain or responsibility of the app itself, so giving a namespace of Models isn't necessarily useful. Instead create a root namespace named after the app, your company, you, or whatever you like, then provide a Model sub-namespace.
For example:
namespace MyGreatApp\Models;
class Event extends \Eloquent{ }
Then you would reference this model under:
use MyGreatApp\Models\Event;
$event = new Event();
In the long run this is a cleaner and more organized approach. This does mean moving your models into a different folder, though. But there's nothing wrong with that. At least that way you know you have all your custom code in your MyGreatApp namespace. :)
I’ve created a workbench package in Laravel 4, which is name-spaced and has two directories: Models and Contexts. Somehow, Laravel is loading my models in my Models directory (I have a model in there called User), however, it doesn’t know about my classes in the Contexts directory.
I want to be able to use my context classes in my app’s controllers without specifying the whole namespace, so I thought I’d add them to Laravel’s IoC container. However, it seems I need to create a façade class for each class I wish to add to the container. This isn’t desirable if I have dozens of context classes, as it would mean creating an equal amount of façade classes too.
Is there a way in Laravel to bulk-add classes to its IoC container?
if you want to use one term facades for your classes the laravel way (e.g. MyModel::someAction()) then you have to create your facades. but i'd advise not to do so for so many classes.
if your classes inside contexts folder aren't found then you should check your composer.json file under the autoload entry or do a composer dump-autoload -o.
I'd just DI the classes within the constructor of the class that uses them, so you end up using $this->myService->someAction().
This should answer both Laravel 4 and 5.
First, you need to use the bind method Illuminate\Foundation\Application class, which serves to register binding in the service container. In the Laravel documentation you will find plenty of examples how to do that, but only for a single binding.
If you take a look a the implementation of bind method here or just the definition here, you will notice that this method accepts a string|array. This means you can provide multiple bindings as an array and register all of them in the container with their fully qualified class names. Something like this:
$this->app->bind(['\App\Acme\Service1', '\App\Acme\Service2', '\App\Acme\Service3', ...]
Having this in mind, you can easily get the classes in one namespace (directory) with a reflection, put them in array and use the above method to register them.
Revisiting this question some time later, I think the appropriate solution would be to autoload the classes using my package’s composer.json file, and then import classes using it’s FQN in controllers and other classes:
<?php
use Vendor\Package\Contexts\ContextClass;
class Laravel4Controller extends BaseController {
protected $context;
public function __construct(ContextClass $context) {
$this->context = $context;
}
}
Error: Class 'Ibooks_Controller' not found in/Users/winas/workspace/media_admin/media_books/application/tasks/sample.php
Class that produces error: class Sample_Task extends Ibooks_Controller
Ibooks_Controller path: /Users/winas/workspace/media_admin/media_books/application/controllers/ibooks.php
How can I properly call the function that Ibooks_controller have inside of sample.php
you can't extend a Controller when making a Task. And more importantly, it would be something really bad to do.
I don't know what it is that you're trying to do, but if you want to access any data, you should use models and/or libraries for that.
Besides that, a short explanation on why the class is not found.
Laravel only autoloads files/classes that are in the "models" and "libraries" directories. (There might be more)
Controllers are only loaded when a Route request that controller to be loaded. And will only then search for which controller to load.
If you need to load classes that are not in one of the standard auto-loaded classes, you can load it using the Laravel Autoloader class:
http://three.laravel.com/docs/loading