Download the PHP package awobaz/compoships without Composer

On this page you can find all versions of the php package awobaz/compoships. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package compoships

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.

Related discussions:

Installation

The recommended way to install Compoships is through Composer

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 reason 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).

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

We can also define many-to-many relationships with composite keys through a pivot table:

All standard belongsToMany operations work with composite keys: attach(), detach(), sync(), toggle(), withPivot(), withTimestamps(), eager loading, and existence queries (has(), whereHas()).

Composite-key input shapes for attach() and sync()

Two input shapes are supported for attach(), sync(), syncWithoutDetaching(), and toggle() on composite-key relations.

A list of composite tuples (each tuple is an array aligned with the related-pivot-key columns):

A map of json_encode($tuple) => $perRowAttributes, equivalent to Laravel's single-key [id => attributes] shape. The key must be the JSON encoding of the composite tuple, produced via json_encode([...]). Per-row attributes override any shared bulk attributes on key conflict, and any per-row attribute keys colliding with the foreign-pivot-key columns are silently dropped to prevent overriding the parent linkage.

Passing an associative array key that is not a JSON-encoded tuple of the correct arity throws Awobaz\Compoships\Exceptions\InvalidUsageException.

Factories

Chances are that you may need factories for your Compoships models. If so, you will probably 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:

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

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

For a many-to-many scenario, imagine users can be assigned to projects, where both the user and the project are identified by a composite key (team_id and department_id):

Supported relationships

Compoships supports the following Laravel Eloquent relationships:

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

Note on belongsToMany: Custom pivot models (via using()) with composite keys are supported. Your custom pivot class should extend Awobaz\Compoships\Database\Eloquent\Relations\Pivot instead of Laravel's base Pivot class to ensure correct behavior for save, delete, and queue operations.

Composite primary keys

By default, Eloquent builds the WHERE clause for UPDATE, DELETE, and refresh() / fresh() using only the scalar $primaryKey. On tables whose primary key spans multiple columns (such as (id, tenant_id) in multi-tenant or partitioned schemas), $model->save() on a hydrated row emits a query like UPDATE table SET ... WHERE id = ?, missing the discriminator. The same scalar id can exist under another discriminator value, so the operation silently targets the wrong row.

Compoships lets you opt into composite primary key handling on the write path. Declare a $compositeKey property on the model that enumerates every column in the primary key (including the scalar slot named by $primaryKey). Keep $primaryKey as the scalar column name so getKey(), Model::find($id), route model binding, and queue serialization continue to work unchanged.

With this declaration, the following operations scope their WHERE clause by every column in $compositeKey:

For example:

The following operations are not affected. They remain identical to stock Eloquent.

Queue serialization (via Illuminate\Queue\SerializesModels, used by queueable jobs, events, and notifications) participates in composite handling for single-model properties on the job: getQueueableId() returns a JSON-encoded array of the composite key columns, and newQueryForRestoration() decodes it back into a query that scopes by every key column on the worker side. Round-tripping a single composite-keyed model through the queue reloads the exact composite row that was queued. Old queued payloads predating this feature (with a scalar id) continue to restore via the parent path, so no queue drain is required on upgrade.

Collection round-trip requires the QueueableCompositeCollection wrapper. A raw Illuminate\Database\Eloquent\Collection of composite-keyed models on a job property will restore as an empty collection. The cause is in Laravel's restoreCollection: it re-keys loaded models by scalar getKey() and looks up by the original queued ids (our JSON-encoded composite strings), so the lookup keys never match. The package ships a wrapper class that sidesteps the issue by capturing composite-key tuples at queue time and rebuilding the collection via composite-aware query at restore time:

The wrapper preserves the original collection order, eager-loaded relations, and the model's connection. It rejects mixed-class collections (throws LogicException) and misconfigured $compositeKey declarations (throws InvalidUsageException) at wrap time. The wrapper is opaque to SerializesModels, so PHP's standard serialization captures its state directly. Each call to restore() issues one database query.

If you declare $compositeKey on a model whose array does not contain the value of $primaryKey, the trait throws Awobaz\Compoships\Exceptions\InvalidUsageException on the first save, delete, or refresh. The array must enumerate the whole primary key.

If you mutate a discriminator column in memory before calling save() (for example, $user->tenant_id = $newTenant), the UPDATE still targets the row as it exists in storage. The WHERE clause uses the original raw value from $model->original, then the SET clause writes the new value.

Nullable composite-key columns are supported. When the original raw value of a column is null, the trait emits WHERE column IS NULL rather than binding null into a = predicate (which SQL evaluates as never-true). This makes $compositeKey safe to use as a composite scoping key for tables that use a UNIQUE(...) index with a nullable discriminator rather than a strict composite primary key.

Note for consumers with their own override

If your model already overrides setKeysForSaveQuery() or setKeysForSelectQuery(), call parent::setKeysForSaveQuery($query) (and the select equivalent) first to inherit the composite key handling. Without parent::, the override loses the composite WHERE silently.

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.

Scope

Compoships targets two specific gaps in Eloquent:

  1. Defining hasOne, hasMany, belongsTo, and belongsToMany relationships across multiple columns.
  2. Scoping the write path (save, update, delete, refresh, fresh) by every column of a composite primary key on models that opt in via $compositeKey.

The package does not re-implement Laravel's primary-key handling end-to-end. The following continue to use the scalar $primaryKey:

Queue serialization (Illuminate\Queue\SerializesModels) is supported for composite-keyed models. See the "Composite primary keys" section for the round-trip contract.

Builder-level bulk operations (Model::query()->...->update(...)) continue to use whatever WHERE clauses you build. For composite-key bulk patterns, the custom Query Builder's tuple whereIn works directly:

Most Laravel applications work best with a single scalar primary key. Compoships exists for the cases where the schema is not under your control (third-party databases, legacy systems, partitioned or multi-tenant tables) or where matching multiple columns in a relationship definition is unavoidable.

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

Run PHPUnit

Running the full CI matrix locally

The package is tested against multiple Laravel and PHP versions in CI. To reproduce that matrix on your machine without setting up each PHP version manually, use the bundled Docker runner:

The script mirrors .github/workflows/run-tests.yml exactly. It iterates over every Laravel and PHP combination, installs the requested Laravel version with Composer inside an ephemeral Docker container, runs PHPUnit, and prints a pass/fail summary at the end. Docker is the only prerequisite.

You can narrow the run to a subset by passing a filter argument that matches against the matrix label (L<laravel> PHP<php>):

Authors

Support This Project

Buy Me a Coffee via Paypal

License

Compoships is licensed under the MIT License.


All versions of compoships with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/database Version ^12.0|^13.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package awobaz/compoships contains the following files

Loading the files please wait ...