The CakePHP framework is a layered structure. My question is:
Where (theoretically) is the best place to implement data query functions? In models or controllers?
With "data query functions" I mean functions like getItemsWithSomeInfo($idItem) etc., i.e functions that are not actions.
Currently, I am implementing these functions in the controller, but I think there are other frameworks in which these functions (or methods) are implemented in the model layer.
I searched on Stackoverflow and found similar issues (Where/how to store custom functions (or methods) in CakePHP), but (in my opinion) are not good answers.
Its better to place such functions in your Model then in Controllers. All data related codes should be in the model. It is always a better idea in the long run, when it comes to refactoring or testing. You know exactly where to find the code. And it can be re-used without copy & paste in other actions/controllers.
Place you function in your corresponding model and then use it in your controller:
Example:
In Model.php
public function getItemsWithSomeInfo($idItem) {
// your code
}
In ModelsController.php
$this->Model->getItemsWithSomeInfo($id);
Related
Basically im doing a "enterprise application" and i want to make code as flexible as possible while keeping it somewhat scalable(its for personal use for now so i don't need to be ultra professional)
The thing is many entities share the same fields and since im trying to learn laravel more in depth i thought that the models (and by extention the traits) acted like some ORM's i've worked before where they would create the sql stuff for me.... they don't so i started doing the migrations but now i see that if i could acess certain columns in the traits it would make the code a lot cleaner and more understandable
basically what i want to do is something like
trait hasValue{
public function getStuff(){
$ret = ModelAttachedTo::select("value", "price")->get();
return $ret;
}
}
Edit: I ended up realizing that with this and other shortcomings of laravel to just completely change back end although if a answer comes i will try to see if it fits the question and works as intended
I don't know if there's simplier way to do this in laravel but in PHP world, you can do this with abstract methods. Traits can declare abstract methods which have to implemented by classes.
So declare an abstract "getPrice" method in trait. All of your classes have to implement that method. And you can call it whenever you want.
I'm trying to understand the MVC pattern in Phalcon.
In my current application I only need ONE template file for each table. The template contains the datagrid, the SQL statement for the SELECT, the form, add/edit/delete-buttons, a search box and all things necessary to interact with the database, like connection information (of course using includes as much as possible to prevent duplicate code). (I wrote my own complex framework, which converts xml-templates into a complete HTML-page, including all generated Javascript-code and CSS, without any PHP needed for the business logic. Instead of having specific PHP classes for each table in the database, I only use standard operation-scripts and database-classes that can do everything). I'm trying to comply more with web standards though, so I'm investigating alternatives.
I tried the INVO example of Phalcon and noticed that the Companies-page needs a Companies model, a CompaniesController, a CompaniesForm and 4 different views. To me, compared to my single file template now, having so many different files is too confusing.
I agree that separating the presentation from the business logic makes sense, but I can't really understand why the model and controller need to be in separate classes. This only seems to make things more complicated. And it seems many people already are having trouble deciding what should be in the model and what should be in the controller anyway. For example validation sometimes is put in the model if it requires business logic, but otherwise in the controller, which seems quite complex.
I work in a small team only, so 'separation of concerns' (apart from the presentation and business logic) is not really the most important thing for us.
If I decide not to use separate model and controller classes,
what problems could I expect?
Phalcon's Phalcon\Mvc\Model class, which your models are supposed to extend, is designed to provide an object-oriented way of interacting with the database. For example, if your table is Shopping_Cart then you'd name your class ShoppingCart. If your table has a column "id" then you'd define a property in your class public $id;.
Phalcon also gives you methods like initialize() and beforeValidationOnCreate(). I will admit these methods can be very confusing regarding how they work and when they're ran and why you'd ever want to call it in the first place.
The initialize() is quite self-explanatory and is called whenever your class is initiated. Here you can do things like setSource if your table is named differently than your class or call methods like belongsTo and hasMany to define its relationship with other tables.
Relationship are useful since it makes it easy to do something like search for a product in a user's cart, then using the id, you'd get a reference to the Accounts table and finally grab the username of the seller of the item in the buyer's cart.
I mean, sure, you could do separate queries for this kind of stuff, but if you define the table relationships in the very beginning, why not?
In terms of what's the point of defining a dedicated model for each table in the database, you can define your own custom methods for managing the model. For example you might want to define a public function updateItemsInCart($productId,$quantity) method in your ShoppingCart class. Then the idea is whenever you need to interact with the ShoppingCart, you simply call this method and let the Model worry about the business logic. This is instead of writing some complex update query which would also work.
Yes, you can put this kind of stuff in your controller. But there's also a DRY (Don't Repeat Yourself) principle. The purpose of MVC is separation of concerns. So why follow MVC in the first place if you don't want a dedicated Models section? Well, perhaps you don't need one. Not every application requires a model. For example this code doesn't use any: https://github.com/phalcon/blog
Personally, after using Phalcon's Model structure for a while, I've started disliking their 1-tier approach to Models. I prefer multi-tier models more in the direction of entities, services, and repositories. You can find such code over here:
https://github.com/phalcon/mvc/tree/master/multiple-service-layer-model/apps/models
But such can become overkill very quickly and hard to manage due to using too much abstraction. A solution somewhere between the two is usually feasible.
But honestly, there's nothing wrong with using Phalcon's built-in database adapter for your queries. If you come across a query very difficult to write, nobody said that every one of your models needs to extend Phalcon\Mvc\Model. It's still perfectly sound logic to write something like:
$pdo = \Phalcon\DI::getDefault()->getDb()->prepare($sql);
foreach($params as $key => &$val)
{
$pdo->bindParam($key,$val);
}
$pdo->setFetchMode(PDO::FETCH_OBJ);
$pdo->execute();
$results=$pdo->fetchAll();
The models are very flexible, there's no "best" way to arrange them. The "whatever works" approach is fine. As well as the "I want my models to have a method for each operation I could possibly ever want".
I will admit that the invo and vokuro half-functional examples (built for demo purposes only) aren't so great for picking up good model designing habits. I'd advise finding a piece of software which is actually used in a serious manner, like the code for the forums: https://github.com/phalcon/forum/tree/master/app/models
Phalcon is still rather new of a framework to find good role models out there.
As you mention, regarding having all the models in one file, this is perfectly fine. Do note, as mentioned before, using setSource within initialize, you can name your classes differently than the table they're working on. You can also take advantage of namespaces and have the classes match the table names. You can take this a step further and create a single class for creating all your tables dynamically using setSource. That's assuming you want to use Phalcon's database adapter. There's nothing wrong with writing your own code on top of PDO or using another framework's database adapter out there.
As you say, separation of concerns isn't so important to you on a small team, so you can get away without a models directory. If it's any help, you could use something like what I wrote for your database adapter: http://pastie.org/10631358
then you'd toss that in your app/library directory. Load the component in your config like so:
$di->set('easySQL', function(){
return new EasySQL();
});
Then in your Basemodel you'd put:
public function easyQuery($sql,$params=array())
{
return $this->di->getEasySQL()->prepare($sql,$params)->execute()->fetchAll();
}
Finally, from a model, you can do something as simple as:
$this->easyQuery($sqlString,array(':id'=>$id));
Or define the function globally so your controllers can also use it, etc.
There's other ways to do it. Hopefully my "EasySQL" component brings you closer to your goal. Depending on your needs, maybe my "EasySQL" component is just the long way of writing:
$query = new \Phalcon\Mvc\Model\Query($sql, $di);
$matches=$query->execute($params);
If not, perhaps you're looking for something more in the direction of
$matches=MyModel::query()->where(...)->orderBy(...)->limit(...)->execute();
Which is perfectly fine.
Model, View and Controller were designed to separate each process.
Not just Phalcon uses this kind of approach, almost PHP Frameworks today uses that approach.
The Model should be the place where you're saving or updating things, it should not rely on other components but the database table itself (ONLY!), and you're just passing some boolean(if CRUD is done) or a database record query.
You could do that using your Controller, however if you'll be creating multiple controllers and you're doing the same process, it is much better to use 1 function from your model to call and to pass-in your data.
Also, Controllers supposed to be the script in the middle, it should be the one to dispatch every request, when saving records, when you need to use Model, if you need things to queue, you need to call some events, and lastly to respond using json response or showing your template adapter (volt).
We've shorten the word M-V-C, but in reality, we're processing these:
HTTP Request -> Services Loaded (including error handlers) -> The Router -> (Route Parser) -> (Dispatch to specified Controller) -> The Controller -> (Respond using JSON or Template Adapter | Call a Model | Call ACL | Call Event | Queue | API Request | etc....) -> end.
I am looking to just get an understanding on how you guys would implement the following.
I think I have a reasonable understanding of OOP. If I have a website and a user account can be created for this website. I understand that I can create a user class that will handle the creation of this user by passing the relevant information through to the class.
If I have to make a CuRL post to pass some information through to a third party. would it make sense to create a CuRL class for this process that the user class can instantiate, also allowing for another class to post data through as well rather than creating a static function in global space or a curl function within each class that requires this function?
Another issue I have with my understanding of OOP, is if I have many similar functions that help to perform what is required. I will tend to bunch these all into one class (utils class?). This could range from passing in an array of data to output as a select element to passing user entered data through to validate and sanitize as required and return.
I think I am just looking for clarity on what is a good implementation of code with regard to OOP. Is it OK to have floating/static functions in global space working along side classes (Can that still be considered as OOP) or should everything I code be grouped as an object within a class that it would best fit?
I hope that makes sense?
Thanks
The concept behind OOP is to structure and divide responsibilities among various classes.
Models
There are various building stones, that are normally used when you consider different aspects of your application. For instance, a User class would often be considered a Model and be tied into an ORM.
The responsibility of a Model is to map the data stored in a database to the data stored in memory by PHP (or any other language). In many cases Models can also instantiate and register themselves in the database. Which is what you're looking for. Laravel's Eloquent ORM is a good example of an ORM which supports this.
cURL helper
Depending on your own opinion and the exact use case, both of your suggestions may be useful. I myself try to divide the responsibilities of each class as much as possible, this is to reach the purpose of a divided responsibility.
So I would create a helper class which can handle communication through cURL, which you can then call from various classes. I would even take if to a further level and create a Transport interface which cURL can implement. This would allow me to easily swap cURL with another transport layer, without having to change all the objects which depends on cURL.
Concept example:
<?php
interface Transport {
const POST = 'post';
public static postRequest($url, $data);
protected static processRequest($method, $url, $data);
}
class cURL implements Transport
{
public static postRequest($url, $data) {
return self::processRequest(self::POST, $url, $data);
}
protected static processRequest($method, $url, $data) {
// Implement method
}
}
This cURL example ties well together with your third question. These are often called helper functions or helper methods. Depending on the code design your choose or the design of the framework you use, the way helper methods are called can vary.
I use Laravel which provides static methods. You can see some examples for the Hash and Auth helpers here.
OOP is not Functional programming
Global function is not a part of OOP. But there's no one to tell you whether this is good or bad practice, that is up to yourself to decide, whether this approach will work the best for your use case. Obviously it requires a certain amount of experience to consider all aspects of the chosen design patterns, but experience comes with time.
To use Laravel as an example again, they do provide some global functions that adhere to old fashioned PHP functional programming style. But the framework is mainly OO.
My suggestion to you
It sounds like you need a boilerplate for what you intend to build. I would suggest that you consider a framework to use, since frameworks will often answer the questions you're asked here. Both in terms of conventions and object responsibilities.
You could check this article for suggestions on PHP frameworks to use.
After reading a fair few posts on Stack, and also some material recommended to me on line, the MVC pattern is quite open to interpretation, so please don't answer with another explanation. Thanks!
I'm reaching the end of designing my own PHP MVC now, and have two possible ways to move forward with the views.
But first, my controllers are currently quite dumb, not containing any classes and simply call public methods from the suitable models, and render the appropriate view.
Views are included as necessary, so naturally the objects are available to them via the constructors, along with all the methods (inc delete/update etc).
My first option is to get data using something like this in the view
foreach($object->fetchData() as $data)
and then looping through the results. However some people do not agree with this, and have suggested that such methods should be excluded from the view. Instead it has been recommended that I assign this to a variable in the constructor, and then use this variable in the view
//constructor
$fetched_data = $object->fetchData()
// view
foreach($featched_data as $data)
I don't like this very much, as it seams messy and unnecessary.
With all my critical methods being made available to the view, could this be considered a problem?
So here's the question. Do I keep it how it is, and create new methods in the MODEL for rendering data (as above) OR can I create a class in the constructor, extend the model into it, protect the critical functions in the model, and then create my read only public methods in the CONSTRCUTOR?
Thanks!
I would create a class in the constructor. Not only would extending the model be a much safer approach, but it'd also minimize the calling of functions in the views. Am assuming you'll have several views, it's much easier to get access the constructor data than calling method functions each time in each view.
You can add classes to your controllers that will call the method functions and pass the data directly into the views, instead of clustering your constructor or bootstrap.
I've noticed that all my models look very similar. Most of them tend to follow a pattern where they are collections of methods containing active record code that are just slight variations on one another. Here is an example:
class Site extends CI_Model {
public function get_site_by_id($id)
{
// Active record code to get site by id
}
public function get_sites_by_user_id($user_id)
{
// ...
}
// ...
public function get_site_by_user_id_and_url_string($user_id, $url_string)
{
// ...
}
// Non active record methods and business logic
// ...
}
This approach has worked fine for me but I'm wondering if there is a more elegant solution. It just doesn't seem right to me that I should have to create a new method every time I need to look up data in a new way. Is this common practice or am I missing a way to refactor this?
Strictly following your request, you could add an intermediate class between the main model class (CI_Model) and your class (Site), something like
class MyCommonMethodsClass extends CI_Model {
}
and you would extend it in your classes (Site), while putting the common code on it. That would work and could be somehow'elegant'. In fact at the end you would end up adding your basic crud, site adapted actions, to it.
Now, if that's 'clean', that's another thing. Again, strictly speaking the model does that. It takes care of common and 'advanced' getters. And yes, they almost always have the tendency to have the same code all around your website. The problem is that, although that looks nice in your code (less code) you're technically sacrificing abstraction between your business logic and the db. Are you a model purist or practical one ?
I think this is matter of opinion but I think best practice is to create some sort of Create, Retrieve, Update, Delete (CRUD) model which does many basic SQL functions like GetID, UpdateByID, GetById and so on.
CRUD models can only go so far in helping you with more modular queries. But it makes sense to call a function called GetId and pass it some parameters than to have different functions for each table.
As I say though, CRUD's can only go so far. For example it would make sense to have a function that queries a database users table to check if a user has verified and username & password match. As this is a unique and not an abstract function, it should have it's own function defined.
Also as a best practice, Logic and Database access should never be mixed in the same file.
It is common practice to have different methods to handle getting your data like that. The Single Responsibility Principal states that every object should only do one thing, by making multiple methods that get very specific data you are creating very maintainable and easy to debug code.
If you have multiple classes that are providing essentially the same functionality, then this would suggest that there may be something wrong with your class hierarchy (a so-called "code smell"). If they have similar interactions then that suggests that they are related in some way. If that's the case then the chances are they should all be inheriting from a common superclass that implements the functionality common to all your subclasses, with each subclass simply specializing the generalized functionality of the superclass.
The advantages of this approach are:
You're not repeating work (SPOT, DRY)
Code that interacts with the classes can be written in a more general way and can handle any object that inherits from the superclass (substitution)
I do not think there is any thing wrong with creating an 'base' model class to extend you other models by. If it is solid and well tested, it can make you life easier. What is the point of creating the same CRUD functions over and over again?
Another benefit of doing it is that you can have a base development repository that you clone to start all new projects.
If you need an example of how to do this then look at a question I previously asked.
You can also do the same with your controllers.