symfony2 routing, optional prefix from database - database

Basically what i want to achieve is this:
I have this paths:
http://SITENAME/dashboard
http://SITENAME/users
And they are mapped to the right controllers and actions:
/**
* #Route("/dashboard")
*/
public function dashboardAction()
{
// handle the request
}
/**
* #Route("/users")
*/
public function usersAction()
{
// handle the request
}
Now I want to make these other paths to map to the same controllers and actions:
http://SITENAME/{companyName}/dashboard
http://SITENAME/{companyName}/users
companyName is a name that I check on db if exists and if not throw a NotFound Exception.
These paths will just add some filter to the queries made, basically showing the same data structure.
I know I can create other actions and put those after the previous ones in order to be catched but I'm asking if there's something clever... something like this:
/**
* #Route("/({companyName}/)dashboard")
*/
public function dashboardAction($companyName = null)
{
// handle the request
}
where companyName is optional.
Thanks...
UPDATE
As Manolo suggested I already tried something like this and it works:
/**
* #Route("/dashboard")
* #Route("/{companyName}/dashboard")
*/
public function dashboardAction($companyName = null)
{
// handle the request
}
But I think there's a clever way of handling it...

Look at this example: http://symfony.com/doc/current/book/routing.html#routing-with-placeholders
// src/AppBundle/Controller/BlogController.php
// ...
/**
* #Route("/blog/{page}", defaults={"page" = 1})
*/
public function indexAction($page)
{
// ...
}
When page is not defined in the route, it is equal to 1.
But this won't work in your case, because you defined two routes for the same action:
/dasboard
/{companyName}/dashboard
So you have two options:
1. Define two routes for the same action (weird).
2. Change your defined route to: /dashboard/{companyName} (better)
Then, you can get /dashboard and /dashboard/{companyName} with the same action.

Try like this:
/**
* #Route("/{companyName}/dashboard")
*/
public function dashboardAction($companyName = null)
{
// handle the request
}

I suggest you to use the #ParamConverter annotation calls converters to convert request parameters to objects.
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
/**
* #Route("/dashboard")
* #Route("/({companyName}/)dashboard")
* #ParamConverter("company", class="AcmeDemoBundle:Company", options={"name" = "companyName"})
*/
public function showAction(Company $company = null)
{
}
The double route definition permit the default null company value
Hope this help

Related

Whats wrong with the DB query code in Console Kernel in Laravel PHP?

I'm trying to figure out why the DB query is not being executed at all. I did everything according to the documentation, but it doesn't work. I run this code in a controller and everything works great. Below is the code that I wrote in the kernel file. Please help with a solution:
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
$schedule->command('sitemap:generate')
->daily();
//
$schedule->call(function () {
DB::table('users')->whereNotNull('subscription_ends_at')->where('subscription_ends_at', '<', Carbon::now())->update(['stripe_account' => 567]);
})->everyMinute();
}
I think you need to create a command file for execute the logic of DB query instead of doing inside kernal file.
I think you will solve your problem by creating separate command file and implement your DB query logic there.
create a command by
php artisan make:command StripeAccountUpdate
Add below code in the App/Console/Commands/StripeAccountUpdate.php
<?php
namespace App\Console\Commands;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class StripeAccountUpdate extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'stripeaccountupdate:cron';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Cron job for update user table stripe_account column';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
DB::table('users')->whereNotNull('subscription_ends_at')->where('subscription_ends_at', '<', Carbon::now())->update(['stripe_account' => 567]);
\Log::info('Cronjob run for update user table stripe_account');
return 1;
}
}
And finally in your kernal.php
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
$schedule->command('sitemap:generate')
->daily();
$schedule->command('stripeaccountupdate:cron')
->everyMinute();
}
}

How to document useCallback with jsdoc?

