I have identified a validation issue in the controller.
The problem looks like this if you specify a connection in the model, and create validation in the controller. In the validation, specify unique columns, then the model is connected as by default.
My code snippets.
Model
protected $connection = 'api';
protected $table = 'pages';
protected $fillable = [
'name', 'title', 'description',
'keywords', 'slug', 'content', 'status',
'sort', 'type'
];
public function sluggable(): array
{
return [
'slug' => [
'source' => 'title'
]
];
}
Controller (resource)
public function store(PagesRequest $request)
{
Pages::create($request->all());
return view('pages.pages.index', [
'pages' => Pages::orderBy('id', 'desc')->paginate(30)
])->with(['success' => true]);
}
PagesRequest
public function rules()
{
return [
'name' => 'required|string|min:5|max:255|unique:pages,name,'.@$this->page->id,
'title' => 'required|string|min:5|max:255|unique:pages,title,'.@$this->page->id,
'description' => 'required|string|min:5|max:255',
'keywords' => 'required|string|min:5|max:255',
'slug' => 'unique:pages,slug,'.@$this->page->id
];
}
As I understand it, in the rules method there is a request to the unique: pages
database and here the model already works not through the connection, but through the default connection.
If I remove checks for "unique", then everything works.
PagesRequest
public function rules()
{
return [
//'name' => 'required|string|min:5|max:255|unique:pages,name,'.@$this->page->id,
//'title' => 'required|string|min:5|max:255|unique:pages,title,'.@$this->page->id,
'description' => 'required|string|min:5|max:255',
'keywords' => 'required|string|min:5|max:255',
//'slug' => 'unique:pages,slug,'.@$this->page->id
];
}
Is there any solution in this situation?
2
Answers
If you are not sure, you can create an issue on the offical repository.
I never faced this issue because I did not have this problem, but let me show you how to check if you are right or not, and then what can you do to solve it.
First, go to the source code, as you did not specify which version you are using the steps are the same but you will have to check it on that version.
So,
validateUnique
is the rule you are using, as you can see the rule is very simple, andparseTable
is the one responsible for parsing what table you want and what connection.I will copy paste what that method does so we can quickly understand how is the connection get:
.
), it will either store a connection name (as a string) or storenull
on$connection
.): if it is able to resolve the table using
str_contains($table, '\') && ... && is_a($table, Model::class, true)
, it will execute$connection ??= $model->getConnectionName();
and use that connection. Using??=
means exactly$connection = $connection ?? $model->getConnectionName();
(that means that if$connection
is notnull
, it will use that value, else executegetConnectionName()
. To pass a "namespace", you must useClassName::class
, that will return a FQDN (Fully Qualified Domain Name ->SomethingInANamespaceClass
->AppModelsClass
)More info here about
??=
.So, possible solutions:
'slug' => 'unique:'.Model::class.',slug,'.@$this->page->id
Rule
class:'slug' => [Rule::unique(Model::class, 'slug')->ignoreModel(@$this->page)]
One quick tip, I think you are using
@
to silence exceptions when you ask for@$this->page->id
, don’t ever do that, never EVER use@
(at least if you are using a framework), you should literally catch the exception and "resolve it" when able or just let it go to the top, you don’t have a value forpage
in$this->page->id
, then accessing->id
MUST throw an exception, the code is just going to be very confusing if you use@