Laravel 4 model method failed with "Call to undefined method" - php

My models extends "\BaseModel" which in its turn extends the Eloquent.
class BaseModel extends Eloquent {
public function foo($attribute)
{
//some code
}
In my collection, where the model being instanced I'm trying to access the "foo()" method, but it responses me with "Call to undefined method".
$data = IncomeDoc::with('details')
->where('type', '!=', 2)
->get();
$data = $data->foo();
Moreover, I tried to place the method "foo" in the model itself, but there was no difference.
Thanks for all

Basically get() method returns a Collection of instances. Assume more than 1 model satisfy type != 2 condition. If you want to get first model under the condition just use first() instead.
$data = IncomeDoc::with('details')
->where('type', '!=', 2)
->first();
$data = $data->foo();
Otherwise:
$collection = IncomeDoc::with('details')
->where('type', '!=', 2)
->get();
$data = [];
foreach($collection as $item) {
$data[] = $data->foo();
}

Actually get() returns a collection, an instance of Illuminate\Database\Eloquent\Collection and in this collection there is no foo method but to call the method that you declared in your model, you need to access the model, so first model in the collection would be 0 and to get it you may use $data->first() or $data->get(0), to get the second item (model) from the collection you may use $data->get(1) and so on but you may also use a loop, for example:
$data = IncomeDoc::with('details')->where('type', '!=', 2)->get();
$dataArray = array();
$data->each(function($item) use (&$dataArray){
$dataArray[] = $item->foo();
});
return View::make('viewname')->with('data', $dataArray);
Also, you may directly pass the $data to your view and can apply the function call from the view within a loop but not recommended.

Related

how to make an eloquent result into an array Laravel

I want to combine two data search results into one array, I use array_merge but there is an array_merge() error:
Argument # 1 is not an array
How to turn $vendor's eloquent results into an array and combine it with $plucked?
$vendor = Vendor::find($id);
$vendor_detail = VendorDetail::where('vendor_id',$id)->get();
$plucked = $vendor_detail->pluck('vendor_profile_value','vendor_profile_name');
$coba = array_merge($vendor,$plucked);
$plucked already an array
I think the problem here is that $vendor is not yet an array
You could do it like this:
$vendor = Vendor::find($id);
$vendor_details = VendorDetail
::select('vendor_profile_value', 'vendor_profile_name')
->where('vendor_id', $id)
->get()
->toArray();
$coba = array_merge($vendor,$vendor_details);
The get() method execute the query returning a Collection instance, in which you can call the toArray() method.
Side note
As far as I can see, you could make use of relationships and eager loading.
If you have a one-to-many relationship defined like this in your Vendor model:
public function details()
{
return $this->hasMany(VendorDetails::class);
}
Then, you could eager load the relationship like this:
$vendor = Vendor::with('details')->find($id);
// ^^^^^^^^^^^^^^
You could even just load the wanted fields:
$vendor = Vendor::with('details:vendor_profile_value,vendor_profile_name')
->find($id);
Then, your object will have a new attribute called "details" containing the related objects (or a collection of the limited selected fields).
You can convert the $vendor to an Array like below.
$vendor = Vendor::find($id)->toArray();

Foreach with eloquent in laravel

I'm trying to loop through the items using eloquent in laravel but I'm getting 0. Please see my code below.
Model
Class Store{
public function products(){
return $this->hasMany('App\Product');
}
}
Controller
$products_count = 0;
foreach($store->products() as $product)
{
if($product->status == 1)
{
$products_count++;
}
}
dd($products_count);
Note: I have data in my database.
You can also use withCount method something like that
Controller
$stores = Store::withCount('products')->get();
or
$store = Store::where('id', 1)->withCount('products')->first();
WithCount on the particular status
$stores = Store::withCount(['products' => function ($query) {
$query->where('status', 1);
}
])
->get();
ref: withcount on relationship
That's because $store->products() returns an eloquent collection which doesn't contain the data from the database yet. You need to do $store->products instead.
If you need to get the count from the database then use
$store->products()->where('status', 1)->count()
With the function-annotation (i.e. products()) you are retrieving the \Illuminate\Database\Eloquent\Builder-instance, not the actual Eloquent-collection.
Instead, you would have to use $store->products – then you will get retrieve the related collection.
In Laravel $store->products() makes you access the QueryBuilder instance, instead there is the Laravel way of doing $store->products, which loads the QueryBuilder and retrieves the collection automatically and down the line is easy to optimise.

json response with 2 table in Laravel 5.6

why my code get error
public function AuditorBagian_Edit($nopek)
{
$user = User::where('nopek', '=', $nopek)->get();
$bagian_user = Bagian::all()->where('kode_bagian', '=', $user->bagian)->get();
return response()->json($bagian_user);
}
I want to show data from Bagian
You can pass collection or array into response()->json() function it will convert as JSON data
public function AuditorBagian_Edit($nopek)
{
$user = User::where('nopek', '=', $nopek)->get();
$bagian_user = Bagian::where('kode_bagian', '=', $user->bagian)->get();
// or $bagian_user = Bagian::where('kode_bagian', '=', $user->bagian)->get()->toArray();
return response()->json($bagian_user);
}
Error result of code
$bagian_user = Bagian::all()->where('kode_bagian', '=', $user->bagian)->get();
Bagian::all() return instance of Illuminate\Database\Eloquent\Collection and find all records in db, then you try to filter ->where('kode_bagian', '=', $user->bagian)->get() specific records but this code wrong because method where() of Illuminate\Database\Eloquent\Collection class return instance of Illuminate\Database\Eloquent\Collection and this class does not haveget() method.
User::where('nopek', '=', $nopek)->get() also return instance of Illuminate\Database\Eloquent\Collection. To get single record use first() method instead of get()
The correct way get result is
$user = User::where('nopek', '=', $nopek)->first();
if(!empthy($user)) {
$bagian_user = Bagian::where('kode_bagian', '=', $user->bagian)->get().
}
Edited, format php code
Just remove the ::all() will do, all() and get() is the same behaviour.
Take not that all(), get(), first() is the final step to get the model data, the condition and with() and ordering() and etc must happen before all the three above mentioned

Laravel query builder returns object or array?

I'm building a very simple web app with Laravel.
I've built two separate Controllers, which each return two separate views, as follows:
ProfileController:
class ProfileController extends BaseController {
public function user($name)
{
$user = User::where('name', '=', $name);
if ($user->count())
{
$user = $user->first();
$workout = DB::table('workouts')->where('user_id', '=', $user->id)->get();
Return View::make('profile')
->with('user', $user)
->with('workout', $workout);
}
return App::abort(404);
}
}
WorkoutController:
class WorkoutController extends BaseController {
public function workout($name)
{
$workout = DB::table('workouts')->where('name', '=', $name)->first();
if ($workout)
{
Return View::make('add-exercise')
->with('workout', $workout);
}
return App::abort(404);
}
}
What is confusing me is what I had to do in order to pass a single workout object to each view. As you might have noticed the query builders for workout are different:
$workout = DB::table('workouts')->where('user_id', '=', $user->id)->get();
and
$workout = DB::table('workouts')->where('name', '=', $name)->first();
On the profile view, I get an object using the ->get(); method, but on the add-exercise view, I must use ->first(); or I will otherwise get an array with only one index, where I can then access the object, i.e. $workout[0]->name instead of $workout->name.
Why is this? Shouldn't I be able to use either get and/or first in both controllers and expect the same type of result from both since I want the same thing from the same table?
get() returns a collection of objects every time. That collection may have 0 or more objects in it, depending on the results of the query.
first() calls get() under the hood, but instead of returning the collection of results, it returns the first entry in the collection (if there is one).
Which method you use depends on what you need. Do you need the collection of all the results (use get()), or do you just want the first result in the collection (use first())?
Model::find(numeric); returns a object
Model::whereId(numeric)->first(); returns a object
Model::whereId(numeric)->get(); - returns a collection
Model::whereId(numeric); - returns a builder

Laravel hasMany relationship returning undefined method

I have a Laravel Model:
class Order extends Eloquent{
protected $table = 'orders';
public function orderItems(){
return $this->hasMany('OrderItem');
}
public static function findByUserMonthYear($user_id, $month, $year){
return Order::where('user_id', '=', $user_id)
->where('month', '=', $month)
->get();
// ->where('year', '=', $year);
}
}
And of course I have an OrderItem class
class OrderItem extends Eloquent{ ...
But if I do:
$order = Order::findByUserMonthYear(Auth::user()->id, Date::getDate(), 2014);
$order->orderItems();
I get the following:
Call to undefined method Illuminate\Database\Eloquent\Collection::orderItems()
What am I doing wrong? If I were to change the statement to Order::with('orderItems') the relationship seems to work fine, but I'd like to delete all the orderItems associated to the current Order.
Your ->get() within you findByUserMonth is returning a Collection. If this query returns only one collection then use the ->first() instead, but if your query returns multiple results then eager load the results of orderItems like so;
public static function findByUserMonthYear($user_id, $month, $year){
return self::with('orderItems')->where('user_id', '=', $user_id)
->where('month', '=', $month)
->get();
// ->where('user_id', '=', $year);
}
Then you can access the results like so;
#foreach($orders as $order)
{{$order->orderItem}}
#endforeach
This is because the return being a collection, so you have to loop through them. The use {{$order->orderItem}} to access the results
Im not too sure on this but i think you can delete all the models within a hasMany like so; $order->orderItem()->delete(); as the return of orderItem() is a Query\Builder instance.
your second class must be extends Order class
use this line for OrderItem class :
class OrderItem extends Order {

Categories