If I have my arrow function, wrapped in a React useCallback, how am I supposed to document it with JSDoc?
const floopPig = useCallback((pigKey, floopCost) => {
const pigAbility = pigs[pigKey];
if (pigAbility.floopCost < magicPoints) {
return pigAbility.activate()
} else {
throw new Error('Not enough magic points');
}
}, [pigs, magicPoints])
I have been trying this in VSCode, but I haven't gotten anything to show up on hover over:
/**
* Floops a pig
* #callback
* #param {number} pigKey unique key for each pig
* #param {number} floopCost how much the ability costs to activate
*/
I think I've followed the documentation for #callback correctly. But based on this answer perhaps I'm using #callback for the wrong purpose?
How am I supposed to document this?
I've had success documenting the callback function itself.
const getNewToken = useCallback(
/**
* Requests a token, either by the normal flow or with a refresh token
* #param {URLSearchParams} axiosBody The body of the axios request
*/
async (axiosBody) => {
//Function
}, [myVar]);
Lower in the code, I can see intellisense working its magic when I call my function. I'm not 100% sure this is the best answer, but this is the best answer I've found

Angular Translate - how to retrieve dynamic variable list

I have this in the translation json file:
{
"test_key" : "Var1: {{var1}} Var2: {{var2}} Var3: {{var3}}"
}
For this to work, I need to provide var1, var2, and var 3. For example:
$translate('test_key', { var1: 1, var2: 2, var3: 3 });
The issue now is that var1, var2, var3 could be any dynamic variables. What I need now is to get all the list of dynamic variables so I can provide whatever values it may need.
Ideally, this is the goal I am trying to achieve (pseudo code)
var dynamicVars = getDynamicVarList(); // I need this, but how?
dynamicVars.forEach(function (key) {
switch (key) {
case "var1":
return 1;
case "var2":
return 2;
case "var3":
return 3;
default:
return null;
}
});
If it is Pascal Precht translate, then you set JSON file in module options, before application init. It's rather not possible with standard mechanisms. It offer JSON, but when it is loaded, then it's hard to change something, without changing source code of angular translate module.
If the reason you want this is to have many languages, then you can set many languages codes in $translate.
Another solution is to load JSON from server, which performs operations on var1, var2, var3 and hence returns static json, but you can do $http calls with commands to change variables in switch statement.
It looks somehow linguistic approach, Java is good for this. Grails may be fine framework for returning REST services.
Again, to restate the problem, the issue is that you do not know ahead of time which dynamic variables are to be used.
I solved the issue by using a customer interpolator.
So when you do
{{'testkey'|translate}}
and your lang.json has:
"testkey" :"this is number {{variable1}}"
It will get resolved to
this is number 1
Code:
app.factory('customTranslateInterpolator',
["$interpolate",
function ($interpolate) {
var $locale;
var customTranslateInterpolator = {};
/**
* This will be your custom dynamic vars resolution method
*/
var resolveExpressions = function (expressions) {
var values = {};
expressions.forEach(function (key) {
values[key] = resolveVariable(key);
});
return values;
}
/**
* The actual method for key:value mapping
*/
var resolveVariable = function(key) {
var retVal;
switch (key) {
case "variable1":
retVal = 1;
break;
default:
retVal = "";
}
return retVal;
}
customTranslateInterpolator.setLocale = function (locale) {
$locale = locale;
}
customTranslateInterpolator.getInterpolationIdentifier = function () {
return 'custom';
},
/**
* Custom interpolate
* interpolateParams will overwrite resolve expressions. This will allow developers
* to pass values to the translate directives or by using $translate service.
*
* #param {string} string the string retrieved from the language json file
* #param {object} interpolateParams the {key:value} object passed to the angular-translate features.
*/
customTranslateInterpolator.interpolate = function (string, interpolateParams) {
var result;
interpolateParams = interpolateParams || {
};
// Retrieve expressions and resolve them
var interpolatedString = $interpolate(string);
var resolvedExpressions = resolveExpressions(interpolatedString.expressions);
// Merge interpolateParams onto resolvedExpressions so that interpolateParams overwrites resolvedExpressions
angular.extend(resolvedExpressions, interpolateParams);
result = interpolatedString(resolvedExpressions);
return result;
}
return customTranslateInterpolator;
}]);
make sure you let angular-translate know you are using a custom interpolator
$translateProvider.useInterpolation('customTranslateInterpolator');
Note that you can still provide your own translate-values, and this will override whatever you have in resolveVariable()
So if you do
{{'testkey' | translate:"{variable1:'2'}"}}
It will resolve to
this is number 2
Hope this helps others.
-Lucky M.

