Design patterns : How edit multiple entities from within a gateway - php

We are now in a situation on a project that we need manipulate multiple user entities at once. By example we will disable 50 users at once. Normally we did that in a gateway
Gateway
Query the data at once by the gateway with a query
OR
Loop through multiple users
Load entity
Manipulate data
validate
save()
But that is not the best practice solution.
The first option overrule the possibility to validate the data.
The second is not good performing, because we need iterate the entity for all users
What do you suggest? We want a fast solution, but also a save solution
Hope someone know the right solution. Thanks!
When we use the

You need an Object Realational Mapper (ORM) that has the feature to load those multiple users that match the loop at once so the load is reduced.
Similar for the save operation at the end. All changed entities should be stored at once with a unit of work.
Check the product documentation of the ORM you're using or contact it's vendor to find out which features it offers to support your development.

I would suggest the first option. Updating them all at once in a single query. But you don't state what kind of data validation you would like to do. Maybe you could start a database transaction and issue a second query to validate the result of your 'user disable query' before committing?

Related

Seeding Laravel DB from external API

I'm new to Laravel. Maybe my questions are a little bit silly... Sorry...
The goal: There are some API resources and I need to take some selective data from them (It will be needed to make extra API queries from data which I already got before to get full sets of required values) and fill my DB tables with it (some as one to many, some as many to many).
The problem: What Laravel tools do I need to use to reach this goal? Is it factory, seeder or somewhat else? In addition I don't understand where I have to write the code for getting data from an external API and where (in terminal manually?) I have to initiate my DB tables filling.
Maybe someone could at least advise what to learn in the Laravel official documentation at first or some helpful reference to some article from which I will be clear how this process may be implemented in Laravel. I mean the tools' set and order to use them. Not the finished code implementation of course.
I will be grateful for any help. Thanks. Sorry for my non native English.
Well, there are multiple ways of achieving what you want:
One is to create a command where you are going to write code to fetch this data (using curl or any similar way). And then you manually run the command when you want with whatever arguments you want.
Other one is to use the previous step and schedule it to run in a desired time with desired arguments.
Other possible way is, if the external API can send data to a specific URL when some action occurs in that system, then you can create a normal Route and the API should point to this Route in your Laravel. It will be specific and only work for this API.
Other one is to fetch data based on an event. Let's say that, if a user register, when this is successful, you are going to fetch User info from an external API using their email (let's say you want to get a profile picture from an API and the only way to get the user picture is sending the user's email). You can do so using Events.
There are more ways, but if you don't give too much context, then this is what I can share with you !

Is this the right development approach in CakePHP?

I would like to know, if I am following the best practices of development in CakePHP framework.
If you have for a example an Invoices Table, and you want to display the status of the Invoice, let's say you want a green label for the status of the invoice like this:
<span class="green">Paid</span>
What i do is the following. I create a virtualfield on my model named statuslabel, in that virtualfield i call a Helper that displays an element.
so it would be Model->Helper->Element
That way anywhere in my application i can call statuslabel like it was a field from that model and i would get the statuslabel.
My big question is if this is the right way to do it or i am doing it all wrong?
You should avoid violating the MVC principles in your code, in this case specifically containing presentation logic in the model code. This equally applies to CakePHP and other MVC frameworks.
You might still go ahead and create a virtual field called status which can calculate the status of your invoice based on other entity fields. If you have the status stored in the database already as a normal entity field, then you can skip the virtual field.
The view layer is where you want all your presentation code. You can either do it directly in views, or move the logic to the helper. The appropriate function in the helper would take your status field as input and output the appropriate classes into the template based on the status value.
The advantage of keeping presentation code in the view layer (template and helper classes in CakePHP) is that it is easy to replace it later on by updating your templates. CakePHP 3 also gives you the option to create themes via plugins, which is how you can easily change the UI of your application on the fly, but only if you stick to the design principles of MVC.
Generally using virtual fields are not an bad idea. Sometimes the logic behind simple answer is quite complex that it can not be done via SQL or with reasonable amount of SQL.
It is important to remember, that most of the time, using queries directly is much faster without extra PHP processing. So for what comes to your question, if you don't have any PHP logic (besides generating SQL expressions), I would say go with it but...
...There is also point for discussion about database design.
I can't really say about your database schema behind the question, but for me such simple thing than invoice status should definitely be in database directly as and int type field. So what comes to my experience about invoicing systems, database schema could be something like:
invoices
id
invoice_status_id
invoice_statuses
id
title
If you create your model associations and query your database correctly, you end up having invoice status in query results and you can use it just like described.
Btw. most of the time, using reusable elements is good practice. Less code to maintain :D

