Having the following Models:
news.php
class News extends Aware {
public static $table = 'noticia';
public static $key = 'idnoticia';
public static $timestamps = false;
public static $rules = array(
'titulo' => 'required',
'subtitulo' => 'required',
);
public function images()
{
return $this->has_many('Image');
}
}
image.php
class Image extends Aware {
public static $timestamps = true;
public static $rules = array(
'unique_name' => 'required',
'original_name' => 'required',
'location' => 'required',
'news_id' => 'required',
);
public function news()
{
return $this->belongs_to('News');
}
}
Then in a controller I do the following:
$image = new Image(array(
'unique_name' => $fileName,
'original_name' => $file['file']['name'],
'location' => $directory.$fileName,
'news_id' => $news_id,
));
News::images()->insert($image);
I keep getting the following error message:
Non-static method News::images() should not be called statically,
assuming $this from incompatible context
Any ideas what am I doing wrong?
Setting public static function images() doesn't seem to be wanted, as after a refresh I get an error saying
$this when not in object context
Gordon said that by doing News::images()->insert($image); I'm doing a static call, but that's how saw to do it
You are missing some steps.
The Image belongs to News, but you're not referencing the News post you want to update.
You probably want to do:
$image = new Image(array(...));
$news = News::find($news_id);
$news->images()->insert($image);
More in the docs.
You're using $this in a function that is called statically. That's not possible.
$this becomes available only after you create an instance with new.
If you turn on strict mode you will get another error, namely that images is not a static function and thus shouldn't be called statically.
The problem is in News::images(), not in images()->insert($image);
$this can only be used within an object instance.
Class::method() calls a static method of the specified class.
In your case, you mixed both.
Your function definition for images is for an object instance:
public function images()
{
return $this->has_many('Image');
}
You are calling it as a static method:
News::images()->insert($image);
The News class would need to be instantiated or the images method be modified to support static calls.
Related
I've created a new API resource called UserResource:
class UserResource extends JsonResource
{
public function toArray($request)
{
/** #var User $this */
return [
'first_name' => $this->first_name,
'last_name' => $this->last_name,
'email_verified_at' => $this->email_verified_at,
];
}
}
And then I'm trying to get current user object and pass it to the resource:
class UserController extends Controller
{
public function index(Request $request)
{
/** #var User $user */
$user = $request->user();
return new UserResource($user);
}
}
But it always throws an exception Trying to get property 'first_name' of non-object. $user variable contains current user.
I'm using Xdebug and I checked that the resource contains formatted json in $this->resource, but not current user's model:
So why? Laravel's documentation says that I'll be able to get current resource (User model in my case) in $this->resource parameter, but it does not work. Any ideas?
UPDATE: here is break point for xbedug in UserResource:
It seems strange to me that you get the User object from the index's request and I reckon that somethings probably wrong there.
Normally, the index method is used to return a listing of all instances of the resp. model, e.g. something like
public function index() {
return UserResource::collection(User::all());
}
Try to return a user object (as resource) which you are sure exists
$user = Users::findOrFail(1);
return new UserResource($user);
and see if the error still persists. If it does not, something is wrong with the data you pass in the request.
I had a look at the JsonResource Class. Look at the contructor:
public function __construct($resource)
{
$this->resource = $resource;
}
Seems like the $user is saved to $this->resource. So you have to change your return statement to:
return [
'first_name' => $this->resource->first_name,
'last_name' => $this->resource->last_name,
'email_verified_at' => $this->resource->email_verified_at,
];
Does that work?
As #Clément Baconnier said in comments to the question, the right way to fix it is reinstalling vendor folder. The problem is that project has been created via Laravel new command from local with php 7.2, but there's php 7.4 in container.
I have an app model that uses a trait. I need the trait to receive some data and using it in the accessor function.
Content model:
use App\Traits\ArchiveTrait;
class Content extends Model
{
use ArchiveTrait;
protected $fillable = ['title','details'];
protected $table = 'contents';
public function getFileName($file_name)
{
return $this->archiving->url.'/media/contents/'.$file_name;
}
}
Archive Trait
trait ArchiveTrait {
private $app_id;
private $archiving;
public function __construct()
{
$this->app_id = config('archiving.id');
$this->archiving = Application::findOrFail($this->app_id);
}
public function guzzleClient() {
$headers = [
'Content-Type' => 'application/json',
'X-Requested-With' => 'XMLHttpRequest',
'Authorization' => 'Bearer ' . $this->archiving->token,
];
$client = new \GuzzleHttp\Client([
'headers' => $headers,
'http_errors' => false
]);
return $client;
}
}
Then problem is, when I try to insert a new content, I get the 'Field 'title' and 'details' doesn't have a default value' SQL error but if I remove the 'use ArchiveTrait' and the getFileName function from the model, then it works just fine. I think there's something wrong with the trait.
Laravel Eloquent models get their attributes passed through via the constructor. Because you are overriding the constructor and not passing anything to the parent constructor, the attributes of your model are never set.
You shouldn't add a constructor in a trait, but if you really needed to, you could fix this by passing the $attributes variable to the parent constructor:
public function __construct($attributes = [])
{
parent::__construct($attributes);
$this->app_id = config('archiving.id');
$this->archiving = Application::findOrFail($this->app_id);
}
I am using Laravel 5.2 on PHP 5.5.9
Instead of hard coding methods in the following controller, I used PHP __callStatic method to dynamically add functionality. It works fine while I tried from Console But while calling methods route, I am getting the following error
Method App\Http\Controllers\showCategory::latest() does not exist
Here is my Route
Route::get('Category/{id}', 'showCategory#latest');
Here is my Controller
class showCategory extends Controller
{
public $methods = [
'latest' => 'created_at',
'newArrival' => 'created_at',
'mostViewed' => 'views'
];
public function get( $link_or_id, $orderBy = 'created_at' )
{
}
public static function __callStatic($func, $arg)
{
$category = new self();
if( array_key_exists( $func, $category->methods ) )
{
return $category->get( $arg[0], $category->methods[ $func ] );
}
}
}
Any help to point where I messed up ?
__callStatic() is triggered when invoking inaccessible methods in a static context.
showCategory::latest(); it works
and it logically how you put latest method in routes and you know if it is found or not, if you put in routes it must be found in controller
I want to override model events and found this example code but am not sure I understand it completely.
SOURCE:
http://driesvints.com/blog/using-laravel-4-model-events/
There is a static method with another static method in it...How does that work? Or is it setting a static property in the boot method somehow?
<?php
class Menu extends Eloquent {
protected $fillable = array('name', 'time_active_start', 'time_active_end', 'active');
public $timestamps = false;
public static $rules = array(
'name' => 'required',
'time_active_start' => 'required',
'time_active_end' => 'required'
);
public static function boot()
{
parent::boot();
static::saving(function($post)
{
});
}
}
static::saving() just calls the static method saving on itself (and parent classes if not existent in current class). So it is essentially doing the same as:
Menu::saving(function($post){
});
So it is registering a callback for the saving event within the boot function.
Laravel documentation on model events
I'm overriding the create() Eloquent method, but when I try to call it I get Cannot make static method Illuminate\\Database\\Eloquent\\Model::create() non static in class MyModel.
I call the create() method like this:
$f = new MyModel();
$f->create([
'post_type_id' => 1,
'to_user_id' => Input::get('toUser'),
'from_user_id' => 10,
'message' => Input::get('message')
]);
And in the MyModel class I have this:
public function create($data) {
if (!Namespace\Auth::isAuthed())
throw new Exception("You can not create a post as a guest.");
parent::create($data);
}
Why doesn't this work? What should I change to make it work?
As the error says: The method Illuminate\Database\Eloquent\Model::create() is static and cannot be overridden as non-static.
So implement it as
class MyModel extends Model
{
public static function create($data)
{
// ....
}
}
and call it by MyModel::create([...]);
You may also rethink if the auth-check-logic is really part of the Model or better moving it to the Controller or Routing part.
UPDATE
This approach does not work from version 5.4.* onwards, instead follow this answer.
public static function create(array $attributes = [])
{
$model = static::query()->create($attributes);
// ...
return $model;
}
Probably because you are overriding it and in the parent class it is defined as static.
Try adding the word static in your function definition:
public static function create($data)
{
if (!Namespace\Auth::isAuthed())
throw new Exception("You can not create a post as a guest.");
return parent::create($data);
}
Of course you will also need to invoke it in a static manner:
$f = MyModel::create([
'post_type_id' => 1,
'to_user_id' => Input::get('toUser'),
'from_user_id' => 10,
'message' => Input::get('message')
]);