skip to Main Content

I am trying to give 2 content types the same singular slug in bolt. both of them should have the same fields, and the same template. at this point i use the record_template: tag to set the default template for each content type.

vervolgpagina:
  name: vervolgpagina
  singular_slug: graszoden
  singular_name: vervolg
  fields:
      titel:
          type: text
          class: large
          group: Content
      slug:
          type: slug
          uses: titel
          group: Content
      body:
          type: html
          height: 500px
          group: Content
      meta_keywords:
          type: text
          group: SEO
          label: "Meta keywords"
      meta_description:
          type: textarea
          height: 50px
          group: SEO
          label: "Meta description"
  record_template: vervolgpagina.twig

graszoden:
  name: graszoden
  singular_slug: graszoden
  singular_name: gras
  fields:
      titel:
          type: text
          class: large
          group: Content
      slug:
          type: slug
          uses: titel
          group: Content
      body:
          type: html
          height: 500px
          group: Content
      meta_keywords:
          type: text
          group: SEO
          label: "Meta keywords"
      meta_description:
          type: textarea
          height: 50px
          group: SEO
          label: "Meta description"
  record_template: vervolgpagina.twig

so if i just put in one of the two content types and add a page to it then it
redirects me to /graszoden/vervolgpagina

so if i add the secont content type and add another page to it /graszoden/randomexample

what happends now. is that the page that worked just fine. says ERROR 404, and the other page gives me an bolt error with “No listing.twig file specified.”

is there a way to show a content type twice in the cms with other names? Or is there a way to give two content types the same singular slug?

Thanx in advance,

2

