为什么Eloquent在插入数据库时没有看到模型中的所有字段
I'm new to Laravel development and am trying to create an Eloquent model backed by an SQLite database. I have the following code on my local development server, which correctly takes a request, builds a model, and saves that model as a row in the callback_requests table.
Below is the model definition file and the database migration file. I've run the migration using
php artisan migrate:reset --force
php artisan migrate
CallbackRequest.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CallbackRequest extends Model
{
public $name;
public $phone;
public $email;
public $preferredTime;
}
create_callback_requests_table (migration).php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCallbackRequestsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('callback_requests', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('phone');
$table->string('email');
$table->string('preferredTime');
$table->string('name');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('callback_requests');
}
}
This is the controller file where I create a new instance of my model, populate it with values from an incoming request, and save it to the DB.
MailController.php
namespace App\Http\Controllers;
use App\Models\CallbackRequest;
use App\Mail\CallbackRequestMailable;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Mail\Mailable;
use Illuminate\Support\Facades\Mail;
class MailController extends Controller
{
public function send(Request $request)
{
$cbReq = new CallbackRequest();
$cbReq->name = $request->get('name');
$cbReq->email = $request->get('email');
$cbReq->phone = $request->get('phone');
$cbReq->preferredTime = $request->get('preferredTime');
var_dump($cbReq);
// save the entity to the database in case mail gets lost in transit
$cbReq->save();
// send an email to the address configured in the .env file
$result = Mail::to(env("MAIL_CALLBACK_DELIVERY_ADDRESS"))->send(new CallbackRequestMailable($cbReq));
}
}
I've dumped the contents of the $cbReq variable to make sure that values have been added correctly, and the output I get (shown below) suggests that they have
object(App\Models\CallbackRequest)#222 (30) {
["name"]=>
string(13) "Customer Name"
["phone"]=>
string(9) "012345678"
["email"]=>
string(14) "cust@email.com"
["preferredTime"]=>
string(7) "morning"
["connection":protected]=>
NULL
["table":protected]=>
NULL
["primaryKey":protected]=>
string(2) "id"
["keyType":protected]=>
string(3) "int"
["incrementing"]=>
bool(true)
["with":protected]=>
array(0) {
}
["withCount":protected]=>
array(0) {
}
["perPage":protected]=>
int(15)
["exists"]=>
bool(false)
["wasRecentlyCreated"]=>
bool(false)
["attributes":protected]=>
array(0) {
}
["original":protected]=>
array(0) {
}
["changes":protected]=>
array(0) {
}
["casts":protected]=>
array(0) {
}
["dates":protected]=>
array(0) {
}
["dateFormat":protected]=>
NULL
["appends":protected]=>
array(0) {
}
["dispatchesEvents":protected]=>
array(0) {
}
["observables":protected]=>
array(0) {
}
["relations":protected]=>
array(0) {
}
["touches":protected]=>
array(0) {
}
["timestamps"]=>
bool(true)
["hidden":protected]=>
array(0) {
}
["visible":protected]=>
array(0) {
}
["fillable":protected]=>
array(0) {
}
["guarded":protected]=>
array(1) {
[0]=>
string(1) "*"
}
}
However, when the app encounters an error on save giving the following message.
{
"message": "SQLSTATE[HY000]: General error: 1364 Field 'phone' doesn't have a default value (SQL: insert into `callback_requests` (`updated_at`, `created_at`) values (2019-03-11 10:19:24, 2019-03-11 10:19:24))",
"exception": "Illuminate\\Database\\QueryException",
...
}
It looks from the error message as if Eloquent doesn't know about the custom columns, and is trying to populate only the auto-increment ID and timestamp. Strangely, when I run this same code on my local server, everything works OK, it's only when the code is deployed to a testing server that I'm encountering the error.
Apologies for the lengthy question, I've tried to include as little as possible while not omitting anything relevant. Any suggestions would be greatly appreciated.
You need to delete your properties from the model. So delete all of these:
public $name;
public $phone;
public $email;
public $preferredTime;
Otherwise when you set $model->phone = $request->phone
, it sets this property on your object instead of setting the key in the model's $attributes
array, which is what gets saved to the database.
This is due to Laravel hooking the PHP magic method __set()
to set attributes of models. This is what's inside the base Model class:
/**
* Dynamically set attributes on the model.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function __set($key, $value)
{
$this->setAttribute($key, $value);
}
If you had those properties for your IDE's IntelliSense (auto completion), you can still use a docblock to hint the dynamic properties:
/**
* Class CallbackRequest
*
* @property-read string name
* @property-read string phone
* @property-read string email
* @property-read string preferredTime
*/
class CallbackRequest extends Model {}
or use a package like Laravel IDE helper to automate this step.