Im new to symfony and have some simple questions. I am trying to understand the module system, but I dont understand how I create the actual homepage or other pages that are not based off of a model from the db. For example, the simple about page that has static info or the homepage that is a combination of a bunch of information from different models.
Can anyone help?
First of all, modules do not have to be restricted to a model from the database. You can have a Foo module which relies on no database content, and a Bar module that is primarily based on 3 different models. The module separation is a way to logically break up your site into manageable sections. Eg an e-commerce site might have a Products module, a Categories module and a Cart module and so on.
Your last sentence can then be split into 2 parts:
1) Static information can be on any page - if it's for things like "About us" and "FAQ" etc, I personally tend to use a "default" or "home" module, and create the various actions in there vis:
./symfony generate:module appname home
and
class homeActions extends sfActions
{
public function executeAbout(sfWebRequest $request)
{
// ...
}
public function executeFaq(sfWebRequest $request)
{
// ...
}
}
with the corresponding template files (aboutSuccess.php, faqSuccess.php).
2) A page can be comprised of data from many different models - just use your preferred ORM's method of retrieving data and set it to the view ($this->data = MyModel->findByColumn(...) etc). If you mean data from different modules, then you'd probably be better off looking at partials or components for elements of a page that can be used across different modules (navigation etc). See the Symfony docs for more details on these.
I'm used to handle static pages in this way.
First I create a new entry in apps/frontend/config/routing.yml:
page:
url: pages/:page
param: { module: page, action: index }
Then I write a "page" module (apps/frontend/modules/page/actions/actions.class.php):
<?php
class pageActions extends sfActions
{
public function executeIndex()
{
$this->page = $this->getRequestParameter("page");
$this->forward404Unless($this->_partialExists($this->page));
}
protected function _partialExists($name)
{
$directory = $this->getContext()->getModuleDirectory();
return (is_readable($directory.DIRECTORY_SEPARATOR."templates".
DIRECTORY_SEPARATOR."_".$name.".php"));
}
}
Last step, put in modules/page/templates/indexSuccess.php this code:
<?php include_partial($page); ?>
So all you have to do from now is to create a partial for each static page ie.
apps/frontend/modules/page/templates/_home.php which you can reach at
http://yousite/pages/home (without the need to add a new routing entry for every page)
You can create a module, e.g. called static and create actions for every static page or only one action that delivers the page depending on a request variable. The only thing this action does is loading a template.
IMHO it would be good if symfony comes with a default module for this.
For example actions of (my custom) module static:
class staticActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
if(!$request->hasParameter('site')) {
return sfView::ERROR;
}
$this->site = $request->getParameter('site');
}
}
With this template:
//indexSuccess.php
<?php include_partial($site) ?>
The actual statics sites are all partials.
In my routing.yml looks like this:
# static stuff
about:
url: /about
param: {module: static, action: index, site: about}
This way you only have to create a new partial and a new routing entry when you add a static site and you don't have to touch the PHP code.
Another way to serve static pages without having to write any controller code is to set up the route something like the following:
myStaticPage:
pattern: /pageName
defaults:
_controller: FrameworkBundle:Template:template
template: MyBundle:Home:pageName.html.twig
Then just create your twig template and it should work fine.
Apart from the above, consider having a CMS for static pages, so you won't need technical savy people to mantain them or change them. This depends on the project, of course.
For really static and independent pages you can simply create any file in [pathToYourProjectRoot]/web directory.
It may by i.e. [pathToYourProjectRoot]/web/assets/static_html/about.html.
Then link to the page directly by http://your.site.com/assets/static_html/about.html.
Related
Is it possible to render another "root" template instead of the Page.ss file for some specific pages / controllers? There are already some pages using the Page.ss template, but now there will be a new "Intranet" section on the website where the pages should have another "root" template: IntranetPage.ss.
Page.ss should stay as is and should not be touched at all.
I mainly want different "root" templates because both templates load different JS and CSS files. Also the "container" HTML is quite different.
I was able to create a custom controller which does manually what I need. Something like this:
class IntranetPageController extends PageController
{
public function index()
{
return $this->customise([
'Layout' => $this->renderWith(['Intranet/Layout/IntranetPageLayout'])
])->renderWith(['Intranet/IntranetPage']);
}
}
The code is inspired from here: https://docs.silverstripe.org/en/4/developer_guides/templates/rendering_templates/
IntranetPage.ss is used now as the "root" template. IntranetPageLayout.ss is displayed for the $Layout placeholder.
That seems to work, however I have many pages which have to be based on IntranetPage.ss. It feels strange to write for every new Controller the very same index function (with a small adjustment to load another LayoutPage).
I am sure, Silverstripe has some convention to do that automatically :)
What I need is very close to having a individual theme per page, but I am not sure if that is possible...
Instead of extending PageController, extend your IntranetPageController in new controllers. Whenever index is called, it will call your index function from your parent class, in your case IntranetPageController.
I have a website which is built on Codeigniter and I want to create some pages with information like terms or privacy, their address should be:
http://domain.com/terms
http://domain.com/privacy
My question is: should I create for each page a controller? In CMS for example, if I add a page it has to create a 'pysical' page on the server (CMS which is built on Codeigniter)?
For static pages like a Privacy Policy or Terms of Service page where they don't really fit under any other controller I usually create a "content" controller that looks something like this:
class Content extends CI_Controller {
public function privacy_policy()
{
$this->load->view('privacy_policy');
}
public function terms_of_service()
{
$this->load->view('terms_of_service');
}
}
Then I add some routes to remove "content" from the URL:
$route['privacy-policy'] = 'content/privacy_policy';
$route['terms-of-service'] = 'content/terms_of_service';
That way you don't need to create a new controller for each page and you can keep your static pages organized in a single spot.
Something I do is make your policy statements as a DL, DT, DD. hide the DD with jquery, show the DD then on a click to the DT. Then have the DD popup as a modal
The entire thing is contained in the footer. No need for anything to do with the controller
I have a site that has a lot of pages that lye at the root (ex. /contact, /about, /home, /faq, /privacy, /tos, etc.). My question is should these all be separate controllers or one controller with many methods (ex. contact, about, index within a main.php controller )?
UPDATE:
I just realized that methods that are within the default controller don't show in the url without the default controller (ie. main/contact wont automatically route to /contact if main is the default controller ). So you would need to go into routes and override each page.
If all of these are just pages, I would recommend putting them into a single controller. I usually end up putting static pages like this into a 'pages' controller and putting in routes for each static page to bypass the '/pages' in my URLs.
If they are share the same functionality, so they should be in the same controller.
for example, if all of them are using the same model to take content from, so, one controller can easily handle it.
Why in one controller? because you always want to reuse your code.
class someController{
function cotact(){
print $this->getContentFromModel(1);
}
function about(){
print $this->getContentFromModel(2);
}
function home(){
print $this->getContentFromModel(3);
}
private function getContentFromModel($id){
return $this->someContentModel->getContentById($id);
}
}
(instead of print, you should use load a view)
See in my example how all of the function are using the same getContentFromModel function to share the same functionality.
but this is one case only, there could be ther cases that my example can be bad for...
in application/config/routes.php
$route['contact'] = "mainController/contact";
$route['about'] = "mainController/about";
$route['home'] = "mainController/home";
$route['faq'] = "mainController/faq";
$route['privacy'] = "mainController/privacy";
and you should add all of these methods within the mainController.php
You can also save the content of the pages in your database, and them query it. For instance, you can send the url as the keyword to identify the page content
$route['contact'] = "mainController/getContent/contact";
$route['about'] = "mainController/getContent/about";
$route['home'] = "mainController/getContent/home";
$route['faq'] = "mainController/getContent/faq";
$route['privacy'] = "mainController/getContent/privacy";
in this case you only have to create one method named "getContent" in the controller "mainController" and this method will look something like this:
class mainController extends CI_Controller
{
public function getContent($param)
{
$query = $this->db->get_where('mytable', array('pageName' => $param));
// then get the result and print it in a view
}
}
Hope this works for you
The page names you listed should probably be different methods inside your main controller. When you have other functionality that is related to another specific entity, like user, you can create another controller for the user entity and have different methods to display the user, update the user, register the user. But its all really a tool for you to organize your application in a way that makes sense for your domain and your domain model.
I've written a blog post about organizing CodeIgniter controller methods that might be helpful to you. Check it out here: http://caseyflynn.com/2011/10/26/codeigniter-php-framework-how-to-organize-controllers-to-achieve-dry-principles/
Im building my first site in Expression Engine, I was wondering how to use custom controllers in EE, like I would in Codeigniter, or what is the EE equivalent?
Controllers are the heart of your application, as they determine how HTTP requests should be handled.
As you're probably well-aware, a CodeIgniter Controller is simply a class file that is named in a way that can be associated with a URI.
<?php
class Blog extends CI_Controller {
public function index() {
echo 'Hello World!';
}
}
?>
The ExpressionEngine equivalent are template groups and templates, and are managed from within the Control Panel's Template Manager.
Since EE's template groups and templates can be named anything you want, the URL structure unsurprisingly loosely mimics a CodeIgniter app — after all, EE is built on CI.
For example, consider this URI: example.com/index.php/blog
CodeIgniter would attempt to find a controller named blog.php and load it.
ExpressionEngine would attempt to find the template group named blog and load the template named index.
Continuing with this example, the second segment of the URI determines which function in the controller gets called (for CodeIgniter) or which template gets loaded (for ExpressionEngine).
Building off the same URI: example.com/index.php/blog/entry
CodeIgniter would attempt to find a controller named blog.php and load it.
ExpressionEngine would attempt to find the template group named blog and load the template named entry.
Starting with the third and beyond URL segments is where CodeIgniter and ExpressionEngine start to take different approaches. (A full explanation of their differences is beyond the scope of this answer).
While there are many similarities between CodeIgniter and ExpressionEngine, at a very low-level, CodeIgniter lets you build Web Apps while ExpressionEngine lets you build Web Sites.
I know this is old, but I just thought someone looking at this might find the actual response useful.
As others have said, routes for controllers are ignored by default in ExpressionEngine.
To change this, you have to edit the first index.php and comment out the routing defaults:
// $routing[‘directory’] = ‘’;
// $routing[‘controller’] = ‘ee’;
// $routing[‘function’] = ‘index’;
Once that is done, you can add controllers just like #rjb wrote on his response.
<?php
class Blog extends CI_Controller {
public function index() {
echo 'Hello World!';
}
}
?>
After this is done, ExpressionEngine will check first for controllers and if none is found, it will look for templates.
Generally-speaking, ExpressionEngine uses template groups and templates to render content.
EE is built on CI, but it doesn't function like CI, as it's a CMS, not an application framework.
How could I prevent mentioned plugin's login form from using default layout? I am aware of this question, but that answer doesnt work for me. For starters, there's no signin module in modules dir, probably plugins handle it in different way, I dont know. Just learning symfony. Thanks in advance :)
For now its not possible to set custom layout for some sfGuardAuth action via custom view.yml.
This is how I did it.
This is my apps/backend/modules/sfGuardAuth/actions/actions.class.php:
<?php
require_once(sfConfig::get('sf_plugins_dir').'/sfDoctrineGuardPlugin/modules/sfGuardAuth/lib/BasesfGuardAuthActions.class.php');
class sfGuardAuthActions extends BasesfGuardAuthActions
{
public function preExecute()
{
$layout = $this->getActionName() == sfConfig::get('sf_login_action') ? 'sfGuardLayout' : $this->getLayout();
$this->setLayout($layout);
}
}
If you just want to set a different layout, you need to add a module (just create it manually) called "sfGuardAuth". Inside the /config/ directory for that, change the layout in the view.yml like for any other module. This is explained in:
http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin/4_0_0
... under section "Customize sfGuardAuth module actions".
However, if you want to "embed" your login form on another existing page, you could turn the login into a component - which means it uses the existing layout of the page it occurs in.
Component action in a custom module:
public function executeSigninLightbox(sfWebRequest $request)
{
$class = sfConfig::get('app_sf_guard_plugin_signin_form', 'sfGuardFormSignin');
$this->form = new $class();
}
... which like all components uses a partial as its view. The partial now has access to $form like a standard login page. The partial for this would be called "_signinLightbox".
Hope that helps.