hasManyJson, multiple foreign keys
Intrflex opened this issue · 16 comments
I was wondering if its possible to add in many foreign keys for an example ['email[]->to', email[]->from]
?
if so is it something that would be easy to implement
Can you share your use case with some sample data?
Is it an OR
constraint where the email address needs to be in email[]->to
or email[]->from
?
Can you share your use case with some sample data?
Is it an
OR
constraint where the email address needs to be inemail[]->to
oremail[]->from
?
I have a table contacts with an email column, I then have an inbound email table with 2 columns to & from both of which are JSON for example {"name": "intrflex", "email": "help@intrflex.com"
i need to be able to do a HasManyJson to the 2 email fields to & from where the email is either the recipient or the receiver
but essentially yes its an OR
constraint new to this, unfortunately, its either going to be from the person or to the person
The package itself doesn't support that, but you can use one of my other packages:
https://github.com/staudenmeir/laravel-merged-relations
Create two HasManyJson
relationships (one for to
and one for from
) and combine them with mergedRelationWithModel()
.
I know this will work with the from column as that's only a JSON object, however, the to column is a JSON array? will this package still work
it returns the following error PDOException::("SQLSTATE[42S22]: Column not found: 1054 Unknown column 'inbound_emails.to[]' in 'field list'"
I'll look into it.
Thankyou, really trying to get this to work
What version of MySQL/MariaDB are you using?
10.4.13-MariaDB
public function mailTo(): HasManyJson
{
return $this->hasManyJson(InboundEmail::class, 'to[]->email' , 'email')->where('public', 1);
}
public function mailFrom(): HasManyJson
{
return $this->hasManyJson(InboundEmail::class, 'from->email', 'email')->where('public', 1);
}
thats both my relationships
and this is my schema
Schema::createMergeView('emailables', [(new Contact)->mailTo(), (new Contact)->mailFrom()]);
You're right, JSON array don't work out of the box. I see two options:
-
You extend the
HasManyJson
relationship in your project and add support for multiple foreign keys. Depending on your use case, this will take a while. -
You use the
laravel-merged-relations
package, but create the view manually (you need to add the rest of your columns):
$view = <<<EOT
CREATE VIEW `emailables` AS
WITH RECURSIVE `to_emails` AS
(SELECT *,
-1 AS `i`
FROM `inbound_emails`
UNION SELECT `inbound_emails`.*,
`to_emails`.`i` + 1
FROM `inbound_emails`
JOIN `to_emails` ON `inbound_emails`.`id`=`to_emails`.`id`
WHERE `to_emails`.`i` < JSON_LENGTH(`inbound_emails`.`to`) - 1 )
(SELECT *, JSON_UNQUOTE(JSON_EXTRACT(`inbound_emails`.`from`, '$."email"')) AS `laravel_foreign_key`,
'App\\\\Models\\\\InboundEmail' AS `laravel_model`,
'' AS `laravel_placeholders`,
'' AS `laravel_with`
FROM `inbound_emails`
WHERE `public` = 1 )
UNION
(SELECT `id`,
`to`,
`from`,
`public`,
JSON_UNQUOTE(JSON_EXTRACT(`to`, CONCAT('$[', `i`, '].email'))) `laravel_foreign_id`,
'App\\\\Models\\\\InboundEmail' AS `laravel_model`,
'' AS `laravel_placeholders`,
'' AS `laravel_with`
FROM `to_emails`
WHERE `public` = 1
AND `i` >= 0 );
EOT;
DB::statement($view);
Then you can create the merged relationship:
class Contact extends Model
{
use HasMergedRelationships;
public function emailables(): MergedRelation
{
return $this->mergedRelationWithModel(InboundEmail::class, 'emailables', 'email');
}
}
- id
- user_id
- public
- email_id
- message_id
- thread_id
- from
- to
- cc
- subject
- email_date
- message
- labels
- snippet
- deleted_at
- created_at
- updated_at
MySQL queries arent really my speciality, i dont even really understand where id add my other columns in ive included my database columns
- id
- user_id
- public
- email_id
- message_id
- thread_id
- from
- to
- cc
- subject
- email_date
- message
- labels
- snippet
- deleted_at
- created_at
- updated_at
MySQL queries arent really my speciality, i dont even really understand where id add my other columns in I've included my database columns
Okay scrap that message i worked it out but, Holy that query takes forever to run it doesn't even complete on a table of 20000 emails laravel returns a 504 time out
Just an update, I worked out a temporary fix, I've extended your MergedRelation swapped out the query so it searches for a foreign key like the email i'm trying to find, hopefully one day this package can support multiple foreign keys i found another packaged that merged yours with compoships but unfortunately the functionality i needed was released in the packages it used
Can you share the code of your solution for others?