phpunit: how to check anything changed at all

I'm pretty new in Unit testing.
We made a test
It starts with a certain content of a database
then there can 2 things happen.
Amsterdam is overwritten with Amsterdam
or
Amsterdam stays Amsterdam.... (nothing happens)
What is the best way to verify what of both happened?
Normally, you would test each case, and you can use a Mock Object to remove the dependency on the database.
In this case, you would structure a test that recognizes that nothing changed in the DB record. The Mock object returns a state from the database indicating that nothing has changed. Your test would then check that the code that executes next, reported this condition, and therefore passes the test.
A second test would then be done where the Mock Object returns the state from the database where the item was changed, so then the code that should be executed does what it should, and passes your test.
Repeat the above tests for failing conditions, and you have your code covered.
class YourDBClass {
private $DBRef;
// Constructor Injection, pass the Database object here
public function __construct($DatabaseObject = NULL)
{
if(! is_null($DatabaseObject) )
{
if($DatabaseObject instanceof YourDBAccessClass)
{
$this->SetDBClass($DatabaseObject);
}
}
}
function SetDBClass(YourDBAccessClass $DatabaseObject)
{
$this->DBRef = $DatabaseObject
}
function GetResult($request) {
$DBR = $this->DBRef;
$result = $DBRef->DoSomething($request);
if ($result->success == false)
$result->error = $this->GetErrorCode($result->errorCode);
}
function GetErrorCode($errorCode) {
// do stuff
}
}
Test:
class YourDBClassTest extends PHPUnit_Framework_TestCase
{
// Simple test for GetErrorCode to work Properly
public function testGetErrorCode()
{
$TestClass = new YourDBClass();
$this->assertEquals('One', $TestClass->GetErrorCode(1)); // Assumes GetErrorCode returns a string
$this->assertEquals('Two', $TestClass->GetErrorCode(2));
}
// Could also use dataProvider to send different returnValues, and then check with Asserts.
public function testGetResultsNoChange()
{
// Create a mock for the YourDBAccessClass,
// only mock the GetResult() method.
$MockService = $this->getMock('YourDBAccessClass', array('GetResult'));
// Set up the expectation for the GetResult() method
$MockService->expects($this->any())
->method('GetResult')
->will($this->returnValue("NoChange"));
// Create Test Object - Pass our Mock as the service
$TestClass = new YourDBClass($MockService);
// Or
// $TestClass = new YourDBClass();
// $TestClass->SetDBClass($MockService);
// Test GetResults
$QueryString = 'Some String since we did not specify it to the Mock'; // Could be checked with the Mock functions
$this->assertEquals('NoChange', $TestClass->GetResults($QueryString));
}
// Could also use dataProvider to send different returnValues, and then check with Asserts.
public function testGetResultsChanged()
{
// Create a mock for the YourDBAccessClass,
// only mock the GetResult() method.
$MockService = $this->getMock('YourDBAccessClass', array('GetResult'));
// Set up the expectation for the GetResult() method
$MockService->expects($this->any())
->method('GetResult')
->will($this->returnValue("Amsterdam Changed"));
// Create Test Object - Pass our Mock as the service
$TestClass = new YourDBClass($MockService);
// Or
// $TestClass = new YourDBClass();
// $TestClass->SetDBClass($MockService);
// Test GetResults
$QueryString = 'Some String since we did not specify it to the Mock'; // Could be checked with the Mock functions
$this->assertEquals('Amsterdam Changed', $TestClass->GetResults($QueryString));
}
}
Steven, I discussed with my colleauges, They understand what you do.
but this is what we actually needed:
mysql UPDATE statement - overhead for same values?
I hope you follow. Nevertheless, thank you so much!

