alanmanderson
alanmanderson

Reputation: 8200

How to organize shared code on website Bonus: across subdomains

How should I organize my website in order to utilize shared packages? Lets use Stackexchange as an example. There are many subdomains:

webapps.stackexchange.com         namespace StackExchange\webapps
programmers.stackexchange.com     namespace StackExchange\programmers
etc.

Each of the subdomains reuse libraries. Maybe there is a Question Class that is reused by all of the sites to help layout the ask a question page.

Would the question package be packaged in every one of the subdomain packages? Or do all of the packages reference the Question package. In other words: which scenario is the case:

StackExchange\webapps\question
StackExchange\programmers\question

OR:

StackExchange\webapps
StackExchange\programmers
StackExchange\question
WHERE StackExchange\Webapps and StackExchange\programmers use StackExchange\question

I ask because I am setting up my website with several independent tools on it. I plan to put each tool in its own subdomain on the same server. I only want to have to update the server in one place whenever I update a package that is used by many subdomains, so I would like it to be stored in its own namespace.

Should I be using a dependency manager like composer or something to take care of this for me? What is the best practice way of accomplishing this?

Upvotes: 4

Views: 439

Answers (2)

hanzi
hanzi

Reputation: 2987

I had to deal with a similar scenario where I had two websites that shared a lot of functionality. Because I had to rewrite one of them, I tried to establish a shared codebase.

Namespaces

How you structure your namespaces is mostly a matter of taste.

Personally, I use Vendor\Package for shared stuff and Vendor\Site\Package for site-specific code.

What you do not want to do is to put a shared package in each site-specific package (as your first example implied) because that way you would have to copy and modify your code files (because you'd have to change the namespace).

Where to put shared packages

You have two options where to actually put your shared packages: local to each application (subdomain) or globally on the server.

Global packages

Here you would put shared code somewhere on your server where every application can access it. rm-vanda's answer pretty much described how this could be done in practice. You don't need Composer for this.

In the pro side, you would only have one instance of the shared package instead of several copies. You can't forget to update one of your applications. If you use a PHP accelerator like APC or OpCache this approach will also save some memory because shared libraries only hit the cache once.

Local packages

Another approach is to have a copy for each application. That's the approach Composer pursues by default. Usually, you'll have a "vendor" directory in your application's main directory where you put this shared stuff (and also third-party code if you use any). That way, each application can use a different version of a shared library.

Personally, I like the local approach most. I can live with the additional deploying work and I think it's the most future-safe way to do it.

  • Have to split up my applications on several servers? No problem, they're pretty much independent already.
  • Number of applications is growing and I can't bother to always check all of them if I update something? Just don't update all of them.
  • I can even have a production environment and a test environment on the same server featuring different versions of a shared library.

Also, using Composer feels the most natural with this approach. And Composer is a really awesome thing, especially when using third-party code.

Upvotes: 1

rm-vanda
rm-vanda

Reputation: 3158

Since everything is going to be on the same server, you can simply have a shared directory in your php.ini 's include path ---

i.e.

/usr/share/php/

Which each project will then be able to include the same files from - (A well-written auto-loader function could do this as well, without the need for an include path)

and when setting the include path for project-specific purposes -

ini_set('include_path', get_include_path().".:/var/www/path/for/this/project");

Or even just include what you need on a per-need basis:

require_once '/usr/share/php/apis/Google_Client.php';

Upvotes: 1

Related Questions