I think I have a weird/complicated situation but I think I'm overlooking something simple. We are setting up a Yii application that will host other "skins" people set up. It's basically one big community but on many different sites. Everything will be handled by one single common core Yii application.
Our plan is to allow two different URL configurations depending on what the skin owner wants to do:
1) whatever.theirsite.com (which is set up as a CNAME to portal.oursite.com - for advanced users)
2) portal.oursite.com/theircommunity - for those who just want it to work with no other configuration
In the first case, it's easy enough to pick out the SERVER_NAME variable, look up the correct theme in the database, and serve up the correct theme/community. I have actually done this in the past and it works fine. However, I'm a little lost on the second case. I can still do the db lookup to find out what theme to serve from portal.oursite.com/theircommunity, but all the routing gets screwed up because theircommunity is not a controller. It's more like a virtual directory but its dynamic. I feel like I'm missing a simple htaccess or possibly a UrlManager rule.
Valid example urls would be:
http://whatever.theirsite.com/mycontroller/myaction
http://portal.oursite.com/theircommunity/mycontroller/myaction
or for a module:
http://whatever.theirsite.com/mymodule/mycontroller/myaction
http://portal.oursite.com/theircommunity/mymodule/mycontroller/myaction
In all cases, both pairs of requests need to go to the same place. Backend processing ensures that they look different but are handled by the same code.
Any advice?
Edit:
One solution I thought of but haven't tested yet (not sure if it is a good idea or not, or if it would even work) would be to extend the URL manager to add new routing rules depending on which community is being asked for.
ex:
before application runs, do a db lookup to figure out which theme we
are using.
if the theme uses a virtual root, then copy all existing url manager rules but append theircommunityname/ to the front of them.
Yes, I think your edit/URL manager setup is probably going to be your best option.
For what it's worth, those routing rules are going to look similar to the module routing rules, so you might be able to fake load a module that has the appropriate name using an app behavior. I did something similar for a client last year; it worked, but was complex. I would suggest your start getting comfortable writing unit tests against this system, you'll want them to make sure you don't break things in the future :-)
Interesting question! I may be way off mark here. But would something like this work?
/portal.oursite.com
/theircommunity1/index.php
/theircommunity2/index.php
In words: create a user-specific subdirectory of your webroot.
This means that user 1 will have the /theircommunity1/index.php entry script. User 2 will have /theircommunity2/index.php. In the entry scripts your can
Set user specific variables
include a 'secondary' entry script that may be outside the webroot.
I'm not sure I understood your scenario correctly. You can extend UrlManager and create some variable based on the site lookup. Eg $_GET['site'] = 'theircommunity'; and you can check for this variable later on your application.
This actually ended up having a simple solution but it took me a while to find it. It was simply a matter of extending CHttpRequest and setting the baseUrl property for the request in init().
if (Yii::app()->domainManager->isPortalDomain) {
// need to set the document root correctly
Yii::app()->request->baseUrl = '/' . Yii::app()->domainManager->domain->name;
}
When I did that, all routing worked and urls were created correctly.
Related
I am new at web development, and I have started to work on a small website just recently. Now the problem is, that since it is my first time, I move my pages a lot on the server, because of which I have to keep updating all the other pages that link to it. So, I was thinking of a dynamic way of linking the pages, so that I don't have to update at several places, but only at one.
How it is going to work is that,
there is going to be a separate database kind of thing that will contain all the webpages' updated address, and a unique key to identify them. eg. page12345 = "/about/us.php"
and anywhere where I want to include a link to the page, instead of typing .., I'll have to type something like .., or something like that
This method will also enable me to assign tags/categories to pages, and, or add other properties to them. And, I'll probably also use it for media files as well later.
Now, the thing is, I can think of only two ways to do so, one is using an array in PHP, and other is using MySQL database. The array will probably be too much to handle when the site grows and there are, like thousands of pages, on ther other hand, MySQL database will probably prove to be slower, and at the same time more of a hassle.
So what is it that you suggest? Which will be more efficient. Or is there a better way, I am open to any other ideas that you may have.
The typical way to manage that is to not worry about URLs manually at all and leave up to a router. In the end, URLs are just a technical implementation detail of the HTTP protocol. What you really want to do is identify specific pages/actions uniquely. Have a look at any reverse-routing capable router; here the Symfony implementation:
blog_show:
path: /blog/{slug}
defaults: { _controller: 'BlogController::showAction' }
Read this blog post.
This is admittedly a very high level abstraction, using YAML for specifying routes and Twig for templating with a custom defined function. However, it hopefully demonstrates the goal: don't worry about URLs much at all in your actual links. You need to have one canonical place where URLs are defined (the path in the above example), everywhere else you just refer to your target page by name (blog_show here). If you need to move URLs around, there's exactly one place where you need to do so. The thing in the middle that makes this work is the router.
Is it bad to use index.php as loader for other scripts or does it make a difference?
i.e. requesting index.php with different query strings and inside it, selecting and including the matching script.
e.g.
www.example.com/?sign-in insteade of www.example.com/sign-in.php
www.example.com/?new-post insteade of www.example.com/new-post.php
In this way you can use index.php to do the common inclusions and processes, like, setting timezone, mb encoding, DB connection, auth, etc..
Best practice is to let apache rewrite all urls to an index.php or some other file which you can use as bootstrap. This bootstrap runs all the basic code and then this bootstrap can figure out which other actions to take based on the url.
Every framework works like this.
several things you might want to do in the bootstrap:
setup, autoloading classes
setup mysql connection
check if user is authenticated for a certain action
There are many tutorials on rewriting urls with apache: http://www.workingwith.me.uk/articles/scripting/mod_rewrite
If you really want to learn about best practices i would suggest looking at existing frameworks, at how they implement certain things. eg: Zend or Symfony
Yes and No
The problem is that by doing it you will lose any SEO value, eg: domain.com/index.php?post=story will rank very poorly against domain.com/post/story . Also your index.php is going to get messy very quickly.
That being said MVC's usually use a index.php, so my url would be domain.com/users/edit/123 which is a very logical url, but what actually gets called is domain.com/index.php , it then looks at the first paramater, "users" and instantiates the user controller and then looks for the function edit inside that and passes the "123" (user id) as the first parameter in the function. If you are not familiar with MVC's I would advise codeigniter as a starting one, more on codeigniter.
In the end you will just be re-inventing the wheel by building it from scratch, rather use a MVC make development much easier.
This is the best approach. You can take control of your website.
Create index.php and include other files on demand.
(Define a constant and use it in included files and so on)
But keep in mind to minimize index.php as much as possible.
Also you can use Apache mod_rewrite to generate SEO friendly URL.
Instead of routing all your requests (through htaccess) to index.php you can also split the routes to map to other files:
/blog/hello-there mapping to blog.php?title=hello-there
/sign/in mapping to login.php?login
etc, thus you create your own simple routing based on the request URL; easy to read and easy to maintain.
This solution is suitable in small projects, for bigger project I advise to use a complete framework like Yii or Symfony.
More and more I find websites that show this kind of links:
website.com/page/
and testing if there's in index.php inside the folder like
website.com/page/index.php
I found always true.
So my question:
Is it a common way to put all your pages in subfolders even if it's a single file that you could also easily put in the root folder (in this case page.php) or is there a "common" rewrite for it?
If yes, I'd like to know how a typical folder structure for this case would look like.
I just got a bit confused and don't want to do it "wrong" on future projects.
And beside: Does this technique effect SEO?
If it's a static site then yes it's quite common to have just one page in a subfolder and having that page named as index.html or index.php because most servers are configured to pick that up without showing the filename.
One reason for doing this is so that if future pages are created that would naturally come under that subfolder then it keeps your site structure and site map neat and tidy.
These days many CMS systems replicate this sort of structure on the fly.
For SEO purposes it's good to have descriptive directory names and/or page names i.e.
news/the-title-of-my-news-article.php
Hope that helps.
URIs more often than not have nothing to do with the actual structure of the files. Take Stack Overflow for example: This page's URL is
http://stackoverflow.com/questions/12090658/is-it-typical-to-put-all-pages-in-subfolders-even-if-its-a-single-page
If we follow your logic, it means that stackoverflow has a questions folder for all questions, then a specific ID folder for every single (over 2 million) question, then another folder, with it's complete name, and inside of it an index file.
No, that's not the case. URLs are often rewritten to allow for increased complexity of application.
As for your specific question, perhaps there's a special meaning, perhaps there is none, it's up to the webmaster to decide that.
Even if you get some results when you hit website.com/page/index.php instead of website.com/page, doesn't mean there's a file there. In fact, it doesn't mean there's even a folder named 'page': the power of mod_rewrite may easily transform the URL
http://example.com/page/index.php
... into
http://example.com/index.php?controller=page
... so there's a single file executed each time someone queries this application (Single Front-End Controller design). Following this approach makes it not necessary to create a slew of folders for each and every possible user story.
But it's quite true that you should organize your web application into modules (which, in turn, are usually organized as sub-sub-folders of /modules application sub-folder). There's a very popular paradigm - MVC; it's quite commonly used by PHP frameworks and CMS built on this language, but it's not necessary to use one of these to follow it. Perhaps this tutorial might be useful for introducing MVC in PHP to you?
I’m in the process of learning to use the Zend Framework, and I’m therefore trying to grasp the concept of MVC. Through the Zend manual, and a very helpful Youtube video tutorial I have sort of understood the concept – still there are some things I need to clarify.
The web project I’m currently working on is a web site for an organization I’m a part of. It consists of:
The public portion, mainly consisting of information about us, a calendar and some media – mostly static information, but a couple of pages, like the calendar, will need to retrieve some data from the DB.
The internal pages, which after a login will allow users to RSVP to events and comment them as well.
The administrative controls , allows the admins to add events and manage users etc.
So far it looks like Zend wants the URL to look like this:
http?://[domain]/[controller]/[action]
So here are my questions:
Do I always have to have an action in the url, or will the lack of an action use the index-action as default?
Can I have a subdirectory to distinguish between the internal and public portions of the site: http://[domain]/internal/[controller]/[action] ?
Can this be done simply by having a subfolder within the different MVC-folders somehow?
The latter question isn’t really that important, but I’d like to separate the two portions of the site somehow.
Do I always have to have an action in the url, or will the lack of an action use the index-action as default?
A controller can have a default action which is triggered when no action is specified in the URL. Look for default action or index action.
Can I have a subdirectory to distinguish between the internal and public portions of the site: http://[domain]/internal/[controller]/[action] ?
Yes you can have, but I assume subdirectory refers to your URL, not to the actual file-layout on the server. You can do so by just having a controller per "subdirectory".
Can this be done simply by having a subfolder within the different MVC-folders somehow? The latter question isn’t really that important, but I’d like to separate the two portions of the site somehow.
You can separate per controller and you can even separate with modules. As far as I know of modules in zend-framework, this will all be in it's own sudirectory per module.
I think you're especially looking for Using a Conventional Modular Directory Structure.
The questions you are asking are in the area of routing which generally means: Given a URL on which the HTTP request is being made:
Which controller should be instantiated?
Which action on that controller should be run?
What parameters should be passed to the action?
The routing docs in the ZF Manual explain how routing works by default and how you can specify your own routing. But looking at them now, I don't think they do a great job of introducing the subject matter for a first time user. This post might be better, though it is only a single, simple example.
I am taking over an existing PHP project. I noticed that the previous developer uses a one index.php page for the entire site, currently 10+ pages. This is the second project that I have seen done like this. I don't see the advantage with this approach. In fact it seems like it over complicates everything because now you can't just add a new page to the site and link to it. You also have to make sure you update the main index page with a if clause to check for that page type and then load the page. It seems if they are just trying to reuse a template it would be easier to just use includes for the header and footer and then create each new page with those files referenced.
Can someone explain why this approach would be used? Is this some form of an MVC pattern that I am not familiar with? PHP is a second language so I am not as familiar with best practices.
I have tried doing some searches in Google for "single index page with php" and things like that but I can not find any good articles explaining why this approach is being used. I really want to kick this old stuff to the curb and not continue down that path but I want to have some sound reasoning before making the suggestion.
A front controller (index.php) ensures that everything that is common to the whole site (e.g. authentication) is always correctly handled, regardless of which page you request. If you have 50 different PHP files scattered all over the place, it's difficult to manage that. And what if you decide to change the order in which the common library files get loaded? If you have just one file, you can change it in one place. If you have 50 different entry points, you need to change all of them.
Someone might say that loading all the common stuff all the time is a waste of resources and you should only load the files that are needed for this particular page. True. But today's PHP frameworks make heavy use of OOP and autoloading, so this "waste" doesn't exist anymore.
A front controller also makes it very easy for you to have pretty URLs in your site, because you are absolutely free to use whatever URL you feel like and send it to whatever controller/method you need. Otherwise you're stuck with every URL ending in .php followed by an ugly list of query strings, and the only way to avoid this is to use even uglier rewrite rules in your .htaccess file. Even WordPress, which has dozens of different entry points (especially in the admin section), forces most common requests to go through index.php so that you can have a flexible permalink format.
Almost all web frameworks in other languages use single points of entry -- or more accurately, a single script is called to bootstrap a process which then communicates with the web server. Django works like that. CherryPy works like that. It's very natural to do it this way in Python. The only widely used language that allows web applications to be written any other way (except when used as an old-style CGI script) is PHP. In PHP, you can give any file a .php extension and it'll be executed by the web server. This is very powerful, and it makes PHP easy to learn. But once you go past a certain level of complexity, the single-point-of-entry approach begins to look a lot more attractive.
Having a single index.php file in the public directory can also protect against in the case of the php interpreter going down. A lot of frameworks use the index.php file to include the bootstrap file outside of the doc root. If this happens, the user will be able to see your sourcecode of this single file instead of the entire codebase.
Well, if the only thing that changes is the URL, It doesn't seem like it's done for any reason besides aesthetic purposes...
As for me - single entry point can help you to have better control of your application: it helps to handle errors easily, route requests, debug application.
A single "index.php" is an easy way to make sure all requests to your application flow through the same gate. This way when you add a second page you don't have to make sure bootstrapping, authentication, authorization, logging, etc are all configured--you get it for free by merit of the framework.
In modern web frameworks this could be using a front controller but it is impossible to tell since a lot of PHP code/developers suffer from NIH syndrome.
Typically such approaches are used when the contents of the pages are determined by database contents. Thus all the work would get done in a single file. This is seen often in CMS systems.