Laravel-eloquent: Call to undefined method Illuminate\Database\Eloquent\Collection::where() - php

I have two models in many-to-one relationship:
class Meal extends \Eloquent {
/**
* public Integer $id; - primary key
* public String $name;
*/
protected $fillable = array('id','name');
public function mealProperties()
{
return $this->hasMany('MealProperty');
}
}
class MealProperty extends \Eloquent {
/**
* public Integer $id; - primary key
* public Integer $meal_id;
*/
protected $fillable = array('id','meal_id');
public function meal()
{
return $this->belongsTo('Meal', 'meal_id');
}
}
if I ask for first meal first mealProperty everything go fine:
$mealProp = Meal::first()->mealProperties->first();
but if I ask for mealProperty with specific id of first meal this way:
$mealProp = Meal::first()->mealProperties->where('id','=','1')->first();
I get this error:
Call to undefined method Illuminate\Database\Eloquent\Collection::where()
I google what I'm doing wrong two hours, but still nothing.
If I can't use where method, what is possible way to get specific mealProperty?
Thank you for help!

UPDATE for Laravel 5:
Since v5 release there is a method where on the Support\Collection object, so this question/answer becomes irrelevant. The method works exactly like filter, ie. returns filtered collection straight away:
$mealProp = Meal::first()->mealProperties->where('id','=','1'); // filtered collection
// that said, this piece of code is perfectly valid in L5:
$mealProp = Meal::first()->mealProperties->where('id','=','1')->first();
You must distinguish Laravel behaviour:
(dynamic property) Eloquent Collection or Model
$meal->mealProperties
Relation Object
$meal->mealProperties()
Now:
// mealProperties is Eloquent Collection and you call first on the Collection here
// so basically it does not affect db query
$mealProp = Meal::first()->mealProperties->first();
// here you try to add WHERE clause while the db query is already called
$mealProp = Meal::first()->mealProperties->where('id','=','1')->first();
// So this is what you want to do:
$mealProp = Meal::first()->mealProperties()->where('id','=','1')->first();

You may try this:
$mealProop1 = Meal::first()->mealProperties->find(1); // id = 1
Or something like this:
$mealProops = Meal::first()->mealProperties;
$mealProop5 = $mealProops->find(5); // id = 5
$mealProop7 = $mealProops->find(7); // id = 7
Instead of this:
$mealProp = Meal::first()->mealProperties->where('id','=','1')->first();
Also, following should work:
$mealProp = Meal::first()->mealProperties->first();

Related

How to write count(*) SQL in DQL, Doctrine ORM

How to get count of rows in database by id?
SELECT count(*) FROM members;
Without performance issues. What are ways to write this query using entityManager?
I am using php version 5.6 and symfony 3
You have to use your EntityRepository
Add a function in it and write something like this:
$queryBuilder = $this->_em->createQueryBuilder()
->select('COUNT(e)')
->from('AppBundle:Entity', 'e');
return $queryBuilder->getQuery()->getSingleScalarResult();
Edit: Just saw Gregoire's answer. That will work. However, if you already have the Entity which has the relation, and it's initialized, the below would allow you to get this info without an additional query to the DB.
You could use the association and get it from the Collection (see Working with Associations in the docs
class SomeEntity
{
/**
* #var Collection|Member[]
*/
protected $members;
// other properties
// PHP >= 7 -> public function countMembers(): int
public function countMembers()
{
return $this->getMembers()->count();
}
// PHP >= 7 -> public function getMembers(): Collection
public function getMembers()
{
return $this->members;
}
// other getters/setters
}

Getting value of joined table Yii 2

Hello I am trying to access a value from a joined table schead.section to store in subjectcontainer.section, mainly I am using the scstock data but the section part is located in schead.section so what I did was to join the schead and schstock together so that I can have access to the section column. Here is what I did.
$subject = ActiveCurriculum::find()
->select('scstock.*')
->leftJoin('schead', 'schead.TrNo = scstock.TrNo')
->where([ 'schead.TrNo' => $TrNo])
->one();
$activesubject = new ActiveSubject();
$activesubject->clientid = $clientid;
$activesubject->TrNo = $subject->TrNo;
$activesubject->subjectcode = $subject->subjectcode;
$activesubject->schedday = $subject->schedday;
$activesubject->schedtime = $subject->schedtime;
$activesubject->section = $subject->section;
$activesubject->room = $subject->room;
$activesubject->units = $subject->units;
$activesubject->save();
//reduces the slot of ccsubject by 1
$subject->slots = $subject->slots - 1;
//never forget the saving part
$subject->save();
First $subject will access sctock table to join will schead via TrNo. then $activesubject will access subjectcontainer table to store the values in. Now my problem is I am getting this error.
Can someone help me in trying to solve this?
Make sure to define relation to the Schead object in your model. Example of such relation:
/**
* #property $schead Schead
*/
class YourModel extends \yii\db\ActiveRecord
{
/**
* #return Schead
*/
public function getSchead()
{
return $this->hasOne(Schead::className(), ['field1' => 'field2']);
}
}
Also, $subject->schead.section is a wrong way of accessing related model attributes. Use $subject->schead->section instead. If having schead is optional, don't forget to check existence of related object first, for example:
$subject->schead ? $subject->schead->section : null
Also check code for typos (probably sched / schead?). You can read more about working with relations in official docs.

Eloquent next record

I am trying to get the last 3 blog post from the database into single variables (for templates). I saw a good implementation at some other thred and it works fine for the next record but on the third query returns with NULL. What is your opinion about this problem?
BlogController.php:
public function getIndex($l = 'hu')
{
$post_last = Post::orderBy('created_at', 'desc')->first();
$post_2 = $post_last->next($post_last->created_at);
$post_3 = $post_2->next($post_2->created_at);
var_dump($post_3);
}
Post.php:(Model)
<?php
namespace Civitas;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* Physical table name
*/
protected $table = 'posts';
/**
* Get next result in record list
*
* #param $created_at
* #return mixed
*/
public function next($c) {
return Post::where('created_at', '<', $c)->get()->first();
}
}
I can't tell why your function doesn't work, but I suggest you try this approach:
$posts = Post::orderBy('created_at', 'desc')->take(3)->get();
$post1 = $posts->shift();
$post2 = $posts->shift();
$post3 = $posts->shift();
This will only run one query instead of three. Calling shift() on the collection will then return the first item and remove it so the second post will be "first" the next time you call it.
In your next function, the result will give the earliest post, not the next one. Therefore, the third call will return null because there is no post after the earliest one. Adding orderBy for created_at field, it will work as expected.
public function next(){
return static::where('created_at', '<' , $this->created_at)
->orderBy('created_at','desc')
->first();
}
Then in your controller, you can call like this:
$post_last = Post::orderBy('created_at', 'desc')->first();
$post2 = $post_last->next();
$post3 = post_last->next()->next();

