i am testing a form. Upon success it must redirect to a route.
Here is the route excerpt
<?php
Route::group(array('prefix'=>'categories'), function(){
Route::get('/', array('as'=>'categories', 'uses'=>'CategoryController#getCategory'));
Route::get('addcategory',array('as'=>'getcategoryform', 'uses'=>'CategoryController#getCategoryForm'));
Route::post('addcategory', array('as'=>'postcategoryform', 'uses' => 'CategoryController#postCategoryForm'));
});
This is the controller
class CategoryController extends BaseController {
// adding Category model instance in the controller through the constructor
public function __construct(Category $category){
$this->category = $category;
}
public function getCategoryForm(){
return View::make('dashboard.addcategoryform');
}
public function postCategoryForm(){
$rules = ['category_name' => 'required|between:3,20', 'options' =>'required'];
$validator = Validator::make(Input::all(), $rules);
if($validator->passes()){
$category = new Category;
$category->category_name = Input::get('category_name');
$category->options = Input::get('options');
$category->save();
Session::flash('message', 'Category Added Successfully');
return Redirect::route('categories');
}else return Redirect::route('getcategoryform')->withErrors($validator);
}
here's the view
#extends('layouts.main')
#section('content')
<div class="g12">
<h1>Add Category</h1>
{{Form::open(array('route'=>'postcategoryform'))}}
{{ Form::text('category_name', Input::old('category_name'), array('placeholder' => 'eg article') )}}
<textarea id="textarea_auto" name="options" value="Input::old('options')" placeholder="eg. author, facts, tags, reference, book"></textarea>
{{Form::submit('Add')}}
{{Form::close()}}
</div>
#stop
This is the test that i tried:
public function testPassedPostCategoryForm(){
Input::replace(['category_name' => 'dummycat', 'options' => 'dummyoption']);
$this->mock
->shouldReceive('create')
->once();
$this->app->instance('Category', $this->mock);
$this->call('POST', 'categories/addcategory');
$this->assertRedirectedToRoute('categories');
}
The test is failing. This is the error i'm, receiving:
There was 1 failure:
1) CategoryControllerTest::testPassedPostCategoryForm
Failed asserting that two strings are equal.
--- Expected
+++ Actual
## ##
-'http://localhost/categories'
+'http://localhost/categories/addcategory'
In your code, the validator is not passed.
So the redirect back to http://localhost/categories leads to fail result.
It goes well if you delete the validator, and simply return such that
public function postCategoryForm(){
$rules = ['category_name' => 'required|between:3,20', 'options' =>'required'];
$validator = Validator::make(Input::all(), $rules);
return Redirect::route('categories');
}
Or you can rewrite the test code as follows,
$this->call('POST', 'categories/addcategory', array( 'category_name'=> 'dummycat' ,
'options' => 'dummyoption'));
or
$this->route('POST','getcategoryform',array( 'category_name'=> 'dummycat' ,
'options' => 'dummyoption'));
instead of
$this->call('POST', 'categories/addcategory');
[Edit] Further, delete followings
$this->mock
->shouldReceive('create')
->once();
,because the 'create' method is not called in the controller.
Related
I want to redirect to my new post when I created a new post in Laravel
But I get a ArgumentCountError
Too few arguments to function App\Http\Controllers\ArticlesController::store(), 1 passed in C:\xampp\htdocs\forum\vendor\laravel\framework\src\Illuminate\Routing\Controller.php on line 54 and exactly 2 expected
How can I fix it? Thanks
web.php
<?php
Route::resource('articles', ArticlesController::class);
Route::get('/', [ArticlesController::class, 'index'])->name('root');
Route::resource('articles.comments', CommentsController::class);
ArticlesController.php
public function store(Request $request, $id) {
$content = $request->validate([
'title' => 'required|max:30',
'content' => 'required|min:10'
]);
//限制只有透過登入才能CREATE文章
auth()->user()->articles()->create($content);
return redirect('articles/'. $id)->with('notice', '文章發表成功!');
}
create.blade.php
<form class="container-fluid" action="{{ route('articles.store') }}" method="post">
Check your store() method. I think it should get only Request $request.
Example
public function store(Request $request) {
$content = $request->validate([
'title' => 'required|max:30',
'content' => 'required|min:10'
]);
//限制只有透過登入才能CREATE文章
$article = Article::create($content); // static is not best practice, only for example
return redirect('articles/'. $article->id)->with('notice', '文章發表成功!');
}
But before using the create method, you will need to specify either a fillable or guarded. Check docs
Presumably you need / have a way of viewing an article anyway, whether it's just been added or not, so in your web.php you would want a GET request to retrieve an article by passing its ID:
Route::get('/article/{id}', [ArticleController::class, 'viewArticle'])-> name('article.view');
Then you would want a POST request to add a new article :
Route::post('/addarticle', [ArticleController::class, 'addArticle'])-> name('article.add');
In your ArticleController, at the end of your addArticle method, once your new article has been created, you can then return a redirect to your "view article" route referencing its name, and passing in the parameter that it expects - the new article's ID - as part of the route, like so :
$article = new Article();
... populate the article's details here ...
return redirect()->route('article.view', ['id' => $article->id]);
I already solved it by my way
remove $id from store() function
just add $article before auth()->user()->articles()->create($content)
$id change to $article->id from redirect()
Example
public function store(Request $request) {
$content = $request->validate([
'title' => 'required|max:30',
'content' => 'required|min:10'
]);
$article = auth()->user()->articles()->create($content);
return redirect('articles/'. $article->id)->with('notice', '文章發表成功!');
}
Thank you
i am new to laravel.Here i have a form where i have to fill up a name field and send it to controllers store() method for validation. Otherwise it will show custom error.But whenever i submit the form with or without input i am getting the following error.
Argument 1 passed to Illuminate\Validation\Factory::make() must be of
the type array, string given, called in
C:\xampp\htdocs\mylaravel\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php
on line 221 and defined
for experiment purpose i am catching the user input using the following format
$data = $request->input('name');
create.blade.php:
<h1>login form</h1>
#if($errors->has())
<div><span> Opps !! </span></br>
<ul>
#foreach ($errors->all() as $error)
<li> {{ $error }}</li>
#endforeach
</ul>
</div>
#endif
{!!Form::open(array('url'=>'user','method'=>'POST', 'files'=>true)) !!}
{!!Form::label('name','Your name')!!}
{!!Form::text('name')!!}
</br>
{!!Form::submit('submit')!!}
{!!Form::close()!!}
store() method in userController.php file:
public function store(Request $request)
{
//
$data = $request->input('name');
$rules = array(
'name' => 'unique:users,name|required|alpha_num'
);
// Create a new validator instance.
$validator = Validator::make($data, $rules);
if($validator->fails()){
$errors=$validator->messages();
return Redirect::route('user.create')->withErrors($validator);
}else{
return Redirect::route('user.index');
}
}
}
According to your error,Validator expects it parameters to be array, but you are passing a string there as $data= $request->input('name') . So, you should pass array in Validator::make() . Below code should work for you.
$validator = Validator::make($request->all(), [
'name' => 'unique:users,name|required|alpha_num'
]);
Here is the doc if you want to explore more .
You need to pass array inside Validator::make.
Right now your are passing string in the form of $data variable.
For example :
$validator = Validator::make(
array('name' => 'Dayle'),
array('name' => 'required|min:5')
);
DOCS : https://laravel.com/docs/4.2/validation
you have pass your params as array in validation,so your code will be
public function store(Request $request)
{
//
$data = $request->all();
$rules = array(
'name' => 'unique:users,name|required|alpha_num'
);
// Create a new validator instance.
$validator = Validator::make($data, $rules);
if($validator->fails()){
$errors=$validator->messages();
return Redirect::route('user.create')->withErrors($validator);
}else{
return Redirect::route('user.index');
}
}
}
Using Yii 2.0 i'm trying to grab some $_POST values in my controller from my view but cannot do this. I will show you my code and talk you through it below.
Models/CaseSearch.php
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Cases;
/**
* CaseSearch represents the model behind the search form about `app\models\Cases`.
*/
class CaseSearch extends Cases
{
public $category;
public $subcategory;
public $childcategory;
public $newcategory;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['case_id', 'year'], 'integer'],
[['name', 'judgement_date', 'neutral_citation', 'all_ER', 'building_law_R', 'const_law_R', 'const_law_J', 'CILL', 'adj_LR'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = Cases::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
$query->andFilterWhere([
'case_id' => $this->case_id,
'judgement_date' => $this->judgement_date,
'year' => $this->year,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'neutral_citation', $this->neutral_citation])
->andFilterWhere(['like', 'all_ER', $this->all_ER])
->andFilterWhere(['like', 'building_law_R', $this->building_law_R])
->andFilterWhere(['like', 'const_law_R', $this->const_law_R])
->andFilterWhere(['like', 'const_law_J', $this->const_law_J])
->andFilterWhere(['like', 'CILL', $this->CILL])
->andFilterWhere(['like', 'adj_LR', $this->adj_LR]);
return $dataProvider;
}
public function searchByCategory($category){
$query = Cases::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
if (!$this->validate()) {
// uncomment the following line if you do not want to any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
$query->andFilterWhere([
'category_id' => $category
]);
return $dataProvider;
}
}
Okay so now is my view:
<?php
$form = ActiveForm::begin();
echo $form->field($searchModel, 'category')
->dropDownList(
ArrayHelper::map($allCategory, 'id', 'name'),
[
'onchange'=>'getSubcategory()',
]
);
//To stop errors, if first category not chosen make subcategory and empty drop down.
$subcategory = array(
"empty" => ""
);
echo $form->field($searchModel, 'subcategory')
->dropDownList(
ArrayHelper::map($subcategory, 'id', 'name'),
[
'onchange'=>'getChildcategory()',
]
);
//To stop errors, if second category not chosen make childcategory and empty drop down.
$childcategory = array(
"empty" => ""
);
echo $form->field($searchModel, 'childcategory')
->dropDownList(
ArrayHelper::map($childcategory, 'id', 'name'),
[
//'onchange'=>'getChildCategory()',
'onchange'=>'submitNow()',
]
);
echo '<div class="form-group">';
echo Html::submitButton('Submit', ['class' => 'btn btn-primary']);
echo '</div>';
ActiveForm::end();
Ok, so when i click the submit button i want to capture the value in my controller so that i can use this to alter the results given in the gridview.
When i inspect the element on the drop down lists the names are weird so i am not sure if this is making a different. for example the name for subcategory is actually: CaseSearch[subcategory]
Now for my controller:
public function actionIndex()
{
//
// This is for the first render of index
//
$model = new Cases;
$searchModel = new CaseSearch();
$allCategory = Category::find()->all();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
//
// This is for when i click the submit button on the view. I want it to submit and then grab the subcategory in variable $subtest. I make $subtest = 1 so that when i first render the page it doesn't throw an error and when submitted it should change to the post value
//
$subtest = 1;
if($searchModel->load(Yii::$app->request->post())){
$subtest = $_POST['subcategory'];
}
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'allCategory' => $allCategory,
'model' => $model,
'subtest' => $subtest
]);
}
However when i try to print_r() the variable $subtest in my view i get the error:
Undefined index: CaseSearch[subcategory]
and its for the line:
$subtest = $_POST['CaseSearch[subcategory]'];
In my controller.
Can anyone please advise as i cannot figure out why?
I think your application design is improvable. Read the Yii guide.
However I think the solution to the question is:
$subtest = $_POST['CaseSearch']['subcategory];
Don't use $_GETand $_POST directly in your controller there are some abstraction layer which filter that input.
$get = $request->get();
// equivalent to: $get = $_GET;
$post = $request->post();
// equivalent to: $post = $_POST;
You should use that classes and methods to get your params.
http://www.yiiframework.com/doc-2.0/guide-runtime-requests.html
Following are my codes:
Model:
class Slide extends \Eloquent {
// Add your validation rules here
public static $rules = [
'title' => 'required|between:3,100',
'image' => 'required',
'url' => 'url',
'active' => 'integer'
];
// Don't forget to fill this array
protected $fillable = ['title', 'image', 'url', 'active'];
}
Controller Update Method:
public function update($id)
{
$slide = Slide::find($id);
$validator = Validator::make($data = Input::all(), Slide::$rules);
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
$slide->update($data);
return Redirect::route('admin.slides.index')
->with('message', 'Slide has been updated.')
->with('message-type', 'alert-success');
}
Route:
Route::group(array('prefix' => 'admin'), function() {
# Slides Management
Route::resource('slides', 'AdminSlidesController', array('except' => array('show')));
});
Form in View:
{{ Form::model($slide, array('route' => 'admin.slides.update', $slide->id, 'method' => 'put')) }}
#include('admin/slides/partials/form')
{{ Form::close() }}
Partial Form is simple form, not sure if I need to share it here or not. Let me know.
Error:
Edit page loads perfectly and populates data from db, but when I submit the edit form, I get following error:
Call to a member function update() on a non-object
The following line seems to be creating problems:
$slide->update($data);
I have searched over the internet for solution but nothing is working. Have tried composer dump_autoload, even tried doing everything from scratch in a new project, still same issue. :(
Help please!!
---- Edit ----
Just quickly tried following:
public function update($id)
{
$slide = Slide::find($id);
$slide->title = Input::get('title');
$slide->save();
return Redirect::route('admin.slides.index')
->with('message', 'Slide has been updated.')
->with('message-type', 'alert-success');
}
Now the error:
Creating default object from empty value
----- Solution: -----
The problem was with my form as suggested by #lukasgeiter
I changed my form to following at it worked like a charm:
{{ Form::model($slide, array('route' => array('admin.slides.update', $slide->id), 'method' => 'put')) }}
use $slide->save(); instead of $slide->update($data);
to update a model please read the laravel doc here
To update a model, you may retrieve it, change an attribute, and use the save method:
EX :
$user = User::find(1);
$user->email = 'john#foo.com';
$user->save();
The actual problem is not your controller but your form.
It should be this instead:
{{ Form::model($slide, array('route' => array('admin.slides.update', $slide->id), 'method' => 'put')) }}
This mistake causes the controller to receive no id. Then find() yields no result and returns null.
I recommend besides fixing the form you also use findOrFail() which will throw a ModelNotFoundException if no record is found.
$slide = Slide::findOrFail($id);
I am trying to modify a form used for editing and updating data. However when I try submitting the 'edit' form, I keep getting a 'MethodNotAllowedHttpException'. I'm not sure if this is because I am using the 'PUT' method incorrectly or my 'EditAlbumsController.php' file is not defined correctly.
edit-album.blade.php:
{{ Form::model($album, array('method' => 'PUT', 'route' => array('edit_album', $album->album_id))) }}
/* Form code here */
{{ Form::close() }}
routes.php:
Route::get('gallery/album/{id}/edit', array('as'=>'edit_album', 'uses'=>'EditAlbumsController#update'));
EditAlbumsController.php:
class EditAlbumsController extends AlbumsController {
public function __construct()
{
parent::__construct();
}
public function update($id)
{
$input = \Input::except('_method');
$validation = new Validators\Album($input);
if ($validation->passes())
{
$album = Album::find($id);
$album->album_name = $input['album_name'];
/* Additional database fields go here */
$album->touch();
return $album->save();
return \Redirect::route('gallery.album.show', array('id' => $id));
}
else
{
return \Redirect::route('gallery.album.edit', array('id' => $id))
->withInput()
->withErrors($validation->errors)
->with('message', \Lang::get('gallery::gallery.errors'));
}
}
Any help is greatly appreciated!
You need to define the PUT route (you are incorrectly using GET)
Route::put('gallery/album/{id}/edit', array('as'=>'edit_album', 'uses'=>'EditAlbumsController#update'));