I am a new Developer in Zend and I am working on a very simple application in Zend wich will allow me to publish the pages.
to do so, I need to create a way to get the controller name and action name if it does not exist.
e.g I have a controller named page and in the view action of that controller I display the page content based on the id I Pass. So he url will be:
http://localhost/page/view/slug/some-slug-value
I want that if I write the following link,
http://localhost/some-slug-value
instead of displaying Invalid controller error, it should also serch the db for that slug and open the view action in the page controller.
I don't want to change the URL http://localhost/some-slug-value even if i have to show some error.
If i had to process the invalid action, I can do it via the __call() function in that controller. so I need a __call function for handling invalid controllers.
As I am a new in Zend, please also mention where I have to write that code which you are going to suggest.
Thanks in advance
Zend_Controller_Plugin_ErrorHandler can handle the exception due to missing controller/action and is enabled by default. You can put your logic inside.
I have answered a similar question before using a custom plugin here.
Basically, it checks if a request can be dispatched and in the event it cannot, it redirects to another controller/action. This happens before the ErrorHandler plugin allowing for the ErrorHandler to handle errors only as intended.
EDIT
I should note that inn the plugin on the linked question, I referenced the username. In your case, you will have to substitute slug for username.
Related
I have a question related to form submission done in PHP application that's built in MVC architecture (self-written framework).
All examples that I've seen so far (including existing back-end frameworks) work this way that once form for adding record to database is submitted then certain method of controller is executed [say i.e. addRecord()], which triggers method of appropriate model. If everything goes OK then record is added and controller's method [addRecord() in this example] renders view of "index" page that displays table with records from database.
What I would like to achieve is to render view with form used to add records (the same that I used to add first record) instead of "index". Obviously I can do it easily by just rendering appropriate view from addRecord() (view with the form).
But the tricky point is when you check url you'll see the following:
The first time you enter it will be i.e.
http://project_name/my_controller/create
Once first form was submietted and you return to the view from addRecord() method then url will be:
http://project_name/my_controller/addRecord
What I would like to see is return to the original url, that is http://project_name/my_controller/create
Not sure if this is clear?
PS. Of course I could use AJAX call for form submission (that way I will stay at the same page) but perhaps it's possible to achieve the same without AJAX.
Thanks in advance,
On the controller you will want to submit to the addRecord route and do the processing. Have a check to make sure it was successful and on successful submission you can redirect back to the create route.
It is hard to give an example since you are using a custom made framework. I use slim which has a redirect method for a route. If what you have made does not have something like that then using should do the trick.
header('Location: '.$createUrl);
die(); //or exit
I have a line of code I wish to run after a view script has rendered, but I want this code to be placed in the action.
This is action specific and only updates a flag in the database, so it seems like overkill to utilise a plugin just for this.
What other options do I have? Could I register an abstract plugin that I can extend and hook into dispatchLoopShutdown() or routeShutdown() from the specific action I am in?
Thanks
By default 'View' is the last thing that the pointer will pass through.
you can:
$this->_helper->removeHelper('viewRenderer');
to globally remove views and then do the rest of action.
Actually, in many of my codes, I load views in chunks and have not faced any issues whilst rendering them before. Example, if I do:
$this->view->shouldGoinHeader;
// some actions here
$this->view->someHere;
// some more action thing
It works! So you can update a flag on your database using try catch if you are checking if view has been rendered.
If something is getting executed, you might want to post your codes?
I'm fairly new to the MVC architecture but I'm picking it up nicely, having my own framework almost done.
Nonetheless, I'm having a 'design issue', how to call the controller?
The controller, as in the function that checks if the user hit the submit button.
Example of controller:
$class->login($_POST['username'], $_POST['password']).
I know a lot of MVC frameworks and apps call it by the URL with $_GET params, but I think it's stupid to have one method or one class for each page that needs a function like logging in.
How do you guys do it? What's your method for this?
Any help is appreciated!
You might want to look up the Front Controller concept (and inversion of control), which you are probably already using in some form, but may not know it. The Front Controller analyzes the URL and current state of things, and determines what controller to load.
In my framework I have "routes" that have attributes, one being "require login". The Front Controller determines what "route"/controller needs to be run and checks for pre-requisites for that route, like login requirement. If the user isn't logged in, then the login "route"/controller is loaded instead of the requested "route"/controller. If login is successful, then control is passed to the appropriate "route" controller.
It shouldn't be the job of each controller to manage logins, only one controller should do that, usually the front controller. Any controller should be able to be loaded under any URL since it's the front controller that determines what controller to load. The sub-controllers don't know "why" they are loading, only that they are loading to do their 1 job.
You could have a base controller which contains a function, requireAccess($access_level). Other controllers would extend this controller. requireAccess() would redirect to the login page if the correct access level is not present.
As for redirection using GET variables for clean urls in MVC, I would not recommend this. It could cause problems down the line with wanting variables that contain slashes in them. Instead we would typically want to get the original request uri, and parse it ourselves.
Typically MVC urls follow the pattern /Controller/Action/Id/etc
Is there any way to get access to a helper class from within a registered plugin. From within the controller, one can use:
$this->_helper->getHelper($helperName);
Specifically, we use the FlashMessenger helper to pass error and info messages around to different pages before we do a redirect. In one of our plugins, we log a user out and set the index and controller to a different page. We could manually set a value in the request but this seems to go against what the FlashMessenger is supposed to be used for and we'd have to do that just for this special case.
You should use the action helper broker to retrieve a helper anywhere outside a controller. See the similar question:
zend-framework, call an action helper from within another action helper
I'm working on building up an interface that I want to function as a "tabbed browsing" sort of function. Each of these tabs has already been written as an action and the tabbed interface works fine as links to the individual tabs. I decided to try writing the "index" page for this controller - putting the content of all the tabs into hidden divs and swapping between them with jQuery, but once I started to use the action view helper - I ran into a lot of people saying that its bad practice. (see this article)
Some of these actions build up forms - grab some data from the model, etc to display. I want each of the actions to continue to function on their own (some parse forms as well).
Browsing to /item should give you the tabbed menu, plus all of the div's contents in a hidden tag - where /item/tab2 is a specific action (form submit for instance).
Another complication/caveat - Some of the actions will throw Access Exceptions if the user doesn't have access to that "tab". I'd prefer not to build access checking into the system twice (thus showing a tab with empty content).
I'm just trying to figure out what the best practice is to handle this sort of thing, and I thought that the action helper might be it. If I try to use View Helpers - I start wondering if that is the right place to assemble a Zend_Form.
Does anyone have any suggestions on the "proper" way to work around not using the Zend_View_Helper_Action ?
The Correct way to work around the action view helper, as I stated in the article you cited, is to create partials which access the model directly to fetch the data they need. This can be through a view helper (you make this yourself ;)) if this would involve a lot of logic in your view.
The action view helper is plagued with more than just performance issues, but also creates horrendous debugging nightmares, and if you need it, then your application is probably not following MVC, and therefore, you are using the controller for reuse, instead of the model, which is the patterns intention.
You can render partials from within your layout or current actions view with the render or partial methods of the view object.
If you have multiple actions to deal with multiple possible posts from your tabs, then you should set all of these actions to render the same view script, which will then render all of the tabs with data direct from the model.
If you're not generating the tab/tab panes from existing markup, and you're loading the content on demand, then you simply must check whether the user has permission to access the tab before displaying the tab itself, and again when attempting to load the tab's content.
Checking whether the user has these access permissions should be an acceptable mode of operation and should not be expensive to perform.
If these actions produce content that works in some standalone page, in addition to the tabs, then the Action view helper is the corrent way to proceed. Simply perform the same ACL (or other) check performed in the action when generating the tab.
I'm not entirely sure what your exact problem is, however you can disable the layout:
$this->_helper->layout->disableLayout();
Then the requested Action will just display it's view script, which you can load into the tab.
Any authorisation code you have will function as normal and you can display the requested view script for the Action, or not depending on if they have access.
You can catch any access exceptions by using a try/catch block:
try { // action throwing exceptions } catch (Exception $e) { // catch silently }