Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sf Shared Repository Laravel Package

loicpennamen/sf-shared-repository

A shared repository package for Symfony applications that provides a reusable base repository layer, centralizing common data-access logic and reducing duplication across entities while keeping persistence code consistent and maintainable. Ideal for teams seeking a clean, reusable data-access founda...

View on GitHub
Deep Wiki
Context7

Getting Started

This is not a Laravel package. It targets Symfony 4 + Doctrine ORM, replacing ServiceEntityRepository (not Eloquent) with a repository that understands the query-string contract DataTables server-side processing sends (draw, start, length, search[value], order[0][column], columns[i][data]). There is no README worth speaking of, no tags, no tests you can rely on, and zero dependents — treat it as vendored source you are adopting, not a dependency you are installing. Before you write a line of integration code, clone it and read src/; the class is a few hundred lines and every behaviour below has to be confirmed against what is actually there.

1. Pull it in by commit, not by version.

"repositories": [
    { "type": "vcs", "url": "https://bitbucket.org/LoicPennamen/sf-shared-repository.git" }
],
"require": { "loicpennamen/sf-shared-repository": "dev-master#<sha>" }

Pin the SHA. Bitbucket repos with no tags move under you.

2. Wire it in the Doctrine way. The class is meant to be used as the repositoryClass on an entity mapping, so getRepository() returns it instead of the default:

/**
 * @ORM\Entity(repositoryClass=ProductRepository::class)
 */
class Product { /* ... */ }

class ProductRepository extends SharedRepository { }

If instead it is a service (constructor taking ManagerRegistry, as Symfony 4.2+ ServiceEntityRepository does), you register it under services.yaml with App\Repository\ resource loading. Check which one it is — this determines whether the entity mapping or the container is your integration point, and it is the single most common source of "repository has no EntityManager" errors.

3. First use case: a server-side DataTables endpoint. One controller action returning JSON, nothing else:

public function list(Request $request, ProductRepository $repo): JsonResponse
{
    return $this->json($repo->searchForDataTables($request->query->all()));
}

The payload shape you must return is DataTables', not Symfony's: draw echoed back, recordsTotal, recordsFiltered, and data. Confirm whether the package builds that envelope or only returns results — that difference decides how much glue you own.

Where to look first: src/ for the public method that accepts the request array, then whatever column/join configuration it expects (protected properties to override, or an argument to the call). Everything else in this package hangs off that one signature.

Implementation Patterns

Keep the controller thin. The value of this class is that filtering, sorting, and pagination for a table live in one repository method instead of a 200-line controller. Resist the urge to post-process rows in the controller; if you need computed columns, do it in the repository or accept the extra pass. Laravel developers coming from yajra/laravel-datatables will look for addColumn/editColumn equivalents — there are none, so plan on array hydration plus a small mapping step if you need derived fields.

Whitelist columns in the repository, not the request. DataTables sends column identity as an index into columns[i][data], and that string arrives from the browser. Any repository worth using here maps it against a declared list before touching DQL:

protected $searchable = ['p.name', 'p.sku', 'c.name'];
protected $sortable   = ['p.name' => 'p.name', 'category' => 'c.name'];

If the package does not already do this (verify), wrap the call and normalise the request array first. A column name interpolated into orderBy() is an injection point that Doctrine will happily execute.

Joins are where the "powerful" part lives and where it breaks. Searching across associations means a leftJoin on the query builder. Two consequences:

  • Sorting or filtering on a joined alias requires that join to be present on both the count query and the data query. If you build the count separately (you usually must), share the join-building code.
  • A to-many join fans out rows, so recordsFiltered must be COUNT(DISTINCT p.id). Get this wrong and your pager silently lies.

Pagination: setFirstResult($start)->setMaxResults($length) on the data query, a separate SELECT COUNT(...) for the totals. Use array hydration (getArrayResult() / getQuery()->getArrayResult()) for tables — you are serialising to JSON anyway and it halves the cost.

Multi-term search. Users type "acme blue" and expect products matching both terms somewhere. Split on whitespace and AND the terms, OR-ing each across your searchable columns:

foreach (preg_split('/\s+/', trim($term)) as $word) {
    $or = $qb->expr()->orX();
    foreach ($this->searchable as $col) {
        $or->add($qb->expr()->like($col, ':w'));
    }
    $qb->andWhere($or)->setParameter('w', '%'.$word.'%');
}

Per-entity subclasses. The intended pattern is one small subclass per entity that declares its searchable columns, sortable map, and default order; the base class does the request parsing and counting. Keep the customisation surface data-only where possible so the base stays upgradeable — which matters more than usual given there is no maintainer.

In a Laravel codebase, you have two honest options: run this only if you are already on Doctrine via laravel-doctrine/orm (the repository works unchanged; you just wire the registry into the container), or skip it and use yajra/laravel-datatables with Eloquent. Porting the class to Eloquent is a rewrite of the query-builder half, and you would be maintaining a fork of an unmaintained package — the cost is almost never worth it for a single table.

Gotchas and Tips

  • Symfony 4 / Doctrine 2 only. ServiceEntityRepository and EntityRepository changed shape between Doctrine 2 and 3 (ManagerRegistry constructor, EntityRepository deprecation). On Symfony 5.4+/Doctrine 3 expect to patch the constructor yourself. Symfony 4 is EOL, so this is not a hypothetical.
  • DataTables sends columns[i][search][value] on every request, usually empty. Do not treat the presence of per-column search parameters as an active filter — check for non-empty strings, or every query gets a LIKE '%%' on every column and the planner gives up.
  • Echo draw back unchanged. Mismatched or missing draw makes DataTables discard the response and retry, and you get an infinite request loop that looks like a server bug.
  • recordsTotal vs recordsFiltered. Total is the unfiltered count; filtered is what matches the search. Swapping them produces a table that renders but whose "Showing X of Y" is nonsense.
  • Empty order array. DataTables omits it when ordering is disabled; always have a deterministic fallback ORDER BY id or pagination returns overlapping pages.
  • Debug by dumping SQL, not by dumping the query object. $qb->getQuery()->getSQL() plus getParameters() inside the profiler, or the Symfony Doctrine panel. Most failures here are a missing join on the count query, which no exception will tell you about — the number is just wrong.
  • Hydration mode changes the row shape. Object hydration gives you entities, which serialise with whatever your normaliser does (and can leak relations); array hydration gives you flat aliased keys. Pick one and make the controller match — this is the most common "the table is blank" cause.
  • Pin the commit and vendor the code if you depend on it in production. No stars, no dependents, no release tags, no issue tracker traffic — there is no upgrade path and no one to ask. Copy the class into your App\Repository namespace with a note of its origin, patch it freely, and stop pretending it is a third-party dependency.
  • Extension points to look for before you start editing: protected searchable/sortable/join declarations, a default order, and any method that builds the count query. If the class exposes none of these, treat that as the first thing you refactor rather than the last.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource