How not to repeat myself in Kohana 3's routes? - kohana

Let's say I want to make a system which can afford a multilingual web project. The system will consist of the modules that are put in Kohana's standard directory modules. Let's say that the standard access to the particular language can be done via lang parameter (i.e. somesite.com/en/somepage). The problem is that I have to repeat myself in defining my modules routes prepending each uri with (<lang>). Is there any way to avoid that? I thought about a separate language route declaration (for example in bootstap.php file), but I guess it won't solve the problem.
It's all about Kohana 3. Thanks to all.
UPDATE:
I think that the way suggested by The Pixel Developer is what one need if some part of the rule in route repeats everywhere.

Move up a level and extend the route class.
http://github.com/kohana/core/blob/master/classes/kohana/route.php#L69
public static function set($name, $uri, array $regex = NULL)
{
return parent::set($name, '(<lang>)'.$uri, $regex);
}
Not tested, but that's the general idea.

If lang is required in route, why don't you just put it in the default route? Surely that's the easiest way to go about. Something like:
Route::set('default', '<lang>(<controller>(/<action>(/<id>)))', array('lang'=> '[a-z]{2}'))
->defaults(array(
'controller' => 'somepage',
'action' => 'index',
'lang' => 'en',
));
Where lang is any 2 letters alphabets which defaults to 'en'.

Related

Best way to define custom functions in loopback api

What is the best way to define custom functions in loopback api that can be used in models defined ?
For example a basic express application can have functions in helper folder on root directory, but doing same in loopback is not recommended and does not maintain loopback way.
Any help would be highly appreciated.
This is very well documented.
Custom logic can be placed in
boot scripts
middlewares
models:
remote methods
remote hooks
operation hooks
application-decoupled logic can very well be put in helper folders, separate folders at root level, etc. There is nothing wrong with modularizing your program this way, it is actually a good thing.
As mentioned by others, the Loopback documentation answers your question like this:
Adding logic to models - adding remote methods, remote hooks and operation hooks.
Defining boot scripts - writing scripts (in the /server/boot directory) that run when the application starts.
Defining middleware - adding custom middleware to the application .
That's a great answer if you have custom functions for a particular model, boot script, or middleware. And as Dharmendra Yadav said, mixins can be another option:
You can use mixins to perform different common actions on models such as observing changes using operation hooks and adding model attributes.
But what about code that simply doesn't fit into any of those categories?
I don't have experience with a lot of web frameworks, but one framework I have used is Grails, which is very opinionated and gives you a place for just about everything. And if your code doesn't fit into any of those categories, they give you a place for that too:
src/main/groovy - Supporting sources
So when I ran into this same problem in Loopback, I just created a src directory under server and that's where I put some helper classes that don't seem to fit anywhere else. And I include them as needed:
const HelperClass = require('../src/HelperClass');
HelperClass.helperFunction()...
Of course you can name the folder however you'd like: src, helpers, support, whatever. And then put it under common or server as appropriate.
The best way to define functions in loopback i found is to use mixins. Here is the sample way of doing so..
https://loopback.io/doc/en/lb3/Defining-mixins.html
You can inherit these defined mixins into your models through .json of your model with {mixins:yourmixin.js}, nice and easy.
Here's some sample code to get you headed in the right direction.
mynewmodel.js
http://domain/api/mynewmodel/myfunc.js
function myfunc(data, callback) {
// ** Put your code here **
console.log('myfunc');
}
function remoteMethod(model) {
model.remoteMethod(
'myfunc',
{
http: { verb: 'post' },
accepts: { arg: 'data', type: 'data' },
returns: [
{ arg: 'returndata', type: 'data' }
]
}
)
}
UPDATE
Generally your js files go in common/models

resource ordering synchronization issue "->" doesn't work?

I have encounter really weird behaviour which goes against what I have learned, tutorial says etc. So I would be glad if someone could explain why that is happening.
I have a role module which is made up of composition of profiles (role-profile pattern). My role consists:
class role::lab_prg_c2_dn inherits lab_prg_c2 {
class { 'profile::cluster_data_node':
namenode_fqdn => $role::lab_prg_c2::namenode_fqdn,
secondarynamenode_fqdn => $role::lab_prg_c2::secondarynamenode_fqdn,
}
->
class{'bigdatasolution':}
}
First class installs technology and second one installs our components and items which are build on top of technology. Hence the technology need to be installed first, thats the reason for "->" dependency. However this seems to me doesn't work correctly. As components from class 'bigdatasolution' are installed somewhere before the class profile::cluster_data_node finishes.
I tried to use require => Class['profile::cluster_data_node'] but that doesn't make any difference!
The content of class{'bigdatasolution':} :
class bigdatasolution {
$hdfs_default_conf = '/usr/local/hadoop.hdfs.conf'
$hbase_default_conf = '/usr/local/hadoop.hbase.conf'
include symlinks
include bdjar
}
Symlinks - create symlinks for the configuration installed in class profile::cluster_data_node and are not directly managed - it will be presented when actually specified package get installed.
bdjar - add our jar to a technology library so content is as follows:
class bigdatasolution::bdjar {
file { "/usr/lib/hadoop/lib/bigdata-properties.jar":
ensure => present,
mode => 0644,
group => 'root',
owner => 'root',
source => "puppet:///modules/bigdatasolution/bigdata-properties.jar"
}
}
I even tried to put require => "technologycalClass" here but that doesn't help either.
Can someone please help me understand what's wrong and how that should be solved properly?
I Using puppet 3 and ordering is specified explicetly - so no arbitrary ordering set by puppet should happen.
Thanks
If your 'profile::cluster_data_node' class 'includes' other classes/modules they will have no dependency ordering with the 'bigdatasolution' class.
I see you actually do include symlinks and bdjar. Basically every piece of ordering you want to have in puppet, you need to write explicitly.
Here you should replace the include statements with require, that way the class cluster_data_node will require the other two modules to complete before it says it has completed. Include is a pretty lose way of importing things in puppet and in my opinion is best to just avoid it and go with explicit require statements instead.
TL;DR: included modules have no transitive ordering; required modules do.

