i'm currently working on a php-framework to abstract and make it fun and easy to work with an external software ($ES) my company consults. My approach is the hexagonal design pattern, which works great so far. My only concern is mapping (and where to map) entities from $ES to our internal structure.
Example:
$externalSoftwareProduct (kind of a god class which handles everything)
is mapped to $internalFrameworkProduct (and many other classes to split responsibilities). This happens in Repositories. In every repository method, i collect those entities from $ES and do
new $internalFrameworkProduct(some arguments here coming from
$externalSoftwareProduct)
foreach of my collected entities which then gets returned. In those repositories there are only generic methods, like getById, getAll, you name it.
Now we use this framework in a customer project and extend those base classes with domain specific extension, like CustomerNameProductRepository.
There you find domain specific methods like getProductsCustomerAlwaysNeeds and so on. At the end of those methods, we map the $internalFrameworkProduct to $customerSpecificProduct which holds data for easier access, which is needed. A method in this specific repository looks like this.
public function getProductsCustomerAlwaysNeeds()
{
$dataStuff = parent::getSomeStuff();
/** #var internalFrameworkProduct[] $products **/
$products = magic();
foreach($products as $product)
{
$customerProducts[] = $this->getCustomerSpecificProduct($product->getId());
}
return $customerProducts;
}
public function getCustomerSpecificProductById(int $productId)
{
$externalSoftwareProduct = new externalSoftwareProduct($productId)
$customerSpecificProduct = new CustomerSpecificProduct(some arguments here coming from $externalSoftwareProduct)
return $customerSpecificProduct;
}
Now this works fine so far. The only problem is in unit tests. We are using phpunit + Mockery. In order to mock those new created instances we have to use mock(overload:externalSoftwareProduct) and mock(overload: CustomerSpecificProduct) which is always a pain (especially if you try to test this with multiple instances, which is needed from time to time).
How would you approach this? There must be a better way to get those 3 Pieces connected (externalSoftwareProduct, internalFrameworkProduct and CustomerSpecificProduct (which extends internalFrameworkProduct)).
I was thinking about using a factory for the CustomerSpecificProduct in order to just mock the factory and let it spit out my Products. But i feel like im overengineering such a simple task.
«.... mapping (and where to map) entities from $ES to our internal structure...»
In the adapter you use to access the external software.
Related
I've been working on a project and I decided it'd be a good idea to have some sort of, like, DAO, but simplified.
Basically, the only thing I want from it (right now, at least) is to fetch me objects by model name and id. I wrote this very simple piece of code:
class DAO {
public static function get($className,$id) {
$queryName = $className."Query";
if (!class_exists($className) || !class_exists($queryName)) {
return false;
}
$q = $queryName::create()->filterByID($id)->find();
return $q;
}
}
However, I found myself stuck with the implementation. I guess I need to somehow autoload it so that it'll be able to check for the existence of the classes and so that I could use it anywhere inside my app, but I don't know how. Can anyone help me out? Or if there's a better way to do that, I'll appreciate any input.
What you're looking for is a Service.
Definition from the documentation:
Put simply, a Service is any PHP object that performs some sort of
"global" task. It's a purposefully-generic name used in computer
science to describe an object that's created for a specific purpose
(e.g. delivering emails). Each service is used throughout your
application whenever you need the specific functionality it provides.
Defining your class as a service is as simple as this:
app/config/config.yml
...
services:
my_dao:
class: Your\Bundle\DAO
...
Now you can access DAO in your controllers doing something like this:
$dao = $this->get('my_dao');
When you make this call, the Service Container will create an instance of your class and return it. There will always be at most one instance (singleton) and if it's never called, it won't even be instantiated.
I recommend reading the documentation.
Opinion
It seems like you're having trouble adapting to the Symfony way.
If you take a look at The Book you'll see that the Entity Manager in conjunction with your entity's Repository handle most of what DAO's traditionally did. In other words, there's really no need for your DAO class.
For example, fetching any object by id is as easy as:
$om->getRepository('YourBundle:YourModel')->find($id);
Anyway, if you're particularly fond of that approach, you may want to try this project.
I'm building a parser system that will parse loads of different XML/JSON feeds upon request/cronjob.
I use Laravel 4.
The purpose of the thread is to use IoC in my context, and not hardcoded Model names in custom-class methods
Providing an example of parser for Soccer Player with XML structure like:
<players category="Midfielders">
<player id="777">
<name>Caio Augusto Paim do Santos</name>
<statistic>
<club name="Camaçari" id="7191" league="Baiano 2" league_id="1136" season="2013" minutes="" appearences="" lineups="" substitute_in="" substitute_out="" substitutes_on_bench="" goals="" yellowcards="" yellowred="" redcards=""/>
I've created an additional directory in my /app folder called /parsers These are custom classes, they all extend or implement custom abstracts/interfaces in the same folder and basically are responsible for receiving path to XML/JSON file and returning a well-structured PHP arrays.
They are added in composer.json in autoload as: "app/parsers"
Screenshot of file structure attached
All is good and the code/classes are testable and not dependent on another classes, but here's the problem.
Checkout the XML example, there's thing like:
<club id="XXX" league_id="YYY" />
this is feed club id and feed league id, but I have my own IDs in database referenced to feed IDs.
Like on this screenshot:
So the logic says: Go to database, check if there's id in league league table with feed_id provided from XML file.
If yes, get it, if not, create a new league and get the id for future references.
This requires me to use Model in my parser classes, now I know you can use IoC and inject models into Controllers, but I'm not sure I can do the same with my parser classes...
So doing something like this in the middle of my parser class:
// Try to get league and season ids from database if they already exists, if not, insert
$leagueId = DB::select('SELECT id FROM league WHERE feed_id=?', array($data['league_id']));
or
$league = new LeagueModel();
Is pretty much incorrect.
Now just to clarify the way it all works, my parsers are getting called in Laravel Command classes like this:
/**
* Execute the console command.
*
* #return void
*/
public function fire()
{
$this->setParser();
$this->setStorage();
$this->parser->parseFile($file);
}
And Laravel Command classes are getting called in my Controllers like:
$stamps = $this->getStamp();
Artisan::call('command:getSoccerPlayer',array('stamps' => $stamps, 'parser_id' => Request::segment(2)));
The Controller itself is called via URI:
/jobs/soccer_player/parse?type=soccer&directory=players
**What do you suggest or how would you overcome this issue to avoid dependencies and still use Models for interactions with the database in this context? **
P.S Please don't pay attention that the whole parse logic on my screenshot is in the same method "parse" now, I will break it into pieces once I see the full picture of how I want it to work/look.
Appreciate any help!
you can still call your namespaced models
use App\Models\League;
class SoccerPlayerParser extends AbstractParser{
//...
public function parse()
{
//...
$league = App\Models\League::find($data['league_id']);
//...
}
//....
}
I see two possible solutions here, but am not 100% sure how to integrate it in your project.
The first is to store the name of the model class to use in a config file and intantiate the model via new $class where $class is a value retrieved via Config::get or similar. This solution is very common in packages, and even Laravel itself uses it (see the model setting in app/config/auth.php).
The other is to not instantiate the model, but instead create an interface for it and then dependency-inject it into your command. You can easily auto-inject stuff into your commands by using Artisan::resolve('MyNamespace\MyCommand') instead of Artisan::add(new MyCommand), and then inject via type hinting as you do via controllers. http://laravel.com/docs/ioc#practical-usage
Once you've set up the interface as an argument to the command's constructor, you can use App::bind('MyInterface', 'MyModel') to tell Laravel which class to inject, and this can be swapped at any point.
I'm building a web application that needs to be able to write data to either a mysql db or an xml file, depending on the online status of the application.
In my model, I have a super class (Dao is data access object)...
abstract class Dao {
static function getInstance($online_status) {
if $online_status = 'online' {
return new DaoMySQL;
} else {
return new DaoXML;
}
}
abstract function dao_select();
abstract function dao_insert();
abstract function dao_update();
abstract function dao_delete();
}
Now, here is the part I'm confused about. I have a domain model/entity class that selects the appropriate Dao using:
$this->dao = Dao::getInstance($online_status);
So, now I have the correct data access object selected. But, the problem is I still two implementations of dao_select() and the other functions. Now, the main implementations are in the respective classes DaoMySQL and DaoXML, but dao_select() in each of those classes require different things. i.e. the DaoMySQL version needs two parameters, $table and $where_statement. DaoXML (which I haven't implemented) will need the element name, and maybe another argument, I don't know.
So, in my domain model class, after calling
$this->dao = Dao::getInstance($online_status);
is this where I need to include two separate local implementations (pertaining to the domain model/entity class only) of dao_select(), or this wrong? It just seems like I'm taking the elegance out of the process by doing something like this:
class EntityModel {
$this->dao = Dao::getInstance($online_status);
if($this->dao->type = 'mysql') {
$result = $this->dao->dao_select($table, $where);
} else {
$result = $this->dao->dao_select($xml_params);
}
}
I feel like I'm taking the simplicity out of the system... Does this approach make sense, or is there a better one?
You are doing it wrong.
Few notes to begin with:
in OOP the extends statement signifies is a relationship. Which means that, while class Duck extends Bird is all fine, writing class User extends Table is NOT.
in MVC the Model is not a class or an instance of a class. Instead it is a layer of application, mostly made of two types of elements:
domain objects: containing domain business rules and logic
data access structures: usually datamapper dealing with storage and retrieval of information
I would argue, that the third significant part of Model layer are services. But there are options on whether it is part-of or above Model.
Currently what you are trying to do is forcing a ActiveRecord (which is fine for small things, but as project grows, it becomes a burden on architecture .. which is what you are face with now) patterns to work with dynamic data sources. And to do so you are resorting to procedural calls.
Anyway, the point is that you should inject your DAO instance into your Domain Objects (what you calls "models"). And you should leave the creating of your DAO to a separate factory instance, which would be responsible for initializing them and providing them with data source (instance of PDO or file path). This way you can, not only separate the responsibilities, but also swap the storage destination "on fly".
To learn more you should investigate what is dependency injection. Here are few video that might help:
Don't Look For Things!
Global State and Singletons
Please be brutally honest, and tear my work apart if you have to.
So I'm re-writing a small web-application that I recently made. The reason for this is simply that the code got pretty messy and I want to learn and apply better OO design. What this application should do is just simple CRUD.
I have a database with 3 tables, companies and partners which are in no relation to each other and city which has a 1:n relation with companies and partners. Very simple, really. Now, I have several questions which i will state at the end of my post. Here i'll just try to explain:
My first approach was that I created classes company, partner and city, fetched all datasets from the database and created objects from that:
class company {
private $id = null;
private $name = null;
private $city = null;
//many more attributes
function __construct( $id, $name, $city, [...] ) {
$this->id = $id;
$this->name = $name;
$this->city = $city;
//huge constructor
}
/*
* getters + setters here
*
* no need to paste the partner class as it looks just like this one
*
*/
}
And that is all these classes did. I fetched every dataset from the database and constructed company, partner and city objects (the attribute city within these classes is an object with several attributes itself) and saved them into two arrays arr_companies and arr_partners, which then held these objects...and it worked fine like that.
Now, what I wanted is to update, insert, delete into the database, and all 3 classes (city, company, partner) need this functionality. My approach was that I created a new class with a constructor that would basically take 2 strings command and object, e.g. ('update', 'company') and it would then update the company directly in the database leaving my objects untouched. That made me really sad, because I had such nicely constructed objects and I didn't know how to make use of them.
Questions:
Is it bad to have such huge constructors (my biggest one would take
28 parameters)?
Should you have a separate class for database
operations or is it better to have maybe an abstract class or
interface for it and let the subclasses themselves handle update, delete, insert?
Is it common to just write, delete from the database whenever or should I just apply these changes to my objects and only execute the commands to the database later, for example when the session ends?
I figure an application like this must have been done a fantastillion times before. What is the proper approach here? create objects, work with objects, save them to the database?
I have so many questions but I think many of them I just don't know how to ask.
Please note that if possible I would not like to use an ORM at this point.
Thank you very much for your time.
Questions posed in OP:
"Is it bad to have such huge constructors (my biggest one would take 28 parameters)"?
Yes. Imagine the calling code. You would have to pass 28 different values, not to mention each call would have to respect the exact order specified in the constructor. If one parameter was out of place, you could wreck havoc with parameter dependent algorithms. If you really need to pass a large number of parameters, I would recommend passing them in as an array (posted an example to another SO question).
"Should you have a separate class for database operations or is it better to have maybe an abstract class or interface for it and let the subclasses themselves handle update, delete, insert?"
Generally speaking, when creating classes, you want to try to identify the nouns that best represent your business needs. In your specific case you would probably have three classes; Company, Partner, and City.
Now within each class (noun), your methods would be in the form of verbs, so symantically your calling code makes sense: if ($company->getName() === 'forbes')
As you mentioned, each class needs a database object (dbo) to work with, so you could implement any number of patterns to expose datase connections to your classes; singleton, singleton with factory, or dependency injection, etc.
Abstract (parent) classes are great for sharing common algorithms across child classes, and should be identified when you are in the psuedo-code stage of your design. Parent classes also allow you to force child classes to have methods by declaring abstract methods within the parent.
Interfaces are a useful tool in certain situations, but I find they are less flexible than declaring abstract methods in parent class. But are good in situations where classes do not share a common parent.
"Is it common to just write, delete from the database whenever or should I just apply these changes to my objects and only execute the commands to the database later, for example when the session ends"?
CRUD activity should happen at the time the action is executed. If you wait for the session to end, you may run into situations where a session is pre-maturely ended due to a user closing a browser, for example. To better protect your data you can wrap your CRUD activity within transactions.
If you are running a high-traffic application, you can implement a queuing system and queue up the work to be done.
"I figure an application like this must have been done a fantastillion times before. What is the proper approach here? create objects, work with objects, save them to the database"?
You are correct, this has been done before, and are commonly referred to as ORMs (object relation mappers). Basically, an ORM will introspect your database schema, and create objects (and relations) which represent your schema. So instead of working with native SQL, you are working with objects. Although you can use SQL for custom business needs, but in the case of Doctrine, you would use Doctrine Query Language (DQL) vs native SQL.
An ORM I would highly recommend is Doctrine.
If you do not want to use an ORM, you can add CRUD methods to your primary classes. I Opted for an interface so your classes don't have to extend from a parent comprised of database operations. Also, check out this post on using a singleton/factory for exposing your classes database object(s).
Consider the following:
// Company.php
class Company implements iDatabaseOperation
public function delete()
{
// Lets use a DBO singleton/factory for DB access
// Uses PDO, which is strongly recommended
$dbo = Database::factory(Database::DATABASE_NAME);
$dbo->beginTransaction();
try {
$sql =
"DELETE FROM " .
" company " .
"WHERE " .
" id = :companyId " .
"LIMIT 1";
$stmt = $dbo->prepare($sql);
$stmt->bindValue(':companyId', $this->getId());
$stmt->execute();
$dbo->commit();
} catch (Exception $e) {
$dbo->rollback();
error_log($e->getMessage();
$e = null; // Php's garbage collection sucks
}
}
}
// iDatabaseOperation.php
interface iDatabaseOperation
{
public function delete();
public function update();
public function insert();
}
It is realy bad. Code is completele unreadable in this case. You have options
to use setters (can add validation logic inside, better readability, no need to fill empty fields with null)
to have separate class builder for each domain class (takes some memory for additional object). Example in java hope you can understand:
class CompanyBuilder {
private final Company c;
public CompanyBuilder() {
c = new Company();
}
CompanyBuilder addId(String id){c.id = id;}
// id should be package visible and class should be located in the same package with builder
CompanyBuilder addName(String name){...}
CompanyBuilder addCity(String city){...}
Company build(){ return c;}
}
hybrid solution to have methods to organise chain(worse debugging, better readability). In java will be methods:
class Company {
...
Company addId(String id){
this.id = id;
return this;
}
Company addName(String name){...}
...
}
Usage:
Company c = new Company().addId("1").addName("Name1");
maybe you can create more granular objects to reuse them later and add specific logic in correct place. For instance it can be Address(Location) object for company.
Follow single responsibility principle. SOLID description on wiki.
It helps to change database specific code without affection of other part of system in your case. Well, separate domain and database specific code, have common interface or abstract class(if you have common logic for all of domain classes - liskov principle). In subclasses implement domain specific part.
If you do not want to lose data you should save them each time or have cluster of servers or have distributed cache. If it is ok to lose save them in the end of session as batch. It will increase youre performance. Also you should save in transaction each time if you have concurrent updates.
Approach is get data from database/construct objects from this data or new objects/ work(update) objects/write data from objects to database
just write more code and read stackoverflow
Finally I suggest to read "Clean Code: A Handbook of Agile Software Craftsmanship" R.Martin.
You are essentially writing your own ORM. So, I wouldn't discount just switching to one that's already been written for you. The advantage to rolling your own is that you gain an understanding of how it works as your write it. But the disadvantage is that someone else has probably already done it better. But assuming you want to continue on...
General Advice: Remember to always break the problem down into simpler and simpler pieces. Each class should only perform a simple function. Also, you should not have to worry about caching updates... unless perhaps your database is on the other end of a remote connection over a modem.
Specific Advice follows:
I would setup your entity instance classes to house data and not to do a lot of data loading. Use other classes and logic for loading the data. I would use the constructor of the entity class only to populate the data that pertains to the class (and it's children).
A simple thing to do is to use static methods on the entity class for loading and saving data. E.g.
class city {
private $id = null;
private $name = null;
function __construct( $id, $name ) {
$this->id = $id;
$this->name = $name;
}
// getters and setters
...
// ---------------------
// static functions
// ---------------------
public static function loadById($cityId) {
// pull up the city by id
$retval = new city(row["id"], row["name"]);
// close db connection
return $retval;
}
public static function loadByCustomerId($customerId) {
// pull up multiple cities by customer id
// loop through each row and make a new city object
// return a hash or array of cities
}
public static function update($city) {
// generate your update statement with $city->values
}
// other methods for inserting and deleting cities
...
}
So now the code to get and update cities would look something like this:
// loading city data
$city = city::loadById(1); // returns a city instance
$cities = city::loadByCustomerId(1); // returns an array of city instances
// updating city data
$city->name = "Chicago"; // was "chicago"
city::update($city); // saves the change we made to $city
The static methods are not the best way to implement this, but it gets you pointed in the right direction. A repository pattern would be better, but that's beyond the scope of this one answer. I find that often I don't see the merit in a more involved solution like the repository pattern until I run into problems with the simpler solutions.
What you are doing looks greate. What you can add is an intermediate layer which maps your business object to your database(object relation mapping). There are a lot of object relational mapping api out there. Check this wikipedia list for ones you can use for PHP
I think a constructor with 28 parameters is too much, you should others classes managing some attributes having some stuff in common. You should give us what kind of others attributes you instanciated, and it could help you to find a way to make more common objects.
I think you should also create a class managing the operations and the database like a DBHandler with delete, update, and so on..
In my opinion, do modifications on tuples in your database directly after functions are called are important.
Why? Because it could avoid conflict, like the case you try to update an object which is supposed to be deleted for example, if you do modifications on your database at the end.
You might want to look at ruby on rails.
You don't necessarily have to switch over to it, but look at how they implement the MVC pattern and achieve CRUD.
From a maintenance and code organization standpoint, in PHP5, does it make sense to create/define objects and classes for XML data coming from a web service?
Using Twitter's API as an example, I would have a class for each API method (statuses, users, direct_messages, etc). For statuses/public_timeline, I would have something like this:
class Statuses {
public $status = array(); // an array of Status objects
public function __construct($url) { // load the xml into the object }
}
class Status {
public $created_at, $id, $text; // and the rest of the attributes follow...
}
$public_timeline = new Statuses('http://twitter.com/statuses/public_timeline.xml');
echo $public_timeline->status[0]->text;
Or is it better to dump everything into an associative array, so items would be accessed like this:
// the load_xml function is just something that will dump xml into an array
$public_timeline = load_xml('http://twitter.com/statuses/public_timeline.xml');
echo $public_timeline['statuses']['status'][0]['text'];
First design:
Strictly following object-oriented principles
Seems like an approach better suited for compiled languages
Second design:
A lot less maintenance would be needed if the API is modified. If the API adds an attribute to the XML, the corresponding class would need to be updated in the first design.
I think this depends on your project ...
First design:
Strictly following object-oriented principles
Seems like an approach better suited for compiled languages
Necessary in a big application
Easy to reuse
Benefiting when passing data around
You have methods to add functionality, not just data
Second design:
A lot less maintenance would be needed if the API is modified. If the API adds an attribute to the XML, the corresponding class would need to be updated in the first design.
Straight forward & quick solution
Little code
I'm with Philippe: if your application is going to be really small (just calling the status methods for example), go with solution 2.
I agree that creating a bunch of classes just to echo status informations isn't really needed in the first place. But if your application it's going to be huge, design with solution 1 in mind. As you go along with your development, you're going to create specific methods that would belong to specific classes. Sometimes you would like to create a method to "order" status messages. Who knows? That's why we create classes, each one with it's own responsibility, so you wouldn't need to search a big php file with hundreds of functions.
I do believe that if you don't know how your application is going to grow, a "best-of-both worlds" approach would be creating classes to at least each Twitter categories (Timeline, Status, User, etc, totalizing maybe 12), instead of each method. Is a good solution IMO in your case, if you don't want to create too many classes.
If you're working with XML in PHP5 then I think the best would be to use SimpleXML. Then you have the best of both worlds. You can access your values in a very array-like way. However you can extend SimpleXML class to provide methods and other custom nice-to-haves.
// To get the effect of an array...
$twitte = 'http://twitter.com/statuses/public_timeline.xml';
$public_timeline = simplexml_load_file($twitte);
echo $public_timeline->statuses->status;
Or extend the SimpleXml Class
class MyXml extends SimpleXml
{
public function quickStatus()
{
$status = $this->xpath("/statuses/status");
return (string)$status[0];
}
}
// then access like
$twitte = 'http://twitter.com/statuses/public_timeline.xml';
$public_timeline = simplexml_load_file($twitte, 'MyXml');
echo $public_timeline->quickStatus();
The above example is just to show how to extend the class. If you'd like more info you can check out the XML class from a library I've created on Google Code