Screenshot of the error page
How do i go about this please? I created another table in my db where i generate OTPs and send to the users. in my table i made user_id and id(primary) but due to the nature of my code and how i want the site to function, i set user_id as a reference of id so that whenever OTP is generated, it will be the current user's ID
It seems there's no default value for user_id so i did ;
UserOTP::create(["user_id"=> auth()->id()]);
but its not working, what is wrong with my code please?
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUserOtpsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('user_otps', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->integer('code');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('user_otps');
}
}
This is the db migration file
It's because you haven't set user_id field in $fillable property. Hence, Laravel ignored provided value for this field when you are using create() method.
However, before using the create method, you will need to specify
either a fillable or guarded property on your model class. These
properties are required because all Eloquent models are protected
against mass assignment vulnerabilities by default.
Related document
protected $fillable = ['code' , 'user_id'];
It's a SQL error not a PHP one. You're trying to insert a new row without a user_id but there's no default value set for that column, so it doesn't know what to set it as.
In your migration class, try giving it a default value:
$table->unsignedBigInteger('user_id')->default(null);
In any case, it also seems like you're not inserting with a user_id, only code, so you need to probably ensure that field can be persisted.
Edit: Yes, now you've posted your model, the problem is you haven't allowed the user_id field to be fillable:
// UserOtp.php
protected $fillable = ['code' , 'user_id'];
Okay so i found it. Instead of keeping the answer to myself, i wanna share to whoever that may have this issue in the future.
so i made a function called rules where i forgot to add user_opts to code .
public function rules()
{
return [
'otpcode' => ['required','numeric',Rule::exists('user_otps','code')->where(function($query){
$query->whereUserId(auth()->id());
})]
];
adding user_otps to code actually solved it and everything is working now. The main problem wasnt this but rather, as the previous answers were saying. My user_id field wasnt receiving a value on submit.
Happy to resolve this issue and thanks to whoever helped
Related
Currently working on a personal project and solving a scenario where on submitting the form a signed URL(action link) is emailed to user, once that link is opened by user and form in that URL is submitted, what I am trying to achieve and facing issue in development is, if anyone again opens that link after submission of form they are shown a screen like which maybe saying your response is submitted. Any hint about that does this kind of functionality is possible to be built with Laravel or which topic I should be searching for that can make me able to understand how to solve such scenarios. Any suggestion or hint would be highly appreciated. Thanks.
This is a common operation in laravel and you can handle this easily with controllers.
The standard way is:
you should create a link and save it on your database. Add a field named isSubmitted . Also, I highly recommend you to have expiration_date field for that link in database.
Create a new migration with artisan using this command:
php artisan make:migration links
Then, add your favorite fileds to migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class LinksTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('links', function (Blueprint $table) {
$table->id();
$table->text("url");
$table->boolean("is_submitted")->default(false);
$table->timestamp("expiration_data")->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('links');
}
}
In next step, when you are submitting that form, in your controller, change the status of isSubmitted field and save it on the database again. On next call of url, you can handle the request according to isSubmitted field
I am trying to query a different table inside my SRC/Model/Table/InspectorsTable.php file within the buildRules() function.
Background info:
Currently, my system uses a User table to store login information. HERE is the model.
This Users table has 3 different profile tables associated with it. Inspectors, Contractors, and Employees.
As of now, an Inspector, Contractor, and Employee record can use the same User foreign key to login.
I am trying to make it so that a single User record, can only use a single record from either Inspector OR Contractor OR Employee to login.
E.g. 1 User Record for 1 Employee Record/Inspector Record/Contractor Record.
I was thinking to do that, I could use the buildRules() function to check the other tables to see if the primary key of Users table is already being used by another table on the creation of an Inspector, Contractor, or Employee. If it is, it will not create the record.
My Attempt:
To try and implement the above logic, I have tried to query one of my other tables (as seen below). However, this is not working.
Here is the SRC/Model/Table/InspectorTables.php:
class InspectorsTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('inspectors');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER',
]);
}
public function buildRules(RulesChecker $rules): RulesChecker
{
$rules->add($rules->existsIn(['user_id'], 'Users'), ['errorField' => 'user_id']);
// this line does not work
print_r($this->Contractor->get(10000000));
return $rules;
}
}
However, I am getting this error when I try to do this:
Undefined property Contractor. You have not defined the Contractor
association on App\Model\Table\InspectorsTable
I believe this is occurring because of the association's setup in the initialize() function of the InspectorsTable.php
Any help/alternative solutions would be great! Thank you!
There is no association between Inspectors and Contractors, hence there's no magic association property that you could access on your InspectorsTable class.
To access "unrelated" tables, use the table locator, for example via the LocatorAwareTrait:
class InspectorsTable extends Table
{
use Cake\ORM\Locator\LocatorAwareTrait;
// ...
public function buildRules(RulesChecker $rules): RulesChecker
{
// ...
$contractorsTable = $this->getTableLocator()->get('Contractors');
return $rules;
}
}
Not sure if your schema is the best solution for your problem domain, so I'm not really going to comment on that, just a note that it looks somewhat unoptimized with all that duplicate fields.
I am coding on Laravel 6, and stumbled up on this problem. I have accessors for a field that i need in my model in some cases, but it does not exist in my database. As i read in documentation, the variable $appends make the field in question to be serialized with the model, but not saved in database.
Then, when i update or save entries of the specific model in database, Laravel gives me back an error saying that field x is not present in field list. I searched here, googled a lot, but didn't found any answer.
This pluggable_data field is not sent by client-side. I create it on server-side because i need its information to do some tasks. But it is not relevant enough to create a column in DB just to store it.
Model
/**
* #var array|null
*/
protected $appends = [
'pluggable_data'
];
/**
* #param array $pluggableData
*/
public function setPluggableDataAttribute(array $pluggableData)
{
$this->attributes['pluggable_data'] = $pluggableData;
}
/**
* #return array
*/
public function getPluggableDataAttribute(): array
{
return $this->attributes['pluggable_data'] ?? []; // Sometimes there is no pluggable data, then i return an empty array
}
Where the error occurs
$activity->setRegisterDate($fields['register_date']);
$activity->setExtraAttribute($fields['extra']);
$activity->update(); <----- Here
return $activity;
The error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'pluggable_data' in 'field list'
Summarizing what i want (in case that you have a better idea): i want a field that will be present in model serializations, even if it is an empty array, but that does not be saved on database.
As #nay said in the comments, all i had to do was to replace the $this->attributes['pluggable_data'] by a real variable, like $this->pluggable_data. This way, Laravel will not think that it is a database column
I have a side project written in PHP that can automatically generate a migration file based on the information from my audit table. Since the file is created by my application without using the artisan command, I have no idea how to make Laravel to see my migration files.
A sample of a migration file my application generated:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class sampleMigration extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('audit_database_index_column_relations', function(Blueprint $table){
$table->integer('relation_id');
$table->integer('database_index_id');
$table->integer('database_column_id');
$table->integer('sequence_position');
$table->integer('is_deleted');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('audit_database_index_column_relations');
}
}
Regarding what I have attempted, I firsly tried to specify the path linking to my migration file. However, it showed an error that is
Symfony\Component\Debug\Exception\FatalThrowableError : Class '' not found
at C:\Users\L0tusw0w\Desktop\Laravel\testProject\vendor\laravel\framework\src\Illumi
nate\Database\Migrations\Migrator.php:448
444| public function resolve($file)
445| {
446| $class = Str::studly(implode('_', array_slice(explode('_', $file), 4)
));
447|
> 448| return new $class;
449| }
450|
451| /**
452| * Get all of the migration files in a given path.
Exception trace:
1 Illuminate\Database\Migrations\Migrator::resolve("sampleMigration")
C:\Users\L0tusw0w\Desktop\Laravel\testProject\vendor\laravel\framework\src\Illum
inate\Database\Migrations\Migrator.php:186
2 Illuminate\Database\Migrations\Migrator::runUp("C:\Users\L0tusw0w\Desktop\Larave
l\testProject/database/migrations/sampleMigration.php")
C:\Users\L0tusw0w\Desktop\Laravel\testProject\vendor\laravel\framework\src\Illum
inate\Database\Migrations\Migrator.php:162
In my second attempt, I replaced the up() function of the default migration "create_user_table" with my up() function as the example, and as I expected, it executed without any problem! In general, I suppose that the error must be from my way of naming the file.
Therefore, I would like to know how I can name my migration file in a way so that Laravel can detect and run them
Thank you in advance!
The error message you're getting when trying to run your migration actually provides the answer you need in this case. The function is using the name of the file to determine what the name of the class for the migration should be. We read chained functions like this from the inside most paranthesis out so starting at the beginning
explode('_', $file)
The method takes the file name and explodes it into an array, splitting on under scores. So
2014_10_12_100000_create_password_resets_table
becomes
[
"2014",
"10",
"12",
"100000",
"create",
"password",
"resets",
"table",
]
Next, the method slices off the first 4 elements of the array. These elements contain a timestamp of when the migration was created, to determine the order to run the migrations, but have nothing to do with the class name
array_slice(explode('_', $file), 4)
So now we have
[
"create",
"password",
"resets",
"table",
]
next the array gets collapsed back into a string, with underscores separating each word
implode('_', array_slice(explode('_', $file), 4))
giving us
create_password_resets_table
And lastly the Laravel Str::studly helper function converts this new string to studly case to determine the class name
Str::studly(implode('_', array_slice(explode('_', $file), 4)));
CreatePasswordResetsTable
So to create a migration file name, start with a timestamp of when you are creating the file, then add the name of the class in all lowercase, separated by underscores.
Class SampleMigration extends Migration
Would be
2019_12_04_37860000_sample_migration
Special note: Don't skip the timestamp or try to throw whatever you want in those first 4 elements. The order that the files appear in the directory is the order the migrations will be run in, the timestamps ensure that migrations are always run in the right order. Skipping this step could cause migrations that change tables to run before the table is created, or changes running out of order and giving you an unexpected result for the current table.
Suppose I have category table and I have used soft delete on it. Now first time I have added one category "Test" after that I have delete this category so it will update my deleted_at column from the database.
Now when again I am trying to add category with name "Test" it is saying me that this name has been taken. I have tried with rules which are posted Here.
But it is not working. I have used trait in my model. Below is my model code.
<?php
namespace App\Models;
use Illuminate\Support\Facades\Validator as Validator;
use Illuminate\Database\Eloquent\SoftDeletingTrait;
class Category extends \Eloquent {
use SoftDeletingTrait;
protected $dates = ['deleted_at'];
/**
* Guarded fields which are not mass fillable
*
* #var array
*/
protected $guarded = array('id');
/**
* Name of the table used
*
* #var string
*/
protected $table = 'travel_categories';
/**
* Validating input.
*
* #param array $input
* #return mixed (boolean | array)
*/
public static function validate($input, $id = null) {
$rules = array(
'name' => array('required','min:2','max:100','regex:/[a-zA-z ]/','unique:travel_categories,name,NULL,id,deleted_at,NULL'),
'description' => 'Required|Min:2',
'image' => 'image'
);
if ($id) {
$rules['name'] = 'Required|Between:3,64|Unique:travel_categories,name,'.$id;
}
$validation = Validator::make($input,$rules);
return ($validation->passes())?true : $validation->messages();
}
}
Did you understand the soft deleting purpose? It will only flag the data to be inactive. It will be there though.
So, if you define the values of that column must be unique, it is right you could not create other one alike.
If it needs to be unique, so you should restore and update the data.
If it can have many ones, so you should remove the unique key applied on it (and call it by relationship for instance).
Look at: Laravel Eloquent Soft Deleting
First: I don't understand a couple of things. Are you trying to validate for create and update? Then why do you allow name to be of length 2 till 100 for creation, and only 3 till 64 for after updates?
Second: I recommend dropping this:
protected $dates = ['deleted_at'];
I don't see the goal of that.
Third, and I'm getting to the point here, what are you trying to do? I guess, what you are trying to do with this filter 'unique:travel_categories,name,NULL,id,deleted_at,NULL' is to check the uniqueness of the name among the active categories. In that case, that should work.
As noted above, a unique index on [category, deleted_at] will not work because when deleted_at is null, many SQL RDBMS will allow multiple records to be inserted despite a unique index existing.
In case anyone is interested I have now created a Laravel extension to handle the SQL unique-index constraints correctly: https://packagist.org/packages/tranzakt/laravel-softdeletesunique
If anyone tries this, please give feedback on Github, thanks.
I know this question is old, but I had a similar issue and I stumbled upon this. I wanted to mention how I fixed it for anyone, who is reading it in the future. The problem I had was that Laravel did not allow me to insert a value in a unique column when there was an old record with the same value, but was deleted using soft_delete.
To summarize, the goal is to ignore old soft deleted records for a unique column when inserting a new record. The solution I found is in the migration for the table. For example, let us assume we have these columns:
category - unique
deleted_at - keeps tracks of the deleted rows
Both should be specified as unique in the migration like so:
Schema::create('table_name', function (Blueprint $table) {
$table->string("category");
$table->softDeletes();
$table->unique(["category", "deleted_at"]);
});
Side note: If you already have the table like I did, you need to change the migration and create the table again (obviously the data will be lost):
Remove the table
Change the migration
Remove the record about it from the migrations table
run "php artisan migrate" to create the table again