GithubHelp home page GithubHelp logo

topclaudy / compoships Goto Github PK

View Code? Open in Web Editor NEW
1.1K 14.0 127.0 252 KB

Multi-columns relationships for Laravel's Eloquent ORM

License: MIT License

PHP 100.00%
laravel composite-keys relationships eloquent multi-columns multi-keys

compoships's Introduction

Compoships

Compoships offers the ability to specify relationships based on two (or more) columns in Laravel's Eloquent ORM. The need to match multiple columns in the definition of an Eloquent relationship often arises when working with third party or pre existing schema/database.

The problem

Eloquent doesn't support composite keys. As a consequence, there is no way to define a relationship from one model to another by matching more than one column. Trying to use where clauses (like in the example below) won't work when eager loading the relationship because at the time the relationship is processed $this->team_id is null.

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function tasks()
    {
        //WON'T WORK WITH EAGER LOADING!!!
        return $this->hasMany(Task::class)->where('team_id', $this->team_id);
    }
}

Related discussions:

Installation

The recommended way to install Compoships is through Composer

$ composer require awobaz/compoships

Usage

Using the Awobaz\Compoships\Database\Eloquent\Model class

Simply make your model class derive from the Awobaz\Compoships\Database\Eloquent\Model base class. The Awobaz\Compoships\Database\Eloquent\Model extends the Eloquent base class without changing its core functionality.

Using the Awobaz\Compoships\Compoships trait

If for some reasons you can't derive your models from Awobaz\Compoships\Database\Eloquent\Model, you may take advantage of the Awobaz\Compoships\Compoships trait. Simply use the trait in your models.

Note: To define a multi-columns relationship from a model A to another model B, both models must either extend Awobaz\Compoships\Database\Eloquent\Model or use the Awobaz\Compoships\Compoships trait

Syntax

... and now we can define a relationship from a model A to another model B by matching two or more columns (by passing an array of columns instead of a string).

namespace App;

use Illuminate\Database\Eloquent\Model;

class A extends Model
{
    use \Awobaz\Compoships\Compoships;
    
    public function b()
    {
        return $this->hasMany('B', ['foreignKey1', 'foreignKey2'], ['localKey1', 'localKey2']);
    }
}

We can use the same syntax to define the inverse of the relationship:

namespace App;

use Illuminate\Database\Eloquent\Model;

class B extends Model
{
    use \Awobaz\Compoships\Compoships;
    
    public function a()
    {
        return $this->belongsTo('A', ['foreignKey1', 'foreignKey2'], ['ownerKey1', 'ownerKey2']);
    }
}

Factories

Chances are that you may need factories for your Compoships models. If so, you will provably need to use Factory methods to create relationship models. For example, by using the ->has() method. Just use the Awobaz\Compoships\Database\Eloquent\Factories\ComposhipsFactory trait in your factory classes to be able to use relationships correctly.

Example

As an example, let's pretend we have a task list with categories, managed by several teams of users where:

  • a task belongs to a category
  • a task is assigned to a team
  • a team has many users
  • a user belongs to one team
  • a user is responsible for one category of tasks

The user responsible for a particular task is the user currently in charge for the category inside the team.

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use \Awobaz\Compoships\Compoships;
    
    public function tasks()
    {
        return $this->hasMany(Task::class, ['team_id', 'category_id'], ['team_id', 'category_id']);
    }
}

Again, same syntax to define the inverse of the relationship:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    use \Awobaz\Compoships\Compoships;
    
    public function user()
    {
        return $this->belongsTo(User::class, ['team_id', 'category_id'], ['team_id', 'category_id']);
    }
}

Supported relationships

Compoships only supports the following Laravel's Eloquent relationships:

  • hasOne
  • HasMany
  • belongsTo

Also please note that while nullable columns are supported by Compoships, relationships with only null values are not currently possible.

Support for nullable columns in 2.x

Version 2.x brings support for nullable columns. The results may now be different than on version 1.x when a column is null on a relationship, so we bumped the version to 2.x, as this might be a breaking change.

Disclaimer

