Fix addapartment error

User
Assistant
You’re getting “The requested page could not be found” because SilverStripe doesn’t know any route for `/appartment/addappartment`. You have two clean ways to wire this up. Pick one.

## Option A — Stand‑alone route (no CMS page)
Use this if you just want a controller endpoint.

1) **Controller:** (extend `Controller`, not `ContentController`)

<?php

namespace AppController;

use SilverStripeControlController;
use SilverStripeControlHTTPRequest;
use SilverStripeSecuritySecurity;

class AppartmentController extends Controller
{
    private static $allowed_actions = [
        'addappartment'
    ];

    private static $url_handlers = [
        'addappartment' => 'addappartment',
    ];

    protected function init()
    {
        parent::init();
        if (!Security::getCurrentUser()) {
            return $this->redirect('/login');
        }
    }

    public function addappartment(HTTPRequest $request)
    {
        return $this->customise([
            'Title' => 'Add Appartment'
        ])->renderWith(['Layout/AddAppartment', 'Page']);
    }
}

> Note: action/method name in **lowercase** in both `allowed_actions` and the method itself. SilverStripe is forgiving, but keeping it lowercase avoids surprises.

2) **Route:** `app/_config/routes.yml`

---
Name: approutes
After: '#rootroutes'
---
SilverStripeControlDirector:
  rules:
    'appartment//$Action/$ID/$OtherID': 'AppControllerAppartmentController'

3) **Flush/build:** visit `/_flush` (or `?flush`) and, if needed, `/dev/build?flush`.

Then `/appartment/addappartment` will hit your controller.

## Option B — CMS page + PageController
Use this if you want a CMS page living at `/appartment` and actions under it.

1) **Create page type:**

// app/src/Page/AppartmentPage.php
namespace AppPage;

use Page;

class AppartmentPage extends Page
{
}
// app/src/Page/AppartmentPageController.php
namespace AppPage;

use PageController;
use SilverStripeControlHTTPRequest;
use SilverStripeSecuritySecurity;

class AppartmentPageController extends PageController
{
    private static $allowed_actions = [
        'addappartment'
    ];

    public function addappartment(HTTPRequest $request)
    {
        if (!Security::getCurrentUser()) {
            return $this->redirect('/login');
        }

        return $this->customise([
            'Title' => 'Add Appartment'
        ])->renderWith(['Layout/AddAppartment', 'Page']);
    }
}

2) **CMS:** run `/dev/build?flush`, create a new **Appartment Page** in the CMS with URL Segment `appartment`, publish it.

Now `/appartment/addappartment` will work.

## Common gotchas to check
– **Spelling/case:** Your URL is `addappartment` — keep the same lowercase name for the method and in `allowed_actions`.
– **Templates:** ensure `templates/Layout/AddAppartment.ss` exists (and `templates/Page.ss` or your site Page layout).
– **Extending the right base class:**
– Stand‑alone routing ⇒ extend `Controller` and add a `routes.yml`.
– CMS page routing ⇒ extend `PageController` and create a Page in CMS.
– **Flush caches:** always do `?flush` after adding routes/classes/templates.

If you tell me which option you prefer, I can drop in the exact file paths and a minimal `.ss` layout to render.

User
NOw
Error detail: Action 'addapartment' isn't available on class AppControllerAppartmentController.
Assistant
You’re hitting the route with **/appartment/addapartment** (single “p” after “d”), but your controller likely exposes **addappartment** (double “pp”). SilverStripe can’t find that action, so it throws:

> Action 'addapartment' isn't available on class AppControllerAppartmentController.

### Quick fix (support both spellings)
Drop this into your controller and flush:

<?php

namespace AppController;

use SilverStripeCMSControllersContentController;
use SilverStripeControlHTTPRequest;
use SilverStripeSecuritySecurity;

class AppartmentController extends ContentController
{
    private static $allowed_actions = [
        'addapartment',
        'addappartment',
    ];

    private static $url_handlers = [
        // map both URLs to the same method
        'addapartment'   => 'addApartmentAction',
        'addappartment'  => 'addApartmentAction',
    ];

    protected function init()
    {
        parent::init();
        if (!Security::getCurrentUser()) {
            return $this->redirect('/login');
        }
    }

    // single handler for both URLs
    public function addApartmentAction(HTTPRequest $request)
    {
        return $this->customise([
            'Title' => 'Add Apartment'
        ])->renderWith(['Layout/AddAppartment', 'Page']);
    }
}

### Also make sure
– Your route exists (e.g. in `app/_config/routes.yml`):

---
  Name: approutes
  After: '#rootroutes'
  ---
  SilverStripeControlDirector:
    rules:
      'appartment//$Action/$ID/$OtherID': 'AppControllerAppartmentController'

– Template `templates/Layout/AddAppartment.ss` exists.
– **Flush caches**: visit `/?flush` (or `/dev/build?flush`).

Now these will both work:
– `/appartment/addapartment`
– `/appartment/addappartment`

User
{$CurrentUser.FirstName.$CurrentUser.LastName}
this not working in ss template
Assistant
In SilverStripe templates you can’t chain dot syntax like `{$CurrentUser.FirstName.$CurrentUser.LastName}`.
Dot notation only drills down **one property at a time**.

✅ Correct ways:

### 1. Output each field separately

$CurrentUser.FirstName $CurrentUser.Surname

### 2. Use `FullName` (built into `Member`)
SilverStripe’s `Member` class already has a `getName()` method (alias `FullName` in templates):

$CurrentUser.Name

That will print *“John Doe”* directly.

### 3. Custom getter (if you really want FirstName+LastName)
In your controller or extension:

public function getFullDisplayName()
{
    if ($user = Security::getCurrentUser()) {
        return $user->FirstName . ' ' . $user->Surname;
    }
    return '';
}

Then in template:

$FullDisplayName

👉 For your case the simplest is:

$CurrentUser.FirstName $CurrentUser.Surname

or just

$CurrentUser.Name

Do you want me to show how to **always make `$CurrentUser` available in every template** (without manually passing from controller)?

Leave a Comment

Your email address will not be published. Required fields are marked *