Our website is going to work as follows:
There's a central site www.example.org where everybody can register, change information, manage their 'business card'.
Also, everybody will have companyname.example.org. Here users can publish a simple site based on information they change in the main site.
This site is being built on CakePHP. I'm wondering what a good setup for this is. After doing some googling it appears to be common to create a separate directory for controllers and models for reusing, but in this case I want to really share all the code, except routes and views.
Is it possible to change routes based on a domainname. Would this be considered 'appropriate' for CakePHP at all. Rather than a solution that 'does' the job, I would prefer to find the best practice.
Thanks!
Solved using this tutorial
Off the top of my head, the routing engine in CakePHP has no concept of domains so what you could theoretically do is map a route eg /company1/post/1 to company1.example.com/post/1 using Apache rewrite
Prefixing in routes is possible as I've used it before to produce a multilingual site eg /en/blog, /es/blog etc so it would be just a case of prefixing the company name in the route.
What you are looking for are themes.
CakePHP 1.3 has a neat implementation of that, but 1.2 works almost as good.
In your AppController, you will want to add something along those lines to load a different theme based on the host:
$mapThemes = array('company.example.com' => 'theme-1', 'store.example.com' => 'theme-shopping');
$this->theme = $mapThemes[env('SERVER_NAME')];
Of course, possibilities are endless. You can load $mapThemes from the database by letting every user define multiple themes, etc. But that's the general idea and what I believe is the Cake way of doing things.
Related
So this past year I have dived into professional web development using laravel, and the journey has been amazing, with stackoverflow helping me tremendously. This question is more of an opinion rather than me asking how to do it. So, I'll break it down with an example.
Suppose I am creating an articles website. For the articles, I create a migration, model, controller and then views. For migration and model, it only requires one set of it because only one table exists for it. For views I have separate folders for admin panel for backend and frontend. Usually in the routes I'll create a group for backend with prefix of admin and auth guard which comes built in with laravel, though in the newer versions of laravel you gotta do composer require laravel/ui. Now, because I have different routes for both backend and frontend, logically what I do is create a completely different Controller for the backend with all the CRUD functionality, and for the frontend I make a separate controller and put index and show function in it.
Is this the best way to deal with it, or is there a more efficient way of handling the backend and the frontend? Also, is the basic workflow of development usually the same as I have mentioned, or do you people have a different take on how to do these things. Please let me know.
Cheers :)
In most projects, frontend and backend, are two different environments with different needs, so using the same controllers would be inappropriate as it might lead in complex - no-clean code.
What works for me best, is to separate the controllers in the following groups:
Frontend
Backend
API
In some cases you might also need a group for the controllers handling the ajax/async requests, i.e. Async group.
I am trying to build a way for a Laravel 4.1 application, which is intended to run multiple domains that essentially do the same thing, to load a different template based on the domain. On top of that I also have to be able to configure multiple environments (dev, qa, stage, live) like you would for any other single-site Laravel setup.
To start off, we already have a Laravel 4.1 instance running and configured for each environment. So that piece of it is good to go. We are using this to replace an old series of websites that was horribly built using an odd mixture of Java and PHP (don't ask, it is a nightmare).
Since every single one of these sites does the exact same thing (they have a homepage, faq, contact us, policy pages, a multi-step application form, and a user portal) we don't see the point in using a duplicate code base and maintaining each one individually (as this is for 5 different looking sites with different names).
So I have been tasked with making a new template for each site that looks identical to the old ones (for now) but in Laravel and running from the same code-base. I am doing that with Bootstrap and Basset. The first template works great with Bootstrap and Basset (to build a custom CSS set for each site from customized LESS files). I am able to get the template test page to load up just fine.
Here is the tricky part. I need to switch which template folder we are pulling our views from based on the domain name (myfirstdomain.com vs myseconddomain.com) while being able to switch environments (dev, qa, stage, and live). The environment is getting set by a current_mode file that is particular to the environment and not checked into the repository. That works great. But we need to be able to detect the domain segment (myfirstdomain, myseconddomain portions of the names) and then use that to set the views sub-folder to use.
I intend to name each template piece the same (header, footer, sidebar, etc). The nav will vary. Other aspects may vary. It would be nice to share a common layout, but at this point I would be happy with just template folder switching.
I spoke with another developer about using namespaces and just detecting and switching views that way. But I am not sure how that would work. I am unsure as to where the best place to detect this would be. I am also not sure the best way to switch/set the template/namespace.
Has anyone tried doing anything like this? Does anyone have any ideas?
I think in this case you don't really need to namespace your views, you can just add to your app/start/global.php something like this:
switch (Request::server('HTTP_HOST')) {
case 'myfirstdomain.com':
$viewPath = 'one'
break;
case 'myseconddomain.com':
$viewPath = 'two'
break;
}
Config::set('view.paths', [__DIR__.'/../views/'.$viewPath]);
And your views would have to be in
app/views/one/*
app/views/two/*
Or just
Config::set('view.paths', [__DIR__.'/../views/'.Request::server('HTTP_HOST')]);
And you would have to add your templates to:
app/views/myfirstdomain.com/*
app/views/myseconddomain.com/*
You can also add some code directly to your app/config/view.php:
'paths' => array(__DIR__.'/../views/'.Request::server('HTTP_HOST')),
As pointed by the OP in comments, you can also, add path locations:
View::addLocation($path);
Connect a namespace to the path:
View::addNamespace('company', $path);.
And if you want to use a company template, now you just have to do:
return View::make('company::layout.default');
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.
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'm looking for advice, tutorials and links at how to set up a mid-sized web application with Kohana 3. I have implemented MVC patterns in the past but never worked against a "formalized" MVC framework so I'm still getting my head around the terminology - toying around with basic examples, building views and templates, and so on.
I'm progressing fairly well but I want to set up a real-world web project (one of my own that I've been planning for quite some time now) as a learning object.
I learn best by example, but example-based documentation is a bit sparse for Kohana 3 right now - they say so themselves on the site. While I'm not worried about learning the framework as I go along, I want to make sure the code base is healthily structured from the start - i.e. controllers are split nicely, named well and according to standards, and most importantly the business logic is separated into appropriately sized models.
My application could, in its core, be described as a business directory with a range of search and listing functions, and a login area for each entry owner. The actual administrative database backend is already taken care of.
Supposing I have all the API worked out and in place already - list all businesses, edit business, list businesses by street name, create offer logged in as business, and so on, and I'm just looking for how to fit the functionality into a MVC pattern and into a Kohana application structure that can be easily extended.
Do you know real-life examples of "database-heavy" applications like directories, online communities... with a log-in area built on Kohana 3, preferably Open Source so I could take a peek how they do it?
Are there conventions or best practices on how to structure an extendable login area for end users in a Kohana project that is not only able to handle a business directory page, but further products on separate pages as well?
Do you know any good resources on building complex applications with Kohana?
Have you built something similar and could give me recommendations on a project structure?
Bounty
I'm awarding the bounty to #antpaw because he provided me with a Kohana application with some business logic that is giving me a lot of examples. Cheers #Pixel Developer for your excellent input as well - as so often, I'd wish one could split a bounty!
Lots of questions to answer here, I'll try my best.
Do you know real-life examples of "database-heavy" applications like directories, online communities... with a log-in area built on Kohana 3 where I could take a peek how they do it?
There's a few example applications out there. Woody Gilk (Kohana founder) has published the code to his personal website on github. For the login area he assigns a cookie value. Kohana 3 / 2.4 sign the cookies which makes it safe and removes the requirement for sessions. This might not be up to everyone's tastes so you can always use built in authentication library that uses both sessions and cookies.
Here are some other projects you might be interested in:
Shindig - Light weight blog module for kohana 3
Kohanut - An extensible CMS written in Kohana 3
Are there conventions or best practices on how to structure an extendable login area for end users in a Kohana project that is not only able to handle a business directory page, but further products on separate pages as well?
If I understand you correctly you want to generate a login box for each of those pages? This is easy with Kohana 3 as we can take advantage of the H in HMVC. Sam de Fressyinet wrote an article detailing what this all about on the iBuilding Tech Blog. Scaling Web Applications with HMVC.
What you can then do is perform an internal request to the login controller or action and dump the response into your view page.
$login = Request::factory('login')->execute()->response;
$login now contains the login form, which you can put anywhere you like. You may want to return a different response if the request is internal which is why this piece of code can be useful:
if (Request::instance() !== $this->request)
{
print 'Internal called made with Request::factory';
}
Do you know any good resources on building complex applications with Kohana?
There's not going to be documentation showing you how to build complicated applications. The view of the Kohana community is that you're a PHP developer and should be able to solve these problems for yourself. If you can't, well you shouldn't be using Kohana then.
Have you built something similar and could give me recommendations on a project structure?
Once you understand how Kohana 3 finds files things are easy to understand.
|- classes
|-- controller
|-- model
|- views
For example:
Controller_Mathew extends Controller
Will look for a file called mathew.php in:
classes/controller
Underscores can be used to specify deeper directories. Example:
Controller_Mathew_Davies extends Controller
will look for a file called davies.php in:
classes/controller/mathew/
As you can see, the underscores in the controller name act as directory separators. This rings true for models and vanilla classes.
i would use the auth module that comes with kohana for the login. This will give you the roles table where you can setup the possible permission options and relating them to the users later. After that you can check inside the __constructor() or action_function() of each controller whether the user has the required role e.g. with the ->has() function. You also should use the ORM module, its just awesome, since you have many relations between the tables. Also the __get() method inside an ORM object can be extremely handy.
Its also pretty easy to extend a controller function by setting the new parameter to NULL and checking for that in a if statement. e.g. you need only one function for editing a old entry or adding a new one.
public funciton action_manage($id = NULL)
{
$entry = ORM::factory('entry', $id); // if id is null a new entry will be returned
}
It's also important that you structure the views into sub folders to avoid a messy view directory.