Compoships doesn't bring support for composite keys in Laravel's Eloquent. This package only offers the ability to specify relationships based on more than one column. In a Laravel project, it's recommended for all models' tables to have a single primary key. But there are situations where you'll need to match many columns in the definition of a relationship even when your models' tables have a single primary key.

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Unit Tests

To run unit tests you have to use PHPUnit

Install compoships repository

git clone https://github.com/topclaudy/compoships.git
cd compoships
composer install

Run PHPUnit

./vendor/bin/phpunit

Authors

Support This Project

Buy Me a Coffee via Paypal

License

Compoships is licensed under the MIT License.

compoships's People

Contributors

axelitus avatar bramus avatar christopheb avatar didac-adria avatar erikn69 avatar fmangelsdorf avatar hms5232 avatar isclopezm avatar jellyfrog avatar leo108 avatar lxshadowxl avatar mdemblani avatar mpyw avatar pedrofmj avatar ragingdave avatar slydave avatar stefket avatar topclaudy avatar wojo1206 avatar y4my4my4m avatar yurii-github avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

compoships's Issues

trait \Awobaz\Compoships\Compoships

After adding
use \Awobaz\Compoships\Compoships

no relationships works on table. Every (hasOne, hasMany) relation returns null.

public function postedTests(){ return $this->hasMany('\App\PostedTest', 'language_id', 'language_id'); return $this->hasMany('\App\PostedTest', ['language_id', 'participant_user_id'], ['language_id','participant_user_id']); }

While I used trait, every relation returns null, once remove trait - old relations work.
Laravel 5.4.

Does not support laravel 5.5?

I used this package to do a lazy eager loading and got this

PHP Warning:  strtolower() expects parameter 1 to be string, array given in /vendor/laravel/framework/src/Illuminate/Database/Grammar.php on line 58

I simply used this trait and load a relation with two keys

$this->belongsTo(A::class, ['key_1', 'key_2'], ['key_1', 'key_2']);

Error Array to string conversion

Work Laravel 5.6 , Compoships dev-master and error "Array to string conversion", please help
problem is format => ['f1', 'f2'], ['f1', 'f2']

"require": { "php": "^7.1.3", "awobaz/compoships": "dev-master", "barryvdh/laravel-cors": "^0.11.2", "fideloper/proxy": "^4.0", "laravel/framework": "5.6.*", "laravel/tinker": "^1.0", "noh4ck/graphiql": "@dev", "rebing/graphql-laravel": "~1.7" },

`namespace App;

use Illuminate\Database\Eloquent\Model;

class A extends Model
{
use \Awobaz\Compoships\Compoships;

public function b()
{
    return $this->hasMany('B', ['f1', 'f2'], ['f1', 'f2']);
}

}
`

Is it support for MongoDB

Hello @topclaudy , I just migrate from mysql to Mongodb, when I migrate I got an error, the error said

Call to a member function prepare() on null

Is this package not support mongodb yet? Thanks

Column names missing from generated SQL

Hello.

I am having an issue with adding relationships between 3 models.

I have a model, Batch, with the following relationships ...

    public function pupil()
    {
        return $this->hasOne(Pupil::class, ['batch_id', 'batch_name'], ['batch_id', 'batch_name']);
    }

    public function requests()
    {
        return $this->hasMany(Request::class, ['batch_id', 'batch_name'], ['batch_id', 'batch_name']);
    }

All 3 classes have the Compoships trait.

When querying a Batch object for either pupil or requests, I get a SQLSTATE[42S22]: Column not found.

The SQL generated looks like this

"select * from `database_name`.`pupil` where `database_name`.`pupil`.`pupil` = ? and `database_name`.`pupil`.`pupil` is not null and `database_name`.`pupil`.`pupil` = ? and `database_name`.`pupil`.`pupil` is not null limit 1 ◀"
array:2 [▼
  0 => 12252
  1 => "2e6885a7-02f1-4669-ae24-5891ecb013ce"
]

I would expect the SQL to look like

"select * from `database_name`.`pupil` where `database_name`.`pupil`.`batch_id` = ? and `database_name`.`pupil`.`batch_id` is not null and `database_name`.`pupil`.`batch_name` = ? and `database_name`.`pupil`.`batch_name` is not null limit 1 ◀"
array:2 [▼
  0 => 12252
  1 => "2e6885a7-02f1-4669-ae24-5891ecb013ce"
]

