Laravel5.4: How to mock the current page? - php

I want to test a helper function using Request::fullUrl in it.
function foo($arg)
{
// Get current full URL.
$url = Request::fullUrl();
// Return modified URL.
return $url;
}
The docs says:
You should not mock the Request facade. Instead, pass the input you desire into the HTTP helper methods such as get and post when running your test.
What are "the HTTP helper methods"?
They mean "TestCase::get" and "TestCase::post"?
Yes, my problem was solved by using $this->get().
But is this correct way?
class MyHelperTest extends TestCase
{
public function testFoo()
{
// Move to index page.
$this->get('/');
// Get a modified URL.
$url = foo('arg');
$this->assertEquals('Expected URL', $url);
}
}

It solved.
Using $this->get('/') is correct way.
https://laravel.com/docs/5.4/http-tests
The get method makes a GET request into the application

Related

Zend Expressive not passing variables to view script

I am using Zend Expressive 2 due to PHP version constraints. If I return variables in step one of pipeline (IndexAction) the variables appear just fine.
If I delegate to the next step (VerifyInputAction) and determine there is an error in the input, I need to return an error to view script. For some reason, it will not take the variables with it that I pass with the template renderer. It will still load the template, just not with the $data array variables.
I'm using Zend View as the template renderer.
My pipeline looks as follows.
IndexAction()
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
{
if ($request->getMethod() !== "POST") {
return new HtmlResponse($this->template->render('app::home-page', ['error' => 'hello']));
} else {
$delegate->process($request);
//return new HtmlResponse($this->template->render('app::home-page'));
}
}
VerifyInputaction()
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
{
$data = [];
$file = $request->getUploadedFiles()['recordsFile'];
$fileType = substr($file->getClientFilename(), strpos($file->getClientFilename(), '.'));
// If file type does not match appropriate content-type or does not have .csv extension return error
if (! in_array($file->getClientMediaType(), $this->contentTypes) || ! in_array($fileType, $this->extensions)) {
$data['error']['fileType'] = 'Error: Please provide a valid file type.';
return new HtmlResponse($this->template->render('app::home-page', $data));
}
$delegate->process($request);
}
Another problem that might be beyond the scope of this question includes, when I make it to the next Action in the pipeline, if I go to render a view script there I get this error...
Last middleware executed did not return a response. Method: POST Path: /<--path-->/ .Handler: Zend\Expressive\Middleware\LazyLoadingMiddleware
I will do my best to provide more code examples, but due to this being an issue at work I might have some problems with that.
Thanks!
Last middleware executed did not return a response. Method: POST Path: /<--path-->/ .Handler: Zend\Expressive\Middleware\LazyLoadingMiddleware
An action needs to return a response. In your VerifyInputaction you don't return a response if there is no valid csv file. I'm guessing this happens in your case and the $delegate->process($request); is triggered, which probably doesn't call another action which returns a middleware.
Looking at your code, it makes more sense to call VerifyInputaction first, check if it is a post and verify. If any of those fails, go to the next action which would be IndexAction. This could display the form with an error message. You can pass error message within the request as explained here: https://docs.zendframework.com/zend-expressive/v2/cookbook/passing-data-between-middleware/
Pipeline:
VerifyInputaction -> Check POST, verify input -> redirect if success
IndexAction -> render template and return response
I don't see any reason in your code why $data is not passed. My guess is that somehow the template is rendered in IndexAction which doesn't have the $data but has error set. You might check for this. The confusion is here that you render the same template in 2 different actions. Using the solution I mentioned, you only need to render it in IndexAction.

CakePHP response stop deprecated

I'm using CakePHP 3.5 and two of the methods I want to use are deprecated and I can't find an alternative.
The methods are:
$this->response->send();
$this->response->stop();
I want to redirect to a different page and stop the execution of the current method. I've tried calling die() after my redirect and it doesn't work.
According to the migration guide the methods have been made obsolete.
Any thoughts?
Edit:
I'm trying to redirect users without access to certain pages. This is in the initialize() method in the controllers.
if ($allowedAccess) {
$this->Flash->error("Insufficient rights to access that location");
$this->redirect($this->referer());
// FIXME - find alternative to deprecated methods
return $this->response;
$this->response->send();
$this->response->stop();
}
Are you trying this in a controller? Simply return the response object from your controllers method:
public function index() {
// Some code
return $this->response;
}
send() was just a wrapper around phps exit(). Use exit() if you need to somewhere.
What happens when you return the response is that the ActionDispatcher processes the return value and if it's a Response object. See the __invoke() method.
The response will go through the middleware layer and will be finally send by the ResponseEmitter which is used by the Server. Check your webroot/index.php to see it:
// Bind your application to the server.
$server = new Server(new Application(dirname(__DIR__) . '/config'));
// Run the request/response through the application
// and emit the response.
$server->emit($server->run());

