I'm trying to call add an item to a model through my public folder in Laravel but I'm getting this error:
Fatal error: Uncaught Error: Call to a member function connection() on null in [..]/Illuminate/Database/Eloquent/Model.php
Here is the file in my public folder:
<?php
require __DIR__.'../../../bootstrap/autoload.php';
use Illuminate\Database\Eloquent\Model;
use \App\Models\Cdr;
$id_ex = '11';
$cdr = new Cdr();
$cdr->id_ex = $id_ex;
$cdr->save();
Do I need to start the app somehow before this? I've also tried calling a method inside a controller from the public folder, but it gives me the same error. For example:
CdrController::storeCdr($id_ex);
My model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Cdr extends Model
{
public $table = 'cdr';
protected $dates = ['deleted_at'];
public $fillable = [];
public $guarded = ['id'];
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [];
/**
* Validation rules
*
* #var array
*/
public static $rules = [];
}
Right now, your script hasn't got a clue of it's environment. It doesn't know there is a database or even a framework for that matter, you have to actually boot the app to make this information available.
You can do this with
$app = require __DIR__ . '../../../bootstrap/app.php';
If this doesn't work, you need to boot at least the ConsoleKernel. Check app/Console/Kernel.php and it's superclass ConsoleKernel for an example how to do that.
Related
Suppose i have a laravel model that works with a certain (MySQL) database table.
Inside of this table there is a column named 'administration'. (example: could be 1, 2 or 3)
At the moment in my controller im using that modal with eloquent and inside of my eloquent statement i ask only to work with records (crud style) that have administration 2 for instance.
I think it should be possible to add 'where administration = x' to my model instead of my controller so that if i use the model in my controller i would just be dealing with records that have that administration set.
Is this possible? I have tried googling it but could not find an answer yet.
Laravel uses global scopes for this.
You would create a scope for the administration:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class AdministrationScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('administration', '=', 2);
}
}
And then you add it as a global scope to the model
<?php
namespace App\Models;
use App\Scopes\AdministrationScope;
use Illuminate\Database\Eloquent\Model;
class YourModel extends Model
{
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::addGlobalScope(new AdministrationScope);
}
}
I am working on Order-Ticket functionality. Many tickets should ideally be generated for a single order.
Earlier, the responsibility of creating tickets was written inside Order Model and that time it worked fine but now that I am trying to move that responsibility to Ticket model itself, it is not working.
I'll start with the Test file 'TicketTest.php'
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\Concert;
use Carbon\Carbon;
use App\Order;
class TicketTest extends TestCase
{
use DatabaseMigrations;
/** #test */
function can_create_multiple_tickets_for_order(){
$numberOfTickets = 2;
// Arrange - Create Concert and Order
$concert = factory(Concert::class)->create(
[
'date' => Carbon::parse('December 1, 2016 8:00pm'),
]
);
$order = $concert->orders()->create([
'email' => 'abc#gmail.com'
]);
// Act - Create Tickets
$order->tickets()->createTickets($numberOfTickets); // This line throws call to undefined method.
// Assert
$this->assertEquals($numberOfTickets, $order->tickets()->count());
}
}
'Order.php' Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
protected $guarded = [];
public function tickets()
{
return $this->hasMany(Ticket::class);
}
}
'Ticket.php' Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Ticket extends Model
{
public function createTickets($ticketQuantity){
foreach(range(1, $ticketQuantity) as $i) {
$this->create([]);
}
}
public function order(){
return $this->belongsTo(Order::class);
}
}
Before Laravel 5.4, I solved this problem by creating a new Relation and using that relation to Map Order to Ticket. Created a file 'app/Relation/TicketOrderRelation.php' and added following code in it
<?php
namespace App\Relation;
use Illuminate\Database\Eloquent\Relations\HasMany;
class TicketOrderRelation extends HasMany {
/**
* Create a Collection of new tickets
*
* #param int $ticketQuantity Number of Tickets to be created
* #return \Illuminate\Database\Eloquent\Collection
*/
public function createTickets($ticketQuantity){
$instances = [];
foreach(range(1, $ticketQuantity) as $i) {
$instances[] = $this->create([]);
}
return collect($instances);
}
}
New 'Order.php' file
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Relation\TicketOrderRelation;
class Order extends Model
{
protected $guarded = [];
/**
* Define a one-to-many relationship. One Order can have many tickets.
*
* This method is duplicate of hasMany method. The only difference is it
* returns object of TicketOrderRelation class at the bottom instead of
* object of HasMany class.
*
* #param string $related
* #param string $foreignKey
* #param string $localKey
* #return \App\Relation\TicketOrderRelation
*/
public function ticketOrderRelation($related, $foreignKey = null, $localKey = null)
{
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
$localKey = $localKey ?: $this->getKeyName();
return new TicketOrderRelation($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
}
public function tickets()
{
return $this->ticketOrderRelation(Ticket::class);
}
}
New 'Ticket.php' file
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Ticket extends Model
{
protected $guarded = [];
public function order()
{
return $this->belongsTo(Order::class);
}
}
After Laravel 5.4, Eloquent builder started supporting create method which makes creation easy.
This answer shows how to create a custom Builder. I have not yet tried if custom builder solves this problem on Laravel 5.4 or not but if it does, then I would prefer that.
So, I have an 'is_abandoned' boolean on one of my tables, where if it's true, I'd like the model to be automatically excluded from any query - just like softDeletes does.
Is there something I can set in the model that'd achieve this? I'm leaning towards maybe a mutator?
These are called Global Query Scopes.
Writing a global scope is simple. Define a class that implements the Illuminate\Database\Eloquent\Scope interface. This interface requires you to implement one method: apply. The apply method may add where constraints to the query as needed:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class AgeScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('age', '>', 200);
}
}
To assign a global scope to a model, you should override a given model's boot method and use the addGlobalScope method:
<?php
namespace App;
use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AgeScope);
}
}
You can just exclude the record using eloquent where function
$lists = List::where('is_abandoned',false);
Here's an example:
Create a function within the Eloquent
class User extends Eloquent {
public function scopeAbandoned($query)
{
return $query->where('is_abandoned', '=', 1/*true*/);
}
}
Then simply use it like this:
$approvedPosts = Post::abandoned()-><put_your_own_condition>;
For detailed info read Eloquent Query Scopes.
No repeated WHERE function calls. Hope It works.
I am Trying to fetch some data for my DB by following the example shown in Laravels documentation.
But for some reason i get syntax error, unexpected '::' in HomeController.php on line 15.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\News;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class HomeController extends Controller
{
public function index()
{
$news = new::all(); // <---------------------- This line
return view ('home', ['news' => $news]);
}
}
And here is the model if needed
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class News extends Model
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'news';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['title', 'text'];
}
new is a reserved word and can not be used as a class.
Your class is called News, not new. So change new::all(); to News::all();.
I am having an issue with laravel not seeing my tags() method for attaching new tags on a new entry. I keep getting Call to a member function on a non-object when I try to run the method and attach tags to my Tile model. All methods are returning their relations. I followed the same order as the documentation says eloquent.
Controller
$tile = \Tiles\Tile::find($tile_id);
$tile->tags()->attach($tag_array);
Model
<?php namespace Tiles;
use Illuminate\Database\Eloquent\Model;
class Tile extends Model {
/**
* The Tile table
* #var string
*/
protected $table = 'tiles';
/**
* Pivot table for tags
* #var string
*/
protected $pivot = 'tag_tile';
/**
* Get the tags associated with the given tile
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags() {
return $this->belongsToMany('Tiles\Tag', $this->pivot, 'tile_id', 'tag_id')->withTimestamps();
}
}
Try it
Model
public function tags() {
return $this->belongsToMany('Tiles\Tag', $this->pivot, 'tag_id', 'tile_id')->withTimestamps();
}
Thanks for all your help. I figured out the solution. I created a method in my model and pushed each to an array and fed it to the attach method. It works now.