I have this problem when I try to do functional test on a form submission:
testSearch.php:
public function testFormSubmission()
{
$client = $this->createClient();
$client->request('POST', '/search', array('nome' => 'Jan'));
...
}
app.php:
$app->post('/search', function (Request $request) use ($app)
{
$post_data = $request->get('form');
...
});
... but $post_data is NULL.
If I do the submission using the submit button in the browser everything works well...
You are calling $request->get('form'), but you didn't set the form parameter to anything. Perhaps this is what you are looking for:
$client->request('POST', '/search', array('form' => array('nome' => 'Jan')));
If not, you'll need to provide more context.
$client->request('POST', '/search', array('nome' => 'Jan'));
the third argument of the request method seems to be for request parameters (?&nome=Jan )
you should use the crawler to simulate a form submission :
from the doc :
$form = $crawler->selectButton('submit')->form();
// set some values
$form['name'] = 'Lucas';
$form['form_name[subject]'] = 'Hey there!';
// submit the form
$crawler = $client->submit($form);
http://symfony.com/doc/current/book/testing.html
or use the sixth parameter to send a raw request body.
Related
I tried to build an instant search using vuejs and laravel 5.3 but somehow It wont work with no errors showing
Controller (fullcode https://pastebin.com/6mQ4eWTf) :
public function index(Request $request) {
$search = $request->search;
$items = Staff::where('nama', 'LIKE', '%'.$search.'%')->paginate(5);
$response = [
'pagination' => [
'total' => $items->total(),
'per_page' => $items->perPage(),
'current_page' => $items->currentPage(),
'last_page' => $items->lastPage(),
'from' => $items->firstItem(),
'to' => $items->lastItem()
],
'data' => $items
];
staff.js method (fullcode https://pastebin.com/NDxzqsyp) :
methods: {
getVueItems: function (page) {
this.$http.get('/staffitems?page=' + page + '&search=' + this.search).then((response) => {
this.$set('items', response.data.data.data);
this.$set('pagination', response.data.pagination);
});
setTimeout(this.getVueItems, 5000);
},
Blade (fullcode https://pastebin.com/6uDZRryE) :
<input v-on:keyup.enter="getVueItems" type="text" class="form-control" name="search" placeholder="Cari..." v-model="search"/>
Routes :
Route::get('/staffcrud', 'StaffController#Crud');
Route::resource('/staffitems', 'StaffController');
The data correctly shown (tested by getting json response from /staffitems?page=1&search=jon with or without search value), but somehow when I do type words to search in input search column, nothing happened as soon as i finished typing, probably event handling in blade are wrong or my method in staff.js any solution for this?
You should add the debounce in your mounted() method:
mounted() {
this.getVueItems = _.debounce(this.getVueItems, 5000); // i'm using lodash here.
}
To build a really effective instant database search you should consider using pusher and laravel echo together with vuex
You can check out this out >>> Ethiel Adiassa's Live Search Tutorial with laravel and pusher
In your blade template use only:
v-on:keyup='vueGetItems'
Because your instant search is firing only on enter key up. I hope this will work or contact me to get full working code.
Given a page retrieved at for example:
http://myapp.dev/path/subfolder?param=abc
Whenever the additional GET parameter called param is present it should be added automatically to all subsequent links in my navigation as constructed in the .volt template. For example:
Go to subfolder 2
I.e. based on this .volt link the the goal is to generate:
Go to subfolder 2
If you want to append Query string parameters only for given links you can go with Luke's solution.
However I think you want to achieve something a bit different and it involves custom logic. For this to happen we should create a custom Volt function.
Custom function definition:
public static function urlFor($params, $queryStringParams = [])
{
$di = \Phalcon\DI::getDefault();
if ($di->getRequest()->has('param')) {
$queryStringParams['param'] = $di->getRequest()->get('param');
}
return $di->getUrl()->get($params, $queryStringParams);
}
The above function acts the same as url() function in Phalcon, it just allows us to write a bit of custom logic before passing the parameters to url().
In your case we check if URL contains desired query param and we add it to every URL generated on the current request. In my case the above function is in Helper file so I can use it anywhere I need to.
This is our View service definition:
$di->set('view', function() use ($di) {
$view = new \Phalcon\Mvc\View();
...
$view->registerEngines([
'.phtml' => function($view, $di) {
$volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di);
$options = [
'compiledPath' => $di->getConfig()->site->path->cache . 'volt/frontend/',
'compiledExtension' => '.php',
'compileAlways' => $di->getConfig()->debug,
];
$volt->setOptions($options);
...
// IMPORTANT PART: Overwriting default url() function in Volt
$compiler = $volt->getCompiler();
$compiler->addFunction('url', function($resolvedArgs, $exprArgs){
return 'Helpers\Common::urlFor(' . $resolvedArgs . ')';
});
return $volt;
}
]);
return $view;
});
Please note the IMPORTANT PART comment in the above code block.
Let us finish with example:
User is on this address:
http://myapp.dev/path/subfolder?param=abc
But somewhere in your code you want to generate a link to News page:
News
Our code will catch the param in the URL and will generate the following address:
http://myapp.dev/news/list?param=abc
I started using Laravel a month ago. Trying to make a page with one form on it and I keep getting a "Controller method not found." error. There is only one form on the page and that method is being called fine and making the query that I want. It does redirect to the same page with that form, /dashboard/edit/module.
It would be awesome if I could see what method is not being found or where it is in my code. Any ideas how I can do this? Someone mentioned App::error or messing with Log::error in global.php but I can't get any more information shown.
Edit:
I found that the form action is only being found if I upload a video to the form. Other then that it gives me the same error. Here is the controller method of this form. The page with this form is /dashboard/edit/module and I would like to reload that page after this runs.
public function postSection(){
$path = public_path() . "/videos/";
$filename = uniqid() . '.mp4';
$file_path = $path . $filename;
$moduleID = Input::get('moduleID');
if(!Input::hasFile('video')){
return Redirect::back()->with('error', 'Must enter a valid video file.');
}else{
try {
Input::file('video')->move($path, $filename);
$section = New Section;
$section->module_id = $moduleID;
$section->video = $file_path;
$section->save();
//I was trying to use this instead of View::make to stop form resubmission
//return Redirect::to('/dashboard/edit/module')->with('moduleID', $moduleID);
return View::make('forms.editMod')->with('moduleID', $moduleID);
}catch ( Exception $e){
return Redirect::back()->with('error', 'Unable to save the video file.');
}
}
}
Edit: And my routes.php
//Route for the home page
Route::get('/', function(){ return View::make('home'); });
//Controllers
Route::controller('dashboard/edit', "ContentController");
Route::controller('user', "UserController");
Route::group(array('before'=> 'auth|dash'), function(){
//dashboard home
Route::get('/dashboard', function(){ return View::make('dashboard');});
//dashboard subs
Route::get('dashboard/modules', function(){ return View::make('forms.module');});
Route::get('dashboard/users', function(){ return View::make('users');});
Route::get('dashboard/reporting', function(){ return View::make('reporting');});
//user pages
Route::get('dashboard/register', function(){ return View::make('forms.register');});
Route::post('dashboard/edit/user', array('before'=>'csrfajax', function(){
$id = Input::get('userID');
$user = User::find($id);
return View::make('forms.editUser')->with('user', $user);
}));
});
And the form...
{{ Form::open(array('files' => true, 'action' => 'ContentController#postSection', 'id' => 'sectionform')) }}
<fieldset>
{{ Form::label('Video (mp4)') }}
{{ Form::hidden('moduleID', $module->id)}}
{{ Form::file('video', array('id' => 'video', 'class' => 'form-control')) }}<br>
{{ Form::submit('Save') }}
</fieldset>
{{ Form::close() }}
In routes.php, to reach this method you're using Route::controller, which results in RESTful routing. If the browser's HTTP request used the POST action, you'd correctly be routed to public function postSection(){}. But if the HTTP request used GET, which is the default for web browsing, especially when no data is being submitted by the browser, Laravel would be looking for a method called public function getSection(){}. This would explain why when you're uploading something (i.e. using POST), you reach the page, but otherwise you don't.
See the official documentation for the full low-down on implicit routing: http://laravel.com/docs/controllers#implicit-controllers
First I declare simple view like this:
$di->set('viewSimple', function() {
$view = new \Phalcon\Mvc\View\Simple();
$view->setViewsDir('../app/views/');
$view->registerEngines(array(
".volt" => 'volt'
));
return $view;
});
then to generate html email, I use it as following:
public function renderHTMLEmail($template_name, $template_params) {
$content = $this->viewSimple->render("emails/$template_name", $template_params);
return $this->viewSimple->render("emails/master", array( 'content' => $content) );
}
My emails are being generated just fine, but whenever I call my renderHTMLEmail function actual page rendering is somehow corrupted and page appears totally blank (I have to use redirect as workaround). This is a mystery to me as main view renderer is completely different object. Can I prevent this?
Or does anybody have recommended method of generating arbitrary pieces of html outside of main view rendering process which would not interfere with it? There is couple of similar questions on SO, but none of solutions work. They either don't generate my email or they corrupt main view.
Found a solution, when registering the "\Phalcon\Mvc\View\Simple" component into the DI container make sure to use a new volt instance otherwise it will join up with the application's \Phalcon\Mvc\View volt instance somehow. This is what lot (https://stackoverflow.com/users/1672165/lot) was suggesting in the comments.
Code sample:
public function getTemplate($name, $params)
{
$parameters = array_merge(array(
'publicUrl' => $this->getDI()->getApp()->url->host . $this->getDI()->getApp()->url->baseUri
), $params);
$app = $this->getDI()->getApp();
$this->getDI()->set('simpleView', function() use ($app) {
$view = new \Phalcon\Mvc\View\Simple();
$view->setViewsDir(APP_DIR . $app->application->viewsDir);
$view->registerEngines(array(
".volt" => function ($view, $di) {
$volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di);
$volt->setOptions(array(
'compiledPath' => APP_DIR . '/cache/volt/',
'compiledSeparator' => '_',
'compiledExtension' => '.compiled'
));
$compiler = $volt->getCompiler();
$compiler->addFunction('is_a', 'is_a');
return $volt;
}
));
return $view;
});
/* #var $simpleView \Phalcon\Mvc\View\Simple */
$simpleView = $this->getDI()->get('simpleView');
foreach ($parameters as $key => $value) {
$simpleView->{$key} = $value;
}
$html = $simpleView->render('emails/' . $name, $parameters);
return $html;
}
Sample was pulled straight from our working app so may need some re-working but should help solve the original issue.
This works for me using \View as the application DI registered view component which renders controller action volt views and the above \View\Simple with fresh volt registration successfully emails and allows the original view with volt to carry on.
This was asked a while ago however i've not seen a working solution anywhere else.
For completeness I've registered a github issue with the findings: https://github.com/phalcon/cphalcon/issues/3096
I recently had to deal with a similar problem, I'm not certain where you're falling short, but one important thing was to use a separate view from the one used by the application – you're already doing this. See if the following works.
protected function renderView($view, $template, array $data = null)
{
return $view
->reset()
->pick('emails/' . $template)
->setVars($data)
->start()
->render(null, null)
->finish()
->getContent();
}
public function renderHTMLEmail($template_name, $template_params)
{
$content = $this->render($template_name, $template_params);
return $this->render('master', array('content' => $content));
}
I am very new to Laravel and I am trying to fully understand how routes work. I want to pass variables through the URL. I understood how I do that, but my problem is a little different:
routes.php
Route::get("/user/{user}", array(
'as' => 'profile-user',
'uses' => 'ProfileController#user'
));
ProfileController.php
class ProfileController extends BaseController{
public function user($user) {
$user = User::where('username', '=', Session::get('theuser') );
if($user->count()) {
$user = $user->first();
return View::make('layout.profile')
->with('user', $user);
}
return App::abort(404);
}
}
In my View, simply:
{{ $user->username }}
Now my problem: This works somewhat, but after the press of a button, this URL will look something like this:
[this is not a link](http://localhost/tutorial/public/index.php/user/%7Buser%7D)
If I get to edit the URL to something like
[this is not a link](http://localhost/tutorial/public/index.php/user/Serban)
it does the same thing. But I do not wish to manually edit the URL. How can I get the second URL line without editing?
When you are building your form, pass the user argument like this
Form::open(array('route' => array('route-name-for-update', $user->username)))
You may also use Form Model Binding (read more on the doc):
Form::model($user, array('route' => array('user.update', $user->username)))
Here, user.update is the route name that requires a route defined with this name for update method.
Meanwhile, a more interesting approach for me is to do something like this:
Route::group(array('prefix' => 'user/{user}'), function()
{
Route::get("/{char}", array(
'as' => 'profile-user',
'uses' => 'ProfileController#user'));
}
);
Controller:
public function user($user, $char) {
$user = User::where('username', '=', Session::get('theuser') );
$char = Character::where('char_name', '=', 'Cucu' );
if($user->count()) {
$user = $user->first();
$char = $char->first();
return View::make('layout.profile')
->with('user', $user)
->with('char', $char);
}
return App::abort(404);
}
It doesn't seem for me to be able to do something like this at the push of a button
$logged_user = Session::get('theuser');
return Redirect::route('profile-user', $logged_user);
because I can't put 2 parameters in the Redirect function. This code will get the URL
[this is not a link](http://localhost/tutorial/public/index.php/user/SerbanSpire)
which obviously doesn't exist
The correct URL would be
[this is not a link]http://localhost/CaughtMiddle/tutorial/public/index.php/user/SerbanSpire/Cucu)
where SerbanSpire is the $user and Cucu is $char. How can I get the correct URL?
When you link to a route you will need to pass the param to the route like so
{{ route('profile-user', 'Serban') }}