I have a script that is passed a table name. I want to be able to load relations of relations for the records returned. For instance, I can get this by using the classname directly:
Item::find($id)->schedules->load('template')->toArray();
This gives me what I want, however, the table name passed is variable, plural and lowercase. To fix this I could just do something like:
$table_class = studly_case(str_singular($table));
$table_class::find($id)->schedules->load('template')->toArray();
However, this is a little clunky. I'd like to do it like so:
DB::table($table)->find($id)->schedules->load('template')->toArray();
But the above doesn't work and I haven't been able to figure out the correct syntax for it. How would I do this using DB::table()?
With DB::table() your are using the query builder. Eager loading is a feature of the eloquent orm. Afiak there is no way to do this via the query builder.
But imho your clunky solution is absolutly ok, I solved a similar problem the same way. If you are just worried about the code style, you could implement a simple ModelFactory that does this "ugly" job, something like this:
ModelFactory::create($table)->find($id)->...
Related
I'm pretty new to Laravel, and still exploring it's features and possibilities, and I've came across a strange issue that I don't quite understand.
First of all, I'm using Laravel 5.0 and I'm trying to make pagination of results that came from model alongside with sorting them.
Here is the code that works, but without sorting:
News::paginate(5);
And here is what I need, but doesn't work:
News::paginate(5)->orderByDesc('published_at');
I've tried doing it like so:
News::all()->sortByDesc('published_at')->paginate(5);
But then, when I call render() method inside view it throws error. I would like to use model's approach since it's handy and few more things depend on it, and not query builder method. Also, would like, if possible to avoid manual or any kind of custom pagination. Thanks
You should write this. This will solve your problem
News::orderBy('published_at','desc')->paginate(5);
Assume A,B,C,D are models. Is there a way to cleanly chain models like so: a->b()->c()->d()->get();? When trying to do this, I get an error since a->b(), b->c(), and c->d() all return sets and not a single object.
Some people have suggested eager loading in other sites, but I have no idea how to use them. So far I have tried using a->load('b.c.d'); in hopes of loading all the models to 'a' but it didnt work.
How can I load all relevant models b,c,and d to a?
You can use with
$v = a->with('b.c.d')->get();
then you can use in your code like this
$v->b->c->d
I'm currently working on a Service in SF2 that queries the database with the QueryBuilder using a class variable set with a repository-specific QueryBuilder in the constructor of this Service.
Which means i would like to make use of this set QueryBuilder as much as possible for neater code and a clean feeling using it.
I want to avoid creating a query on the EntityManager, but instead solely query using this predefined Querybuilder.
I'm looking for something that would look/work like the following:
$query = $this->fooRepository->createQueryBuilder('f')->select('*');
return $query->getResult(Query::HYDRATE_ARRAY);
The above would (if it worked) return all the foo in the database as far as i know..
If you think i'm being stupid and should do something different in regard to the predefined QueryBuilders or just use the:
createQuery()
method because it simply isn't good practice or impossible, don't hesitate to tell me.
Thanks!
Try:
$qb = $this->fooRepository->createQueryBuilder('foo');
return $qb->getQuery()->getResult(Query::HYDRATE_ARRAY);
No need for a select(*). All the foo items will be selected since no where clauses were added.
It looks like when I forget to put leftJoin in my queries, Doctrine will lazy-load relations after I pick them. Ie if I do something like:
$property = PropertyTable::getInstance()->createQuery('o')
->leftJoin('o.Features f')
->execute() ;
I will still be able to access $property->Attraction , even if I didn't load them in this query. So I guess Doctrine does it internally by calling another 'SELECT'. Is there a way to prevent this auto-loading by throwing some exception? This would help me create better and faster queries.
Have you looked at the actual sql it produces?
Try ->getSql(). It is likely it is doing another query when you attempt to access a related field.
If you want to avoid that, don't access related fields!
I would have liked to know if it was a good idea to return a select object from a method like '$selectObj = getSomethingByName($name)' to then pass it to another method like 'getResult($selectObj)' which will do the trick.
The idea is to be able to pass the select object to any usefull function like 'setLimit(10)' or addCriteria('blabla') depending on my model...
But is it a good idea to do this ? it could be 'unsecure' because user will be able to modify the object himself, and i should not want to this..
I used to do simple method before like above but returning the result as a row... but it's sometimes painfull when you have complex statement depending on different tables..
The problem you are facing (complex statements depending on different tables) is an old and widespread problem with ORM frameworks in general. There are lots of things SQL can do, that an ORM doesn't do very well. Inevitably, you have to make up the different in complexity by writing lots of complicated code in your Controller or your View.
Instead, use a Domain Model pattern and encapsulate the complex multi-table database logic into one place, so your Controllers and Views don't have to know about all the sundry details. They just know about the interface of your Domain Model class, and that class has the sole responsibility to know how to fetch the information from the database.
Remember: a Model "HAS-A" table (or multiple tables) -- instead of Model "IS-A" table.