CakePHP: Managing table names in a controller with a single variable

In controller A, I load a model not associated with this controller. I'm interested in managing the model name of controller B with a single variable, so I don't have to manually change many lines if the table/model B's name changes.
For example below is the controller A's code:
public $modelBName = 'ModelB';
public function controller_a_function() {
$this->loadModel($this->modelBName); // I use the variable here for model B
$this->ModelB->model_b_function(); // COMMENT #1
}
Question:
For the line commented "COMMENT #1," how do I use the variable name instead of explicitly written out word 'ModelB'? This line appears multiple times throughout the code, and I would like to use the variable $modelBName if possible. ModelB will likely not change, but if it does for some reason, it would be nice to just change one variable instead of editting multiple lines.
The simple answer; use this:
$this->{$this->modelBName}->find('all');
Note the curly brackets {} around the property name. more information can be found in the manual;
http://php.net/manual/en/language.variables.variable.php
A cleaner approach may be a sort of 'factory' method;
/**
* Load and return a model
*
* #var string $modelName
*
* #return Model
* #throws MissingModelException if the model class cannot be found.
*/
protected function model($modelName)
{
if (!isset($this->{$modelName})) {
$this->loadModel($modelName);
}
return $this->{$modelName};
}
Which can be used like this;
$result = $this->model($this->modelBName)->find('all');
debug($result);
And, if you don't want to specify the model, but want it to return a '$this->modelBName' automatically;
/**
* Load and return the model as specified in the 'modelBName' property
*
* #return Model
* #throws MissingModelException if the model class cannot be found.
*/
protected function modelB()
{
if (!isset($this->{$this->modelBName})) {
$this->loadModel($this->modelBName);
}
return $this->{$this->modelBName};
}
Which can be used like this:
$result = $this->modelB()->find('all');
debug($result);
I think you are confused between model name and table name. You can set a model to use a different database table by using the $useTable property, for example:
class User extends AppModel {
public $useTable = 'users_table'; // Database table used
}
class Product extends AppModel {
public function foo() {
$this->loadModel('User');
$this->User->find('all');
}
}
You should never need to change the name of the model, and if the name of the database table changes you can simply update the $useTable property in the model.

Working with a MY_Model

I’m using jamie Rumbelow’s MY model as a way to better deal with my application.
https://github.com/jamierumbelow/codeigniter-base-model
The MY_model is the same except I have an added in variable for defining whether or not an item in the db is marked as being soft deleted or not.
protected $soft_delete_value = 3;
I only have that variable defined and have not altered his code yet to account for this value.
I have two things I want to do with this titles model that I need help understanding.
Titles Table - title_id, title_name, title_status_id
Title_Statuses_Table - title_status_id, title_status_name
What I want it to do is retrieve all of the rows that have a title_status_id of 1 and 2 and 3 because the soft delete value is different than the default set in the MY Model. What I would also like to have is instead of it returning the integer have it return the name of the status.
Expected results:
An array of objects that contain a title_id, title_name, title_status_name for which the titles have a status id of 1,2, or 3.
Testing
$titles = $this->titles_model->get_all();
echo "<pre>";
print_r($titles);
echo "</pre>";
Actual results:
SELECT *
FROM (`titles`)
WHERE `title_status_id` = 0
<pre>Array
(
)
My Code
class Titles_model extends MY_Model
{
/* --------------------------------------------------------------
* VARIABLES
* ------------------------------------------------------------ */
/**
* This model's default database table.
*/
public $_table = 'titles';
public $primary_key = 'title_id';
/**
* Support for soft deletes and this model's 'deleted' key
*/
public $soft_delete = TRUE;
public $soft_delete_key = 'title_status_id';
public $soft_delete_value = 4;
public $_temporary_with_deleted = FALSE;
public function __construct()
{
parent::__construct();
}
}
Anybody else have any additional ideas/suggestions?
EDIT:
I've been tryign to figure this out all day and have hit a dead end.
well here would be the function that you would need to get your expected result
$this->db->select('
titles.*,
status.*,
')
->join('status s', 'titles.title_status_id = s.title_status_id', 'LEFT')
->where('titles.title_status_id', 1)
->or_where('titles.title_status_id', 2)
->or_where('titles.title_status_id', 3)
->from('titles')
->get()
->result_object();

Categories