Calling a function that exists inside another function - php

i just want to know how i would include a function inside another function. TRying to query my database for users 3 levels deep.
<?php
namespace App\Repositories\Referrals;
use Auth;
/**
*
*/
class EloquentReferrals implements ReferralRepository
{
function __construct(User $model)
{
return $this->model->all();
}
function __construct(User $model)
{
return $this->model->all();
}
public function getallreferrals()
{
return $this->model->where('referred_by', Auth::user()->referral_id)->get();
}
public function getallreferrals2gen()
{
}
public function getallreferrals3gen(){
}
public function getallreferralsbyID($id){
}
public function getallreferrals2gen($id){
}
public function getallreferrals3gen($id){
}
}
in my repository the get all referrals function returns all direct referrals. I want to use the result to get the referrals of those referrals. How do i include it inside my getallreferrals2gen function?

use $this to call a function from a function in the same class;
property, like so;
public function getallreferrals()
{
return $this->model->where('referred_by', Auth::user()->referral_id)->get();
}
public function getallreferrals2gen()
{
$this->getallreferrals()(
}

Related

How can I filter this with eloquent

I try to filter SurveyQuestionnaire which have Answer = 'poor' and their Questionnaire have step = 'rating'.
I've tried to look through the documentation of Eloquent and I've found nothing help.
This is my models.
class Questionnaire extends Model {
...
public function surveysQuestionnaires() {
return $this->hasMany(SurveyQuestionnaire::class, 'question_id');
}
public function answers() {
return $this->hasMany(Answer::class, 'question_id');
}
public function questionnaires() {
return $this->hasMany(QuestionnaireTranslation::class, 'question_id' );
}
}
class SurveyQuestionnaire extends Model {
public function survey() {
return $this->belongsTo(Survey::class ,'survey_id');
}
public function questionnaires() {
return $this->belongsTo(Questionnaire::class, 'question_id');
}
public function answer() {
return $this->belongsTo(Answer::class, 'answer_id');
}
}
Well, the hasMany method returns query builder, so you can simply add some conditions:
public function surveysQuestionnaires() {
return $this->hasMany(SurveyQuestionnaire::class, 'question_id')->where('Answer', 'poor');
}
Also, you can read this link Constraining Eager Loads and add your conditions manually after taking an instance of your model:
$items = App\Questionnaire::with(['surveysQuestionnaires' => function ($query) {
$query->where('Answer', 'poor');
}])->get();

How to sum of function value from related table?

I have two Classes: Share and related EquityGrant
I have this this math function in EquityGrant
public function share() //relationship
{
return $this->belongsTo(Share::class, 'share_id');
}
public function capitalCommitted() //my math function
{
return $this->share_price * $this->shares_amount;
}
But now I need to return in my Share class sum of capitalCommitted() function and here I'm stuck.
My Share class:
public function grants() //relationship
{
return $this->hasMany(EquityGrant::class);
}
public function totalIssued() //sum, works good
{
return $this->grants->sum('shares_amount');
}
public function totalCommitted() //Stuck here
{
//need help here, Must be like this: array_sum($this->grants->capitalCommitted());
}
Use this:
public function getCapitalCommittedAttribute()
{
return $this->share_price * $this->shares_amount;
}
public function totalCommitted()
{
return $this->grants->sum('capitalCommitted');
}

Chaining Symfony Repository Methods ( Filters )

What is the best practice to chain repository methods to reuse query building logic?
Here is how I did it, but I doubt if this is the right way:
use Doctrine\ORM\Mapping;
use Doctrine\ORM\EntityManager;
class OrderRepository extends \Doctrine\ORM\EntityRepository
{
private $q;
public function __construct(EntityManager $em, Mapping\ClassMetadata $class)
{
parent::__construct($em, $class);
$this->q = $this->createQueryBuilder('o');
}
public function getOneResult()
{
return $this->q->getQuery()->getOneOrNullResult();
}
public function getResult()
{
return $this->q->getQuery()->getResult();
}
public function filterByStatus($status)
{
$this->q->andWhere('o.status = :status')->setParameter('status', $status);
return $this;
}
public function findNextForPackaging()
{
$this->q->leftjoin('o.orderProducts', 'p')
->orderBy('o.deliveryDate', 'ASC')
->andHaving('SUM(p.qtePacked) < SUM(p.qte)')
->groupBy('o.id')
->setMaxResults(1);
return $this;
}
}
This allows me to chain method like this:
$order = $em->getRepository('AppBundle:Order')->filterByStatus(10)->findNextForPackaging()->getOneResult();
This is of course just an example. In reality there are many more methods that can be chained.
One big problem with this is the fact that I need a join for some of the "filters", so I have to check if the join has already been set by some method/filter before I add it. ( I did not put it in the example, but I figured it out, but it is not very pretty )
The other problem is that I have to be careful when using the repository, as the query could already be set to something, so I would need to reset the query every time before using it.
I also understand that I could use the doctrine "matching" method with criteria, but as far as I understood, this is rather expensive, and also, I don't know how to solve the "join" Problem with that approach.
Any thoughts?
I made something similar to what you want:
Controller, this is how you use it. I am not returning Response instance but serialize the array in kernel.view listener but it is still valid example:
/**
* #Route("/root/pending_posts", name="root_pending_posts")
* #Method("GET")
*
* #return Post[]
*/
public function pendingPostsAction(PostRepository $postRepository, ?UserInterface $user): array
{
if (!$user) {
return [];
}
return $postRepository->begin()
->wherePublished(false)
->whereCreator($user)
->getResults();
}
PostRepository:
class PostRepository extends BaseRepository
{
public function whereCreator(User $user)
{
$this->qb()->andWhere('o.creator = :creator')->setParameter('creator', $user);
return $this;
}
public function leftJoinRecentComments(): self
{
$this->qb()
->leftJoin('o.recentCommentsReference', 'ref')->addSelect('ref')
->leftJoin('ref.comment', 'c')->addSelect('c');
return $this;
}
public function andAfter(\DateTime $after)
{
$this->qb()->andWhere('o.createdAt > :after')->setParameter('after', $after);
return $this;
}
public function andBefore(\DateTime $before)
{
$this->qb()->andWhere('o.createdAt < :before')->setParameter('before', $before);
return $this;
}
public function wherePublished(bool $bool)
{
$this->qb()->andWhere('o.isPending = :is_pending')->setParameter('is_pending', !$bool);
return $this;
}
}
and BaseRepository has most used stuff, still work in progress:
namespace wjb\CoreBundle\Model;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
abstract class BaseRepository extends EntityRepository
{
/** #var QueryBuilder */
private $qb;
public function begin()
{
$this->qb = $this->createQueryBuilder('o');
return $this;
}
public function qb(): QueryBuilder
{
return $this->qb;
}
public function none()
{
$this->qb()->where('o.id IS NULL');
return $this;
}
public function setMaxResults($maxResults)
{
$this->qb()->setMaxResults($maxResults);
return $this;
}
public function addOrderBy($sort, $order = null)
{
$this->qb()->addOrderBy($sort, $order);
return $this;
}
public function getResults()
{
return $this->qb()->getQuery()->getResult();
}
}
This helps me a lot in chaining calls like in controller example.

Eloquent Relationships (Laravel 5.4)

I'm making a Laravel 5.4 application, but I'm having a hard time figuring out how I should structure my data with eloquent relationships.
This is my models and how I want them to be related:
School → Has classes, users and events
User → Can belong to a school. Can have classes and sessions (with cases)
Class → Belongs to a school. Has users and subjects. Can have homework
Subject → Belongs to a class
Session → Belongs to a user. Can have cases
Case → Belongs to a session
Event → Belongs to a school
Homework → Belongs to a class
How should I structure this with eloquent relation functions (belongsTo, hasMany and so on) in my Laravel 5.4 project?
Assuming Class, User and Event models has a property school_id and the primary key you ant to use is id of the respective model, your Class, User, Event and School models should look like as follow.
School
class School extends Model
{
public function users(){
return $this->hasMany('App\User');
}
public function classes(){
return $this->hasMany('App\Class');
}
public function sessions(){
return $this->hasMany('App\Session');
}
}
User
class User extends Model
{
public function school(){
return $this->belongsTo('App\School');
}
public function classes(){
return $this->hasMany('App\Class');
}
public function events(){
return $this->hasMany('App\Event');
}
}
Class
class Class extends Model
{
public function school(){
return $this->belongsTo('App\School');
}
public function users(){
return $this->hasMany('App\User');
}
public function subjects(){
return $this->hasMany('App\Subject');
}
public function homeworks(){
return $this->hasMany('App\Homework');
}
}
Event
class Class extends Model
{
public function school(){
return $this->belongsTo('App\School');
}
}
You can use these relationships to define queries with chaining capability. e.g. if you want to get all the events associated with a School that has a id property equals to $id you can write,
$events = App\School::find($id)->events;
Laravel Documentation explains it well
The correct way to do this is
SCHOOL
public function classes()
{
return $this->hasMany('App\Class');
}
public function users()
{
return $this->hasMany('App\User');
}
public function events()
{
return $this->hasMany('App\Event');
}
CLASS
public function school()
{
return $this->belongsTo('App\School');
}
public function subjects()
{
return $this->hasMany('App\Subject');
}
public function homeworks()
{
return $this->hasMany('App\Homework');
}
public function users()
{
return $this->belongsToMany('App\User','class_users','class_id','user_id');
// this should be many to many because users can also have many classes
}
USER
public function school()
{
return $this->belongsTo('App\School');
}
public function classes()
{
return $this->belongsToMany('App\Class','class_users','user_id','class_id');
// this should be many to many as explained to class
}
public function sessions()
{
return $this->belongsToMany('App\Session','session_users','user_id','session_id');
// like classes do, this should be many to many relationship because sessions can also have many users
}
SUBJECT
public function class()
{
return $this->belongsTo('App\Class');
}
SESSION
public function users()
{
return $this->belongsToMany('App\User','session_users','session_id','user_id');
// should be many to many as well
}
public function cases()
{
return $this->hasMany('App\Case');
}
CASE
public function session()
{
return $this->belongsTo('App\Session');
}
EVENT
public function school()
{
return $this->belongsTo('App\School');
}
HOMEWORK
public function class()
{
return $this->belongsTo('App\Class');
}
With the School model and underlying table created, it’s time to create the relation. Open the School model and create a public method named classes, users and events; inside it referencing the hasMany method:
School :
class School extends Model {
public function classes()
{
return $this->hasMany('App\Class');
}
public function users()
{
return $this->hasMany('App\User');
}
public function events()
{
return $this->hasMany('App\Event');
}
}
User :
class User extends Model {
public function school(){
return $this->belongsTo('App\School');
}
public function classes(){
return $this->hasMany('App\Class');
}
public function sessions(){
return $this->hasMany('App\Session');
}
}
Class :
class Class extends Model {
public function school(){
return $this->belongsTo('App\School');
}
public function users(){
return $this->hasMany('App\User');
}
public function subjects(){
return $this->hasMany('App\Subject');
}
public function homeworks(){
return $this->hasMany('App\Homework');
}
}
Subject :
class Subject extends Model {
public function class(){
return $this->belongsTo('App\Class');
}
}
Session:
class Session extends Model {
public function user(){
return $this->belongsTo('App\User');
}
public function cases(){
return $this->hasMany('App\Case');
}
}
Case :
class Case extends Model {
public function session(){
return $this->belongsTo('App\Session');
}
}
Event :
class Event extends Model {
public function school(){
return $this->belongsTo('App\School');
}
}
Homework:
class Homework extends Model {
public function class(){
return $this->belongsTo('App\Class');
}
}
For more details of hasMany relationship, Please check the link here : EasyLaravelBook

Eager loading on polymorphic relations

class Admin {
public function user()
{
return $this->morphOne('App\Models\User', 'humanable');
}
public function master()
{
return $this->hasOne('App\Models\Master');
}
}
class Master {
public function admin()
{
return $this->hasOne('App\Models\Admin');
}
}
class User {
public function humanable()
{
return $this->morphTo();
}
public function images()
{
return $this->hasOne('\App\Models\Image');
}
}
class Image {
public function user()
{
return $this->belongsTo('\App\Models\User');
}
}
Now if I dump this:
return \App\Models\Admin::where('id',1)->with(array('user.images','master'))->first();
I get the perfect result one master, one user and one image record.
But if I do this
return $user = \App\Models\User::where('id',1)->with(array('humanable','humanable.master'))->first();
I only get one Admin record, the query get * from masters doesn't even run.
Any idea what I'm doing wrong, I'm sure this is possible.
If I remember correctly Laravel has lots of pitfall. You can try to use the protected $with var in Admin model instead of query builder with function.
class Admin {
protected $with = ['master'];
public function user() {
return $this->morphOne('App\Models\User', 'humanable');
}
public function master() {
return $this->hasOne('App\Models\Master');
}
}
In query builder, only need to include humanable. Now you should see master inside the humanable object.
return $user = \App\Models\User::where('id',1)->with('humanable')->first();
Hope this help.

Categories