I am making a blogging application with Laravel 8 and Bootstrap 5.
I run into a problem with adding an article into the articles
table.
In the migration file that generated the articles
table, I have:
public function up() {
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
$table->unsignedInteger('category_id');
$table->foreign('category_id')->references('id')->on('catergories');
$table->string('title');
$table->string('slug');
$table->string('short_description');
$table->longText('content');
$table->tinyInteger('featured')->default('0');
$table->string('image')->nullable();
$table->timestamps();
});
}
In the Article
model, I have:
class Article extends Model {
use HasFactory;
protected $fillable = [
'user_id',
'category_id',
'title',
'slug',
'short_description',
'content',
'featured',
'image',
];
// Join users to articles
public function user() {
return $this->belongsTo(User::class);
}
// Join categories to articles
public function category() {
return $this->belongsTo(ArticleCategory::class);
}
}
In the controller, I have:
namespace App\Http\Controllers\Dashboard;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Models\ArticleCategory;
use App\Models\Article;
use Illuminate\Http\Request;
class ArticleController extends Controller {
private $rules = [
'category_id' => 'required|exists:article_categories,id',
'title' => 'required|string|max:255',
'short_description' => 'required|string|max:255',
'image' => 'image|mimes:jpeg,png,jpg|max:2048',
'content' => 'required|string',
'featured' => 'required'
];
private $messages = [
'category_id.required' => 'Please pick a category for the article',
'title.required' => 'Please provide a title for the article',
'short_description.required' => 'The article needs a short description',
'content.required' => 'Please add content'
];
public function categories() {
return ArticleCategory::all();
}
public function index() {
$articles = Article::paginate(10);
return view('dashboard/articles',
['articles' => $articles]
);
}
public function create() {
// Load the view and populate the form with categories
return view('dashboard/add-article',
['categories' => $this->categories()]
);
}
public function save(Request $request) {
// Validate form (with custom messages)
$validator = Validator::make($request->all(), $this->rules, $this->messages);
if ($validator->fails()) {
return redirect()->back()->withErrors($validator->errors())->withInput();
}
$fields = $validator->validated();
// Upload article image
$current_user = Auth::user();
if (isset($request->image)) {
$imageName = md5(time()) . $current_user->id . '.' . $request->image->extension();
$request->image->move(public_path('images/articles'), $imageName);
}
// Data to be added
$form_data = [
'user_id' => Auth::user()->id,
'category_id' => $fields['category_id'],
'title' => $fields['title'],
'slug' => Str::slug($fields['title'], '-'),
'short_description' => $fields['short_description'],
'content' => $fields['content'],
'image' => $fields['image'],
'featured' => $fields['featured']
];
// Insert data in the 'articles' table
$query = Article::create($form_data);
if ($query) {
return redirect()->route('dashboard.articles')->with('success', 'Article added');
} else {
return redirect()->back()->with('error', 'Adding article failed');
}
}
}
The form:
<form method="POST" action="{{ route('dashboard.articles.add') }}" enctype="multipart/form-data" novalidate>
@csrf
<div >
<label for="title" >{{ __('Title') }}</label>
<div >
<input id="title" type="text" placeholder="Title" name="title" value="{{ old('title') }}" autocomplete="title" autofocus>
@error('title')
<span role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div >
<label for="short_description" >{{ __('Short description') }}</label>
<div >
<input id="short_description" type="text" placeholder="Short description" name="short_description" value="{{ old('short_description') }}" autocomplete="short_description" autofocus>
@error('short_description')
<span role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div >
<label for="category" >{{ __('Category') }}</label>
<div >
<select name="category_id" id="category" >
<option value="0">Pick a category</option>
@foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
@endforeach
</select>
@error('category_id')
<span role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div >
<div >
<p >Featured article?</p>
<input type="checkbox" name="featured" id="featured">
<label for="featured">{{ __('Toggle') }}</label>
</div>
</div>
<div >
<label for="image" >{{ __('Article image') }}</label>
<div >
<input type="file" name="image" id="file" >
@error('image')
<span role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div >
<label for="content" >{{ __('Content') }}</label>
<div >
<textarea name="content" id="content" placeholder="Content" cols="30" rows="6">{{ old('content') }}</textarea>
@error('content')
<span role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div >
<div >
<button type="submit" >
{{ __('Save') }}
</button>
</div>
</div>
</form>
The routes:
// Article routes
Route::group(['prefix' => 'articles'], function() {
Route::get('/', [ArticleController::class, 'index'])->name('dashboard.articles');
Route::get('/new', [ArticleController::class, 'create'])->name('dashboard.articles.new');
Route::post('/add', [ArticleController::class, 'save'])->name('dashboard.articles.add');
});
The problem:
Even though the form passes validation, and a redirect occurs, the record is not actually added to the articles
table.
Laravel throws the error General error: 1366 Incorrect integer value: 'on' for column 'featured' at row 1
.
What is my mistake?
CodePudding user response:
When dealing with checkboxes you need to know that;
a) you cannot use required
since the checkbox is not sent with the form data if it is unchecked.
b) the default value is 'on' but actually, the presence of the field in the data means it was checked so what I normally do is like;
'featured' => $request->has('featured')
this will return a boolean true or false, suitable for storing in your db
CodePudding user response:
Your column is defined as a tinyInteger
that can only accept a single digit, but you seem to be passing a string on
to it.
$table->tinyInteger('featured')->default('0');
General error: 1366 Incorrect integer value: 'on' for column 'featured' at row 1
Try setting the value of your checkbox to 1
.
<input type="checkbox" name="featured" id="featured" value="1">
Edit, make sure to add boolean
to your validation rules after adding the value to your input element.
private $rules = [
'category_id' => 'required|exists:article_categories,id',
'title' => 'required|string|max:255',
'short_description' => 'required|string|max:255',
'image' => 'image|mimes:jpeg,png,jpg|max:2048',
'content' => 'required|string',
'featured' => 'required|boolean'
];