Asked  2 Years ago    Answers:  5   Viewed   97 times

I have a phone_models, phone_problems, and a phone_model_phone_problem pivot table. The pivot table has an extra column 'price'.

PhoneModel:

class PhoneModel extends Eloquent
{
    public function problems()
    {
        return $this->belongsToMany('RLPhonesEntitiesPhoneProblem')->withPivot('price');
    }
}

PhoneProblem:

class PhoneProblem extends Eloquent
{
    public function models()
    {
        return $this->belongsToMany('PhoneModel')->withPivot('price');
    }
}

What I'm trying to do is get the price of a specific phone with a specific problem.

This is how I have it now but I feel like Laravel has a built in Eloquent feature I can't find to do this in a much simpler way:

$model = $this->phoneService->getModelFromSlug($model_slug);
$problem = $this->phoneService->getProblemFromSlug($problem_slug);

all this does is select the specific model and problem from their slug.

then what I do is with those credentials I get the price like so:

$row = DB::table('phone_model_phone_problem')
->where('phone_model_id', '=', $model->id)
->where('phone_problem', '=', $problem->id)
->first();

so now I can get the price like so $row->price but I feel like there needs to be a much easier and more 'Laravel' way to do this.

 Answers

5

When using Many to Many relationships with Eloquent, the resulting model automatically gets a pivot attribute assigned. Through that attribute you're able to access pivot table columns. Although by default there are only the keys in the pivot object. To get your columns in there too, you need to specify them when defining the relationship:

return $this->belongsToMany('Role')->withPivot('foo', 'bar');

Official Docs

If you need more help the task of configuring the relationships with Eloquent, let me know.

Edit

To query the price do this

$model->problems()->where('phone_problem', $problem->id)->first()->pivot->price
Friday, December 2, 2022
2

You can't do that using with, because it executes separate query.

What you need is simple join. Just translate the query you have to something like:

Posts::join('comments as c', 'posts.id', '=', 'c.id')
    ->selectRaw('posts.*, count(distinct c.id) as numComments')
    ->groupBy('posts.id', 'posts.post_title')
    ->with('user', 'vote', 'tags')
    ->get();

then each post in the collection will have count attribute:

$post->numComments;

However you can make it easier with relations like below:

Though first solution is better in terms of performance (might not be noticeable unless you have big data)

// helper relation
public function commentsCount()
{
    return $this->hasOne('Comment')->selectRaw('posts_id, count(*) as aggregate')->groupBy('posts_id');
}

// accessor for convenience
public function getCommentsCountAttribute()
{
    // if relation not loaded already, let's load it now
    if ( ! array_key_exists('commentsCount', $this->relations)) $this->load('commentsCount');

    return $this->getRelation('commentsCount')->aggregate;
}

This will allow you to do this:

$posts = Posts::with('commentsCount', 'tags', ....)->get();
// then each post:
$post->commentsCount;

And for many to many relations:

public function tagsCount()
{
    return $this->belongsToMany('Tag')->selectRaw('count(tags.id) as aggregate')->groupBy('pivot_posts_id');
}

public function getTagsCountAttribute()
{
    if ( ! array_key_exists('tagsCount', $this->relations)) $this->load('tagsCount');

    $related = $this->getRelation('tagsCount')->first();

    return ($related) ? $related->aggregate : 0;
}

More examples like this can be found here http://softonsofa.com/tweaking-eloquent-relations-how-to-get-hasmany-relation-count-efficiently/

Tuesday, August 16, 2022
 
1

You are probably going to have to develop your own relationship classes. Ex:

MODEL

public function answers()
{
    $instance = new Response();
    $instance->setSid($this->sid);
    return new QuestionAnswerRelation($instance->newQuery(),$this);
}

RELATIONSHIP

use IlluminateDatabaseEloquentBuilder;
use IlluminateDatabaseEloquentCollection;
use IlluminateDatabaseEloquentRelationsRelation;
use PivotalSurveyModelsAnswer;
use PivotalSurveyModelsCollectionsAnswerCollection;
use PivotalSurveyModelsQuestionInterface;
use PivotalSurveyModelsSurveyInterface;

class QuestionAnswerRelation extends Relation
{

    /**
     * Create a new relation instance.
     *
     * @param  IlluminateDatabaseEloquentBuilder  $query
     * @param  IlluminateDatabaseEloquentModel  $parent
     * @return void
     */
    public function __construct(Builder $query, QuestionInterface $parent)
    {
        $table = $query->getModel()->getTable();
        $this->query = $query
            ->select(array(
                DB::raw($parent->sid.'X'.$parent->gid.'X'.$parent->qid . ' AS value'),
                'id'
            ));

        $this->query = $query;
        $this->parent = $parent;
        $this->related = $query->getModel();
        $this->addConstraints();
    }


    public function addEagerConstraints(array $models)
    {
        parent::addEagerConstraints($models);
    }

    public function initRelation(array $models, $relation)
    {

    }

    public function addConstraints()
    {

    }

    public function match(array $models, Collection $results, $relation)
    {

    }

    public function getResults()
    {
        $results = $this->query->get();
        $answerCollection = new AnswerCollection();

        foreach($results as $result)
        {
            $answer = new Answer($result->toArray());
            $answer->question = $this->parent;
            $answerCollection->add($answer);
        }

        return $answerCollection;
    }

In this case we are using Lime Survey which creates a unique table (note the $instance->setSid() changes the table name) for each of its surveys and a unique column for each of its answer -> question values. ( note $parent->sid.'X'.$parent->gid.'X'.$parent->qid. 'AS value')

Where sid = survey_id, gid = group_id(I think) and qid = question_id

Its was quite irritating.

Note how I reference values from the parent to further develop the query. You should be able to follow a similar route to achieve whatever your heart desires and still maintain the feasibility to use Eloquent.

Thursday, November 17, 2022
 
ckozl
 
1

In XML, it would look something like this:

style="?header_background"

programmatically, it's a little trickier. In your activity:

private static Theme theme = null;

protected void onCreate(Bundle savedInstanceState) {
   ...
   theme = getTheme();
   ...
}

public static int getThemeColors(int attr){
   TypedValue typedvalueattr = new TypedValue();
   theme.resolveAttribute(attr, typedvalueattr, true);
   return typedvalueattr.resourceId;
}

And when you want to access an attribute of the theme, you would do something like this:

int outside_background = MyActivity.getThemeColors(R.attr.outside_background);
setBackgroundColor(getResources().getColor(outside_background));

It's a little more convoluted, but there you go ;-)

Wednesday, August 17, 2022
 
3

The option values don't have the ValDate attribute - you've probably meant to get value attribute instead. Replace:

dropdown.getFirstSelectedOption().getAttribute("ValDate");

with:

dropdown.getFirstSelectedOption().getAttribute("value");
Friday, September 16, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 

Browse Other Code Languages