Using a weka decision tree classifier without the whole weka library?

I have trained a classifier for my instances, and now want to export it to an Android application, where the Weka library will be unavailable.
It is not suitable to simply add the Weka library in the Android application, because of it's size (6.5 Mb).
Is there any other way to use my classifier to evaluate and label other unlabeled instances? Are there any smaller, independent library specifically design for this?
Of course I could, eventually, write my own library to interpret the output model of Weka, but it would seem logical to me, that such a solution already exists. (although it escapes me, somehow)
There are no independent libraries that would do what you want. You could remove all the parts of Weka you don't need and package that into a library.
In your particular case, the easiest thing to do might be to take the decision tree that Weka learns and put it directly into the code in a series of if...else statements. You could even write a script that takes the (graphical) output of the decision tree and writes that code for you.
After paying more attention the output model of weka, I noticed that by using the option that generates the tree in a Java class form, I can use it separatly from the weka library.
You can remove the generated WekaWrapper and keep only the internal class, which is a basic implementation of the tree:
The class looks something like this:
public class WekaWrapper
extends Classifier {
/**
* Returns only the toString() method.
*
* #return a string describing the classifier
*/
public String globalInfo() {
return toString();
}
/**
* Returns the capabilities of this classifier.
*
* #return the capabilities
*/
public Capabilities getCapabilities() {
weka.core.Capabilities result = new weka.core.Capabilities(this);
result.enable(weka.core.Capabilities.Capability.NOMINAL_ATTRIBUTES);
result.enable(weka.core.Capabilities.Capability.NOMINAL_CLASS);
result.enable(weka.core.Capabilities.Capability.MISSING_CLASS_VALUES);
result.setMinimumNumberInstances(0);
return result;
}
/**
* only checks the data against its capabilities.
*
* #param i the training data
*/
public void buildClassifier(Instances i) throws Exception {
// can classifier handle the data?
getCapabilities().testWithFail(i);
}
/**
* Classifies the given instance.
*
* #param i the instance to classify
* #return the classification result
*/
public double classifyInstance(Instance i) throws Exception {
Object[] s = new Object[i.numAttributes()];
for (int j = 0; j < s.length; j++) {
if (!i.isMissing(j)) {
if (i.attribute(j).isNominal())
s[j] = new String(i.stringValue(j));
else if (i.attribute(j).isNumeric())
s[j] = new Double(i.value(j));
}
}
// set class value to missing
s[i.classIndex()] = null;
return WekaClassifier.classify(s);
}
/**
* Returns the revision string.
*
* #return the revision
*/
public String getRevision() {
return RevisionUtils.extract("1.0");
}
/**
* Returns only the classnames and what classifier it is based on.
*
* #return a short description
*/
public String toString() {
return "Auto-generated classifier wrapper, based on weka.classifiers.trees.Id3 (generated with Weka 3.6.9).\n" + this.getClass().getName() + "/WekaClassifier";
}
/**
* Runs the classfier from commandline.
*
* #param args the commandline arguments
*/
public static void main(String args[]) {
runClassifier(new WekaWrapper(), args);
}
}
class WekaClassifier {
private static void checkMissing(Object[] i, int index) {
if (i[index] == null)
throw new IllegalArgumentException("Null values are not allowed!");
}
public static double classify(Object[] i) {
return node0(i);
}
protected static double node0(Object[] i) {
return 0.0; // unacc
}
}
So, yeah, in fact you can do it really easy. Things to remember:
to classify an instance, call the classify(Object[]) method;
the return value will be a float value;
the return values are explained in comments, right next to the return command;
the parameters have no validation, so be careful in which order you are inputing them (this part was done by the weka dependent part);
the order is the one defined in the arff file.
If you want to run RandomForests, you can use a little script I wrote that turns the output of WEKA's -printTrees option of the RandomForest classifier into Java source code.
http://pielot.org/2015/06/exporting-randomforest-models-to-java-source-code/
The code you need to include into your Android app will consist of three classes only: the class with the generated model + two classes to make the classification work.

Resources