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?
Related
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();
I'm using Laravel and Eloquent (ORM) specifically, but I believe this to be a general MVC question...
I have a view and a couple of controller methods that receive an Eloquent Object, and can access the attributes by $foo->bar (again this is an Model Object).
I want to re-use these same views\controller methods with some objects that I create manually. These objects will not be persisted to the DB, but they have the same design and structure as the Eloquent objects (they are essentially a heavily filtered\modified subset of data retrieved that I'm unable to re-create from an Eloquent statement).
Let's assume I have a Foo.php model that Eloquent uses. For the manually created Foo object, should I use the Foo.php model or create another Foo.php class?
And specific to Laravel, where should this live and how to do I keep from being confused about which Foo I'm using?
In other words. To re-use code (in view\controller) that receives and Eloquent (ORM) Object, should I create a new class for objects not retrieved from the DB (created manually), or should I use the existing model?
It really depends on the size of your project and how much you want to decouple the Eloquent from your views.
If this is a huge project that maybe in the future you would remove eloquent, so create a class that will be passed to the views as simple data objects.
If you think that eloquent is here to stay, so simply create manually the eloquent object and pass it to the views.
here are some of the options:
option 1: manually create eloquent object (without persisting)
$eloquentForView = new Whatever();
$eloquentForView->username = "just for view";
option 2: create an object specifically for your views
class WhateverDataView {
public $username;
}
option 3: simply pass an array
from eloquent object:
$eloquentObj->toArray();
simple code
$dataForView = ['username'=>'whatever username'];
I've got an object with values that are stored in my database. My object also contains another object which is stored in the database using just the ID of it (foreign key).
http://framework.zend.com/manual/2.0/en/modules/zend.stdlib.hydrator.html
Before the Hydrator/exchangeArray functionality in ZF2 you would use a Mapper to grab everything you need to create the object. Now I'm trying to eliminate this extra layer by just using Hydration/exchangeArray to populate my objects but am a bit stuck on creating the nested object.
Should my entity have the Inner object's table injected into it so I can create it if the ID of it is passed to my 'exchangeArray' ?
Here are example entities as an example.
// Village
id, name, position, square_id
// Map Square
id, name, type
Upon sending square_id to my Village's exchangeArray() function. It would get the mapTable and use hydrator to pull in the square using the ID I have.
It doesn't seem right to be to have mapper instances inside my entity as I thought they should be disconnected from anything but it's own entity specific parameters and functionality?
I think you may benefit from looking at Zend\Stdlib\Hydrator\Strategy\StrategyInterface.
By creating a Strategy class you can attach this to your Hydrator, so when a specific key is found (square_id in this case) the Hydrator passes the data onto the Strategy class to either extract() or hydrate().
The Strategy class can then do whatever is required to hydrate and extract the data. I use a couple of Strategy classes that simply getArrayCopy()/exchangeArray() and other strategies that hydrate/extract multiple entities.
I'm just wondering if someone can help me understand how to make the best use of objects in PHP.
My understanding of a PHP object is that is should represent an entity, providing methods to get and alter the properties of that entity. For example an object entitled Post would hold all the properties of a single post, which could be accessed and modified as appropriate.
What causes me some confusion is that libraries like CodeIgniter don't use objects in this manor. They treat classes more like wrappers for a group of functions. So a 'Posts' class in CodeIgniter would not hold properties of one post, it would provide functions for fetching, editing and deleting posts.
So what happens if I want to get every post out of a database and put it into a Post object? My understanding of it is I would in fact need two classes 'Posts' and 'Post', one that defines the Post object and one that handles fetching the Posts from the database and putting them into Post objects.
Do these two types of class have a name ('Proper' objects / Collections of functions)? And is it common to have two classes working together like this or have I completely misunderstood how to use objects?
Instead of having a Post object would it make more sense to have a method in my Posts class called getSinglePost($id) that just returned an array?
Hopefully that question makes sense, looking forwards to getting some feedback.
For an introduction, see What is a class in PHP?
For the answer, I'll just address your questions in particular. Search for the terms in bold to learn more about their meaning.
My understanding of a PHP object is that is should represent an entity, providing methods to get and alter the properties of that entity.
Entities are just one possible use for objects. But there is also Value Objects, Service Objects, Data Access Objects, etc. - when you go the OO route, everything will be an object with a certain responsibility.
What causes me some confusion is that libraries like CodeIgniter don't use objects in this manor.
Yes, Code Igniter is not really embracing OOP. They are using much more of a class-based-programming approach, which is more like programming procedural with classes and few sprinkles of OOP.
They treat classes more like wrappers for a group of functions. So a 'Posts' class in CodeIgniter would not hold properties of one post, it would provide functions for fetching, editing and deleting posts.
That is fine though. A posts class could be Repository, e.g. an in-memory collection of Post Entities that has the added responsibility to retrieve and persist those in the background. I'd be cautious with Design Patterns and Code Igniter though since they are known to use their own interpretation of patterns (for instance their Active Record is more like a Query Object).
So what happens if I want to get every post out of a database and put it into a Post object?
Lots of options here. A common approach would be to use a Data Mapper, but you could also use PDO and fetch the data rows directly into Post objects, etc.
My understanding of it is I would in fact need two classes 'Posts' and 'Post', one that defines the Post object and one that handles fetching the Posts from the database and putting them into Post objects.
That would be the aforementioned Repository or Data Mapper approach. You usually combine these with a Table Data Gateway. However, an alternative could also be to not have a Posts class and use an Active Record pattern, which represents a row in the database as an object with business and persistence logic attached to it.
Do these two types of class have a name ('Proper' objects / Collections of functions)? And is it common to have two classes working together like this or have I completely misunderstood how to use objects?
Yes, they work together. OOP is all about objects collaborating.
Instead of having a Post object would it make more sense to have a method in my Posts class called getSinglePost($id) that just returned an array?
That would be a Table Data Gateway returning Record Sets. It's fine when you don't have lots of business logic and can spare the Domain Model, like in CRUD applications
Class should ideally has the same interpretation as anywhere else in PHP as well. Class starts with abstraction, refining away what you don't need. So it's entirely up to you to define the class the way you want it.
Codeigniter does have a strange way of initiating and accessing objects. Mainly because they are loaded once and used afterwards, prevents it from having functionality around data. There are ways around it and normal handling of classes still possible. I usually use a auto loader and use normal classes.
"So what happens if I want to get every post out of a database and put it into a Post object? My understanding of it is I would in fact need two classes 'Posts' and 'Post',"
You are essentially referring to a MODEL to access the data ("posts") and an Entity to represent the "post". So you would load the model once and use it to load up as many entities as you would like.
$this->load->model("posts");
$this->posts->get_all(); // <- This can then initiate set of objects of type "Post" and return. Or even standard classes straight out from DB.
Your understanding of an object is correct. A post is a single object of a class Post. But of course you need a function, that retrieves posts from a database or collects them from somewhere else. Therefore you have so called Factory classes. That's what can cause some confusion.
Factories can be singletons, which normally means that you have one instance of this class. But you don't need to instantiate a factory at all (and instead use static functions to access the functionality):
$posts = PostFactory::getPosts();
And then the function:
static function getPosts() {
$list = array();
$sql = "select ID from posts order by datetime desc"; // example, ID is the primary key
// run your sql query and iterate over the retrieved IDs as $id
{
...
$post = new Post($id);
array_push($list, $post);
}
return $list;
}
Inside this factory you have a collection of "access"-functions, which do not fit elsewhere, like object creation (databasewise) and object retrieval. For the second part (retrieval) it is only necessary to put the function into a factory, if there is no "parent" object (in terms of a relation). So you could have an entity of class Blog, you instantiate the blog and then retrieve the posts of the blog via the blog instance and don't need a separate factory.
The naming is only there to help you understand. I wouldn't recommend to call a class Post and it's factory Posts since they can easily be mixed up and the code is harder to read (you need to pay attention to details). I usually have the word "factory" mixed in the class name, so I know that it is actually a factory class and others see it too.
Furthermore you can also have Helper classes, which don't really relate to any specific entity class. So you could have a PostHelper singleton, which could hold functionality, which doesn't fit neither in the object class nor in the factory. Although I can't think of any useful function for a Post object. An example would be some software, which calculates stuff and you have a Helper, which performs the actual calculation using different types of objects.
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.