It appears as if the table name is being used in place of the column name.

This is occurring as part of the tap function in getRelationshipFromMethod.

Thanks for your help.

belongsTo does not work on laravel 5.7

Using Array for foreignKey on belongsTo in Laravel 5.7 will cause the following warning when accessing the relation:

PHP Notice: Array to string conversion in /srv/app/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php on line 78

In Larvel 5.7, the code added to the getResults method of the Illuminate / Database / Eloquent / Relations / BelongsTo class references the foreignKey member variable, which is probably the cause.

has/whereHas error 'Array to string conversion' when used with relation belongsTo

Hello
I need to filter the objects by relation belongsTo.
For example, you can take 2 models from your phpunit test (PickupTime and PickupPoint).
Models are left as is. In ComposhipsTest.php add method

public function testHasWithBelongsToRelation()
{
  $pickup_times = PickupTime::has('pickupPoint')->get()->toArray();

  $this->assertInternalType('array', $pickup_times);
}

As a result, the test falls with an error

ErrorException: Array to string conversion

I use Laravel 5.4 and compoships 1.1.12

How could I do this work?

Array to string conversion error

I am currently on v.1.1.9 but as soon as I upgrade to 1.1.10 (or even 1.1.11) I get the following errors:

0: {,…}
call: "Illuminate\Foundation\Bootstrap\HandleExceptions::handleError(8, 'Array to string conversion', '/home/vagrant/b2b/vendor/awobaz/compoships/src/Database/Eloquent/Concerns/HasRelationships.php', 170, array(3))"
file: "/home/vagrant/b2b/vendor/awobaz/compoships/src/Database/Eloquent/Concerns/HasRelationships.php"
line: 170
1: {,…}
call: "Awobaz\Compoships\Database\Eloquent\Model::sanitizeKey(instance of App\Models\SiteProductAttribute, array(2))"
file: "/home/vagrant/b2b/vendor/awobaz/compoships/src/Database/Eloquent/Concerns/HasRelationships.php"
line: 64

And here is how I am using it on my model:

public function siteProductAttributes()
{
    return $this->hasOne(SiteProductAttribute::class, ['site_id', 'product_id'], ['site_id', 'product_id']);
}

Support for period in column names

Period MySQL column name is perfectly legal. To indicate such column we enclose it in backticks. In Laravel in order to use backticks you have to use DB::raw() expression. This library in current version is not supporting DB::raw(). Especially 'HasOneOrMany.php:getForeignKeyName()' blindly explodes column name by period which brakes the query that relies on column names with periods.

Dependencies' versions locked in composer.lock

You have composer.lock file in your package. So when I added compoships into my project it downgraded some of my dependencies.
This could lead to some major incompatibility in the future.
I do not think that the package needs this file, composer.json is enough.
Do you think you could remove composer.lock?

Use trait on related model makes me use compoships for all models, including vendor models

I have two models that are related using compoships. The problem is that all my models are related to each other, including some models that are vendor-defined. I now have to add the trait to all my models as well as those provided by the vendor (which may be more difficult and prevents easy upgrade).

Is there any way to relax the requirement for both models being compships?

Problems Defining Special Relation

Hi,

I already tried to explain my problem in another package's issue, but it was not the right place either. I'm just going to link this issue and really hope anyone of you can help me out.

staudenmeir/belongs-to-through#37

I would also be open to add some custom tweaks to the relation, but I need to make it also work for eager loading.

I've tinkered a bit, but have not been successful so far.
The following code is one example I came up with. The problem is there is binding of the current model's service_jobs.id. So how is that done anyways? If I would use $this->id from within the relation function I would lack the option of eager loading the relation, because the relation function would be called on a dummy model with empty attributes. Where does the binding come from on a normal belongsTo relation for example? What is done if this relation is eager-loaded? There are many questions, because I have not fully understood the whole concept of how the relation queries are constructed etc.

