First question on StackOverflow (I don't know if I'm doing this right, so sorry if I mess it up)
Background:
My controller has a method that list all actions in my app and plugins called getActions().
And I need to use getActions() in a Helper that overrides HtmlHelper->link() method, because the purpose of this method is return null if the link is forbidden by Acl, thus not rendering any link that would lead to a forbidden action.
Question
How to share this method? I'm doing this wrong?
Lib is the right way to go?
This doesn't seem right: In CakePHP, how do I call an AppController method from a helper?
Don't share the method, share its output. as mentioned in the link to the other question.
I assume that this data is static, meaning: if it will be called from any part in the application, it will return the same value.
Call the method in the controller, store its output in a view-variable or in the session, and write a helper that will access this information and do the acl logic.
It won't break the MVC and will avoid DRY.
The right place for the method is Lib, because its a general purpose method that is going to be used in differents places with differents objectives.
CakePHP's core has many examples of this approach like: CakeTime, CakeNumber and others.
Others examples could be seen in some of CakeDC plugins too.
IMHO #yossi was right about "assuming the data as static", but his approach of storing the data in Session just would make my code more confusing.
In my particular case I'm taking the Lib way. Thanks for the help.
Related
So I have been reading through From Apprentice to Artisan by Taylor Otwell, Laravel Author
And I came across this 'mantra' : HMVC usually indicates poor design.
Which is kind of true...
Also Taylor has suggested
Feel the need to call controllers from other controllers? This is often indicative of poor
application design and too much business logic in your controllers. Extract the logic into a
third class that can be injected into any controller.
And I don't seem to find such way yet..
How can I avoid HMVC and extract the logici nto a third class that can be injected to any controller?
I came up with a neat way to do it, and it seems to have helped me speed up my workflow...
I think this alternative I made can replace HMVC, as well as the conventional way of using controllers... as now controllers are but somehwere where our -what I called- 'motors' are injected.
Check out my article at coderwall where I went through the whole thing.
Read through it, and hopefully it will provide a better way of doing things, starting from the models to and finishing at controllers.
However if you wish to proceed your own way, make sure what was required to be shared between two controllters hiarchecly gets shared in a more neater way, as taylor suggested, shared through injection.
For instance, you are in AdminsController and you feel the need to call an action from UsersController, just make that action and its siblings into a third class, and in your AdminsController
//AdminsController
use ThirdClass;
public function __construct(ThirdClass $mything)
{
$this->myThirdClass = $mything;
}
public function mySharedAction()
{
$this->myThirdClass->mySharedActionFromUsersController();
}
And like so.
Update
If you have gone through my article at coderwall, the one I have mentioned above, I have made a little package that generates all of the mentioned components in there.
Check it out at github
I've had a quick search on Stackoverflow but not really found an answer to a question that I have. Sorry if it's already been answered and I've missed it!
I'm working on an application, and similarly to Facebook, there will be 'notifications' but in my case it'll be items that require actions from the user. It would just be a 'count' of the actions that are required and nothing else.
I've followed a fat model, skinny controller approach through my application and so far so good. I have a good idea of what goes where, and when to use a plugin, app model, app controller, etc.
However, I'm a little confused about where to put this notification/action 'count'. I'm guessing either afterFilter() in the app_controller.php file, but that's just a guess. I'm just looking for the most efficient place to put it.
So, where's the best/fastest/most efficient place to put this count call?
Thanks!
Kingsley
EDIT: I just realised it's worth pointing out that this particular call is on a model. So, at the moment I have to load that model, and then call it.
The ideal place is in an Element. You can then use requestAction() to tell it where to retrieve it's data from.
The Element is placed into a view (or used to display a Flash message). Within it, it pulls it's data (requestAction) from a Controller's Action. That action get's it's data from the Model of your choice just like you would in any other action. This allows complete separation of concerns (ie MVC).
When trying to adhere to established best practices like avoiding singletons, registry, static properties and base controllers, how I can populate my layout(and partials used by the layout) with data that is only used by the layout and common across all actions?
The typical scenario is menu which is built on variable data, like an database. Keeping separation of concerns in mind, the views/layout should never talk to an backend directly, but rather be told what to contain.
Using a front controller plugin is simply not possible without using the singleton "feature" in Zend_Layout. The plugin only knows the request and response object, neither has access to controllers, views or the layout.
Zend's action helpers have init/preDispatch/postDispatch methods. One can add action helpers to the HelperBroker (ex. using the bootstrap) and these will be executed in the normal application flow.
Using the init-method to inject data into the view is not possible since it's trigged before the controller/view is ready. preDispatch/postDispatch is possible, but not perfect, since these methods are always triggered when executing a controller action.
That means that all uses of the Zend_Controller_Action::_forward() will also execute the preDispatch/postDispatch in all action helpers. This doesn't have any big implications for the code except speed, I really do not want to be setting a view (or an view helper) variable several times. One can code around this issue using some sort of $firstRun variable, but I really don't want to track this in my own code.
Another method is doing this in the bootstrap, but in my opinion it really does not belong there.
So, how can I populate my layout/view helper with data from the database, doing it only once and still keep a good separation of concerns?
I've followed the ActionHelper approach, setting the view variables on the preDispatch method. It was the most logical place, in my opinion. In addition, my projects weren't using Zend_Controller_Action::_forward(), so I didn't have any speed concerns about multiple triggering of the helper.
Hope that helps,
You could go with Action Helpers as stated in this answer (take a look at the question too, its pretty much similar to yours)
I'd use action helpers too. Just fill the view variables and display them using plain PHP/partials/render/viewHelper (depending on complexity).
Your problem with multiple runs using preDispatch could be solved using
if (!($this->view->myVar)) { // or array_key_exist or isset - depending on your use case
$this->view->myVar = $someModel->getSomeData();
}
Which is just fine IMO.
I've been working on creating my own MVC app in PHP and I've seen a lot of differing opinions online about how exactly this should be set up. Sure, I understand there seems to be a general "It's MVC, it is what you make of it" approach, but I'm running into 2 seemingly conflicting viewpoints.
A little background on my app: I'm using smarty as my presenter and an object-oriented approach. Seems simple enough, but I'm trying to figure out the ubiquitous "what is a model" question.
If I take a look at some tutorials and frameworks, they seem to view the model as strictly a class that inherits DAL methods from an abstract class, with a little bit extra defined in the class itself as your data needs differ from object to object. For example, I might see something like $productModel->get(5) that returns an array of 5 products from the database. So what if I need to query multiple models? Do I store all of the data in the controller or an array and pass that to the view? Then if I'm dynamically calling my controller, how can I persist the data unique to the controller necessary to render the view? This seems bad, especially because I then have to pass in things like "controllerName", "controllerData", and my View::render() method gets hugely bloated with parameters, unless I pass in the controller itself. Maybe I'm missing something here.
Let's say I want to make a login that queries a users table. Login is a model or a controller, depending on certain implementations I've seen online. Some implementations (I'll call this method 1) make a LoginController with method login() that might do a comparison of $_POST and what's returned from the user model instance $user->get(1) to see if a user is validated. Or maybe login() might be a method in a default controller. On the flipside, an implementation (implementation method 2) that resembles more of a Joomla approach would make a Login model and declare all of the actions inside of that. Then any data that needs to get assigned to the view would get returned from those methods. So login->login() would actually check post, see if there's a match, etc. Also the User model would probably be instantiated inside that model method.
My feelings about 1: The controller is fat. Additionally the controller is storing data pulled from models or passing in ten thousand variables. It doesn't seem to jibe with the idea that the model should be passing data to the view that the controller should be blind to. Also, let's say I want to wrap everything that is in a specific model handled by a specific controller in an outer template. I'd have to copy this template-setting code all across my controller functions that interface with this model. It seems grossly inefficient.
My feelings about 2: It doesn't make for having actions that aren't model methods. If I want to go to my site root, I have to make an index model or something that seems like overkill in order to have a model that passes data to the view. Also, this doesn't seem to be a very popular approach. However, I do like it more because I can just do View::render(mymodel->func()) and ensure that the data is going to be passed back just the way I like it without having to crap up my controller with code merging a thousand query results together.
I've waded through far too many religious arguments about this and want to know what you guys think.
I've built my own framework in the past too so I know what you're going through. I've heard the saying "build fat models" and I agree with that -- as long as the main goal is to return data. I considered the controller to be "The Overlord" as it manipulated data and directed where it should go.
For a login controller i might create something it like...
Post URI: http://example.com/login/authenticate
LoginController extends ParentController {
public function authenticate() {
$credential_model = $this->getModel('credentials');
// Obviously you should sanitize the $_POST values.
$is_valid = $credential_model->isValid($_POST['user'], $_POST['email']);
$view = $is_valid ? 'login_fail.php' : 'login_success.php';
$data = array();
$data['a'] = $a;
// .. more vars
$this->view->render($view, $data);
}
}
In my opinion data should always flow from the model -> controller -> view as it makes the most sense (data, manipulation, output). The View should only have access to what it has been given by the controller.
As for this...
Then if I'm dynamically calling my controller, how can I persist the data unique to the controller necessary to render the view?
Well I would imagine you're building a 'base' or 'parent' controller that gets extended off of by your dynamically called controllers. Those child controllers can have properties that are needed for for the view to render -- honestly I'd need an example to go further.
Hopefully this helps a bit. If you ask more specific questions I might be able to give a better thought out opinion.
If you're writing your own app, I think the best solution is to do it yourself and find out.
Ultimately, whatever makes the most sense to you, and whatever makes it easier for you to conceptualize your app and quickly add to or change it, is going to be your best option.
If one way is "wrong", then you'll find out through experience, rather than someone else telling you. And you'll know the entire situation that much better, and know EXACTLY why one way is better.
What helped me when I was writing my own framework in PHP was, strangely enough, CherryPy. It made the concept of an object-oriented web app so simple and obvious, and I enjoyed using it so much, that I modeled the basic structure of my PHP framework to imitate CherryPy.
I don't mean to imply you should learn CherryPy. I mean that simplicity, clarity, and enjoying developing with your own web app go a LONG way.
If I were to give one piece of specific advice, I'd say try to avoid retyping code; write your code to be reusable in as many situations as possible. This will not only be good for your app, but for future apps you may write or work on.
You might check out Eric S. Raymond's Rules for Unix Programming. I think they're definitely applicable here.
Today at work someone tried to convince me that:
{$obj->getTableInfo()}
is fine for smarty/mvc/templating because it is using an objects method. I argued that because it makes a call to the database it has no place being there and it should be in the controller (we don't actually use MVC). Am I right in my understanding of the logical separations that are used in MVC and generally in templating? Or is there something that I am missing?
You're right. He's wrong.
Database calls, no matter in what form, should live in the controller if you want to do MVC right.
Obviously people piss all over what it should be and do stuff like that, but it's not the correct way.
Well, there are no "official" rules or anything, but I think something like that belongs in the controller. I don't do anything in my view code except display variables, nothing more complex than an if or a foreach-type loop is allowed. Certainly not calling functions that access the database. That should all be loaded by the controller, the view should only decide whether it needs to display it or not.
Depends on its context and scope really.
Is $obj the controller or the model layer? That should answer whether or not it is valid in my opinion.
In response to reading the other answers.
The functions name in itself pertains it to being a simple getter method. It may make a call to the db through a controller layer. Which I would say is ok. Especially if it used some form of caching in memory. (ie the getter is the setter as you only want to cache it when it is used once.)