From time to time one of my models will need to call another. What's the best way to track this?
I was using an array in the base class of each model, so that if Model A called Model B more than once, the second and successive calls would return the existing instance, rather than loading a new one.
While this works fine for simple cases, I can see it has limitations. For example, take the case where Model A loads Model B and Model C; then Model C needs access to Model B (or even A) - it will load the class again!
I suspect that I need a coordinating object, external to the model classes, which acts as a repository. What patterns should I be looking at?
BTW, I am using PHP.
EDIT: Another consideration is that my views may call model methods directly too. In these cases it would make sense to serve up an already instantiated model, rather than a new one...
Thanks!
Take a look at the observer pattern thats used in such case.
Its easy .. each model have a list with listeners and when something happens it says to all Listeners hey something happend
Related
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'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.
Because of other answers (like this), I'm just wanting to clarify what should be used in CakePHP 1.3.
Specifically, I have a situation that calls for a Model to depend on another, so from a method in that Model I'd like to load another, do some stuff with the info, etc.
The documentation for the App Class says:
In previous versions there were different functions for loading a needed class based on the type of class you wanted to load. These functions have been deprecated, all class and library loading should be done through App::import() now.
I'm assuming this covers the use of ClassRegistry, etc, but I just want to it to be clear, and certain:
Should I use App::import('Model', ...) to utilize one Model from another, or something else? If something else, what?
It appears that, even two years since 2008, the best method is to use ClassRegistry::init(), despite the cited documentation.
This is made evident in the actual API/documentation for the specific classes/methods.
App::import()
Finds classes based on $name or specific file(s) to search. Calling App::import() will not construct any classes contained in the files. It will only find and require() the file.
ClassRegistry::init()
Loads a class, registers the object in the registry and returns instance of the object.
Examples Simple Use: Get a Post model instance ClassRegistry::init('Post');
As you can see, even the API Documentation points out examples of using ClassRegistry to load models, instantiating them for you, as opposed to App::import (which does much less), and despite the changed wording in the CakePHP "Book" documentation.
If you can relate the models then the best way is to Dynamically bind the relations using
$this->bindModel("hasOne" => array("Model2")).
If you can't relate the model and you want to use the second model in just one occurrence then you can use
ClassRegistry::init('Model2')->find('allThatIWant');
if you want to use it in several occurrence then you must try
$this->model2 = & ClassRegistry::init('Model2')
$this->model2->find('allThatIWant');
As of 2.6.x of course it is ClassRegistry::init() still.
There is a major difference. App::import will just include/require it. On the other hand ClassRegistry::init() will instantiate it and fetch you a fully loaded object of the model.
So to say, for example you loaded a model in beforeFilter of your AppController. You add some custom properties to it using $this->Model->__something. Now you do call ClassRegistry::init('Model') somewhere where you do not have $controller object available, for example, in a behavior. The object returned by ClassRegistry::init('Model') will have your custom property $this->Model->__something in tact.
Btw, $controller->loadModel() seems the ideal way to load model where you have a $controller object available, for example in your components.
$this->loadModel('model name') will do unless u need it for the entire controller, Then just define the relationship in the model such as hasone, belongsto... and call $this->model->model2.
I need help in designing my PHP classes where I need to extend from multiple classes.
I have a general class, Pagination.php that does all sort of pagination and sorting. All other classes will use this for pagination.
To make my life easier, I made a class generator that generates a class from MySQL table. All the properties, getters, setters and common methods are created automatically, which really saves time and money.
As an example, class Staff_Base in Staff_Base.php is generated automatically from SQL table t_staff.
Since class Staff_Base is automatically generated from SQL table, any 'custom' methods / properties are located in another class that extends Staff_Base.php. (So that whenever a new field is added, I can simply regenerate Staff_Base class and overwrite in Staff_Base.php).
So I have class Staff.php that extends Staff_Base.php.
The problem is, Staff.php also needs to extend another class, Pagination.php.
(The current workaround is to put methods in Pagination.php into every class. This is really troublesome whenever I make changes to the pagination/sorting methods.)
How do I do this?
What is the best design pattern to achieve this?
I know common suggestions to restructure my classes, but I really think hard of other workaround/solution. Also, I may also need to extend other classes than Pagination.php.
Thanks!
Can you have your generated Staff_Base class inherit from Pagination? Or does Staff_Base already inherit from another base class (that you do not have control over)...
Sounds like either Doctrine or Propel, I do not recall which uses the *_Base class system.
My suggestion would be to rewrite pagination to be able to be used by your entity classes instead of requiring your entity classes to extend it.
So if I am reading what you wrote correctly, since you can't inherit from 2 classes you are duplicating paginate into every class you have.
Class stacking is a solution. One of the first things I googled.
I would recommend changing your Staff_Base.php generator to make that class extend Pagination by default. That way Staff extends Staff_Base, and Staff_Base extends Pagination. I think that's probably the cleanest (and most object-oriented) way of getting the results you want.
you cant, multiple inheritance is not supported in php, but if you do a google search on this topic you can find some workarounds...
It sounds like you're mixing things up here. A class (such as a Staff class) is used to represent a single entity. Eg:
$john = new Staff('John');
How exactly does the paging fit into this? Being page-able (paginatable?) sounds like a property of whatever it is that allows access to these Staff entities, not of the entity itself. That way, the way is clear for each type of Staff class you create to inherit from the base class.
So, what I believe would be the solution you need:
A Staff class (Staff_Base, and its graph of children)
A Staff Data Access Object (DAO\Staff would be a nice name, if you're using namespaces)
An Interface, to signal to the world that a DAO can be paged
Import to note is that there is no direct inheritance between the DAO class and the Staff class. You can still generate the Staff_Base class based on its properties in the database, and extend from there... as long as you don't include the actual data access in that class.
The code using this would then look something like this:
<?php
$staffDao = new DAO\Staff;
$staffMembers = $staffDao->getPagedResult($start, $amount);
?>
Edited to emphasize that the inheritance structure should be separate from the actual retrieval
Well, you might already know that PHP doesn't support multiple inheritance. One way around might be using Interfaces instead of superclasses, although, if the logic is identical for each implementing of the interface, this might become tedious. How about writing a code generator, that simply injects the methods to each class? You seem to already do that on the "common methods".
Oh, and using getters and setters (as they are used in e.g. Java) in PHP is considered not a good idea. Objects are slow as they are, so using public fields is considered the norm.
Edit: Then there's the __call()-hack, which could recognize the methods that actually reside in your other classes, and call them manually.
An instance of class A instantiates a couple of other objects, say for example from class B:
$foo = new B();
I would like to access A's public class variables from methods within B.
Unless I'm missing something, the only way to do this is to pass the current object to the instances of B:
$foo = new B($this);
Is this best practice or is there another way to do this?
That looks fine to me, I tend to use a rule of thumb of "would someone maintaining this understand it?" and that's an easily understood solution.
If there's only one "A", you could consider using the registry pattern, see for example http://www.phppatterns.com/docs/design/the_registry
I would first check if you are not using the wrong pattern: From your application logic, should B really know about A? If B needs to know about A, a parent-child relationship seems not quite adequate. For example, A could be the child, or part of A's logic could go into a third object that is "below" B in the hierarchy (i. e. doesn't know about B).
That said, I would suggest you have a method in B to register A as a data source, or create a method in A to register B as an Observer and a matching method in B that A uses to notify B of value changes.
Similar to what Paul said, if there's only one A, you can implement that as a singleton. You can then pass the instance of A as an argument to the constructor (aggregation), with a setter method (essentially aggregation again), or you can set this relationship directly in the constructor (composition).
However, while singletons are powerful, be wary of implementing them with composition. It's nice to think that you can do it that way and get rid of a constructor argument, but it also makes it impossible to replace A with something else without a code rewrite. Peronsally, I'd stick with aggregation, even if using a singleton
$foo = new B( A::getInstance() );
$foo = new B($this);
Code like this unfortunately does not match my needs. Is there any other way to access the parent object properties?
I'll try to explain why. We write a game software and some classes have very "unusual" dependencies and influence each other in different ways. That's why code sometimes gets almost unsupportable without links to parents in every instance (sometimes even several parents from different contexts i.e. a Squad may belong to Battle and to User etc...).
And now the reason why links don't satisfy me. When I generate an output for the client side, I use a kind of serializing objects in XML. It works very nice until it meets recursive references like those links to parents. I can make them protected, but then they loose their usage i.e. (dummy example)
$this->squad->battle->getTeam($tid)->getSquad($sqid)->damageCreature(...);
The other way - to implement serialization method in every serializable class and call it inside serializer like this:
$obj->toXML($node);
$this->appendChild($node);
but that's a lot of stuff to write and to support! And sometimes i generate the objects for serializer dynamically (less traffic).
I even think about a hack: to "teach" serializer to ignore some properties in certain classess )). Huh... bad idea...
It's a long discussion, but believe me, that Registry and Observer don't fit. Are there any other ideas?