public function customerService()
{
    return $this->belongsTo(
        CustomerService::class,
        ['customer_service.service_id', 'customer_service.customer_id'],
        ['service_jobs.service_id', 'jobs.customer_id']
    )
        ->select('customer_serice.*')
        ->join('jobs', function ($join) {
            return $join->on('jobs.id', '=', 'service_jobs.job_id');
        })
        ->join('service_jobs', function ($join) {
            return $join->on('service_jobs.id', '=', \DB::raw('?'));
        });
}

I would be really glad about any help

Exception: Illegal offset type in isset or empty

I'm getting this error when running the ide-helper, and can't for the life of me figure out what's causing it.

I'm getting no debug messages or anything, and it only happens when i use this package.

"awobaz/compoships": "1.1.6",
"laravel/framework": "5.7.21",

    /**
     * @return \Awobaz\Compoships\Database\Eloquent\Relations\HasOne
     */
    public function user_module()
    {
        return $this->hasOne(UserModule::class, ['module_id', 'user_id'], ['module_id', 'user_id']);
    }

strtolower() expects parameter 1 to be string, array given

A very awesome one.

I have faced the below error when calling the relation

strtolower() expects parameter 1 to be string, array given

My model looks like

namespace App\parts;
use Awobaz\Compoships\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class RslfParts extends Model
{

 public function CompanyLinked()
{

    return $this->hasMany('App\CompanyPart',['part_stock_number', 'stock_number'], ['dept_short_code', 'short_code']);
}

}

Compoships on referred model

I have two methods which use a compoship method to retrieve the corresponding model:

class Match extends Model
{

    use \Awobaz\Compoships\Compoships;
    public function thuisPouleTeam(){
        return $this->hasOne('App\PouleTeam', ["teamGuid", "pouleGuid"], ["thuisGuid", "pouleGuid"]);
    }
    public function complementaireMatch()
    {
        return $this->hasOne('App\Match', ["thuisGuid", "uitGuid", "pouleGuid"], ["uitGuid", "thuisGuid", "pouleGuid"]);
    }
}

The second one, which is a relation to itself, can be eagerly loaded without a problem. The first method can be lazy loaded, but when i try to load it eagerly i get an exception.

After trying many different things, i figured out the referring model, in this case App\PouleTeam must also use \Awobaz\Compoships\Compoships;

Maybe it's me, but i it's not clear the referred class must also implement the compoships model.

\InvalidUsageException: The related model 'App\UserCover' must either extend 'Awobaz\Compoships\Database\Eloquent\Model' or use the 'Awobaz\Compoships\Compoships' trait

So I need to update my User Model that has several relationship.

One of the is called address. This is the only thing where I have composite keys.

However, I get the error:

Awobaz\Compoships\Exceptions\InvalidUsageException: The related model 'App\UserCover' must either extend 'Awobaz\Compoships\Database\Eloquent\Model' or use the 'Awobaz\Compoships\Compoships' trait

I don't want to use comoships on UserCover.

public function covers(){
    return $this->hasOne(UserCover::class)
                ->withDefault([
                    'covers' => $this->standardCovers()
                ]);
}

whereHas seems not to work

Dear Claudin,

thank you for creating compoships!

Is it possible that the whereHas query does not work?
When I try to query my model with whereHas and a compoship I get an Array to String conversion Exception. I use Laravel 5.5 and have both models extend compoships

Thank you for taking the time, compoships seems to make my life easier!
best
cornelius

//Allocation and TrackingTask extend Awobaz\Compoships\Database\Eloquent\Model
Allocation::whereHas('trackingTask');

results in:

bildschirmfoto 2018-05-17 um 04 22 31

withCount/hasManyThrough: mb_strpos() expects parameter 1 to be string, array given

When using withCount on an hasManyThrough relationship, we end up in this call
return $this->throughParent->qualifyColumn($this->firstKey);

firstKey is an array, but the base Eloquent\Model class uses it as a string

I know hasManyThrough is not listed as supported, but defining an hasManyThrough relationship with composite keys actually works fine as long as withCount is not used

Call stack:

  • Illuminate\Database\Eloquent\Builder::withCount
  • Illuminate\Database\Eloquent\Relations\Relation::getRelationExistenceCountQuery
  • Illuminate\Database\Eloquent\Relations\HasManyThrough::getRelationExistenceQuery
  • Illuminate\Database\Eloquent\Relations\HasManyThrough::getQualifiedFirstKeyName
  • Illuminate\Database\Eloquent\Model::qualifyColumn
  • Illuminate\Support\Str::contains
  • mb_strpos
  • ErrorException