Mvc and only selecting fields needed

I cant seem to find an acceptable answer to this.
There are two big things I keep seeing:
1) Don't execute queries in the controller. That is the responsibility of business or data.
2) Only select the columns that you need in a query.
My problem is that these two things kind of butt heads since what is displayed in the UI is really what determines what columns need to be queried. This in turn leads to the obvious solution of running the query in the controller, which you aren't supposed to do. Any documentation I have found googling, etc. seems to conveniently ignore this topic and pretend it isn't an issue.
Doing it in the business layer
Now if I take it the other way and query everything in the business layer then I implicitly am making all data access closely reflect the ui layer. This is more a problem with naming of query functions and classes than anything I think.
Take for example an application that has several views for displaying different info about a customer. The natural thing to do would be to name these data transfer classes the same as the view that needs them. But, the business or service layer has no knowledge of the ui layer and therefore any one of these data transfer classes could really be reused for ANY view without breaking any architecture rules. So then, what do I name all of these variations of, say "Customer", where one selects first name and last name, another might select last name and email, or first name and city, and so on. You can only name so many classes "CustomerSummary".
Entity Framework and IQueryable is great. But, what about everything else?
I understand that in entity framework I can have a data layer pass back an IQuerable whose execution is deferred and then just tell that IQueryable what fields I want. That is great. It seems to solve the problem. For .NET. The problem is, I also do PHP development. And pretty much all of the ORMs for php are designed in a way that totally defeat the purpose of using an ORM at all. And even those dont have the same ability as EF / IQueryable. So I am back to the same problem without a solution again in PHP.
Wrapping it up
So, my overall question is how do I get only the fields I need without totally stomping on all the rules of an ntier architecture? And without creating a data layer that inevitably has to be designed to reflect the layout of the UI layer?
And pretty much all of the ORMs for php are designed in a way that totally defeat the purpose of using an ORM at all.
The Doctrine PHP ORM offers lazy loading down to the property / field level. You can have everything done through proxies that will only query the database as needed. In my experience letting the ORM load the whole object once is preferable 90%+ of the time. Otherwise if you're not careful you will end up with multiple queries to the database for the same records. The extra DB chatter isn't worthwhile unless your data model is messy and your rows are very long.
Keep in mind a good ORM will also offer a built-in caching layer. Populating a whole object once and caching it is easier and more extensible then having your code keep track of which fields you need to query in various places.
So my answer is don't go nuts trying to only query the fields you need when using an ORM. If you are writing your queries by hand just in the places you need them, then only query the fields you need. But since you are talking good architectural patterns I assume you're not doing this.
Of course there are exceptions, like querying large data sets for reporting or migrations. These will require unique optimizations.
Questions
1) Don't execute queries in the controller. That is the responsibility of business or data.
How you design your application is up to you. That being said, it's always best to consider best patterns and practices. The way I design my controllers is that I pass in the data layer(IRepository) through constructor and inject that at run time.
public MyController(IRepository repo)
To query my code I simply call
repository.Where(x=> x.Prop == "whatever")
Using IQueryable creates the leaky abstraction problem. Although, it may not be a big deal but you have to be careful and mindful of how you are using your objects especially if they contain relational data. Once you query your data layer you would construct your view model in your controller action with the appropriate data required for your view.
public ActionResult MyAction(){
var data = _repository.Single(x => x.Id == 1);
var vm = new MyActionViewModel {
Name = data.Name,
Age = data.Age
};
return View();
}
If I had any queries that where complex I would create a business layer to include that logic. This would include enforcing business rules etc. In my business layer I would pass in the repository and use that.
2) Only select the columns that you need in a query.
With ORMs you usually pass back the whole object. After that you can construct your view model to include only the data you need.
My suggestion to your php problem is maybe to set up a web api for your data. It would return json data that you can then parse in whatever language you need.
Hope this helps.
The way I do it is as follows:
Have a domain object (entity, business object .. things with the same name) for Entities\Customer, that has all fields and associated logic for all of the data, that a complete instance would have. But for persistence create two separate data mappers:
Mappers\Customer for handling all of the data
Mappers\CustomerSummary for only important parts
If you only need to get customers name and phone number, you use the "summary mapper", but, when you need to examine user's profile, you have the "all data mapper". And the same separation can be really useful, when updating data too. Especially, if your "full customer" get populated from multiple tables.
// code from a method of some service layer class
$customer = new \Model\Entities\Customer;
$customer->setId($someID);
$mapper = new \Model\Mappers\CustomerSummary($this->db);
if ($needEverything) {
$mapper = new \Model\Mappers\Customer($this->db);
}
$mapper->fetch($customer);
As for, what goes where, you probably might want to read this old post.