Kohana multiple default controllers based on roles

I want to display completely different layouts for users in different roles on the root url of my application. I am currently achieving this using the following lines in bootstrap.php.
if (Auth::instance()->logged_in()){
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array('controller' => 'profile','action' => 'index',));
}
else{
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array('controller' => 'welcome','action' => 'index',));
}
What is the best practice to achieve this in Kohana? Is it ok to add more lines for different roles in bootstrap.php.
Thanks
you should consider using lambdacallback-route-logic
If allows you to modify the requested URL dynamically and much more cleaner than writing something in bootstrap.php
Why dont change basic template in ONE controller (and using the same route)? I think, your controller code doesn't differs if user logged in or not.
I do it like this:
Create an abstract class Controller_Rolebased where in before() method you can implement Role checking.
And then for example:
class Controller_Profile extends Controller_Rolebased
{
protected $_accept_roles = array('user', 'admin'); // this array Controller_Rolebased class will use in before method.

Kohana 3 experts, handling request arguments Route::set(), request->params() in K3 v. >= 3.1

Originally in Kohana 3 you were able to pass controller action arguments/parameters through URL as in:
http:/website/controller/actionname/param1/param2/.../paramX
and handle it by simply defining the action as in:
public action_actionname($params)
{
$params_array = explode("/", $params);
//you can now use $params_array[0], $params_array[1], ...
}
Now it seems that since v3.1 they decided to deprecate this feature (here is the link) and it should be eliminated in v3.2
And it seems they want you to use Route::Set() and request->param() methods instead. Does this mean that every time you define a method/action in a controller, you have to define a separate routing for each argument someplace else in your application?
Can anyone please explain to me how this works in simple terms. It just seems like a lot of unnecessary "hassle" to do all of that to simply call a function.
Maybe you should consider using the regex param in your route to override the default matching behavior... I typically use this to capture multiple URL parameters in one KO3 "param". Example:
Route::set('route1', '<controller>/<action>(/<param_list>)', array('param_list'=>'.*'))
->defaults(array(
'controller' => 'my_default_controller',
'action' => 'my_default_index'
));
Now in your controller, $this->request->param("param_list") will equal whatever matches the regex expression .* which means you can capture the rest of the URL just like you were hoping, with slashes and all!

Question from Pro Drupal 7 Book: Annotate module

So this is likely a shot in the dark, but for anyone out there who knows a bit of Drupal and better yet has implemented the annotate module from Ch. 2 of Pro Drupal 7 Development
Do you know how to alter the annotate module so all users can annotate? Right now, only the admin can annotate and it's being presented as an extension to editing.
The specific code being used is in this repository (pretty much straight from the book): http://github.com/dsharkey/Drupal-Module-Development--Annotate-Module
Further, I'm not really seeing how the annotate module is told to be presented at all? I believe its by the following lines of PHP (from annotate.admin.inc):
$instance = array(
'field_name' => 'annotation',
'entity_type' => 'node',
'bundle' => $key,
'label' => t('Annotation'),
'widget_type' => 'text_textarea_with_summary',
'settings' => array('display_summary' => TRUE),
'display' => array(
'default' => array(
'type' => 'text_default',
),
'teaser' => array(
'type' => 'text_summary_or_trimmed',
),
),
);
$instance = field_create_instance($instance);
But I'm not sure how that does anything more than create an instance and attach itself to a node. Why does it display where it does (as an option next to edit)?
Thanks all!
I'm not sure what you're referring to when you say "as an option next to edit", but the code you uploaded (and double-checking the book itself, the code used) wouldn't cause that. In fact, you should just see a field below the body field when you edit a node with annotations enabled:
The reason it only shows up when you edit an existing node (and not when you create a new node) is related to your first question about it not letting all users annotate the node: in the hook_node_load() implementation, it specifically checks to see if the user editing the node is the same as the owner of the node; if it isn't, it hides the annotation field:
/**
* Implements hook_node_load()
*/
function annotate_node_load($nodes, $types) {
global $user;
// Check to see if the person viewing the node is the author. If not then
// hide the annotation.
foreach ($nodes as $node) {
if ($user->uid != $node->uid) {
unset($node->annotation);
}
}
}
So the only person who should ever see the annotate field is the owner. If you want to allow anyone with edit access annotate the node, remove that function.
As for allowing anyone to make annotations to the node as a separate function to editing the node itself, that's not what the example was about and is entirely separate from the code used. You'll have to seek elsewhere for that and look at examples like the Drupal.org project Annotate for ways to do it. Basically, the annotations would be their own separate entities that would reference the node, much in the same way comments work.
But if I may be so bold, you've run into a big problem with Pro Drupal 7 Development in that it's not as good a reference for development as the previous editions were: it doesn't explain things very well, spends too much time on minor things and not enough time on really major things, introduces really bad practices (including several in the annotate example), and completely misses large sections of what Drupal 7 introduced. I'd recommend checking out Drupal 7 Module Development instead.

Resources