hasMany relationship doesn't seem to work

I have the following database structure:

  • a user table (id, name, email, ...)
  • a conversation table (id, user_id_1, user_id_2)

To get all conversations of a user, I needed to create a relationship on both columns (user_id_{1, 2}) of the conversation table. Therefore I'm using this package. But it doesn't seem to work for me. I'm using the latest version (1.1.9). The following is a code snippet of the relationship in the user model:

public function conversations() { return $this->hasMany('App\Conversation', ['user_id_1', 'user_id_2']); }

The conversation model inherits from the compoship eloquent model, the user model uses the trait variant, because it inherits from Authenticatable. I'm assuming that the hasMany relation defaults the local keys to id, but I already tried passing ['id', 'id'] as local keys and it doesn't work either.

EDIT: I should say that I don't get any error. When I call $user->conversations, it returns an empty collection. As soon as I pass in only one foreign key (e.g. user_id_1) it works, but obviously gives me the conversations, where the user_id_1 equals $user->id and not where user_id_2 equals $user->id, too.

Undefined property: App\

Hi there,

I haven't updated since 1.1.0, and today I have updated the package.
Now, if there is a relation within the $this->relation i get an Undefined property: App\Model

Please advise what needs to change in my code to support?

use DB::raw

I think it might be a good idea to use DB::raw, for example, I want to use a date with Y-m-d format but another field to compare has the format Y-m-d H:i:s, if you could use DATE_FORMAT with same format it would be great

Eager loading - Illegal offset type

I'm getting an ErrorException (E_WARNING) - Illegal offset type when trying the below:

public static function getNotificationById(int $notificationID){
    return Notification::with('challengePeriod')->findOrFail($notificationID);
}

My model has the relationship as:

class Notification extends Model
{
    use Compoships;

    public function challengePeriod(){
        return $this->belongsTo(ChallengePeriod::class, ['challenge_id', 'date_challenge_ini_pri'], ['challenge_id', 'date_challenge_ini']);
    }
}

Therefore, the error happens if the relationship returns any row.

Could someone help me?

SQL error when using whereHas() after upgrading to 1.0.6

my database: PostgreSQL 10.4

my models:
Text --hasMany--> Translation

public function translations()
{
    return $this->hasMany(Translation::class, 'text_id', 'text_id');
}

when i am calling

$text->whereHas('translations', function($q) {
    $q->where('language_id', '=', 1);
});

i now get the following sql error

SQLSTATE[HY093]: Invalid parameter number: parameter was not defined (SQL: select count(*) as aggregate from "t_text" where exists (select * from "t_text_translation" where "t_text"."text_id" = "t_text_translation"."text_id" and "language_id" = 1))

the query itself works fine on any db client.
after downgrading back to 1.0.5 the application also runs.

has() not working on self relations

Thank you for a nice package!

I'm having troubles using has() when the relationsship refers to it's own class.

To reproduce:

In your test-suite, add following relation to TrackingTask.php:

public function subtasks()
{
    return $this->hasMany(TrackingTask::class, 
        ['booking_id', 'vehicle_id'],
        ['booking_id', 'vehicle_id']);
}

Try adding and running following unittest:

public function testHasForSelfRelation()
{
    $trackingTask = TrackingTask::has('subtasks')->get()->toArray();

    $this->assertInternalType('array', $trackingTask);
}

It is the method getRelationExistenceQueryForSelfRelation that tries to make a string comparision.

I might have time to take a further look and make a PR, but not today unfortunatly.

Doc update request in regard to multi connections

If your models happen to use different connection you must provide protected $connection = 'connection_name' for each model. Otherwise, belongsTo() will call default database which is defined in $this model instead of connection defined in belongsTo() model.

Compoships produces a little bit redundand SQL

I have two models:

class User extends Model
{
    use Compoships;

    [...]

    public function user_metrics_current()
    {
        return $this->hasOne(UserMetrics::class, ['user_id', 'begin_at'], ['id', 'last_reset_date']);
    }
}