DB Transaction in Controllers

I have created a crud system. Here I have a main model and then dependent details model. So their are multiple rows (some times > 100 ) entered into details model related to parent model. All operations handled through grid ( inline edit ). So create, update, delete operations are performed through single request (logical checking via DB).
Now I am considering to use DB transaction to whole operations. But I am confused, how I can implement this using same structure. I already have suggestions to move my all code to one model, So transaction can be applied there. But I am thinking, if any other approach can be used for retain separation of main and details model code.
Are you using AJAX for the changes or does it rely on manual form submissions?
You can use what's called a UnitOfWork pattern.
Save any changes that the user makes to each line of the grid but don't actually commit them to the DB. Then, place a geneic save button on the page that will cause your server to actually commit all the changes through a transaction.
You can keep a list server side of each row that the user changes. You don't need to track all the rows because if they don't change anything you don't need to save anything.
What sort of approach are you using in your Models? Do your models know about their own persistence (do you do things like $user->save()), or are you doing a more data-mapper approach ($userManager->save($userEntity))? The latter makes transaction handling a lot easier.
If you're doing the active-record type of patter ($user->save()), your best bet is probably just to manually grab your db connection and manage the transaction in your controller.
If you're doing data-mapper stuff, you have more options, up to and including doing a whole unit-of-work implementation.
As for my last comment, Moving code to parent model is my solution for now. So I think I should mark this thread answered.

Using virtual fields in Doctrine_Query

Is there a way to insert logic based on virtual fields into a Doctrine_Query?
I have defined a virtual field in my model, "getStatus()" which I would ultimately like to utilize in a Where clause in my Doctrine_Query.
...
->AndWhere('x.status = ?',$status);
"status", however, is not a column in the table it is instead computed by business logic in the model.
Filtering the Collection after executing the query works in some situations, but not when a Doctrine_Pager is thrown in the mix, as it computes it's offsets and such before you have access to the Collection.
Am I best off ditching Doctrine_Pager and rebuilding that functionality after modifying the Doctrine_Collection?
If you can do it in SQL you can do it in Doctrine. All doctrine is doing is working out what you are putting into the DQL parser, be it strings or values and turning that into SQL then hydrating objects from the result.
You can't use Doctrine_Pager to page on non query objects, however you could use sfPager and pass it the results of the Doctrine_Collection as an array? In the worst case you could pass it the results of the query minus any limits in the query and let it handle the paging, however this is really inefficient.
It might be quicker to write the pager "old skool" like you would in plain old PHP.
I don't really know what business logic you're applying to work out the status, but if it's not live (as in, computed per request), I'd compute it on save (using a Doctrine Record Listener or simply a preSave/preInsert hook in the model) and store it in the table, or set up a symfony task to refresh it periodically and run that as a cronjob. That would let you query it in Doctrine just fine and boost performance as a fringe benefit.
Alternatively, if status is dependent on the state of related objects, you can put an event trigger on them that updates the status of the parent object when they're modified. It's hard to recommend a best approach without more context. :)

Categories