I need to setup multisite in phalcon where I need some common functionalities to be done among all sites and also will have site specific. Say it would have some common controllers modals and views, if I need anything to be changed in one particular site I should be able to change in that particular site with out affecting other sites. just by creating single view template and extending the controllers and modals. If i need to change anything in all sites then I could be able to change it in a single place.
1 Answers
multisite/shared
├── apps
│ ├── common
│ │ ├── controllers (Register namespace Common/Controller)
│ │ │ ├── IndexController.php
│ │ │ ├── LoginController.php
│ │ │ └── ProductsController.php
│ │ ├── models (Register namespace Common/Model)
│ │ │ └── Products.php
│ │ └── views
│ │ ├── login
│ │ │ └── index.volt
│ │ └── products
│ │ | └── index.volt
| | └──index.volt
│ ├── example.com
│ │ ├── controllers
│ │ │ ├── IndexController.php (extend Common/Controller)
│ │ │ ├── LoginController.php (extend Common/Controller)
│ │ │ ├── ProductsController.php (extend Common/Controller)
│ │ │ └── UsersController.php Site Specific Controller
│ │ ├── models
│ │ │ └── Products.php (extend Common/Model)
| | | └── Users.php (Site Specific Model)
│ │ └── views
│ │ └── products (Other view templates will refer to Common view folder)
│ │ └── index.volt
│ ├── example2.com
│ │ ├── controllers
│ │ │ ├── IndexController.php (extend Common/Controller)
│ │ │ ├── ProductsController.php (extend Common/Controller)
│ │ │ └── SitespecificController.php Site Specific Controller
│ │ ├── models
│ │ │ └── Products.php (extend Common/Model)
| | | └── SiteSpecific.php (Site Specific Model)
│ │ └── views
│ │ └── sitespecific (Other view templates will refer to Common view folder)
│ │ └── index.volt
└── public
└── example.com (Will contain Js CS Images to support site specific theme)
└── example2.com (Will contain Js CS Images to support site specific theme)
└── index.php
Refer : http://monkpal.com/Multisite-Set-up-with-shared-views-controllers-and-modals-Phalcon
Steps to setup multiple site with different domain name
Steps to acheive it
Step 1 : Register the namespaces of common controllers and models
Step 2 : Extend the phalcon view engine to cascading the view (say for example View engine will look for specific template file in site specific view folder if its not exist it will look in common views folder, there is no need to replicate all the template files in all sites views directories, you can overwrite single template file alone).
Step 3 : Extend Phalcon volt to provide Skin path for templates Step 4: Create site specific Volt cache folder
Step 5 : Create seperate folders with sitenames in public folder for js/css/images Step 6: Create common contollers, views, modals
Step 7: Extend common controllers , modals in site specific folderss , Views wil be taken from common folder. if you want to overwrite any template you can overwiite that alone no need all view folder. Step 8 : Set sitename by current domain name. this sitename will be used to register contollers models directries
Step 9: Set two views directory one is common and another is sitename (thi can be done only if you have extened the phalcon view to add two directories refer step 2) Files extended are here this should be in your public directory.
Files extended are here, this should be in your root directory.
custom/CustomVolt.php
<?php
namespace Custom;
use Phalcon\Mvc\View\Engine\Volt;
use Phalcon\Mvc\View\Engine\Volt\Compiler;
class CustomVolt extends Volt
{
public function getCompiler()
{
if (!$this->_compiler) {
$this->_compiler = new VoltCompilerExtension($this->getView());
$this->_compiler->setOptions($this->getOptions());
$this->_compiler->setDI($this->getDI());
}
return $this->_compiler;
}
}
class VoltCompilerExtension extends Volt\Compiler
{
public function compileFile($path, $compiledPath, $extendsMode = null)
{
$skinPath = $this->getOption('skinPath');
if ($skinPath) {
$skinTemplate = str_replace(
$this->getDI()->getView()->getViewsDir(),
$skinPath,
$path);
if (is_readable($skinTemplate)) {
$path = $skinTemplate;
}
}
return parent::compileFile($path, $compiledPath, $extendsMode);
}
}
custom/CustomView.php
use Phalcon\Mvc\View\Exception;
use Phalcon\Mvc\View;
use Phalcon\Cache\BackendInterface;
class CustomView extends View
{
protected $_viewsDirs;
/**
* @var
*/
protected $_eventsManager;
/**
* @param $path
*
* @return $this
*/
public function addViewsDir($path)
{
$this->_viewsDirs = $path;
$this->setViewsDir($path);
return $this;
}
/**
* @param $view
* @param array $vars
*
* @return string
*/
public function getPartial($view, $vars = [])
{
ob_start();
$this->partial($view, $vars);
$content = ob_get_contents();
ob_end_clean();
return $content;
}
protected function _engineRender($engines, $viewPath, $silence, $mustClean, BackendInterface $cache = NULL)
{
if (is_object($cache)) {
throw new Exception('Cache view not supported...');
return;
}
$viewsDirs = is_array($this->_viewsDirs) ? array_reverse($this->_viewsDirs) : [$this->_viewsDir];
$notExists = true;
$viewEnginePath = null;
foreach ($engines as $extension => $engine) {
foreach ($viewsDirs as $viewsDir) {
$viewsDirPath = $this->_basePath . $viewsDir . $viewPath;
$viewEnginePath = $viewsDirPath . $extension;
if (is_file($viewEnginePath)) {
if (is_object($this->_eventsManager)) {
$this->_activeRenderPath = $viewEnginePath;
if($this->_eventsManager->fire('view:beforeRenderView', $this, $viewEnginePath) === false) {
break;
}
}
$engine->render($viewEnginePath, $this->_viewParams, $mustClean);
if (is_object($this->_eventsManager)) {
$this->_eventsManager->fire('view:afterRenderView', $this);
}
$notExists = false;
break 2;
}
}
}
if ($notExists) {
if (is_object($this->_eventsManager)) {
$this->_activeRenderPath = $viewEnginePath;
$this->_eventsManager->fire('view:notFoundView', $this);
}
if (!$silence) {
$exceptionMessage = 'View "'.($viewPath).'" was not found in the views directories';
throw new Exception($exceptionMessage);
return;
}
}
}
}
public/index.php
<?php
use Phalcon\Loader;
use Phalcon\Mvc\Application;
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Url as UrlProvider;
use Custom\CustomVolt;
use Custom\CustomView;
if($_SERVER['HTTP_HOST'] == "example.com") {
define('SITENAME',"example.com" );
}
if($_SERVER['HTTP_HOST'] == "example2.com") {
define('SITENAME',"example2.com" );
}
define('APP_PATH', realpath('..') . '/');
try {
$loader = new Loader();
$loader->registerNamespaces(array(
'Common\Controller' => '../app/common/controllers',
'Common\Model' => '../app/common/models',
'Custom' => 'custom'
))->register();
$loader->registerDirs(array(
'../app/'.SITENAME.'/controllers/',
'../app/'.SITENAME.'/models/'
))->register();
$di = new FactoryDefault();
$di->set(
'voltService',
function ($view, $di) {
$volt = new CustomVolt($view, $di);
$volt->setOptions(
array(
"compiledPath" => "../cache/volt/".SITENAME."/",
"compiledExtension" => ".compiled",
'compileAlways' => true,
'skinPath' => '../app/'.SITENAME.'/views/'
)
);
return $volt;
}
);
$di->set(
'view',
function () {
$view = new CustomView();
$view->addViewsDir(array('../app/common/views/','../app/'.SITENAME.'/views/'));
$view->registerEngines(
array(
".volt" => 'voltService'
)
);
return $view;
}
);
$application = new Application($di);
$response = $application->handle();
$response->send();
}
catch (\Exception $e) {
echo "Exception: ", $e->getMessage();
}
To render Js and css site specific in volt tempaltes
You use can like this
{{ stylesheet_link(constant('SITENAME') ~'/css/main.css') }}
{{ javascript_include(constant('SITENAME') ~'/js/main.js') }}