Answers


  1. Chosen as BEST ANSWER

    After some more projects in bolt using twig ive got some other solution.

    If you want to use singular slugs multiple times u are forced to create a listing page. But with this you will not have to. Just create an local extension and fill in the part highlighted at the end in this answer.

    Link to sourcecode No readme yet. But I hope the explanation here is good enough.

    Here is the extension file code (This code is litteraly all the functionality, you will have to create a local extension for this to work ):

    class MatchAllController
    {
    /**
     * The bolt application
     *
     * @var
     */
    protected $app;
    
    /**
     * The path to the config.yml
     *
     * @var string
     */
    protected $configPath = __DIR__ . '/../../config/config.yml';
    
    public function matchAll(Request $request, $slug, Application $application)
    {
        $this->app = $application;
    
    //        var_dump($this->getConfig());die;
        $contentTypes = ['provincies', 'vervolg'];
    
        foreach($contentTypes as $contentType)
        {
            if(null !== $result = $this->record($request, $contentType, $slug)) {
                return $result;
            }
        }
    
        $this->abort(Response::HTTP_NOT_FOUND, "Page $slug not found.");
        return null;
    }
    
    protected function getConfig()
    {
        return Yaml::parse(file_get_contents($this->configPath));
    }
    
    public function record(Request $request, $contenttypeslug, $slug = '')
    {
        $contenttype = $this->getContentType($contenttypeslug);
    
        // Perhaps we don't have a slug. Let's see if we can pick up the 'id', instead.
        if (empty($slug)) {
            $slug = $request->get('id');
        }
    
        $slug = $this->app['slugify']->slugify($slug);
    
        // First, try to get it by slug.
        $content = $this->getContent($contenttype['slug'], ['slug' => $slug, 'returnsingle' => true, 'log_not_found' => !is_numeric($slug)]);
    
        if (!$content && is_numeric($slug)) {
            // And otherwise try getting it by ID
            $content = $this->getContent($contenttype['slug'], ['id' => $slug, 'returnsingle' => true]);
        }
    
        // No content, no page!
        if (!$content) {
            return null;
        }
    
        // Then, select which template to use, based on our 'cascading templates rules'
        $template = $this->templateChooser()->record($content);
    
        // Setting the canonical URL.
        if ($content->isHome() && ($template === $this->getOption('general/homepage_template'))) {
            $url = $this->app['resources']->getUrl('rooturl');
        } else {
            $url = $this->app['resources']->getUrl('rooturl') . ltrim($content->link(), '/');
        }
        $this->app['resources']->setUrl('canonicalurl', $url);
    
        // Setting the editlink
        $this->app['editlink'] = $this->generateUrl('editcontent', ['contenttypeslug' => $contenttype['slug'], 'id' => $content->id]);
        $this->app['edittitle'] = $content->getTitle();
    
        // Make sure we can also access it as {{ page.title }} for pages, etc. We set these in the global scope,
        // So that they're also available in menu's and templates rendered by extensions.
        $globals = [
            'record'                      => $content,
            $contenttype['singular_slug'] => $content,
        ];
    
        return $this->render($template, [], $globals);
    }
    
    /**
     * Get the contenttype as an array, based on the given slug.
     *
     * @param string $slug
     *
     * @return boolean|array
     */
    protected function getContentType($slug)
    {
        return $this->storage()->getContentType($slug);
    }
    
    /**
     * Returns the Entity Manager.
     *
     * @return BoltStorageEntityManager
     */
    protected function storage()
    {
        return $this->app['storage'];
    }
    
    /**
     * Shortcut to abort the current request by sending a proper HTTP error.
     *
     * @param integer $statusCode The HTTP status code
     * @param string  $message    The status message
     * @param array   $headers    An array of HTTP headers
     *
     * @throws HttpExceptionInterface
     */
    protected function abort($statusCode, $message = '', array $headers = [])
    {
        $this->app->abort($statusCode, $message, $headers);
    }
    
    /**
     * Shortcut for {@see BoltLegacyStorage::getContent()}
     *
     * @param string $textquery
     * @param array  $parameters
     * @param array  $pager
     * @param array  $whereparameters
     *
     * @return BoltLegacyContent|BoltLegacyContent[]
     *
     * @see BoltLegacyStorage::getContent()
     */
    protected function getContent($textquery, $parameters = [], &$pager = [], $whereparameters = [])
    {
        return $this->storage()->getContent($textquery, $parameters, $pager, $whereparameters);
    }
    
    /**
     * Return the BoltTemplateChooser provider.
     *
     * @return BoltTemplateChooser
     */
    protected function templateChooser()
    {
        return $this->app['templatechooser'];
    }
    
    /**
     * Shortcut for {@see UrlGeneratorInterface::generate}
     *
     * @param string $name          The name of the route
     * @param array  $params        An array of parameters
     * @param int    $referenceType The type of reference to be generated (one of the constants)
     *
     * @return string
     */
    protected function generateUrl($name, $params = [], $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
    {
        /** @var UrlGeneratorInterface $generator */
        $generator = $this->app['url_generator'];
    
        return $generator->generate($name, $params, $referenceType);
    }
    
    /**
     * Renders a template
     *
     * @param string $template  the template name
     * @param array  $variables array of context variables
     * @param array  $globals   array of global variables
     *
     * @return BoltResponseBoltResponse
     */
    protected function render($template, array $variables = [], array $globals = [])
    {
        return $this->app['render']->render($template, $variables, $globals);
    }
    }
    

    Becouse this is an new starting project. The only thing that is variable is this part

    public function matchAll(Request $request, $slug, Application $application)
    {
    $this->app = $application;
    
    //Fill your costum routes in here
    $contentTypes = ['VARIABLE SINGULAR SLUG', 'VARIABLE SINGULAR SLUG 2'];
    
    foreach($contentTypes as $contentType)
    {
        if(null !== $result = $this->record($request, $contentType, $slug)) {
            return $result;
        }
    }
    
    $this->abort(Response::HTTP_NOT_FOUND, "Page $slug not found.");
    return null;
    }
    

    $contentTypes = ['VARIABLE SINGULAR SLUG', 'VARIABLE SINGULAR SLUG 2'];

    This particular piece of code is where u fill in the singular slug u want to use. It can contain infinite slugs

    Hope this helps someone else later on. Happy coding!


  2. No, you can’t. If you have two contenttypes with the same slug and same fields, it should really just be one CT.

    Perhaps what you might want is a “Grouping Taxonomy”, see the example in taxonomy.yml for that.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search