class UserMetrics extends Model
{
    use Compoships;

    [...]
}

The following expression

User::query()->whereDoesntHave('user_metrics_current')->get();

will generate a little bit redundand sql

select * from `users` where not exists (select * from `user_metrics` where `users`.`id` = `user_metrics`.`user_id` and `users`.`last_reset_date` = `user_metrics`.`begin_at` and `users`.`id` = `user_metrics`.`user_id` and `users`.`last_reset_date` = `user_metrics`.`begin_at`)

Ran composer require and laravel isn't finding it.

Laravel: 5.7.22
Compoships: 1.1.6

Nothing I do seems to allow it to be found.

I've tried clearing caches, composer dump-autoload with and without -o
Nothing I do allows Laravel to find it. Also the Package discovery isn't working either. As the providers doesn't get updated in app.php

Maybe it's end of day blues, but I'm good and stumped!

Parents

I'm having trouble with a concept and I don't know if this is supported in Compoships.

Currently, I have a one to one relationship for mother and father, so

public function father() {
        return $this->hasOne(Person::class, 'id', 'father_id');
    }

    public function mother() {
        return $this->hasOne(Person::class, 'id', 'mother_id');
    }

And this works great, but for ease of traversing family trees, i'd like to add parents

public function parents() {
        return $this->hasMany(Person::class, 'id', ['mother_id', 'father_id']);
    }

And also, to get children

public function offspring() {
        return $this->hasMany(Person::class, ['mother_id', 'father_id'], 'id');
    }

I guess that Compoships isn't working as I'd expect in this situation and I was wondering if there is a way to get this to work or if it's a limitation in Compoships.

has() relationship not working

After defining a relationship like
public function locales() { return $this->hasMany( ProgramsVersionsLocale::class, ['id_program', 'id_version'], ['id_program', 'id_version'] ); }
we get the following error:
PHP Notice: Array to string conversion in /opt/app/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php on line 393

The error is related with getQualidiedKeyName() that is an array, but it expects a string. Furthermore it is not possible to be used as static, so I need to do something like ProgramsVersion::query()->has('locales')->get(); instead of ProgramsVersion::has('locales')->get();

How could I do this work?

Thanks beforehand!

No method override for qualifyColumn?

Laravel 5.5, PHP 7.1.16

Sale::class

public function extra()
{
    return $this->hasOne(SaleExtra::class, ['AccountId', 'DealNumber'], ['AccountId', 'DealNumber']);
}

SaleExtra::class

public function sale()
{
    return $this->belongsTo(Sale::class, ['AccountId', 'DealNumber'], ['AccountId', 'DealNumber']);
}

Calling out to

Sale::whereHas('extra', function ($query) use ($b) {
    $query->where('a', '=', $b);
})

I receive the error below

In Str.php line 103:
                                                             
  [ErrorException]                                           
  mb_strpos() expects parameter 1 to be string, array given 

With a stacktrace like

Exception trace:
 Illuminate\Foundation\Bootstrap\HandleExceptions->handleError() at n/a:n/a
 mb_strpos() at vendor/laravel/framework/src/Illuminate/Support/Str.php:103
 Illuminate\Support\Str::contains() at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:260
 Illuminate\Database\Eloquent\Model->qualifyColumn() at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php:399
 Illuminate\Database\Eloquent\Relations\HasOneOrMany->getQualifiedParentKeyName() at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php:207
 Illuminate\Database\Eloquent\Relations\Relation->getRelationExistenceQuery() at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php:340
 Illuminate\Database\Eloquent\Relations\HasOneOrMany->getRelationExistenceQuery() at vendor/awobaz/compoships/src/Database/Eloquent/Concerns/QueriesRelationships.php:35
 Awobaz\Compoships\Database\Eloquent\Builder->has() at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php:131
 Illuminate\Database\Eloquent\Builder->whereHas() at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1470
``

Not unique table/alias error

I'm having an issue with the latest version of Compoships whenever I use whereHas()

The code:

        $type = $this->type;

