Hot answers tagged

13

Is the registerSiteRoutes hook what you're looking for?


9

The simplest way to transform dynamic routes into advanced routes, is to go to your craft_routes table and copy it out of urlPattern: Example: If you have set this in your backend: news-sort/month/<year>/<month> You'll find this in urlPattern: news\-sort\/month\/(?P<year>\d{4})\/(?P<month>(?:0?[1-9]|1[012])) Just remove the ...


9

No, Craft doesn't have a REST API (edit: or any other web service) built-in. The "API" mentioned in the first quote (and elsewhere related) would be the more generic meaning of the term and refers to the service layer. With a very consistent MVC based architecture based on Yii, Craft is well suited for REST implementation, though. See this G+ thread for P&...


8

Craft automatically includes the entry variable if the slug matches the url: If the URI matches an entry’s or category’s URI, the section’s/category group’s template will get loaded, and the matched element will be made available to the template via a pre-populated entry or category variable. In your case contact-us gets matched automatically, but ...


8

You need to explicitly allow allow anonymous access to your controller's action. More info on how to do that here: http://buildwithcraft.com/docs/plugins/controllers#allowing-anonymous-access-to-actions


8

Yes, prefixing a template's filename with an underscore does what it says on the box – any underscored template will be excluded from route mapping. A typical use case is to use underscores for partials or wrappers, e.g. "_mainmenu.html" or "_baseTemplate.html" – essentially any template that doesn't make any sense to load up or access directly in the ...


7

Craft will only check for templates in your plugin’s templates/ folder during CP and action requests. When you start routing to your controller action via a site-facing route, it’s no longer either one of those; it’s just a normal Site request. So you will need to point Craft to your plugin’s templates folder explicitly. // Point Craft to this plugin's ...


7

To quote @Brandon from here: Yep you just need to include a $variables argument in your controller function, typeset to an array: public function actionArchive(array $variables = array()) { $variables['year'] ... }


7

To pull this off, first you’ll have to make sure all of your Element API endpoints begin with something consistent, like api/ or data/, etc. Then create a route in craft/config/routes.php that will match everything besides those Element API endpoints: <?php return array( '(?!api\/).*' => 'index' ); 'index' is the template path the requests ...


6

My two cents: I wouldn't use different url's for the same product, that's considered bad seo. Instead use something like domain.com/product/slug. That way you can change product categories while keeping the links intact, and it'll be easier to get the url of entries. If there is no specific reason for using structures, use native categories. Instead of ...


6

You might check out the routing docs on accessing subpatterns in your templates. Here is the example given in the docs (which provides the variables 'year' and 'month' to the template that correspond to the matched uri segments — which would match `news/2015/02'): 'news/(?P<year>\d{4})/(?P<month>\d{2})' => 'news/_archive', So I would ...


6

There are a couple of issues here: Any action methods in the controller class needs the "action" prefix to their name, i.e. actionIndex() for your "index" action, or actionLogin() for another action route calling "myPlugin/access/login". In other words, rename your index() method in the controller to actionIndex(), and it should work. For action routes, ...


6

You can't have tokens in your plugin routes, but you can easily add a segment variable that recreates the asterisk token's functionality with some regex. According to the the official docs on routing, the asterisk represents (...) any string of characters, except for a forward slash (/) Here's what the defintion for a route with a "asterisk-like" segment ...


6

If you only need to create a JSON API for fetching existing entries, etc., check out the Element API plugin.


6

Brad nails the problem in his comment: The error is because you've got two named subpatterns with the same name (<slug>) And the solution is simple... Change the name(s) of your subpattern(s). The term slug is just a convention of Craft. It doesn't matter what the names are, they can be anything useful to you: (?P<domain>[^/]+)/(?P<...


6

The routes.php config file doesn't support multi-environment setups in the manner that general.php or db.php does – in other words, your example code using a multidimensional array would throw an error. As a workaround, you can write some PHP in your routes.php file. For simple stuff, a ternary operator may suffice: return array( 'test' => strpos(...


6

In case someone uses Craft 3, this should work: <? return array( '<url:(?!api\/).*>' => ['template' => 'index'] );


5

Based on your code excerpts, things look good. I've encountered issues with spelling and caps when referencing controllers and templates within my controllers...so pay close attention to them. I would suggest referencing the 'Cocktail Recipes' sample plugin: https://github.com/seandelaney/cocktailrecipes (Craft 2.x) as it contains an example of what you'...


5

Just an idea, but are you Allowing Anonymous Access to Actions? Maybe you are logged in on your Desktop, but not on your iPhone. Example: protected $allowAnonymous = true;


5

You can have entry type specific templates for your entry pages, see this docs article on how you can do this. And for your archive pages, just set a route for each of them and point it to the corresponding index/listings template. So basically you end up with something like this for your entries: media/_entry.html (example.com/2014/01/01/example-entry) ...


5

You can’t access the current Twig variables (the “context”, as Twig calls them), from a Template Variable class, but you can access them with a template hook. From your plugin’s init() function: craft()->templates->hook('errorCheck', function(&$context) { if (isset($context['errors'])) { // do something with $context['errors']; ...


5

Yes it’s possible. First you will need to update your route key so that you’re capturing the name parameter with a valid named subpattern. (You were close, but missing the actual pattern part of it). return array( 'api/test/(?P<name>[^\/]+)' => ['action' => 'api/element/section'], ); Any named subpattern matches in your route will be passed ...


5

In Craft assets do not get "their own page" by default, but you can easily create them with a Dynamic Route. So go to Settings → Routes and add a new route with a number token, e.g. assets/<number> and route those URIs to a new template, e.g. assets/_entry. With this route set up you can now link to an asset's entry page like so: <a href="{{ url('...


5

You can use the registerSiteRoutes() hook in your plugin's primary class. Assuming your custom URL formats are stored in an array in a plugin setting called customRoutes (use AttributeType::Mixed for arrays), and that the array consists of key/value paired routes and template paths: public function registerSiteRoutes() { return $this->getSettings()['...


5

You forgot to setup the routes for your search URLs. In this case I’d recommend to use an advanced route with a regular expression, as it allows to use patterns that will ignore the slashes between your search terms. You’d setup the route in your craft/config/routes.php file (see Advanced Routing in the Craft docs). return array( 'search/(?P<query&...


5

You told Craft to look for tags/_tag And then you created templates/tags/_tags.html Note you have no s on the end in the route definition, but you do in the template name.


5

Alright, if you didn't already create a custom plugin I suggest you to visit Pluginfactory.io to create the boilerplate. Let's assume your plugin handle is awesome-plugin, just for testing purposes. You create a controller with the name RouteController that contains the function actionMyAwesomeRoute In summary: handle: awesome-plugin controller: ...


4

To generate the url, use the slugify plugin: href="{{tag.name|slugify}}". Slugify uses Craft's slug technology, so the slugs are always recognized by the router. To resolve the url back to a tag, use search in the news/_tag template: {% set thisTag = craft.tags.search('name:"'~tag~'"').first() %} craft.tags.name(tag).first() will often work, but not for ...


4

If they can live at different URL's, you could setup multiple routes under Settings->Routes. Give them different URL structures like so: blog/slug loads mytemplatefolder/blog_template another-url/slug loads mytemplatefolder/another_template


4

If you want to "redirect" all parent entries of your structure that have child entries, you could do something like this in your navigation (untested code!): <ul> {% nav page in pages %} <li> {% if page.getChildren()|length %} <a href="{{ page.getChildren().first().url }}">{{ page.title }}</a> ...


Only top voted, non community-wiki answers of a minimum length are eligible