Phalcon router sends the wrong parameters - phalcon

I have a problem with my router in Phalcon.
I have an action in my controller which ether takes a date parameter or not.
So when I access an URL: http://example.com/sl/slots/index/2017-06-27
everything works ok.
But when I go to: http://example.com/sl/slots/index
I get the following error:
DateTime::__construct(): Failed to parse time string (sl) at position
0 (s): The timezone could not be found in the database.
So the router actually takes the "sl" in the beginning as a parameter.
My router for this kind of url is set like this:
$router->add(
"/{language:[a-z]{2}}/:controller/:action",
array(
"controller" => 2,
"action" => 3
)
);
Btw it does the same withut the index: http://example.com/sl/slots
Oh and my slots index action looks like this:
public function indexAction($currentDate = false){ //code }
So the $currentDate is set to "sl" when I call the action without a parameter
Thank you for the help

Well you need to add language in first argument of action too. Then it should work.

In addition to #Juri's answer.. I prefer to keep my Actions empty or as slim as possible. Imagine if you have 3-4 parameters in the Route, you will end up with something like:
public function indexAction($param1 = false, $param2 = false, $param3 = false....)
Here is how I prefer to handle Route parameters:
public function indexAction()
{
// All parameters
print_r($this->dispatcher->getParams());
// Accessing specific Named parameters
$this->dispatcher->getParam('id');
$this->dispatcher->getParam('language');
// Accessing specific Non-named parameters
$this->dispatcher->getParam(0);
$this->dispatcher->getParam(1);
...
}

Related

Nestjs: Cannot PUT, Cannot DELETE (404 not found)

I'm on a task to write a simple CRUD program for a users list, following a similar nestjs example. While GET, POST and GET by id works fine, PUT and DELETE does not work properly. I get 'User does not exist' however user exists in database.
Controller
#Controller('users')
export class UsersController {
constructor(private userService: UsersService) {}
.....
//Update a user's details
#Put('/update')
async updateUser(
#Res() res,
#Query('userid') userID,
#Body() createUserDto: CreateUserDto
) {
const user = await this.userService.updateUser(userID, createUserDto);
if (!user) throw new NotFoundException('User does not exist!');
return res.status(HttpStatus.OK).json({
message: 'User has been successfully updated',
user
})
}
//Delete a user
#ApiParam({ name: 'id' })
#Delete('/delete')
async deleteUser(#Res() res, #Query('userid') userID) {
const user = await this.userService.deleteUser(userID);
if (!user) throw new NotFoundException('Customer does not exist');
return res.status(HttpStatus.OK).json({
message: 'User has been deleted',
user
})
}
Service
// Edit user details
async updateUser(userID, createUserDto: CreateUserDto): Promise<User> {
const updatedUser = await this.userModel
.findByIdAndUpdate(userID, createUserDto, { new: true });
return updatedUser;
}
// Delete a customer
async deleteUser(userID): Promise<any> {
const deletedUser = await this.userModel
.findByIdAndRemove(userID);
return deletedUser;
}
I'm using swagger to perform my tests. I'm passing id as a parameter to find and update user.
Based on your code repository, you aren't using URL Parameters, but rather you are using Query Parameters. The difference in the two is how they are passed to the server and how they are told to the server to listen for them.
Query Parameters
With query parameters, you pass them to your server starting with a ? in the url, and concatenating each one after by using a &. An example could look something like http://localhost:3000?name=Test&id=a26408f3-69eb-4443-8af7-474b896a9e70. Notice that there are two Query parameters, one named name and one named id. In Nest, to get these parameters in your route handler, you would use the #Query() decorator. A sample class could look like
#Controller()
export class AppController {
#Get()
getHello(#Query() query: { name: string, id: string }) {
return `Hello ${name}, your ID is ${id}`;
}
}
Notice how with the url above, the route called is the base route (/), with the query parameters added on.
URL Parameters
URL parameters are a way to dynamically build your routes without needing to specify what each possible URL. This is useful for things like IDs that are dynamically generated. Taking a similar URL as above, the sample URL this time could look like http://localhost:3000/Test/a26408f3-69eb-4443-8af7-474b896a9e70. Notice how this time there is no ? or & and it just looks like a full URL. To specify URL Params in nest, you need to a a colon(:) before the param name in the resource declaration decorator, along with any other part of the path necessary. Then to access the URL Parameters, you need to use the #Param() decorator in the route handler, similar to how you would the #Query() decorator. The class sample for this would be
#Controller()
export class AppController {
#Get(':name/:id')
getHello(#Param() params: { name: string, id: string })
return `Hello ${name}, your ID is ${id}`;
}
}
Problem and Solution
You're currently calling off to http://localhost/users/update/<ID> acting as if you are using URL parameters, but in your route handler you are expecting #Query() to grab the id. Because of this, there is no handler to find /users/update/:id and so you are getting a 404 in return. You can either modify your server to listen for URL Parameters as described above, or you can modify the URL to send the request using Query Parameters instead of URL parameters.

pass global variable between two function on zf2 controller

I should change on zf2 controller a variable global. In practice, I'd like a function to insert the value in the global variable and another function prints the value of the variable. for example:
protected $variablename;
public function setAction()
{
$this->variablename = "hi friends!";
}
public function getAction()
{
var_dump($this->variablename);
}
In this example, when I print the variable I always get NULL.
Any suggestions? tnx
simone
indirectly you can't because of the lifecircle in a zend/php request. after you set up your variable in actionA the variable is reseted if you request actionB
if you want to set your variabel data in actionA and make the data present in actionB you need a persistent save storage (like a db, cookie or session. otherwise it is only possible to forward the current request to another request in your controller. then have a look at the forward controller helper in zend.
http://framework.zend.com/manual/2.3/en/modules/zend.mvc.plugins.html#zend-mvc-controller-plugins-forward
//edit after comment
you can use a session in zend like this
set session
$session = new Zend\Session\Container('base');
$session->offsetSet('someSettings', 'someValue');
get session
$session = new Zend\Session\Container('base');
if( $session->offsetExists('someSettings') )
{
$someSettingValue = $session->offsetGet('someSettings');
}

How do I make a construct to have beforeAuth only apply to certain views/functions in Laravel 4

I have a resource in Laravel I have called artists with an ArtistsController. I would like to add filters to some of the pages, but not all. I know I can add a filter to all of the functions/views in the resource controller like so:
public function __construct()
{
$this->beforeFilter('auth', array('except' => array()));
}
How do I add the beforeAuth filter to only a certain view/function? I would like a user to be logged in in order to go the "index" view, but I would like a user to be able to go to the "show" pages without necessarily being logged in:
public function index()
{
$artists = Artist::all();
return View::make('artists.index', compact('artists'))
->with('artists', Artist::all())
->with('artists_new', Artist::artists_new());
}
public function show($id)
{
$artist = Artist::find($id);
return View::make('artists.show', compact('artist'))
->with('fans', Fan::all());
}
Is there a way to do this? Thank you.
Not sure if this helps but you could use the only key instead of the except (if I understand your question correctly).
$this->beforeFilter('auth', array('only' => array('login', 'foo', 'bar')));
Although that would still go in the constructor.

Is there any reason why a urlencoded string would throw a 404 error?

I'm trying to pass two parameters, one of which is an email address.
routes (also tried (:any))
Route::any(
'user/confirm_request/(:any?)/(:any?)', array(
'uses' => 'user#confirm_request'));
controller (also tried post_confirm_request())
public function get_confirm_request($email, $term)
{
//do stuff
}
Ultimately, all I'm trying to do is hit that route and send an email to a user with those two parameters. But I keep getting a 404 error. The email gets encoded and the route looks like this:
/email%40gmail.com/someString
I'm able to take out %40 and it works just fine (just gives me an error for the sendmail).
Why would the %40 be throwing a 404 error? Could it be a Laravel thing?
One solution would be to pass the email as a url parameter.
First, remove the second argument from the route. (You could also remove both if needed.)
Route::any('user/confirm_request/(:any?)', array('uses' => 'user#confirm_request'));
Then append the email to the action url, something like this..
$url = URL::base() . '/user/confirm_request?email=' . $email;
Then in your controller, you can grab that data.
public function get_confirm_request()
{
$email = Input::get('email');
}

Defaults in Symfony2 routing not being passed properly

I am currently trying to configure a routing option in Symfony2 so /cms will route to /cms/role/view. However, the passing of defaults doesn't seem to work properly.
/src/MyProject/CMSBundle/Resources/config/routing.yml
MyProjectCMS_specific:
pattern: /cms/{page}/{option}
defaults: { _controller: MyProjectCMSBundle:Main:index, page: role, option: view }
requirements:
_method: GET
/src/MyProject/CMSBundle/Controller/MainController.php
<?php
namespace MyProject\CMSBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class MainController extends Controller
{
public function indexAction($page, $option)
{
$response = null;
/* Switch statement that determines the page to be loaded. */
return $response;
}
}
?>
The problem is that when I try to go to `localhost/app_dev.php/cms', it gives me the following error:
Controller "MyProject\CMSBundle\Controller\MainController::indexAction()" requires that you provide a value for the "$page" argument (because there is no default value or because there is a non optional argument after this one).
500 Internal Server Error - RuntimeException
However, if I try to visit localhost/app_dev.php/cms/role or localhost/app_dev.php/cms/role/view, it gives me the correct page. I've tried adding a default route to /cms, but it still gives me the same error. How is this possible and how can I fix this?
Thanks in advance.
I don't know what is the difference between what you wrote and
public function indexAction($page = "role", $option = "view")
but maybe you could try it and tell us.