Eloquent : querying models depending on model's relationships - laravel

I'm looking for a way to query models depending on the existence of the model's relationships.
http://paste.laravel.com/xuh Here's a paste with what I'm looking to accomplish.
The basic idea would be to search for Collections only where the User has access in the shared_access table.
Dreamcode (doesn't work):
Collection::where('sharedAccess.user_id', '=', Auth::user()->id->get())

Check out the fancy has() method. It basically allows you to do things like this:
Collection::has('sharedAccess')->get();
That would fetch all collections that have a related SharedAccess instance.

Related

How to use Query Builder to make a relation in an array? Laravel

I would like to make a relation with query builder... I have three tables, and I would like to join the tables for work with the function.. I'm working in a model.. not in a controller
This is my function
public function map($contactabilidad): array
{
$relation = DB::table('tbl_lista_contactabilidad')
->join('tbl_equipo_postventaatcs', 'tbl_equipo_postventaatcs.id', '=', 'tbl_lista_contactabilidad.postventaatc_id')
->join('users', 'users.id', '=', 'tbl_equipo_postventaatcs.asesor_id')
->get();
return [
$contactabilidad->$relation->name,
$contactabilidad->postventaatc_id,
$contactabilidad->rif,
$contactabilidad->razon_social,
$contactabilidad->fecha_contacto,
$contactabilidad->persona_contacto,
$contactabilidad->correo_contacto,
$contactabilidad->numero_contacto,
$contactabilidad->celular_contacto,
$contactabilidad->comentarios,
$contactabilidad->contactado,
$contactabilidad->respuesta->respuesta
];
}
Query\Builder is best thought of as the primary tool used by Eloquent, but is, nontheless, a completely different package. Query\Builder's purpose is to decouple SQL syntax from the logic that feeds into it, whereas Eloquent's purpose is to decouple that logic from table structures and relationships. So only Eloquent supports Model and Relation classes, Query\Builder does not. And what you're asking for has to do with Relations, so in short, you're kind of barking up the wrong tree.
By the way, I'm differentiating 'Query\Builder' here because Eloquent also has its own wrapper for that class called Eloquent\Builder that shares most of the same syntax. For better or for worse, Eloquent attempts to allow the developer to interact with it in a way that's familiar; not having to track a new set of method names even if you've been seamlessly dropped out of Eloquent and into a Query\Builder object via a magic __call method. It also does something similar regarding Eloquent\Collections vs. Support\Collections. But that can make things very confusing at first, because you have to just kind of know what package you're talking to.
So, to answer your question...
Build a Model class for each of your three tables
Apply relationship methods to each one to pre-configure the model with an awareness of your foreign keys
Call on them using lazy or eager-loading
Something else to note is that with() does not ask Eloquent to perform a JOIN. All it does is run the parent query, extract the key values from the result, run the child query using them in an IN() statement, and marrying the results together afterwards. That's what results in nested results. Speaking from experience, it's kind of a mess generating true JOIN statements off Model Relations and keeping the table aliases unique, so it makes sense this package just skips trying to do that (except with pivot tables on many-to-many relations). This also has the added benefit though, that your related tables don't need to live in the same database. A Query\Builder join() on the other hand, as you have there, would present all fields for all tables at the top-level.

How do the "has" and "whereHas" methods work in Eloquent?

I have a relationship defined between users and permisson, a user can have many permissions.
When I use "with" I get the data normally.
$user->with('permisson')->get();
I get the user with their permissions.
When I use "has" it only returns the user.
$user->has('permission')->get();
For what I've read, I should get the permissons if the user contains at least one permission.
I am using Postgres driver.
with is used for eager loading a relationship. You'd use it to fetch all of the specified relationships for each model (individually, or in a collection).
has is for using the relationship as a constraint or filter. As you said, using something like has('permission') will add a constraint to the query that says "only get Users that have at least one permission". This does not automatically load the relations like with(), it only creates the constraint.
You can combine the two if you want to take advantage of both the constraint and eager loading the results.
User::has('permission')->with('permission')->get();
Seems a bit redundant, I know.
From laravel docs:
If you wish to limit your results based on the existence of a relationship, you should use the has method. For example, if you want to retrieve all blog posts taht have at least one comment, yo may pass the name of the relationship to the has and orHas methods:
$posts = Post::has('comments')->get();
So, when you use the has method, it will not return the relationship, but just the post models which has at least one comment.
The whereHas and orWhereHas methods allows you to add customized constraints to a relationship constraint, such as checking the content of a comment (using the laravel example):
$posts = App\Post::whereHas('comments', function (Builder $query) {
$query->where('content', 'like', 'foo%');
})->get();
When you use the with method, you are loading the realtionship with the model:
$user->with('permission')->get()
This code will load the user and the permission relationship, while this one
$user->has('permission')->get();
will load the user who has some permission.
Hope it helps.

get laravel eloquent model relationships

is there any way to get the defined relationships in eloquent model. I have a situation where I need to get the model relationships so I can update all other eloquent models that relies on a specific id before delete it
There's no unified method to iterate over all registered relationships of a class. You can, however, access all the currently loaded relationships of a model instance (via the ->relations attribute or the getRelations() method), but that's not what you're up to. I'd suggest you take a look at laravel's documentation on inserting and updating relationships. So far that's the best laravel provides out of the box, the rest is developing approaches.
Try this function:
public function getRelations()
You can use
$model->getRelations()
function to get all relations
Also refer below link for details https://laravel.com/api/5.7/Illuminate/Database/Eloquent/Concerns/HasRelationships.html#method_getRelations

Models responsability

I have a doub about Laravel. The models are used to define the relationships between the models like hasMany, belongsTo, etc. Also the models are used to define the fillable fields. But he models are only for that? Because I already check some examples that it seems that some queries are executed in the models instead of the controller so Im not understanding if the models should also have the querying of the relationships or not. Can you give a help to understand better what is the correct use of models (what should be placed in the models)?
Its same way to execute queries on model or controller. Written queries in model make your controller more clean. We can write mutator, accessor or query scope in eloquent model. Correct me if I'm wrong.
Visit https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Model.html
You can refer this documentation, it's quite helpful if you want to know deep basics and responsibilities about particular part in Laravel.
Models are mostly used to make an outlook of the data i.e what fields are going to be saved in the database and we also use it to associate the relationships with other related data as you already know but we also use it to alter the values that are either going in/out of the data base which you can check in the documentation in link bellow https://laravel.com/docs/5.6/eloquent-mutators
the main purpose is to divide the code between controller and model (were it best fit to be)

How to use eager loading with custom query builder in Laravel

I am new to Laravel 5.4 and working on some query manipulation. Now I have created an query using query builder which is shown below:
$view = DB::table('blocks')
->leftjoin('programmes', 'blocks.programme_id', '=', 'programmes.id')
->select('blocks.id', 'blocks.programme_id', 'blocks.name', 'blocks.colour', 'blocks.year', 'programmes.title AS programme');
I have two more table "dates" and "modules". Each dates as well as module belongs to blocks.
Now I want to fetch all blocks with programmes, dates and modules. I know i can use with() method to get all of these. But as per my knowledge on Laravel, I can use with() method only if I have model file of each table and have relationship between them.
But do not want to use model and define relationship between them. I just want to know How can I get block data with programmes, dates and modules without creating model and defining relationship betwen them in model? Is there any other way to use with() method without model?
Block dates and modules are conditional, Sometime I dont want get data of this table with block.
Please help me on this.
You can't do it automatically. Eager loading is only for Eloquent model so you cannot use it with query builder. However in most cases you can use Eloquent also for getting more complicated queries (you can also use joins when using Eloquent) so you will be able to use eager loading.
But if you don't want to use Eloquent at all, obviously you will need to create some custom mechanism for eager loading.

Resources