Good day to all, I am new to Laravel and the thing that I encountered with and cannot understand is utility methods that are used in the framework, for example, Customer::all() where Customer is model or Customer::find(). So, what is the point of utility methods and why all() and find() are static.
Utility functions in general offer some sort of utility, i.e. functionality which is usually just for convenience and can also be achieved by following a set of steps.
For example Model::find() is functionality that can also be achieved by creating a query builder object and then performing a query e.g.
Model::getQuery()->where('id', '=', $id)->first();
For convenience you can just do Model::find($id) which is shorter and more intuitive.
It is static because it does not make sense for it not to be static. A non-static method requires an instance of the class however in ORMs an instance of a class corresponds to a potential database entry (which either exists or could exist).
Therefore since find is used to retrieve a database entry it makes no sense to require a backing database entry in order to use it.
In short what this means is, if you execute method $object = Model::find(1) you will get back a model which corresponds to database entry with identifier 1. There is a 1 to 1 mapping of the PHP object to the relational object. If make changes to $object and call $object->save() then changes will be persisted in the database (i.e. $object already exists). If on the other hand you do $object = new Model() you will get back a new model which does not currently correspond to a database entry. However calling $object->save() will make that object correspond to a new database entry and it will be updated accordingly (i.e. the new object could exist). If a framework required you to make a "dummy" object just to access some helper methods there's always a chance that (either by omission or through unknown side-effects) save() gets called on that dummy object and you end up filling up your database with what is essentially junk.
The takeaway from this is that in an ORM it does not make sense to create a model instance if you don't intend to store it in the database. Laravel does not strictly obey this rule, but in general it does, and you should too.
The same applies to all which gets all database entries. It doesn't make sense to get all database entries by requiring to first get one entry.
Same applies to getQuery used above which returns a query builder instance. Note that most people don't actually use getQuery because it runs implicitly when someone uses something like e.g. Model::where(..) so technically Model::where() is also a utility. I mention this because when you see something like Model::where('id', $id)->where('name', $name) the 2nd where is after a -> which implies it's on an instance rather than static, however that instance is actually a query builder instance and not a model instance.
When you do User::find() , you are actually asking for a new instance, either an instance of Collection or a QueryBuilder.
Illuminate\Database\Eloquent\Model : https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Model.php
As a side note, you'll also see another way of using static methods in Laravel e.g. Input::get(). These are called Facades.
Facades provide a "static" interface to classes that are available in the application's IoC container ... Laravel "facades" serve as "static proxies" to underlying classes in the IoC container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.
When a user references any static method on the ... facade, Laravel resolves the cache binding from the IoC container and runs the requested method (in this case, get) against that object.
You can read more about Laravel Facades at: http://laravel.com/docs/facades
Laravel includes a variety of global "helper" PHP functions. Many of
these functions are used by the framework itself; however, you are
free to use them in your own applications if you find them convenient.
So, basically, helpers in Laravel are built-in utility functions that you can call from anywhere within your application. If they hadn't been provided by the core framework, you might have ended up developing your own helper classes.
Although the core provides a variety of helpers already, there’s always a chance that you’ll need your own and would like to develop one so you don’t have to repeat the same code here and there, thus enforcing better maintainability.
all() find() where() etc.. these methods are not utility methods, they are orm methods and coming from Query Builder.
They are static so they provide you using them without creating an instance
Those methods are part of the Eloquent system and help you to retrieve records from your database.
The all method gets all of the records for the given model from the database and returns a Collection of instances of that model. If you were to do User::all(), a collection of every single user in your database would be returned as a Collection of User objects.
$users = User::all(); // Returns a Collection of User objects
foreach ($users as $user) {
// Here, each $user will be an instance of User
}
The find method is used to find a model in the database by its primary key. This method actually returns a single model instance if it finds a record matching the given primary key, or null if it doesn't find anything.
$user = User::find(1); // Find a User with the primary key 1, or null
Those methods aren't actually static, though you can use them as if they were. The find method is a non-static method on the Illuminate\Database\Eloquent\Builder object and the all method is a utility method on Illuminate\Database\Eloquent\Model which eventually calls the Builder object's get method.
When you call User::find(1), Laravel will create a new query or a Builder object and call the find method on the Builder which will return you a new User object, or null. Similarly, when calling User::all(), Laravel will create a new query or Builder object and call the get() method which will return your collection of models.
The Illuminate\Database\Eloquent\Model class uses the __callStatic magic method to redirect static method calls for non-existent static methods to the Builder object. That's how you're able to call them in a static context:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
So you could effectively do this to achieve the same results:
$user = (new User)->find(1);
$allUsers = (new User)->get();
Related
Okay, so here's the deal. I'm working with a custom CMS, and I'd like for the code to be as optimized as possible. I've been reading/watching tuts/etc. like crazy about the repository pattern in general as well as specifically using it with Laravel's Eloquent. There are probably some really dumb questions/thoughts in here, but bear with me. :-) Sometimes there's no easy way to ask about terminology/best practices without looking silly.
As with many things, there are million ways I could "make it work"; my dilemma is essentially a matter of "best practice."
General Scenario/Question
Let's assume I am trying to get a Page for my CMS from the database. From what I can understand the typical way to set up the repository pattern with Eloquent is to have the following files:
Page.php -- the Eloquent Model
PageRepositoryInterface.php -- the "contract" for what should be in Page repo's
EloquentPageRepository.php -- the Page repository that can grab data via Eloquent
Easy enough. So I might use it this way. Assuming I have a getPageById method in EloquentPageRepository.php, I could just do something like this from my controller:
$page = $this->repo->getPageById();
Now my question arises: what type of data should getPageById() return? Some people recommend setting it up to return an Eloquent collection. Others say just a plain array or generic object.
Ideally I feel like my scenario would best lend itself to having EloquentPageRepository grab the data from Eloquent and actually return an instance of a custom Page class that I have. For example, something along the lines of this:
<?php namespace Acme\Repositories\EloquentPageRepository;
use Acme\...\PageObject as PageObject; // Better name than PageObject?
//...
class EloquentPageRepository implements PageRepositoryInterface {
// Omitting constructor, etc.
public function getPageById($id)
{
// Grab the row via Eloquent (obviously not stored in Page:: at
// this point. I'm just using it here for clarity and time's sake.
$page = Page::find($id);
// Now we have an Eloquent collection stored in $page, but I'd
// like to return the data inside an instance of my custom class.
$pageObj = new PageObject($page->title, $page->body);
return $pageObj;
}
}
To me, this seems good because it gives a consistent delivery format from repo to repo. It also allows me to perform some constructor logic on my pageObject. Finally, it allows me to have some custom methods on the PageObject (that are repository-agnostic).
It's similar to a collection, but I don't think it's exactly that. It's basically just an instance of a class that I'm immediately populating with my database info.
My questions, listed:
Is it considered bad practice to use a repo to stuff eloquent data into a specific object and return it?
I don't want to call my class "PageObject," because that's just lame. I'd way rather call it something like "PageCollection," except for the fact that it's not actually a collection. Is there actually a name for the way that I'm using this class? It's not a collection, it's a ...? I have no idea about this, I'm just searching for any input you have.
It whole depends on what you expect from the repository pattern. Are you using the repository pattern because in the future you're going to swith of data layer and needs a new repository. If you're using Eloquent as long as your cms live then you can return an eloquent object. If you want it very flexible then make a new page object(PageComposer as mentioned in the comments). This is one of the strengts of the repository pattern so I suggest you make a PageComposer class which you instantiate and return by the repository.
Normally you can call it Page because its a page and it ships some information of a page. But that name you've already give to the Eloquent model. You can consider changing the eloquent models name and call your return object Page.
I'm using the Symfony2 PHP framework with Doctrine ORM and mysql for storing data.
My goal is to populate Doctrine entities(PHP objects) by loading the data from a legacy database system which returns the data in key:value pairs.
I have many PHP objects('Company','Employee',etc.) that extend the same Abstract Class('AbstractDatabaseRecord').
My abstract class('AbstractDatabaseRecord') has a property('DatabaseTable') which tells me which table to use when loading data for each object('Company','Employee',etc.).
My abstract class implements an interface ('DatabaseLoadable') which requires a method called getColumns() which should return an array of the columns that make up the objects properties. The interface also requires a method called loadDatabaseData() which should process the array returned from the legacy system, and run the appropriate setters to populate the PHP object.
I have a Symfony2 service(PHP class) called LegacyDatabase that has a couple methods called findOne() and findAll().
findOne(AbstractDatabaseRecord $object, $id) accepts an object, uses the DatabaseTable property to determine which table to query, and then queries that table using the id. It then populates the object using its loadDatabaseData() method and returns the object to me so that I can use it.
I think this one is structured OK, but I am not sure how to implement the findAll() function.
findAll(AbstractDatabaseRecord) accepts an object, uses the DatabaseTable property to determine which table to query, and then selects ALL records from that table. I then loop through the results and ideally will populate a new object for each record found, place the objects in an array, and return the array of newly created objects for me to use.
However in the function I only have the one instance of the object. What would be the best way to create additional instances given that I do now know the Concrete Parent class that is passed in?
From my research it seems like I want to clone the object to get a shallow copy, and then populate that new copy and add it to my array of objects. Is this the best approach?
I use Eloquent to implement my models. It has a lot of methods that makes working with models much easier. However, in some cases I have to implement functionality that is accessing the database, but doesn't return an Eloquent model.
For example, imagine a common User model. Eloquent helps me a lot in CRUD operations for the User model, but what if I have to implement a method that returns some statistics about users (ex. how many total users, how many active users, etc.).
Where should I implement this functionality? In the Eloquent model, as a public static function, (e.g. User::getStats()), or should have a different class for this.
It seems a little bit unnatural to have these methods on a Eloquent model, because they are not Eloquent related.
It's really up to you, but it's a good idea to decide on a convention and stick to it.
My rule of thumb is this:
if it's related to a single item that is normally represented by an Eloquent model, do it as a public static method on that model. For example, in my current project, I have a Contract model. I needed a method that would generate a contract ID string (for compatibility with legacy systems) for new contracts. This is related to a single item (a contract) but for technical reasons needed to be generated separately from the Eloquent model (ie. it was based on a separate database with a different connection). So I created a public static method: public static function generateContractIdentifier($id, $salesRep). If you're using a repository for access to your database, you could put it there.
If it's more general (ie. not tied to an instance of the Eloquent model), I put it into a separate library. For example, in the same application I have a queue for processing items for printing (an industrial process). The application has a dashboard and I needed to show the current queue status for management. For this I created a ProcessStatus library and implemented a method: public function getStatus() which runs a query and provides the results as an array for display in a view. This is not related to any particular item in the queue, so I put it in a separate library.
As always, it depends on your project and what role the user plays in it.
But basically, no, I don't think the logic for building reports belongs on the user model. While it may be related to the user, regarding the SOLID-principle the User class should only have one responsibility, which in this case is to handle the User entity.
This contains getting and setting properties on an instance, in a simple project it's probably also fine to define some scopes on the model, e.g. to select only active users, like User::getActive();
But as your project grows, you should consider using more specific classes.
For instance, you could abstract the Eloquent functionality into a User-Repository. So now you have a handler for operations on the entitiy itself, like
$userRepo->getAll();
$userRepo->getActive();
$userRepo->getInactive();
and a handler for a User instance:
$user->getName();
$user->setStatus();
Creating reports and statistics is yet a completely different topic. So you could have something like a UserReportBuilder oder UserStatisticsService:
$userStats->getMostActive();
$userStats->getRegistrationsPerDay();
A simple example:
// UserRepository:
class UserRepository
{
protected $model = $model;
public function __construct($model)
{
// you pass in an instance of the actual Eloquent model
// so you have the whole power of eloquent in here
$this->model = $model;
}
public function getActive()
{
// this returns a collection of models
return $this->model->where('status', 'active')->get();
}
}
$userRepo = new UserRepo(new User);
And that's pretty much it. You can still work with Eloquent, but you have separated the functionality in parts with a clewar responsibility. So your UserStats class would only be resposible for building user statistics:
class UserStats
{
// You could pass in the Repository through the constructor
// or just use the Eloquent model directly
public function getRegistrationsPerDay()
{
return User::groupBy('day')->get(
[
DB::raw('DATE(created_at) as day'),
DB::raw('count(*) as registration_count')
]
);
}
}
The User instance or the UserStats-builder do not need to know how to fetch all users, and the User instance or the UserRepository do not need to know how to calculate registrations per day, so it makes sense to split that functionality into separate, independent parts that do exactly one thing.
I think you get the idea and I hope it makes sense. Maybe you should make yourself more familiar with the SOLID-principles and try to keep them in mind when you get stuck on problems like that.
I know that Singleton pattern is bad because it uses global state. But in most applications, you need to have a single instance of a class, like a database connection.
So I designed my Database object without using the singleton pattern but I instanciate it only once.
My question is, how can I access my object in the low level classes (deep in the object graph) without passing it all over the place?
Let's say I have an application controller which instanciates (ask a factory to instanciate it actually) a page controller which instaciates a User model which requires the database object.
Neither my app controller nor my page controller need to know about the database object but the User class does. How am I suppose to pass the object to it?
Thanks for your time!
Consider using a global container:
You register the objects that are indeed relevant to the several subsystems of the application.
You then request that container those objects.
This approach is very popular in dependency injection frameworks (see Symfony DI, Yadif).
Singleton is bad, no doubt about it.
In the case you describe, the database object is an implementation detail of the User object. The layers above need only know about the User, not the database object.
This becomes much more apparent if you hide the user object behind an interface and only consume that interface from the layers above.
So the page controller should deal only with the interface, not the concrete class that depends on the database object, but how does in create new instances? It uses an injected Abstract Factory to create instances of the interface. It can deal with any implementation of that interface, not only the one that relies on a database object.
Once more, you hide the page controller behind an interface. This means that the concrete implementation's reliance on the Abstract Factory becomes another implementation detail. The Application Controller only consumes the page controller interface.
You can keep wrapping objects like that like without ever needing to pass around instances. Only in the Composition Root do you need to wire all dependencies together.
See here for a related answer with examples in C#: Is it better to create a singleton to access unity container or pass it through the application?
The way I've always accomplished this is to implement a static getInstance function that will return a reference to the single instance of that class. As long as you make sure that the only way you access the object is through that method, you can still ensure that you only have one instance of the singleton. For example:
class deeply_nested_class {
public function some_function() {
$singleton = Singleton::getInstance();
}
}
There are two main objects involved in loading/saving a user using the database: the user and the repository.
You seem to have implemented the functionality on the User, but I think it belongs on the Repository. You should pass the user to the Repository to save it.
But, how do you get hold of the Repository? This is created once at the top level and passed into services that need it.
The construction dependency graph and the call dependency graph are not the same thing.
Given the example you outlined, you are almost there. You are already using a factory to instantiate your page controller, but your page controller is instantiating the users directly and as your User needs to know the database.
What you want to do is use a factory to instantiate your User objects. That way the factory can know about the database and can create User instances which know about it too. You will probably be better off making interfaces for all the dependencies, which will help with testing and will mean your code is nicely decoupled.
Create an IUserFactory which creates IUser implementations and pass this into your PageControllerFactory, then your ApplicationController only needs to know about the PageControllerFactory, it doesn't need to know anything about the IUserFactory or the database.
Then in your application start up you can create all of your dependencies and inject them in to each other through the constructors.
I'm working on a PHP web app and I'm trying to use the MVC model. I have a lot of things that exist as 'database entities' -- a row, or a set of related rows, that are conceptually one human recognizable 'thing'. So I often try to provide an interface to that thing in a model class.
So of course, the run of the mill functionality is to have an existing entity, get some data from it, and sometimes update it. However, where I run into problems is when I need to create a new entity. None of the default data for an existing entity exists yet!
For instance, my __construct() methods will often have arguments (i.e. $id for WHERE id = $id) so that I can select data from the database and populate all the properties of the object from that data. However, when I want to create a new entity, the values for those arguments don't exist yet!
How do you all handle this situation? Do you
try to provide functionality for both creation and subsequent manipulation in the same object
have another class just for generating the entity
avoid __construct and have somthing like create() for new entities and instantiate() for existing ones
something else?
If you need the ability to create "new" objects, then I don't think your constructors should be loading from the database by default. Since PHP doesn't support function overloading (so you can't have overloaded constructors), you can either just remove the "populate from database" code from the constructor into a function for that purpose, or give the $id-type argument a default value that indicates that properties shouldn't be populated from the database:
function __construct($id = 0)
{
if ($id == 0)
// create with blank properties
else
// load from database
}
Then if you want a new object, you just call it with no arguments, and if you want to load from the database, you include the id argument.