Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sushi models can relate to non-sushi models #98

Merged

Conversation

amadeann
Copy link
Contributor

In the current version, you cannot have belongsTo relationship from a sushi model to a non-sushi one. The reason behind this is that Laravel assumes the related model is in the same database as the one in which the relation is defined unless you explicitly set the connection name on the related model. With this PR, the default connection is used if the name is not specified.

The first commit adds the failing test, the second one the fix.

@christian-forgacs
Copy link

Any update if and when this pr will merged?

@poxin13
Copy link

poxin13 commented Jan 14, 2022

Dang thank you, I was struggling to figure this out when using Sushi in conjunction with Nova. Kept saying no such table but I was staring right at it!

@bradenkeith
Copy link

In the meantime, adding this to my Model provided the workaround:

    protected function newRelatedInstance($class)
    {
        return tap(new $class, function ($instance) use ($class) {
            if (!$instance->getConnectionName()) {
                $instance->setConnection($this->getConnectionResolver()->getDefaultConnection());
                parent::newRelatedInstance($class);
            }
        });
    }

@bobmulder
Copy link

@calebporzio, can this PR be merged?

@deviationist
Copy link

This should definitely be merged, very useful!

@francoism90
Copy link

francoism90 commented Aug 18, 2023

Anyone know how Sushi would work with a BelongsToMany? :)

I tried adding the provided method, but it results in General error: 1 ambiguous column name.

Edit: fixed by adding https://github.com/staudenmeir/eloquent-json-relations

@CamilleScholtz
Copy link

Is there a reason this is not being merged?

@kritsot
Copy link

kritsot commented Sep 20, 2023

The solution seems to work even with HasMany relationships.
However, unfortunately, this does not seem to work when using withCount

@ziming
Copy link

ziming commented Sep 23, 2023

hoping this can be merged!

@rezakiamanesh
Copy link

rezakiamanesh commented Nov 29, 2023

Hello, I have a model named group with an intermediate table
On the other hand, I have another section called products whose model follows this library
The relationship between grouping and products is many to many, unfortunately this relationship is supposed to be one-way and products grouping is not available, it gives the following result:

@amadeann @calebporzio @bradenkeith

SQLSTATE[HY000]: General error: 1 no such table: group_product (SQL: select "products".*, "group_product"."group_id" as "pivot_group_id", "group_product"."product_id" as "pivot_product_id" from "products" inner join "group_product" on "products"."id" = "group_product"."product_id" where "group_product"."group_id" = 1)

When I use newRelatedInstance it returns empty

`
class Product extends Model
{
use HasCategory, Sushi;
public $incrementing = false;
protected $keyType = 'string';
public $sushiInsertChunkSize = 50;
public $timestamps = false;

protected $schema = [
    'okcs_id' => 'integer',
    'Name' => 'string',
    'Barcode' => 'string',
    'CategoryId' => 'string'
];

// Read Live Data With API
public function getRows()
{
    $products = null;
    $productsArray = array();
    if (!Cache::has('products')) {
        $data = ['objectName' => "WebsiteStoreProductDetails", 'param' => "Null,Null,1,10000", 'ip' => '', 'imei' => '', 'token' => (string)WebServices::$token];
        $webService = new WebServices();
        $productsData = json_decode($webService->requestPost(WebServices::$url, $data));
        if (isset($productsData->result) && !empty($productsData->result)) {
            $products = Cache::remember("products", 86400, function () use ($productsData) {
                return $productsData->result;
            });
        }
    } else {
        $products = Cache::get('products');
    }
    if (isset($products) && !empty($products)){
        foreach ($products as $key => $product){
            $productsArray[$key]=json_decode(json_encode($product), true);
            $productsArray[$key]['id'] = $product->Id;
            $productsArray[$key]['okcs_id'] = (int)$product->Id;
            unset($productsArray[$key]['Id']);
        }
    }
    return $productsArray;
}

protected function sushiShouldCache()
{
    return false;
}

public function category()
{
    return $this->belongsTo(Category::class,'CategoryId','okcs_id');
}

public function groups(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
    return $this->belongsToMany(Group::class);
}

}

class Group extends Model
{
use HasFactory, SoftDeletes, Sluggable,HasCategory;

protected $guarded = [];
protected $dates = ['deleted_at'];
public static $preventAttrSet = false;
public const P_TYPE_PERCENT = 1, P_TYPE_PRICE = 2, P_TYPE_UPTO_PERCENT = 3, P_TYPE_PRICE_AND_PERCENT = 4, P_TYPE_DECLARATION = 5;

public function __construct(array $attributes = [])
{
    parent::__construct($attributes);
    $this->connection = (string)env('DB_CONNECTION');
    $this->table = $this->getTable();
}


public function sluggable():array
{
    return [
        'slug' => [
            'source' => 'title'
        ]
    ];
}

protected static function boot()
{
    parent::boot();
    static::deleting(function ($item) {
        $item->products()->detach();
    });
}

public function user()
{
    return $this->belongsTo(User::class);
}

public function products(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{

// return $this->newRelatedInstance(Product::class)->belongsToMany(Product::class,"group_product",'group_id','product_id','id','okcs_id');
// return $this->newRelatedInstance(Product::class)->belongsToMany(Product::class)->using(GroupProduct::class);
return $this->belongsToMany(Product::class);
}

public function setSlugAttribute($value)
{
    if (empty($value) || $value == "") {
        $this->attributes['slug'] = SlugService::createSlug(__CLASS__, 'slug', $this->title);
    }
    $this->attributes['slug'] = $value;
}

public function getStatusAttribute($value)
{
    if (self::$preventAttrSet == false) {
        $status = Status::getStatus($value, 1, $this);
        return $status;
    }
    return $value;
}

public function getTypeAttribute($value)
{
    if (self::$preventAttrSet == false) {
        return self::typeEach()[$value];
    }
    return $value;
}

public static function typeEach()
{
    return [
        self::P_TYPE_PERCENT => 'درصد',
        self::P_TYPE_PRICE => 'قیمت',
        self::P_TYPE_UPTO_PERCENT => 'تا درصد',
        self::P_TYPE_PRICE_AND_PERCENT => 'قیمت و درصد',
        self::P_TYPE_DECLARATION => 'اعلام',
    ];
}

public static function getTableName()
{
    return (new self())->getTable();
}

}

`

@Pab89
Copy link

Pab89 commented Dec 22, 2023

Same problem here

The

protected function newRelatedInstance($class)
    {
        return tap(new $class, function ($instance) use ($class) {
            if (!$instance->getConnectionName()) {
                $instance->setConnection($this->getConnectionResolver()->getDefaultConnection());
                parent::newRelatedInstance($class);
            }
        });
    }

Fixes it for me. :) But would be great if it could be merged or some alternative

@calebporzio
Copy link
Owner

Thanks!

@calebporzio calebporzio merged commit e7ce22a into calebporzio:main Jan 21, 2024
@francoism90
Copy link

@calebporzio Could you also create a new release? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet