I have a menu which I need to create dynamically (some blog pages are added from a database). ZF2 Dynamic Menu with Zend\Navigation\Navigation addresses how to do this for an individual controller/action.
But how should this be done for all requests, at the moment of initialising the module?
I need at least the routeMatch object (to get the language parameter) and I have seen the below to get that:
public function onBootstrap(EventInterface $e)
{
$app = $e->getApplication();
$em = $app->getEventManager();
$em->attach(MvcEvent::EVENT_ROUTE, function($e) {
$routeMatch = $e->getRouteMatch();
});
}
But in the docs it says:
"the onBootstrap() method is called for every module implementing this feature, on every page request, and should only be used for performing lightweight tasks such as registering event listeners."
What would be the best place and way to initialise dynamic navigation (or other more complicated logic) in Zend Framework 2?
The correct place is indeed bootstrap to do this sort of things. Bear in mind the code at bootstrap is run at every request, so make it as lightweight as possible. If you want to inject navigation, try to cache the navigation structure from your database and inject the version from cache.
This behaviour is something I did in ensemble. It fetches data from the database to build routes dynamically and based on the routes, the navigation structure is build. The routes and navigation are injected in respectively the router and navigation container, so at dispatch of the application is seems there is nothing different from a "normal" request with routes configured in the module.config.php.
For some examples you should check out the kernel, currently only availble with a Doctrine adapter (Zend\Db coming soon). It registers listeners to hook up early, it parses the database results into a route and navigation structure and those can be cached to increase performance.
If you need more specific information, please update your question to ask more about what you miss in the bigger picture.
Related
Could someone concisely summarize which responsibilities should be handled with Ember's routing system?
After 2 weeks with Ember, I suddenly feel like I don't have an accurate grasp of what routing does. It looks kind of does everything; establishing urls, setting arbitrary controllers/templates/etc, forwarding routes, pre/post load events for models, etc.
The broad capabilities of Ember Routing leave me uncertain what should be handled by the router vs an MVC object. The official docs (http://emberjs.com/guides/routing/) do a good job of explaining how to do many things, but kind of prevents me from seeing the forest for the trees...
A Conceptual Model
One way to think about it is that Routes & Controllers are both controllers in the MVC nomenclature. Controllers are concerned with controlling the connection between Models and their display, and getting data into and out of them, and Routes are concerned with controlling the connection between Models, between Models and the application, and between Models and their persistence layer.
Application: the granddaddy model
In this view Application is the granddaddy model (and it is always there: even if you don't explicitly refer to it there is an ApplicationRoute and ApplicationController being anonymously created). So naturally, routes control the connection between the Application and other Models.
The Most Common Setup
For a given model, there will typically be (as a basic starting point) two Routes and two Controllers. One Route manages the retrieval of a collection of the Model, and a corresponding Controller connects that collection to a view of the collection, and another Route manages the choosing of a single instance of the Model, binding it to a controller that manages its connection to a view.
Who handles Actions?
Views, Routes and Controllers can all intercept and handle actions. They each have a special ability that the others do not.
The Controller Special Ability
The special ability of Controllers is that they know about the specific instance or collection of a Model that the action concerns. If an action comes to a controller it is generally originating in a view element concerned with that controller's model. So, actions defined on controllers should do something with a model or model collection. If an action does not care about a model/collection, it probably belongs on a Route.
The Route Special Ability
The special ability of Routes is that they know the hierarchy into which models/collections have been organized. This means that they can do things involved with navigation more naturally than controllers can.
The View Special Ability
The special ability of Views is that they know about the interface, and events animation etc.
Handling Actions with multiple Handlers
Although it is not necessary, I often split an action into two (or even three) handlers, often with the same name. In the case of two, one handler lives on a Controller, and does the part of the action concerned with selecting, querying, or otherwise talking to a Model. The other handler lives on a route and is concerned with the navigational part of the action. When actions are split up this way, you find your app becomes easier to refactor, and you have to do less gymnastics to accommodate "weirdness" in the html structure of your views (in particular for negative actions like cancel or deselect).
Sometimes a third handler lives on the View and does jquery-ish things or css animation. In each case when a component has done their part of an action, it uses send to forward the action to the next component that should deal with it. Typically that means View->Controller->Route.
Summary
So to sum up, Routes should focus on managing the retrieval of models and the connections between them and between them and your app, handling the parts of actions concerned with navigation and app state. Controllers should focus on managing the connection of models with html view elements, handling the parts of actions concerned with choosing/unchoosing/modifying a particular model or model collection (note: choosing is usually switching to a new route, and handled by a Route. But sometimes controllers handle non-route choices, like setting an attribute on one model by choosing an item from a list of another model). Views should handle the parts of actions concerned with changing the html they represent, ie, animation, css changes that reflect state, etc.
I found a very concise and explanatory blogpost about routing: http://hashrocket.com/blog/posts/ember-routing-the-when-and-why-of-nesting
Understanding the proper use of the Router in an Ember.js app is a fundamental core concept of the framework. The docs tell us that the router translates a URL into a series of nested templates and almost all available tutorials show how to nest routes as part of an explanation of how the Router works.
This is great when you want a UI where a list of items are present at
the same time a single item is shown. This leaves many beginners
struggling, however, as they try and replace the entire contents of a
page with another route’s template. Today we’ll explore two ways to
tackle this problem.
I would like to "simulate" global variables in Angular. I would also like to be able to initialize those "global variables" in an App_Init()-type of handler. Such an initialization will require $http calls to populate those variables. I want all of the "global variables" to be completely loaded before Angular "calls up" controllers and views, because controllers would depend on the initialized data.
What are some best practices for that in Angular? Nested controllers? Services?
Example: An app that manages items in a restaurant's menu. Each item will be associated with a category (beverage, appetizer, dessert, etc.). I need to load all of those categories first before Angular "even touches" the controllers and views for the food items.
Are you using ng-view and the $routeProvider service for your app? Assuming you are or will consider, here is what you can do in order of steps:
Build a service that provides acces to the categories to its called. My idea is that this service would load the categories from the server when it's first called and then cache the data loaded, so the next time it's called a cache copy is served, instead, to save a request to the server. Let's call this service categories for now.
Use the resolve property of route object to ensure the dependency on the categories service is resolved before loading the view the user is requesting (and the corresponding controller). As a result, you can inject the categories service into the controller and be sure the service is always available because it has already been resolved.
If you have never worked with the resolve property in configuring routing before, Here is an example and the part of the official docs that talks about it. I recommend you go through them.
Also, in order to understand how resolve works, you need to be familiar with the concept of promise and deferred. If you are not, here is a good starting point on the topic. $q is AngularJS's implementation of promise/deferred.
I can't comment on if the above approach is the best practice, but I know it's a good practice to use service to provide access to some data/functions like if there were global variables.
You can create a service to load the configuration from server and put it in rootScope, in your controller you can call this service on your function and this function you call from ng-init in your view.
View
<mytag ng-init="myFunc()">
Controller
module.controller('MyCtrl', function($scope, myService){
$scope.myFunc = function(){
myService();
}
}
your service (initialize app)
module.service('myService', function($http, $rootScope){
//do something
$rootScope.config = configLoaded;
}
another tip
if you are in trouble with asynchronous calls you can try to use
var deferred = $q.defer();
//when your call come back
deferred.resolve(yourData);
//and in the last line of function
deferred.promise;
I have this idea of generating an array of user-links that will depend on user-roles.
The user can be a student or an admin.
What I have in mind is use a foreach loop to generate a list of links that is only available for certain users.
My problem is, I created a helper class called Navigation, but I am so certain that I MUST NOT hard-code the links in there, instead I want that helper class to just read an object sent from somewhere, and then will return the desired navigation array to a page.
Follow up questions, where do you think should i keep the links that will only be available for students, for admins. Should i just keep them in a text-file?
or if it is possible to create a controller that passes an array of links, for example
a method in nav_controller class -> studentLinks(){} that will send an array of links to the helper class, the the helper class will then send it to the view..
Sorry if I'm quite crazy at explaining. Do you have any related resources?
From your description it seems that you are building some education-related system. It would make sense to create implementation in such way, that you can later expand the project. Seems reasonable to expect addition of "lectors" as a role later.
Then again .. I am not sure how extensive your knowledge about MVC design pattern is.
That said, in this situation I would consider two ways to solve this:
View requests current user's status from model layer and, based on the response, requests additional data. Then view uses either admin or user templates and creates the response.
You can either hardcode the specific navigation items in the templates, from which you build the response, or the lit of available navigation items can be a part of the additional information that you requested from model layer.
The downside for this method is, that every time you need, when you need to add another group, you will have to rewrite some (if not all) view classes.
Wrap the structures from model layer in a containment object (the basis of implementation available in this post), which would let you restrict, what data is returned.
When using this approach, the views aways request all the available information from model layer, but some of it will return null, in which case the template would not be applied. To implement this, the list of available navigation items would have to be provided by model layer.
P.S. As you might have noticed from this description, view is not a template and model is not a class.
It really depends on what you're already using and the scale of your project. If you're using a db - stick it there. If you're using xml/json/yaml/whatever - store it in a file with corresponding format. If you have neither - hardcode it. What I mean - avoid using multiple technologies to store data. Also, if the links won't be updated frequently and the users won't be able to customize them I'd hardcode them. There's no point in creating something very complex for the sake of dynamics if the app will be mostly static.
Note that this question doesn't quite fit in stackoverflow. programmers.stackexchange.com would probably be a better fit
I am new to MVC, CodeIginter. Instead of getting things easy, it needs lot of code to be written for a simple application. These are might be happening becouse I am new. So I have few confusions about this thing. Any kind of help is appreciated.
1) Methods are written in one controller can not be accessed in another controller classes. I have to write a new function for the same functionality.
2) To create website administration panel (back-end) in none mvc panel, we usually create it in a new folder. Is this thing possible in CodeIgniter? If not what about the admin (back-end)??
Let's try to clear some of your doubts about this.
1) Calling a controller's method from another controller is not possible, and it's whtouth meaning by the way.
A controller is supposed to get an action from the URL (which is routed by CI to the right controller for the task) and, based on that, decide which Model and which model's method needs be called to elaborate the data requested.
The model, then, hands back the result of this elaboration to the controller, which , in turns, decides to which view pass this results.
The view, eventually, is structured to get those datas and display them.
SO, as you can see, calling a controllers' method from another controller is nonsense, it would be like going to a page and finding another one instead; if you want to pass to another controller the request...well, there's the redirect for that.
If you find out you have the same functionalities in several moment, think twice:
What is a funcionality? Do you mean somehtin like "display posts" in controller "archive" and "display posts" in controller "news" ? they're hardly the same functionality; they can maybe share views, or models, but that's it.
For functions that doesn't relate to URLs, but involve some further elaboration (which might be wrong to do in Models) and are nonetheless called in a controller, you have library instead. Think at the "form_validation" library, which is called in a controller's method, but has its own peculiar (and encapsulated) functionalies. Ora a "session" library, or an "authentication" library
2) To create an admin panel the easiest thing is: create an "admin" controller (which is accesible then to www.mysite.com/index.php/admin), and put all the administration actions there, in its methods: create_page(), edit_page(), manage_users(), whatever.
In order to avoid people accessing it freely you need to build an authentication system, which, in its simplest and barabone strucutre, might be a check of wheter a session is set or not (maybe a check done at __construct() time).
But you can find nice Auth libraries out there already made, such as Ion Auth or Tank Auth (the 2 most popular to my knowledge)
Hope things are a bit clearer now. See also Interstellar_Coder's comment at this answer if you're interested in the modular HMVC approach.
1) Methods are written in one controller can not be accessed in another controller classes. I have to write a new function for the same functionality.
What's the functionality about? Perhaps you should write a library/helper instead, controller's logic should be limited to request flow or something else but not too complicated. For that, put the functionality in the model, or if more general, in library/helper.
2) To create website administration panel (back-end) in none mvc panel, we usually create it in a new folder. Is this thing possible in CodeIgniter? If not what about the admin (back-end)??
I don't get it, could you elaborate more?
The text is quite long, the question is actually simple and written in bold. The other text is only for trying to explain the problem.
I have recently started to use CodeIgniter for developing my website. Currently, I'm writing a side menu where you can filter the items showed in the view (basic e-commerce functionality).
The idea I had was to have an array in my Shop-controller where I store my filtering values which are passed to and from my filterview, so the filter menu kan handle several types of filters.
The problem is that it seems like the constructor of the controller is run each time the controller is called. I thought that the controller was constructed only once when the user enters the website. I'm pretty new at website devlopment and am mainly a C++-guy, so this seems a bit strange for me.
My question is pretty simple actually: Is it true that the controller instance is created at each call to a controller function? Otherwise, what am I doing wrong to cause the controller instance to be reinstantiated at each controller call...
I hope that my question is not too fuzzy. It is important for me to understand the lifecycle behaviour of CodeIgniter to be able to find a simple solution for this. I would like to avoid using $_SESSION, because I would like to use a OOP like solution.
Is it true that the controller
instance is created at each call to a
controller function? Otherwise, what
am I doing wrong to cause the
controller instance to be
reinstantiated at each controller
call..
Yes, the controller instance is re-instantiated every time you make a call to that controller. In CodeIgniter, there is no such thing as a persistent instance of your controller for each user interacting with your application (unlike single-user apps built in C++). What you do have is session management, where you use Session variables to store data persistent to that particular session between the user's browser and your web server (more). Another way to do this is by using cookies. I personally prefer session over cookies.
There is no harm in using $_SESSION for the purpose of your filter, and it is not against OOP principles. What matters is how you use the data stored in your Session variable once your controller instance has loaded ( that's where the OOP concepts come into play).
Shivaas, the same answer can by safely used with models? What about autoloading models? I mean, autoloading it's just a way to avoid typing $this->load->model('the_model') when needed? There's no way to use singleton pattern without recurring to use session/database?
private $instance;
function init_model() {
if ($this->instance === NULL) {
$this->instance = array();
}
return $this->instance;
}
Once init_model exits, the class instance is destroyed so $instance will be always initialized to a new array()?