SubType::query()
            ->whereHas('types', function ($query) {
                $query->where('id', '=', config('constants.types.licenceTypes'));
            })
            ->whereIn('id', $type->extra_data['available_licences'])
            ->get($columns);

The SQL error I get:

"SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'type_has_data' (SQL: select id, name, colour from type_data where exists (select * from types inner join type_has_data on types.id = type_has_data.type_id inner join type_has_data on types.id = type_has_data.type_id where type_data.id = type_has_data.data_id and types.id = LICENCE-TYPES and type_data.id = type_has_data.data_id and types.id = LICENCE-TYPES) and id in (BEE_KEEPER_PERMIT, COMMERCIAL_SNAKE_LICENCE, FULL_TECHNICIAN, TIMBER_PEST) and type_data.deleted_at is null)"

(SQL:SELECT id, 
       NAME, 
       colour 
FROM   type_data 
WHERE  EXISTS 
       ( 
                  SELECT     * 
                  FROM       types 
                  INNER JOIN type_has_data 
                  ON         types.`id` = type_has_data.`type_id` 
                  INNER JOIN type_has_data 
                  ON         types.`id` = type_has_data.`type_id` 
                  WHERE      type_data.`id` = type_has_data.`data_id` 
                  AND        types.`id` = licence-types 
                  AND        type_data.`id` = type_has_data.`data_id` 
                  AND        types.`id` = licence-types) 
AND    id IN (bee_keeper_permit, 
              commercial_snake_licence, 
              full_technician, 
              timber_pest) 
AND    type_data.`deleted_at` IS NULL)

I notice that it is doing the inner join on the table twice, which is the error.
If I remove the Compoships trait from the SubType model then I get no errors and it works properly.

Having some problems with whereHas and Builder class

Hello,

first of all thank you for your awesome package.

I'm trying to add some (request) filter's to my app. Unfortunately i get some error when i use the Builder class.

Laravel: 5.6,
compoships: 1.1.3

I have Two models, (both have traits pulled in):

Models\Adressen:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use App\Filters\Address\AddressFilters;
use Illuminate\Http\Request;
use App\Models\Kontokorrent;

class Adressen extends Model
{
    use \Awobaz\Compoships\Compoships;
    protected $table = 'Adressen';
    protected $primaryKey = 'Adresse';
    public $incrementing = false;
    public $timestamps = false;

    public function kontokorrent() 
    {
        return $this->hasOne(Kontokorrent::class, ['Mandant', 'Adresse'], ['Mandant', 'Adresse']);
    }

    public function scopeFilter(Builder $builder, Request $request, array $filters = []) 
    {
    	return (new AddressFilters($request))->add($filters)->filter($builder);
    }

}

Models\Kontokorrent:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Models\Adressen;

class KHKKontokorrent extends Model
{
    use \Awobaz\Compoships\Compoships;
    protected $table = 'Kontokorrent';
    protected $primaryKey = 'Adresse';
    public $incrementing = false;
    public $timestamps = false;

    public function adressen() {
    	return $this->belongsTo(Adressen::class, ['Mandant', 'Adresse'], ['Mandant', 'Adresse']);
    }
}

and then when i use a specific filter:

namespace App\Filters\Address;

use Illuminate\Database\Eloquent\Builder;
use App\Filters\FilterAbstract;

class KtoArtFilter extends FilterAbstract
{
	public function filter(Builder $builder, $value)
	{
		return $builder->whereHas('KtoArt', function(Builder $builder) use ($value) {
			$builder->where('KtoArt', $value);
		});
	}
}

$value (='D') is just an url param value (localhost:8000?ktoart=D)
i get an error:

Method Awobaz\Compoships\Database\Query\Builder::KtoArt does not exist.

how can i use the Builder class with your package ?

best regards
Greg

Overhead during every query.

The drawback I face with this library is that it enforces the base model, the derived model and every model which are connected with these models recursively. In my case every class has to be changed to derive from this Awobaz model instead of Eloquent model (or every model has to use the Compoships trait) which will add an extra overhead to every query. If this can be avoided then this would be good.

I have a very huge project and I had to change every model because of this.

If I don't do that, I get this error.

The related model 'App\Model\XYZ' must either extend 'Awobaz\Compoships\Database\Eloquent\Model' or use the 'Awobaz\Compoships\Compoships' trait"

