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.
Related
I would like to more in depth knowledge about using static methods . I'm using laravel 5.2 framework for my application.
In my application mostly i have used static functions For example i have model class name like post and method name is get_post() and its declared as static only if i missed static keyword in laravel it throws error
class Post extends Eloquent(){
public static function get_post(){
return DB::table('post')->get();
}
}
In my controller i will call this above method
Post::get_post()
How could i avoid to call this method as static ? as per the PHPMD 1.4.0 rule
Anyone please explain clearly.
Laravel's Eloquent is called via the static method, so I'm not sure how to avoid this. By the way, instead of the functions you wrote, you can of course write
Post::all();
Another abstraction possibility is to use the Repository Pattern, where the Controller doesn't call the Model's functions directly, but rather something like
$activePosts = $postRepository->getActiveAndApproved();
where the $postRepository would do some of the heavy lifting on Laravel's Eloquent model doing e.g. ->where('something', true) and stuff like that - Symfony has this already a bit stronger included in their framework.
See https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5/ for more detailed instructions.
Seeing also that Laravel uses Facades a lot, which is a simplified way to access functions in the service container (e.g. see config/app.php or https://laravel.com/docs/5.2/facades for more infos), it might be difficult to avoid static function calls.
I am developing a package for Laravel 5, and now I need to benefit from dependency injection to have a more scalable and relaible application, I don't know which approach is the best to take and why, this is a piece of my code and I need to injected the Lang class dependency
class MyController extends \App\Http\Controllers\Controller
{
public $text;
public $lang;
public function __construct()
{
// Some codes here
}
public function myFunction(){
$this->text = \Lang::get('package::all.text1');
}
}
In this link http://laravel.com/docs/4.2/ioc 2 approaches are suggested, Basic Usage and Automatic Resolution based on my understanding from the link
taking the first approach I need to add
App::bind('lang', function($app)
{
return new \Lang();
});
to the register part of application and then in the function I'll have something
like this :
public function myFunction()
{
$lang = \App::make('lang');
$this->text = $lang::get('package::all.text1');
}
The other way is to modify the constructor like
public function __construct(Lang $lang)
{
$this->lang = $lang;
}
And then instantiate object from Class like
$myController = App::make('MyController');
Which way is the better way to take for, considering that this class is a Controller and it will be called in the routes file, or please correct me if my understanding from the link is not right. please also inform me why you suggest any of those approaches.
It should be noted that using local IoC resolution ($app->make() stylee) is not much better than using the facades directly (Lang::get() stylee) - you're still very much relying on Laravel's specific classes without really making your code explicitly state that it needs these exact classes. So the general advice is to, as much as possible, code to an interface if you want your code to be as portable as possible.
Of course there are a couple of big downsides to this currently in PHP development:
These interfaces are not generally defined (except the PSR-3 LoggerInterface interface) so you still have to rely on a particular instance of the interface (in this case, Laravel's).
If you decide to make your own generic interface (or the FIG eventually creates some of these), the classes that Laravel provides for translation (for example) don't implement it anyway, so you then need to subclass the existing ones just to make it look like it implements your own interface. But hey, that's the current best practice, so I guess if you wanna be using the current best practices, code to an interface, and don't worry for the time being that the interface you're coding to is Laravel-specific.
But anyway, here are my thoughts on your specific question. First off I should say that I haven't actually used Laravel 5 yet (just the 4s), but I have generally followed its development.
If the class I am coding will use a given dependency quite a lot or as a core part of how the class works I will use constructor dependency injection. Examples here are the Request or some Repository class in a controller, or a business logic class in a console command class.
If what I need I only need for a specific purpose (maybe redirecting from a controller and needing to generate a URI) I will resolve a local version from the IoC container ($this->app->make()) and then use that. If I were using Laravel 5 and the method was called by Laravel directly (e.g. a controller's action method) I may use method injection for this, I'm not 100% sure.
As a final note, the general advice is that if your constructor method signatures get too big due to a lot of dependencies:
It's time to have a look at if your code relies too much on external dependencies. Maybe some of the functionality of your class can be extracted to its own class that splits the dependencies between the two.
You should consider using setter methods rather than constructor injection - so instead of accepting a Request object, you have a $class->setRequest() method. The downside of doing this is that you need to tell Laravel's IoC container how to instantiate your object (i.e. that these setters must be called). It's not that big a deal but something worth noting.
Relevant links:
Laravel 5's IoC article
Laravel 5's Controller injection advice
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;
}
}
I would like to check if my assumption about codeigniter is right ?
We would normally extend a class when we are trying to include more functionality to the core, such as MY_Controller extends Controller, MY_Model extends Model etc...
But for example, if we are in the checkout library retrieving some checkout info(eg, product_id), we can just $this->load->library('product_lib',array('product_id'=>$product_id)) and we can easily $this->product_lib->product_name etc... from the checkout library right?
The $this->load thing is kind of equivalent to "hard code" checkout library to extend product_lib(class checkout_lib extends product_lib) to be able to use whatever methods/variables there is in the product_lib.
Please enlighten me.
In CodeIgniter $this->load is like having a resource manager (e.g. resourceManager->load("path/to/file")) and it takes care of loading the library, and passing any arguments you specify and such, easily allowing you to quickly get to using it.
So if you have a variable named product_name in your product_lib then yes calling $this->product_lib->product_name will be accessing that variable.
Really it just places the library into an array with the library name as the key and the instance of the library as the value so calling $this->product_lib is really calling something similar to $loadedLibraries['product_lib'] and returning the instance.
I hope that answers what you are asking, I'm quite tired and could have miss understood you question.
I think you misunderstood the OO paradigm and the way CI work.
$this->load is same with instantiate an object of the library/model, or load the helper file. CI have some sort of management to see if the helper/library/model already uploaded or not.
In other hand, the extends is used when defining a class, to tell PHP that the class will be inherit the parent class properties and method. A class is a blue print of object it will produce.
Maybe you can start by understanding the OO concept first. You can read this as a start, and see the reference used there.
I have a user class with static methods getById and getByUsername
I have the class in the application/libraries folder
How do I call the classes from a controller?
Theory 1:
$this->user = new User();
$this->user::getById;
Theory 2:
$user = new User();
$user::getById;
or is there a clean way of doing it much like how Kohana helpers do it; much like:
text::random();
here's what I am trying to accompplish:
I want to call a static mehthod in the user library from my controller
In PHP you usually include the file (User.php) and the static methods are ready
User:getById
but then how would I do the same thing in an MVC framework?
shall I do an include too?
Like include ('User.php');?
User::getById();
and
User::getByUserName();
Edit: In response to your question edit, generally frameworks have an auto-loading mechanism that will find and load a class file for you once you reference that class. So when you type User::getById(), the PHP interpreter will see that it needs to load the User class (if it hasn't been loaded already), and run the autoloading procedure to find the correct code to include.
I've never used Kohana, but I would be quite surprised if it didn't use some form of autoloading. If it does not, then yes, a simple include('User.php') will be enough to make the static method calls to User work.
The confusing thing is Kohana's convention of writing "helper" classes with lowercase names.
Your user php file will probably all ready be loaded if your using it as a model, so you can use zombat's suggests of User::getById();.
I don't like to follow their naming convensions for helpers or libraries and instead do:
require_once(Kohana::find_file('libraries', 'user_utils', TRUE, 'php'));