Create single page passing URL parameters

Permalink
I am loving the new concrete 5.7 look and feel but am stuck creating a single page to display content from a separate database. I don't want to add the pages separately into concrete, so I want my page to generate the content based on the URL the visitor has entered.

My single page will be called 'cheese' accessed on my site at this URL:

http://www.my-site.com/cheese/

All the URLs will end with the name of the cheese:

http://www.my-site.com/cheese/chedder...
http://www.my-site.com/cheese/red-leicester...
http://www.my-site.com/cheese/camembert...

I read in the documentation
http://www.concrete5.org/documentation/how-tos/developers/use-query... that I can catch the last part of the URL in a controller method, but so far I can't even see the controller being called by passing variables from the controller to the view.

I started adding it into the app directory but I could only get the view to display so I tried to add it as a package and now I get an error about the file not being available.

Here is the code:

packages/cheese/controller.php

<?php       
namespace Concrete\Package\Cheese;
use Package;
use SinglePage;
use Page;
use Loader;
use Concrete\Core\Routing\Router;
defined('C5_EXECUTE') or die(_("Access Denied."));
class Controller extends Package
{
   protected $pkgHandle = 'cheese';
   protected $appVersionRequired = '5.7.1';
   protected $pkgVersion = '1.0';
   public function getPackageDescription()
   {


packages/cheese/controllers/cheese.php

<?php
namespace Concrete\Package\Cheese\SinglePage\Cheese;
use \Concrete\Core\SinglePage\SinglePageController;
defined('C5_EXECUTE') or die("Access Denied.");
class CheeseController extends Controller {
   public function view($cheese)
   {
      $this->set('cheese', $cheese);
      $this->set('color', 'red');
   }
}


packages/cheese/single_pages/cheese.php

<?php  defined('C5_EXECUTE') or die("Access Denied.");
?><pre><?php print_r($cheese)?></pre><?php
?><pre><?php print_r($color)?></pre><?php
echo "End of view display";


The package installs fine, but if I use the URL:

http://www.my-site.com/cheese/

I get the error: 'An unexpected error occurred.'
include(/Library/WebServer/localhost/concrete.cheese/concrete/single_pages/cheese.php): failed to open stream: No such file or directory

If I try the URL with the cheese name:

http://www.my-site.com/cheese/chedder...

It responds with 'Page not found'

Also read:
https://www.concrete5.org/community/forums/customizing_c5/single-pag... but I think I got the naming right?

Any help would be much appreciated.

View Replies:
hutman replied on at Permalink Reply
hutman
In your single page controller the namespacing is incorrect it should be

<?php
namespace Concrete\Package\Cheese\Controller\SinglePage;
use PageController;
class CheeseController extends PageController {
   public function view($cheese)
   {
      $this->set('cheese', $cheese);
      $this->set('color', 'red');
   }
}


Once you change that, try clearing the cache (event if it is turned off) and refreshing the single page from the dashboard and then accessing your page again.

If your page is not going to ALWAYS have /cheese/something-else you should put = '' in your view function variable, otherwise you'll get an error
lisamullova replied on at Permalink Reply
Thank you hutman

I have changed the controller as per your instructions and did all the refreshing and cache clearing but I must still be missing something. I wonder, have I installed the controller / singPage correctly in the install controller:

<?php       
Namespace Concrete\Package\Cheese;
use Package;
use SinglePage;
use Page;
use Loader;
use Concrete\Core\Routing\Router;
defined('C5_EXECUTE') or die(_("Access Denied."));
class Controller extends Package
{
   protected $pkgHandle = 'cheese';
   protected $appVersionRequired = '5.7.1';
   protected $pkgVersion = '1.0';
   public function getPackageDescription()
   {


Thanks,

Lisa
hutman replied on at Permalink Reply
hutman
I don't see anything in this code that would install a Single Page. When you go to Dashboard -> Pages & Themes -> Single Pages do you see your page listed there?
lisamullova replied on at Permalink Reply
Yes, its there and refreshes ok.

I got confused as to how to install it??
hutman replied on at Permalink Reply
hutman
In the list of Single Pages, if these pages say that they are connected to your package, try double checking the namespaces to make sure they are right, uninstalling the package and reinstalling the package. From other people's comments lately it seems like if the namespace was wrong when you installed the package the pages don't work right.
hutman replied on at Permalink Reply
hutman
In you package controller can you add these things and try reinstalling and see what happens with your Single Page?

Add this to the install function

$this->installSinglePages($pkg);


Add this function

private function installSinglePages($pkg) {        
    $path = '/cheese';
    $cID = Page::getByPath($path)->getCollectionID();
    if (intval($cID) > 0 && $cID !== 1) {
        Loader::db()->execute('update Pages set pkgID = ? where cID = ?', array($pkg->pkgID, $cID));
    } else {
        $p = SinglePage::add($path, $pkg);
        if (is_object($p) && $p->isError() !== false) {
            $p->update(array('cName' => t('Cheese')));
        }
    }
}


Hopefully this will update the Cheese page, if not hopefully it will atleast make it so when you remove the package the page is also removed.
lisamullova replied on at Permalink Reply
Ok, so what I was seeing was a single page that I had previously installed and removed the code! After a visit to sitemap and deleting, then finding the bin to delete from there, the page no longer works - no cheese! So you are right the package is not installing. I took the code from one downloaded that should have worked as I can't find any working example over here!
Any ideas, if you think the namespaces are right?
hutman replied on at Permalink Reply
hutman
If you go into Dashboard -> System & Settings -> Debug Settings do you have Output error information to site users checked and Show the debug error output selected?

If you go to Dashboard -> Extend Concrete5 does your package show up ready to be installed?

If you install the package after adding the code I put in my last post do you get errors? Does the Single Page install?
lisamullova replied on at Permalink Reply
Thank you so much for sticking with me on this one. The debug screens were just what was needed to resolve this and lead me to agree with your earlier comment that the single-page was not installing. So I added in the line to install using previous (pre 5.7) code as I could not find anything particular for 5.7:

$sp = SinglePage::add('cheese', $pkg);


Once getting my head around namespaces I changed the namespaces in my controller to:

namespace Concrete\Package\Cheese\Controller\SinglePage;


Now the debug screen told me that it could not find Controller under that namespace and after fiddling around I found that the controller needs to have a different use command and extend a different controller:

<?php
namespace Concrete\Package\Cheese\Controller\SinglePage;
use \Concrete\Core\Page\Controller\PageController;
use Loader;
defined('C5_EXECUTE') or die("Access Denied.");
class Cheese extends PageController {
   public function view($cheese = '')
   {
      $this->set('cheese', $cheese);
      $this->set('color', 'red');
   }
}


And, hey presto I have cheese!!

Thanks again :-)
ntisithoj replied on at Permalink Reply
ntisithoj
This is a great post! thanks. I have been wrestling with the same thing. I gave up, but when I saw this I tried again... and I still have the same problem... which is, I can't get C5 to find any singlepages in the /packages/ folder.

I saw your example, and tried it (the only diff from mine being was the lack of leading slash).
$sp = SinglePage::add('shows', $this);


but I still get

include(/store/jw/sites/istandc57/web/concrete/single_pages/shows.php): failed to open stream: No such file or directory


which is technicxally correct, as the file is in

/store/jw/sites/istandc57/web/packages/single_pages/shows.php


I was under the impression that the packages folder is automatically seen, but that seems to not be the case.

Obviously you got yours to work, so I am missing something (that you found ;)

thanks
hutman replied on at Permalink Reply
hutman
Your file is not inside of a package... the directory structure should be

/packages/PACKAGE_NAME/single_pages/shows.php
rockface replied on at Permalink Reply
rockface
So glad I am not alone on this one!!!

Hello, my name is Cliff and my controller will not talk to my single page :-(

\packages\member_gallery\controller.php
<?php
namespace Concrete\Package\MemberGallery;
use Package;
use SinglePage;
use Page;
use Loader;
use Concrete\Core\Routing\Router;
use BlockType;
class Controller extends Package {
    protected $pkgHandle = 'member_gallery';
    protected $appVersionRequired = '5.7.0.4';
    protected $pkgVersion = '1.0.0';
    public function getPackageDescription() 
   {
          return t("Member driven art gallery with artist spotlight page.");


\packages\member_gallery\controllers\single_pages\spotlight.php
<?php
namespace Concrete\Package\MemberGallery\Controller\SinglePage;
use \Concrete\Core\Page\Controller\PageController;
use Loader;
defined('C5_EXECUTE') or die(_("Access Denied."));
class Spotlight extends PageController 
{
    public function view($search = '')
    {
     $search = "This is a test from view";
      $this->set('search', $search);
    }
   public function on_start() 
   {
     $search = "This is a test from on_start";


\packages\member_gallery\single_pages\spotlight.php
<?php defined('C5_EXECUTE') or die("Access Denied.");
   echo "searching for (" . $search . ")";
?>


Results show onhttp://localhost/index.php/spotlight...
searching for ()


Results show onhttp://localhost/index.php/spotlight/32...
404 ERROR
Page not found.


- I get no block or page install errors.
- The Single page correctly loads in dashboard > Pages & Themes > Single Pages
- The Single page correctly shows in the Sitemap
- I'm wondering if this is a bug in 5.7.4.2

So, the controller can nether set the value of $search nor understand the url path should not be going to a page called 32.php

Any help would be GREATLY appreciated!
hutman replied on at Permalink Reply
hutman
I think I see your issue right away, your controller should be in

\packages\member_gallery\controllers\single_page\spotlight.php


Note single_page is not plural for controllers folder structure
rockface replied on at Permalink Reply
rockface
Wholly smokes bat man, that worked!

I spend two days on this!!!!

Your amazing!
rockface replied on at Permalink Reply
rockface
On a similar note...
Do you know why the controllers folder is called "Controller" in the namespace?
Am I the only one confused by this?
hutman replied on at Permalink Reply
hutman
Sadly I don't really understand the namespacing structure, but I'm glad you got it working.
MrKDilkington replied on at Permalink Reply
MrKDilkington
@rockface and anyone having issues with namespaces

Community member mesuva put together a post and a video explaining their use in concrete5. They are excellent references materials.

Namespacing in concrete5.7
https://www.youtube.com/watch?v=FjJJUrggPM0...

https://www.concrete5.org/community/forums/5-7-discussion/so-hows-ev...
rockface replied on at Permalink Reply
rockface
Came across a hole in the cheese.

If you create a single page using the URL to feed parameters to your view function, it will also intercept ajax calls made by any blocks you install on the page.

Note: This is ONLY a problem when you install a block on your custom single page.

The ajax function is passed to the page controller and the function name becomes the 1st parameter value. So, you think your calling action_MyFunction() in the block controller, when your actually back in the view() function of the page controller!

See:http://www.concrete5.org/community/forums/5-7-discussion/view-actio...

Ended up adding this to the block's package controller to fix it.
public function on_start() {
      Route::register('/MyFunction', '\Concrete\Package\MyPackage\Block\MyBlock\Controller::action_MyFunction');
   }
rockface replied on at Permalink Reply
rockface
Came across a hole in the cheese.

If you create a single page using the URL to feed parameters to your view function, it will also intercept ajax calls made by any blocks you install on the page.

Note: This is ONLY a problem when you install a block on your custom single page.

The ajax function is passed to the page controller and the function name becomes the 1st parameter value. So, you think your calling action_MyFunction() in the block controller, when your actually back in the view() function of the page controller!

See:http://www.concrete5.org/community/forums/5-7-discussion/view-actio...

Ended up adding this to the block's package controller to fix it.
public function on_start() {
      Route::register('/MyFunction', '\Concrete\Package\MyPackage\Block\MyBlock\Controller::action_MyFunction');
   }