I've got a class Widgets. Widgets are made up of Doohickies. I'm never going to need to access Doohickies directly via url -- they're essentially a private class, only used by Widgets. Where do you put your code to define the Doohicky class? In /app/controllers/doohicky.php? in app/controllers/widget.php? somewhere else? Obviously, the former seems cleaner, but it's not obvious to me how to make the Doohicky class available to Widget.
It sounds like your Widgets and Doohickies are probably Models in MVC architecture.
In which case, your paths would be:
app/models/widget.php
app/models/doohickies.php
I see the question has been answered already, but there are a few things to bear to expand on it.
You could put widgets and doohickies in the libraries folder, if they are there to do a job rather than provide a data service.
Also, take a look at HMVC, which favours the idea that you can have mini-apps that look after various parts of your website (e.g. messages panels, search box/results, doohickies...). This enables you to have smaller view partials dedicated to their widget controllers; and then the main controller calls in widgets but doesn't need knowledge of how they came about.
http://codeigniter.com/wiki/Modular_Extensions_-_HMVC/
Related
Started an project using kostache.
I have made some partials like banner,navigatons and footer in my class View_Layout with extends kostache_layout . Partials work fine on each page.
One problem. The navigation show always the same links. My goal is to show links that are appropriate to the user who is logged. How can I put logic in the partial of navigation? I know I can write functions in the View_Layout class but View_Layout must know the user role?
Hope somebody can help me.
In mustache, partials inherit from the surrounding template's variable stack. You'd need to do this logic in your view class. If different pages need different links, do that in your specific view class.
Option 1: evolve your views
The best option would be to expand the capabilities of your views. Actually in MVC-inspired patterns the views should be instances which handle UI logic and can choose from which (usually, more then one) templates to create the response. If that response even needs to be a HTML .. maybe a simple HTP header would be enough.
The default toolset in Kohana is geared towards very simple usecases, but it is possible to expand it.
My recommendation would be start using fully implemented views.
Option 2: use HMVC
Alternatively, you can utilize HMVC capabilities in Kohana. This would mean, that you have one or few "main controllers", which then create sub-requests. The responses from those requests is passed in/bound to the template, which said controller supervise.
In you particular case the menu would be governed by separate sub-controller.
I have an object oriented framework that uses a page design, where each page extends a view of the framework. So, for instance, my index page for a site is actually a class that implements the abstract class View provided by the framework. I hook the framework by including a startup script at the top of the page and after some processing the framework creates an instance of the page and processes its view data. To add flexibility to the system, I don't require the class name to be the name of the file itself. This allows me to create something like a support class and have it behave as the index for the /support/ subdomain.
I was initially passing the page's class name into the framework via the framework's constructor, but this added a few more steps to the top or bottom of the page. I currently obtain the class name via a pages table in the database identified by a filtered requested URI. I use this table to build navigation and adding an extra table column was practically free. This works OK as long as I have a database connection, but I'm trying to implement static page support for status messages and error reporting, and I need another method for creating an instance of the page's class. If I use the standard convention of naming the class the file's name, then I know I have a dependable way of extrapolating the class name. I don't really want to name all my classes index just for presentation reasons. What is some advice or some standards for how object oriented frameworks are initialized?
View.inc
<?php
abstract class View
{
abstract function getView();
}
?>
Startup.inc
<?php
require_once("View.inc");
require_once("CoreController.inc");
$Framework = new CoreController();
$Framework->Initialize();
exit;
?>
index.php
<?php
require_once("Startup.inc");
class Index extends View
{
public function getView()
{
echo "<pre>View Data</pre>";
}
}
?>
Within my framework I have a TemplateController that processes the page. The page class is known because it is mapped via another class. Without a database however, I would like to discover the class within, say, index.php without changing the way it's currently set up. Here is the actual code within the TemplateController.
//Get the View Class from Page
$view = $page->getPageClass();
//We need to catch View creation failure
$this->Page = new $view($this->Framework);
//Initialize the Page View
$this->Page->Initialize();
//Cache the Page View
$this->cacheView($this->Page, $page->getPageName(), $this->SiteID.TCS_PAGE_SORTID);
In the snippet above $view is the actual name of the class that was mapped from another controller. I'm passing a reference to the framework to the view's constructor and the rest is really irrelevant. I'm trying to come up with a similar mapping technique to identify the page class in the event the database is down. I like the one include line for the framework startup and would like to keep it that simple.
At the top of the TemplateController I have to also reinclude the actual page, since my startup script is at the top, the actual class is not included even though it is the requested page.
include($_SERVER['SCRIPT_FILENAME']);
Please review Stack Overflow question Identifying class names from $_SERVER['SCRIPT_FILENAME'] for more information on what I'm attempting to do.
Here is my checklist of page routing:
Adding new page must be quick
You must not be able to add page unintentionally
Application with million pages should not be slower or more bloated than application with 2 pages
Provide simple way and let people enhance it if they want
Allow easy re-factoring, such as moving several pages into different location
Make framework detect everything. Don't force user to specify base URL, etc.
Create simple to understand page names (hello/world).
Clean illegal characters from the URL
Make it possible to add static pages easy
Provide a way to generate URLs from page names.
Allow user to use pretty URLs by changing what appears before and after the page in the URL
And most importantly
- Stop copying, think about the best approach.
All of those suggestions I have used in the PHP UI framework - Agile Toolkit where I am a contributor.
Relevant sources: Agile Toolkit - a PHP Framework with jQuery, Agile Toolkit - PageManager.php, Agile Toolkit - URL.php and Agile Toolkit - PathFinder.php.
We wanted to make it really simple for developers. And secure too. And flexible. Therefore the "page" class is selected based on the URL. How? Quite easy:
/hello.html -> page_hello
/hello/world.html -> page_hello_world
Class then is mapped into filename. page/hello/world.php
Then there are cases when we want to use dynamic URLs too, such as: /article/234
Many frameworks implement a complex techniques here (arrays, regular expressions, front-controllers). We don't. There is mod_rewrite for this. Just rewrite this into page=article&id=234 and it works. And scales.
Apart from pages, there are other classes, but those classes can't be accessed directly. Therefore pages live under the /page/ folder, do distinguish them and maintain security.
Then comes the designer saying - "I won't write PHP". So we introduce static pages. If class page_hello_world is not defined, we'll look into template/skin/page/hello/world.html. That's a easy shortcut for designers and non-developers to add a new page.
What if a page is not found? Api->pageNotFound() is called. Feel free to redefine and load pages from SQL or display 404 page with a picture of a pink elephant.
And then there are some pages which come from add-ons. We don't want to enable them by default, but instead let users add them to their app somewhere. How?
class page_hello_world extends Page_MegaPage
Next question, is how we handle sub-pages of that page, since sometimes all the functionality can't fit on single page. Well, let's add support for page_edit() method (or any page_XX) as an alias for a sub-page inside those classes. Now add-on developer can include a multifunctional page which can be extended, customized and placed anywhere in the application.
Finally there are hackers, who want to do something really fast. For them we apply same technique to the API. You can define function page_hello_world in the API, and you don't need class.
Some might say that there are too many ways to do a simple thing. Oh well.
I hope that this was helpful.
Use __autoload(). Most major PHP frameworks use autoloading to streamline class loading.
You need some way to map a URL to an object, which is usually handled by a routing component in most frameworks. Might want to take a look at libraries such as https://github.com/chriso/klein.php, or the routing components of the major Frameworks out there (Zend, Symfony, etc.).
Why not to use information from URL to detect correct class? Since you won't use database for static pages, you have to somehow store mapping between URL and class in file. I.e. you will have a file mapping.php:
return array(
'about' => 'AboutView',
'copyright' => 'CopyrightView',
);
Here, about and copyright are URL components and values represent appropriate child classes of View. You can have URL's like http://example.com/index.php?page=about and use rewriting capabilities of webserver to make them look good.
You will change implementation of Page::getPageClass() in order to return correct view class. Depending on URL it will use static mappings from the file above or use database.
What's the problem with this approach?
Hi i'm a PHP developer trying to convert to Django and im having a bit of a hard time understanding where to put things and how to use the new language. Basically what i want to know is for example in codeigniter i would make classes and functions in my controllers. Where do i do that in django?
I believe the 'view' in django is more like the controller in an MVC framework but all the examples i can find of the view are very simple and just call a template and pass it some data.
I currently have an index view and a 'rates' view in my current project. The index page will call rates via JS and pass it some GET variables. In my php version i used these to instantiate my rates class which when had all the needed functions in it. I want to do this in Django.
The reason that it is called, "MVT" instead of "MVC" is that "View" to Django means, "presentation of data (according to given logic)" and "Template" means, "display of data presented." In a traditional MVC paradigm, "Controller" means "executer of logic" and "View" is "presentation of the result of the executed logic". (They are almost the same idea, but not quite).
So, what does this mean? Basically, if I were building something in Symfony, I would put all of the logic in the sfAction components. In CodeIgniter, it would be in the CI_Controller. In Django, I will place all of the logic in the "Views".
Just like CI (and Zend and others) will then call a "View" from the Controller descendant, the Django view will also call a "Template" from its "View". (Symfony's views are often called in a different syntax, so I will leave that to the reader to research if so desired).
Looking at your example, it looks like you want to call a method in the "View" (which view is configured in urls.py) which simply instantiates another object which has "all of your logic in it". Something like:
def ratesHandler(request):
rate = MyRatesClass(request.GET)
return HttpResponse("Insert something here. ") #or render_to_response
The logic always belongs in the view. You can put whatever logic you like there - no need to put it into a class, unless you want to. If the logic is related to a specific model, though, it is best to make it a method of the model or the model's Manager.
In django: "models" go in models.py, "controllers" go in views.py and "views" go in templates.
Models tend to be classes that subclass django.db.models.Model
Controllers (in views.py) are often functions but you can use classes if you like.
Note that if you're just displaying data from the database you can often use generic views so you hardly have to do any coding at all.
I can't tell whether there is a question in the last 2 paragraphs of your post. If there is a question there, please edit your post so it's clear.
I was looking on many template libraries, som I have fair mess in general idea what is out there ready to download/use and what I want to use, so maybe you could help me with this.
I'm currently learning CodeIgniter, thinking about moving to Kohana later. I would like to include controllers/modules(/module function maybe?) based on needs of template/site.
Example, so you would understand:
I have xml-defined page saved in mysql, which states, that in
<div id="sidebar">, i want to use news panel/widget - something like:
<div id="sidebar">{widget:news;3;60}</div>.
I'm looking for template parser and/or way to do it, so in main application I load page, then template. then I look up what modules/widgets page/template use and load them dynamically, pass them parameters (in example news;3;60 - module news, 3 last, 60 characters limit each), and echo their result in place of where i called them.
The usage for this should be understandable - if I use news module on 27 pages, just somewhere with last 3 news, somewhere last month, etc., i want to include it simply and edit it on one place.
Other problems in my mind are: I'm thinking that it would be best to have all modules at one time (not load them one there, one here), so I can access database on one place, etc.
I'm kind of lost and maybe someone will have some idea for me :)
The two best ways to do this are:
Use my CodeIgniter Dwoo implementation and build plugins
Use wiredesignz' Widget plugin
You could of course use Smarty plugins but yuck, who still uses Smarty?
Remember when creating Dwoo plugins that the CodeIgniter instance is available to any PHP loaded in on that request, so wether its Dwoo plugins, modifiers, blocks, etc you can always use:
$CI =& get_instance();
$CI->load->model('something');
//etc
If you're using Kohana3, you could use the HMVC-capabilities. A quick way would be to create a helper-class that you can use in your views. In your view you then make a call to this helper. This helper would start a new request that would trigger the correct controller/action.
There is some kind of widget-class in the Kohana-forums, but that requires a class for the widget instead of utilizing the (already existing?) controllers via the HMVC-capabilities of Kohana3.
1) Where does the homepage of your website fit into "controllers"? I've seen some people use a "page" controller to handle static pages like, about, home, contact, etc., but to me this doesn't seem like a good idea. Would creating a distinct controller just for your homepage be a better option? After all, it may need to access multiple models and doesn't really flow well with the whole, one controller per model theory that some people use.
2) If you need a dashboard for multiple types of users, would that be one dashboard controller that would have toggle code dependent upon which user, or would you have say a dashboard action within each controller per user? For example, admin/dashboard, account/dashboard, etc.
3) It seems to me that using the whole simple CRUD example works like a charm when trying to explain controllers, but that once you get past those simple functions, it breaks down and can cause your controllers to get unwieldy. Why do some people choose to create a login controller, when others make a login function in a user controller? One reason I think is that a lot of us come from a page approach background and it's hard to think of controllers as "objects" or "nouns" because pages don't always work that way. Case in point why on earth would you want to create a "pages" controller that would handle pages that really have nothing to do with each other just to have a "container" to fit actions into. Just doesn't seem right to me.
4) Should controllers have more to do with a use case than an "object" that actions can be performed on? For all intensive purposes, you could create a user controller that does every action in your whole app. Or you could create a controller per "area of concern" as some like to say. Or you could create one controller per view if you wanted. There is so much leeway that it makes it tough to figure out a consistent method to use.
Controllers shouldn't be this confusing probably, but for some reason they baffle the hell out of me. Any helpful comments would be greatly appreciated.
1) I use a simple homebrew set of classes for some of my MVC stuff, and it relates controller names to action and view names (it's a Front Controller style, similar to Zend). For a generic web site, let's assume it has a home page, privacy policy, contact page and an about page. I don't really want to make separate controllers for all these things, so I'll stick them inside my IndexController, with function names like actionIndex(), actionPrivacy(), actionContact(), and actionAbout().
To go along with that, inside my Views directory I have a directory of templates associated with each action. By default, any action automatically looks for an associated template, although you can specify one if you wish. So actionPrivacy() would look for a template file at index/privacy.php, actionContact() would look for index/contact.php, etc.
Of course, this relates to the URLs as well. So a url hit to http://www.example.com/index/about would run actionAbout(), which would load the About page template. Since the about page is completely static content, my actionAbout() does absolutely nothing, other than provide a public action for the Front Controller to see and run.
So to answer the core of your question, I do put multiple "pages" into a single controller, and it works fine for my purposes. One model per controller is a theory I don't think I'd try to follow when working with Web MVC, as it seems to fit an application with state much better.
2) For this, I would have multiple controllers. Following the same methods I use above, I would have /admin/dashboard and /account/dashboard as you suggest, although there's no reason they couldn't use the same (or portions of the same) templates.
I suppose if I had a gazillion different kinds of users, I'd make things more generic and only use one controller, and have a mod_rewrite rule to handle the loading. It would probably depend on how functionally complex the dashboard is, and what the account set up is like.
3) I find CRUD functionality difficult to implement directly into any layer of MVC and still have it be clean, flexible and efficient. I like to abstract CRUD functionality out into a service layer that any object may call upon, and have a base object class from which I can extend any objects needing CRUD.
I would suggest utilizing some of the PHP ORM frameworks out there for CRUD. They can do away with a lot of the hassle of getting a nice implementation.
In terms of login controller versus user controller, I suppose it depends on your application domain. With my style of programming, I would tend to think of "logging in" as a simple operation within the domain of a User model, and thusly have a single operation for it inside a user controller. To be more precise, I would have the UserController instantiate a user model and call a login routine on the model. I can't tell you that this is the proper way, because I couldn't say for sure what the proper way is supposed to be. It's a matter of context.
4) You're right about the leeway. You could easily create a controller that handled everything your app/site wanted to do. However, I think you'd agree that this would become a maintenance nightmare. I still get the jibbly-jibblies thinking about my last job at a market research company, where the internal PHP app was done by an overseas team with what I can only assume was little-to-no training. We're talking 10,000 line scripts that handled the whole site. It was impossible to maintain.
So, I'd suggest you break your app/site down into business domain areas, and create controllers based on that. Figure out the core concepts of your app and go from there.
Example
Let's say I had a web site about manatees, because obviously manatees rock. I'd want some normal site pages (about, contact, etc.), user account management, a forum, a picture gallery, and maybe a research document material area (with the latest science about manatees). Pretty simple, and a lot of it would be static, but you can start to see the breakdown.
IndexController - handles about page, privacy policy, generic static content.
UserController - handles account creation, logging in/out, preferences
PictureController - display pictures, handle uploads
ForumController - probably not much, I'd try to integrate an external forum, which would mean I wouldn't need much functionality here.
LibraryController - show lists of recent news and research
HugAManateeController - virtual manatee hugging in real-time over HTTP
That probably gives you at least a basic separation. If you find a controller becoming extremely large, it's probably time to break down the business domain into separate controllers.
It will be different for every project, so a little planning goes a long way towards what kind of architectural structure you'll have.
Web MVC can get very subjective, as it is quite different from a MVC model where your application has state. I try to keep major functionality out of Controllers when dealing with web apps. I like them to instantiate a few objects or models, run a couple of methods based on the action being taken, and collect some View data to pass off to the View once it's done. The simpler the better, and I put the core business logic into the models, which are supposed to be representative of the state of the application.
Hope that helps.