Now my Pull request will not be approved as this will be an overhead to every query. I want to touch maximum 1 file and get this done.

When I use whereHas, the sql's where condition is duplicated.

UserBinding Model

public function user()
{
return $this->hasOne('App\User', ['strName', 'strPwd'], ['strName', 'strPwd']);
}

When I use whereHas

$query->whereHas('user', function (Builder $query) use {
$query->where('user.iEnable', '=', 1);
});

select count(*) as aggregate from user_bindings where (exists (select * from user where

user_bindings.strName = user.strName and user_bindings.strPwd = user.strPwd and user.iEnable = '1'

and

user_bindings.strName = user.strName and user_bindings.strPwd = user.strPwd and user.iEnable = '1')

Have any idea? Thank you very much.

hierarchy problem

Hi, I got this error:

message: "Awobaz\Compoships\Database\Eloquent\Relations\HasOne and Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels define the same property ($withDefault) in the composition of Awobaz\Compoships\Database\Eloquent\Relations\HasOne. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed

Using make() function on relation returns error

Since, there is a possibility of a model having a composite key, there are certain scenarios where we just need the instance of the related model without persisting it to the database. To achivie this, there is a make() function in relations such as HasOneOrMany.

Currently it defaults to the one provided by Eloquent, and hence it returns an error.

does not work if the column values are NULL.

does not work if the column values are NULL.
like here
$this->hasMany('Bar', ['f1'], ['f2']);
if f1 column has NULL value and f2 also have NULL then it should take that record from DB but it Does Not :(

Compoships returning null value even though there is data

I'm using Laravel 5.5.42

Here's my Models

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class CrmClientActions extends Model{
	use \Awobaz\Compoships\Compoships;
	protected $table = 'crm_client_actions';
	protected $primaryKey = 'id';
	protected $fillable = ['user_id', 'client_id', 'group_id', 'action', 'status', 'note', 'next_followup', 'assigned_by'];
	protected $dates = [
		'next_followup',
		'created_at',
		'updated_at',
	];
public function crmclient() {
		return $this->hasOne("App\Models\CrmClients", "client_id", "client_id")->where('group_id', $this->group_id);
	}
	public function crm() {
		return $this->hasOne("App\Models\CrmClients", ["client_id", "client_id"], ["group_id", "group_id"]);
	}
	public function crm_many() {
		return $this->hasMany("App\Models\CrmClients", ["client_id", "client_id"], ["group_id", "group_id"]);
	}
}

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use DB;
use Carbon\Carbon;

class CrmClients extends Model {
	use \Awobaz\Compoships\Compoships;
	protected $table = 'crm_clients';
	protected $primaryKey = 'id';
	protected $fillable = ['client_id', 'group_id', 'status', 'points'];
	protected $dates = [
		'created_at',
		'updated_at',
	];
}

the call to the crm function
CrmClientActions::whereHas('crm')->get()
always returns empty collection, even though there are entries in tables

Let me know if I'm doing something wrong.

Thanks.

self::has not working in model

When querying relationship existence from within a model itself thats using the Compoships trait the has() function doesn't work. See the following example:

class Bookmark extends Model {

    use \Awobaz\Compoships\Compoships;

    public static function folders() {
        return self::has('product')
            ->orderBy('folder')
            ->groupBy('folder')
            ->pluck('folder', 'folder');
    }
}

This creates the following error: Non-static method App\Models\Bookmark::has() should not be called statically

I'm using Laravel 5.5 and Compoships 1.0.8.

Eager loading doesnt work.

I add relation (hasMany and belongsTo) into 2 model using trait. Relation work correctly, but if try eager load relation return null. It should work and i make mistake, or it should not work?

Is there a reason that belongsToMany relationship isn't supported?

Is there a reason that belongsToMany relationship isn't supported?

i.e.

$this->belongsToMany('App\User', 'friends', ['requestor_id', 'receiver_id'], ['receiver_id', 'requestor_id']);

At the moment, to have two-way belongsToMany relationships (i.e. a friendship system) in Laravel is to have two different relationships, 2 different DB calls, and merging both results on-access.

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.