How to use a different protocol with $AbsoluteLink in Silverstripe

In the Silverstripe templating syntax $AbsoluteLink returns the full URL of a page/object, including the protocol and host:
http://www.example.com/event/ics
I want to be able to call a full URL with a different protocol:
webcal://www.example.com/event/ics
What is the best way to achieve this?
Define a custom link method that replaces the current website protocol with your desired one. ie.
public function WebCalLink()
{
return str_replace(Director::protocol(), 'webcal://', Director::protocolAndHost()) . $this->Link();
}
Make a new getter function on your page:
public function WebcalLink() {
$absolute = $this->AbsoluteLink();
$webcal = str_replace(Director::protocol(), "webcal://", $absolute);
return $webcal;
}
You can call it from your template using $WebcalLink

oriceon/oauth-5-laravel install controller request error

This is my first time implementing OAuth to my projects. I found a walkthrough on github for laravel-5 oriceon/oauth-5-laravel. I followed all the steps correctly. However when I get to the controller function I get an error saying:
Call to undefined method Illuminate\Support\Facades\Request::get()
Here is my controller function:
public function loginWithFacebook(Request $request)
{
// get data from request
$code = $request->get('code');
// get fb service
$fb = \OAuth::consumer('Facebook');
// check if code is valid
// if code is provided get user data and sign in
if ( ! is_null($code))
{
// This was a callback request from facebook, get the token
$token = $fb->requestAccessToken($code);
// Send a request with it
$result = json_decode($fb->request('/me'), true);
$message = 'Your unique facebook user id is: ' . $result['id'] . ' and your name is ' . $result['name'];
echo $message. "<br/>";
//Var_dump
//display whole array.
dd($result);
}
// if not ask for permission first
else
{
// get fb authorization
$url = $fb->getAuthorizationUri();
// return to facebook login url
return redirect((string)$url);
}
}
In the app you can see that i did add the correct provider and alias:
'OAuth' => Artdarek\OAuth\Facade\OAuth::class,
Artdarek\OAuth\OAuthServiceProvider::class,
In my view I call the route that leads to the correct controller function and I keep arriving to this error. What could it be that does this? Should the function be calling to the provider or something? Thanks for looking at this Stack!
First up, I hope your view isn't calling a route- that's backwards. Routes are used immediately to determine the controller, which is then used to determine and respond with the proper view.
... That aside, Request is the name of a facade in Laravel. That's why the error message says it's looking for the get() method on the Illuminate\Support\Facades\Request class. You'll want to namespace the Request class you're using so that it's able to use the correct get() method. Depending on your version, I do this with use Illuminate\Http\Request; at the top of my controller file (immediately after the namespace declaration for the controller).

Efficiently Map RESTful URI to API endpoint Architecture

When creating an api each valid URI is mapped to an action. This action can be a specific function call or can set some parameters passed to a generic function.
My question is how or what are the good method to map an uri such as /auth/create to the right action.
To illustrate my attempts:
I thought about naming a function the same as a the URI replacing the / with Z to directly call the function by its name. I could basically simply execute the $request_uri directly without testing.
// from $request_uri = '/auth/create' I make;
$request_uri ='ZauthZcreate';
function ZauthZcreate($email, $password) {
echo "i've been called as expected \n";
}
$request_uri($_GET[email],$_GET[password]);
but it wouldn't work with something like /user/123123. I am trying to avoid falling in an endless cascade of if-else.
EDIT
I've iterated on this concept and found another solution:
$request_uri = '/api/auth/login';
$request_path = ltrim($request_uri,'/');
$request = explode('/', $request_path);
// begin point for api
if($method = array_shift($request)) {
if ($method == 'api') {
$method($request);
}
}
function api($request) {
$method = __FUNCTION__.'_'.array_shift($request);
if(is_callable($method)) {
$method($request);
}
}
// In a dedicated file for the scope auth
function api_auth($request) {
$method = __FUNCTION__.'_'.array_shift($request);
if(is_callable($method)) {
$method($request);
}
}
function api_auth_login($request) {
// api end point implementation here
}
function api_auth_create($request) {
// api end point implementation here
}
I wouldn't use those Z's, that's going to be needlessly difficult to read. In your above example you could do the same thing with just AuthCreate. You could also do this with OO design by making a base class for your main verbs (like Auth) and then having them declare their member functions.
Ultimately you wont want to resolve this with if/else blocks, but rather parse each part of the URI and see if a function in the right namespace exists, and once it doesnt start using your slashes as inputs (for your example above with /user/123123).
It might also do you well to look at how other REST API's are structured, because this is something of a solved problem

Categories