- 201
- 3
- 7
-
1Is this self-promotion? – Timothy Aug 11 '16 at 10:41
-
1No offence, but if you are [self-promoting your blog, you should disclose so](http://meta.stackexchange.com/questions/57497/limits-for-self-promotion-in-answers/59302#59302). And Phalcon has ["official" examples of "multi site" setups](https://github.com/phalcon/mvc) – Timothy Aug 12 '16 at 06:39
-
How does your routing even work? Where do you define your modules? Does your answer work without these things? – Timothy Aug 12 '16 at 06:40
-
yes without modules it will work, I have working site on it – Karthikeyan Manivasagam Aug 12 '16 at 12:46
-
you can even use module for separate routing ,or you can have one routing class file too. without modules it will work because the thing we are segregating the site by domain name, here you can use same routing path url in all sites. say site-1 can have article/23 site2 can have article/34. Main feature here is we are using common views folder ans sitespecific views folder without duplicating the whole views directory erverywhere. – Karthikeyan Manivasagam Aug 12 '16 at 12:53
-
there is lot of difference between multi module site and multisite – Karthikeyan Manivasagam Aug 12 '16 at 13:03
-
I'd also like to note that the `$_SERVER['HTTP_HOST']` value can be spoofed. – Timothy Aug 12 '16 at 13:12
-
At the core, All frameworks /core php/content management systems are using multisite in single installation with the help of the domain name only. – Karthikeyan Manivasagam Aug 12 '16 at 13:24
-
you can use SERVER_NAME – Karthikeyan Manivasagam Aug 12 '16 at 13:30
-
Indeed you can use `SERVER_NAME`. But note that your webservice should be correctly configured. And like you mentioned; your "multisite" would be better if you configured it at the "core" (your webservice: apache/nginx/..) – Timothy Aug 12 '16 at 13:33