Hi I'm using Laravel 4 and I have three models, Project (table name projects), Status (tables name: statuses) and AssignedProjectBoardStatus (table name: assigned_project_board_statuses). Now when I create a project statuses are automatically assigned if they are not selected from a list. The assigned_project_board_statuses table has two foreign keys the table schema is below:
id|project_id|status_id|order|created_at|updated_at
project_id and status_id are the foreign keys. Now I have a model as so:
app/models/AssignedProjectBoardStatus.php
class AssignedProjectBoardStatus extends AbstractModel {
public function projects() {
return $this->belongsTo('Project');
}
public function statuses() {
return $this->belongsTo('Status');
}
}
app/models/Project.php
class Project extends AbstractModel
{
public function assignedProjectBoardStatus() {
return $this->hasMany('AssignedProjectBoardStatus');
}
app/models/Status.php
class Status extends AbstractModel {
public function assignedProjectBoardStatus() {
return $this->hasMany('AssignedProjectBoardStatus');
}
There when I am fetching the projects and I want to see the statuses assigned I would call this as follows:
Project::assignedScrumBoardStatuses();
However this throws the following error:
Non-static method Project::assignedProjectBoardStatuses() should not be called statically, assuming $this from incompatible context
So I've changed the function as follows:
app/models/Project.php
class Project extends AbstractModel
{
public **static** function assignedProjectBoardStatus() {
return $this->hasMany('AssignedProjectBoardStatus');
}
However this then threw the following error:
Using $this when not in object context
So i then changed the function as follows:
public **static** function assignedScrumBoardStatuses() {
return **static::**hasMany('AssignedScrumBoardStatus');
}
And this then threw this error:
Non-static method Illuminate\Database\Eloquent\Model::hasMany() should not be called statically
Any ideas what I'm doing wrong and how I can get the assigned statuses from the model??
You can’t call Project::assignedScrumBoardStatuses() because when you do, the Project model doesn’t know which record you’re trying to fetch the assigned scrum board status for. It has no context.
Instead, find a record so you have a model instance, and you can then call your relation methods on that:
$project = Project::find($id)->assignedScrumBoardStatuses();
Related
I am using Laravel/Passport and already can get data by id:
api.php/Controller.php
Route::get('members/{member}', 'MemberController#show');
public function show(Member $member)
{
return $member;
}
This just return all data by id, now I want to get member by phone number, so I created:
Route::get('members/{phone}', 'MemberController#phone');
public function phone(Member $member)
{
return $member;
}
Error:
exception:
"Symfony\Component\HttpKernel\Exception\NotFoundHttpException" file:
"C:\Users\xx\xx\xx\xx\vendor\laravel\framework\src\Illuminate\Foundation\Exceptions\Handler.php"
line: 204 message: "No query results for model [App\Member]
2929292222"
route
Route::get('members/{phone}', 'MemberController#phone');
controller
public function phone(Member $member)
{
return $member;
}
Go to Member.php model
and add this method getRouteKeyName
public function getRouteKeyName()
{
return 'phone';
}
Laravel by default it will automatically inject the model instance that has an ID matching the corresponding value from the request URI.
If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model:
for more information check the documentation
I have the following table structure in my database:
products
id
product_formats
id
product_id
product_prices
id
product_format_id
When I'm trying to do $this->format->product; inside my ProductPrice class, I get an error:
LogicException: App\ProductPrice::product must return a relationship instance.
When I perform a dd inside my function:
dd($this->format()->first()->product);
I get the instance of the product. However, removing the dd would still throw the exception.
Why am I getting the LogicException?
ProductPrice
class ProductPrice extends Model
{
public function format()
{
return $this->belongsTo(ProductFormat::class, 'product_format_id');
}
public function product()
{
return $this->format->product;
}
}
ProductFormat
class ProductFormat extends Model
{
public function product()
{
return $this->belongsTo(Product::class);
}
}
Update
The result of dd($this->format); returns an instance of ProductFormat.
After investigating the HasAttributes::getRelationshipFromMethod(), I've noticed that if the property does not exist in the properties attribute of the class, it will try to retrieve a relation, hence the error.
To fix it, I had to add the following to my class:
protected $attributes = ['product'];
Otherwise, I could call product as a function instead of attribute:
$price->product();
I'm not sure I am asking the questions correctly, but this is what I am trying to do.
So we can get the current from
$model = Model::find($id)
Then we can get it's relationships like:
$model->relationships()->id
Then we have actions like:
$model->relationships()->detach(4);
My question is, can we have a custom method like:
$model->relationships()->customMethod($params);?
and in the model it may look like:
public function customMethod($params){
//Do something with relationship id
}
But further more, how in the customMethod would I get the $models info like id?
Sorry if this may be a bit confusing.
First of all, if you want to access a related object, you do this by accessing an attribute with the same name as the relation. In your case, in order to access object(s) from relationships, you need to do this by:
$model->relationships //returns related object or collection of objects
instead of
$model->relationships() //returns relation definition
Secondly, if you want to access attributes on the related object, you can do it the same way:
$relatedObjectName = $model->relationship->name; // this works if you have a single object on the other end of relations
Lastly, if you want to call a method on a related model you need to implement this method in related model class.
class A extends Eloquent {
public function b() {
return $this->belongsTo('Some\Namespace\B');
}
public function cs() {
return $this->hasMany('Some\Namespace\C');
}
}
class B extends Eloquent {
public function printId() {
echo $this->id;
}
}
class C extends Eloquent {
public function printId() {
echo $this->id;
}
}
$a = A::find(5);
$a->b->printId(); //call method on related object
foreach ($a->cs as $c) { //iterate the collection
$c->printId(); //call method on related object
}
You can read more about how to define and use relationships here: http://laravel.com/docs/5.1/eloquent-relationships
Could you provide an example usage. Description will be highly appreciated. I can not find a good example for it.
The Active Query represents a DB query associated with an Active Record class. It is usually used to override the default find() method of a specific model where it will be used to generate the query before sending to DB :
class OrderQuery extends ActiveQuery
{
public function payed()
{
return $this->andWhere(['status' => 1]);
}
public function big($threshold = 100)
{
return $this->andWhere(['>', 'subtotal', $threshold]);
}
}
If you worked before with Yii 1 then this is what replaces Yii 1.x Named Scopes in Yii2. All you have to do is to override the find() method in your model class to use the ActiveQuery class above :
// This will be auto generated by gii if 'Generate ActiveQuery' is selected
public static function find()
{
return new \app\models\OrderQuery(get_called_class());
}
Then you can use it this way :
$payed_orders = Order::find()->payed()->all();
$very_big_orders = Order::find()->big(999)->all();
$big_payed_orders = Order::find()->big()->payed()->all();
A different use case of the same ActiveQuery class defined above is by using it when defining relational data in a related model class like:
class Customer extends \yii\db\ActiveRecord
{
...
public function getPayedOrders()
{
return $this->hasMany(Order::className(),['customer_id' => 'id'])->payed();
}
}
Then you can eager load customers with their respective payed orders by doing :
$customers = Customer::find()->with('payedOrders')->all();
I look at many search results with this trouble but i can`t get it to work.
The User Model:
<?php namespace Module\Core\Models;
class User extends Model {
(...)
protected function Person() {
return $this->belongsTo( 'Module\Core\Models\Person', 'person_id' );
}
(...)
And the Person Model:
<?php namespace Module\Core\Models;
class Person extends Model {
(...)
protected function User(){
return $this->hasOne('Module\Core\Models\User', 'person_id');
}
(...)
Now, if i use User::find(1)->Person->first_name its work. I can get the Persons relations from the User Model.
But.. User::with('Person')->get() fails with a Call to undefined method Illuminate\Database\Query\Builder::Person()
What im doing wrong? i need a collection of all the users with their Person information.
You have to declare the relationship methods as public.
Why is that? Let's take a look at the with() method:
public static function with($relations)
{
if (is_string($relations)) $relations = func_get_args();
$instance = new static;
return $instance->newQuery()->with($relations);
}
Since the method is called from a static context it can't just call $this->Person(). Instead it creates a new instance of the model and creates a query builder instance and calls with on that and so on. In the end the relationship method has to be accessible from outside the model. That's why the visibility needs to be public.