My app uploads an image and stores the image info in the database. If needed it manipulates the image. There are several points in the site where images can be managed like this.
In each case I have an action imageuploadAction() that handles things. Because I have slightly different requirements depending on the part of the site the image is going to be used in there are several different imageuploadActions in various controllers of the site. I want to combine them all into one, however, to make the app easier to manage.
So, my question is what is the best way to handle a site wide image upload capability within Zend Framework? I feel it must either be:
Have one action that does it all and the various controllers would use that action, or...
Create some sort of plugin that does it. An Action Helper Plugin perhaps? Maybe a controller plugin of some sort? What sort of plugin is the best way to do this?
I'm inclined to think 2 is the way to go but want your feedback on this. Thanks!
Oh, and the plugin (or action) will handle physically uploading the photos, categorizing them, flagging them for various uses, resizing as needed, passing data to the DB for all CRUD actions as necessary, etc. etc.
What you are describing is what action helpers were designed for, so I'd suggest creating an action helper for handling uploads and moving as much of your processing code into that as possible. However you still need to call that helper from your controllers, so then it really comes down to what suits your application - a central controller that handles the uploads (by calling your helper) or calling the helper from the relevant points in your existing controller methods.
If you can get to a point where your image upload actions are as simple as this:
public function imageuploadAction()
{
if ($this->_helper->HandleImageUpload([...])) {
[...]
}
}
then I'd say you're in pretty good shape, and you can always reuse the helper elsewhere if any parts of your app need to handle an image upload and some other data in the form at the same time.
Related
I have an application with several controllers dedicated each to its own part, say, "news", "articles" and "shop". They are not connected to each other, but they should be, as I need to insert data from them, like news related to current shop category. I have not found a clean way to access controllers other than the current one that is handling the request.
The structure of the modules is:
Site.pm is the main project file.
Articles.pm handles articles.
News.pm handles news.
Shop.pm handles shop.
Site.pm loads each of the above dynamically from an array of module names and calls its register function to set routes up and other things at startup. Articles, news, etc all take content from database, and it is rendered as inline template, thus, I can't just take related news and slam them into the stash, as not all entries in shop might even need that information.
This is a theoretical answer without code.
You probably have the database stuff decoupled from the actual controllers as models. That's good.
So let's assume we're in the shop and we want to show news related to the current product. There are at least two ways to do that.
You call your models directly. Your model for news provides a way to get the news for a product. You do that in the shop controller that displays the product page. This controller needs to put the stuff in the stash so the templates can access it.
You create a method in your news controller that is not accessible from the outside. You make it take a product id and find related news articles and populate them into the stash. You forward to it from your product page controller in the shop controller. Afterwards, the product page controller continues. This is the more decoupled way.
In both cases, your shop template includes another template that knows how to deal with the stuff in the stash for displaying news. You might be able to recycle a news template here.
I have not worked on Mojolicious but IMO this is the best approach -
Your Site controller should send GET requests to whatever other controllers it wants and these controllers should return JSON data which can then be rendered at the client side. Take a look Rendering JSON. Hope that helps.
Based on my experience, coding-blood, and a lot of shame for my code, I advise:
each method in a controller should only call a single function and pass the results to the template. This is somehow similar to the answer of #simbabque.
This will help you later testing the controller, writing API instead of providing html templates, even change the framework completely (as long as it is Perl).
So, I would add an optional layer between the Controller and the Models:
$t->get('/books/:id')->to('books#get')
sub Books::get{ my $self = shift; my $book = FBooks::get($self->param('id')); # plus template call }
sub FBooks::get{ # here you call your Model }
# your Model calls your DB
You provide the FBooks::get only then, when you need to make multiple calls to your model/s (maybe this is not a perfect example, but I hope you get my point). I prefer this instead of an army of helpers. If there is any other better way, I am happy to learn it.
I have an edit page which is grows with the size of the app. We're now running in to a situation where the server side action (MVC) is handling image uploads and conversions alongside regular text saving to database.
What's the best way to make this more maintainable? Separate controller for images uploads, so that we create an writeable API? Or more actions within the same controller?
There are few ways, which could let you mitigate the problem with rising complexity :
Implement HMVC, where each controller calls sub-controllers. This would let you to split up the "update" tasks in logical and manageable chunks. Especially, if i am correct in thinking that there is more the one "update page". The HMVC structure would let you to assemble different update pages from existing fragments with quite minor additional hustle. Main disadvantage: relatively large change in architecture.
Split the update page(s) in smaller forms, each submitting to a different controllers action (or maybe a different controller altogether). Main disadvantage: user can update only one part at the time
Evolve the model layer, so that the API you use interacts with service layer instead of domain model layer. This will let you isolate the complexity of updated and provide a simpler interface to use in controller. This too would have the added benefit of composing update form(s) from manageable pieces. But i don't know the penalties that come with this approach .. never have used it myself.
The bottom line is: you will have to change one part of MVC. In your situation i would choose the HMVC way, but mostly because i am familiar with it, and multiform page might induce rage from users.
I'm looking for some help wrapping my head around a good approach/architecture to handle images in my ASP.NET MVC 2 application. The application is a client for a middle-tier web service application that encapsulates our domain logic and rules. The images are stored in a back-end database that is only accessible through the web service.
For the sake of this discussion, we'll use the classic case of a Product which has an associated image. Whenever I display information about the Product, I also show the image. So, for instance, when viewing a list of Products to an admin for editing, I will show the image and the name of the product as a hyperlink. when editing, the user can see the existing image and upload a replacement. I also show the image when users browse lists of Products or look at what items are in their 'shopping cart'.
Needless to say, I have to obtain the image data a lot. (And, yes, caching will be a part of the solution but not part of my question.)
My first task was to create the controller and views used to edit Product data which includes the ability to upload the image. I followed the approach described in Pro ASP.NET MVC 2 Framework where I set the image element's src to a controller action which returns the image data. The controller receives a reference to the ProductManagementServiceAgent in its constructor and delegates to the agent which handles the call to the web service. This works great but, of course, it means two calls back to the service to display the information.
Next I have to display the list of Products, with images, to the admin. In this case it's not a problem because I'm using the same controller with the same action, so I can use the same approach. Unfortunately, now I'm making 'n+1' calls to the service.
My quandry comes when figuring out how best to handle all of the other use cases where I need to display the image. Inside the 'shopping cart', for instance. Should my ShoppingCartController also reference ProductManagementServiceAgent and use the same method to retrieve the product image? This would mean any controller that displays a product image would have to reference the agent, yes?
The first thing that bothers me about this is that I don't like injecting multiple dependencies into a class if I really don't need to and see long parameter lists in constructors as smelly code (tells me the object is trying to do too much). Plus, the ProductManagementServiceAgent is really intended for the admin UI, so maybe a different agent would be better? Or a different approach all together?
I have to think that others have already charted this territory, so I appreciate any wisdom to set me in the right direction.
Have a dedicated controller for images.
It will have one dependency - the ProductManagementServiceAgent.
Cache it both server side and client side to minimise requests.
I actually went with a suggestion not posted to this site so I can't give proper credit. In a nutshell, we expose additional actions on our controller when an image is required. So, for instance, our ProductController has a ProductImage action method that accepts the product id and returns the image. It seems to satisfy our needs.
I have a situation with my MVC2 app where I have multiple pages that need to submit different information, but all need to end up at the same page. In my old Web Forms app, I'd have just accomplished this in my btnSave_Click delegate with a Redirect.
There are three different types of products, each of which need to be saved to the cart in a completely different manner from their completely different product pages. I'm not going to get into why or how they're different, just suffice to say, they're totally different. After they're saved to the cart, I need to "redirect" to the Checkout view. But it should be noted, that you can also just browse straight to the Checkout view without having to submit any products to add to the cart.
Here's a diagram of what I'm trying to accomplish, and how I think I need to handle it:
Is this correct? It seems like a common scenario, but I haven't seen any examples of how I should handle this.
Thank you all in advance.
Yes, this is certainly one way to handle it. If your widgets, whatzits, and whozits views are really that different, than it's probably not worth it to try any sort of inheritance scheme or smart view that is capable of displaying any of them depending on what's passed in as the view model.
If you're asking for how to handle the redirect, you should probably use RedirectToAction("Action", "Checkout") when handling the save actions on your widget, whatzit, and whozit controllers.
It would be good if you had a base Model class for each of these XYZIt items and could pass them as a collection of CheckOutItems to the checkout controller directly instead of having these intermediate controllers in there. Not really sure why you need to have these extra controllers.
You can use RedirectToAction
I am in the process of building a website content management system for one of my clients. It's a highly customized system, so I cannot use any "of the shelve" solution.
I need to allow my client to add pages to the website on the fly. I have two options here:
(1) Create a database driven page in the format of www.mycompany.com/page.aspx?catID=5&pageID=3 (query the database with the category and page ID's, grab the data and show it on the page) - or -
(2) Allow the management system to create static pages, something like www.mycompany.com/company/aboutus.aspx and www.mycompany.com/company/company_history.aspx , etc.
I believe that, while the former is much easier to implement, the latter is a better both for the user AND for Google.
My questions are (finally): (1) Would you agree that the latter is a better solution, and (2) What is the best way to implement such a solution? Should I create and update each file using the FileSystem (i.e. - the site's management system requires the user to supply a page/file name, page title and content, and creates the page on the fly based on these parameters)? Is there a better way?
Thank you!
It's entirely possible to have database driven pages with nice URLs. StackOverflow itself is a great example - this question's URL is http://stackoverflow.com/questions/1119274/adding-pages-on-the-fly-with-a-cms-system, but the page is built from the database, not static HTML.
I would use the first solution, but mask the addresses using a custom request handler. Basically, give each of your pages a unique string ID (such as about-us) and then, with your request handler that takes all requests, find this particular page in the database and render it.
See this article for some additional info (found it when googling for custom http handlers in ASP.NET.) In that article, it has the following handler added:
<add verb="*" path="*.piechart" type="PieChartHandler"/>
You would probably want to catch all paths (*), excluding certain media paths used for CSS, images and JavaScript.
More resources:
Custom HTTP Handler
HttpHandler in ASP.Net
I'd stay clear of static pages if I where you. Dynamic Data, MVC and some good planning should take you a long way!
What you need to do is to create some or many templates that each view/controller in mvc can use. Let whoever is responsible for the content handle it through dynamic data entities.
I would use the first idea, but work out a better URL scheme. If the system doesn't provide nice URLs (without ?), you'll have trouble getting the search engines to parse the whole site. Also using numbers instead of words make it hard on users to pass around URLs.
If you start to have performance problems you could add caching that would generate static pages from time to time. I would avoid doing that until you have to; caching can cause many headaches along the way to getting it right.
Although the existing advice is more-or-less sound, the commentators have failed to consider one factor which, admittedly, you haven't given much detail on. Are these pages that they'll edit once they're built, or a they one-shot creations? If the latter, your plan of generating static pages isn't quite so bad as they suggest. Why bother even having to think about database schemas and caching, when you can just serve flat content.
It will probably make for pretty lifeless, end-of-the-road pages, but if that's what you want ...