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') }}
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.
Here is my action
public function actionUpload()
{
$model=new Sop;
if(isset($_FILES['files'])){
print_r($_POST['name']);exit;
$tmp_name = $_FILES['files']['tmp_name'][0];
$filename = $_FILES['files']['name'][0];
$new_url = Yii::app()->basePath."/docfile/".$filename;
move_uploaded_file($tmp_name, $new_url);
/*if(move_uploaded_file($tmp_name, $new_url)){
//print_r($filename);exit;
echo $filename;
}*/
}
else "error";
}
Now i want to pass $tmp_name , $ filename and $new_url to another action in this controller.
I'm not exactly sure what you are trying to achieve as actions within controllers are designed to be processing requests and generating responses. It seems you are not using the Controller correctly.
If you however insist on using the controller-action you can use the redirect with a parameters as shown in the Documentation here: http://www.yiiframework.com/doc-2.0/yii-web-controller.html#redirect()-detail
An example could be (from inside a controller):
// /index.php?r=site/destination&tmp_name=$tmp_name&new_url=$new_url&filename=$filename
$this->redirect([
'site/destination',
'tmp_name' => $tmp_name,
'new_url' => $new_url,
'filename' => $filename,
]);
Please note that this is far from ideal. I'm not sure what you are trying to achieve but I would suggest using a Component for finishing the upload(?) job instead of sending parameters to a controller-action that finishes it.
You can use $this->forward('action') to execute another action without redirecting to that url:
$params = array(
'tmp_name' => $tmp_name,
'filename' => $filename,
'new_url' => $new_url,
);
$action = $this->createUrl('controller/action', $params);
$this->forward($action);
The other action header could look like this:
public function actionAction($tmp_name, $filename, $new_url)
lets say you want to pass $tmp_name , $filename and $new_url parameters to an action named "next" in same controller, it can be done simply like this,
in your actionUpload() call action next as $this->actionnext($tmp_name , $filename and $new_url).
public function actionUpload()
{
//code for actionupload()
$this->actionnext($tmp_name , $filename , $new_url); //call to next action.
}
in controller, definition of actionnext() should look like this:
public function actionnext($tmp_name , $filename , $new_url)
{
//your code goes here.
}
and in actionnext function defination "$tmp_name , $ filename , $new_url" are just variables so you can use any name here.
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 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.