I cannot access model methods when using DB Facade in laravel - php

I have this model and I don't want to use eloquent due to some performance and slow query, even though I'm using Eager Loading the performance changes little bit. But unlike DB Facade the query is much faster. My problem is how can I access the method inside my model by using DB Facade?
----------------------
Table: user
id | fname | lname
-----------------------
and this is my model
class User extends Model {
public function complete_name() {
return $this->fname . " ".$this->lname;
}
}
but when Im using
$users = DB::table('user')->get();
and loop through it
$result = [];
foreach ($users as $user) {
$result[] = $user->complete_name();
}
return $result;
I cannot access the method "complete_name()". Is there any techniques or style in order for me to access the method inside User class?

your model User.php
class User extends Model {
public function complete_name() {
return $this->fname . " ".$this->lname;
}
}
You can also use like this
use App\User;
$users = User::all();
Then You can access your complete_name() method.
$result = [];
foreach ($users as $user) {
$result[] = $user->complete_name();
}
return $result;

there is no need to call the complete_name method on there, because the Query builder not return model. you can write your code like below:
$users = DB::table('user')->get();
your loop could be like:
$result = [];
foreach ($users as $user) {
$result[] =$user->fname.' '. $user->lname;
}
return $result;

For using methods in model you must use eloquent instead query builder
Like first answer
otherwise
public function index(){
$users = DB::table('user')->get();
$result = [];
foreach ($users as $user) {
$result[] = $this->complete_name($user);
}
return $result;
}
public function complete_name($user) {
return $user->fname . " ".$user->user;
}

Related

get many to many with where clause in laravel

I Have this 3 tables like below :
Tools
Parts
Part_details
it is my the table structure :
Tool -> has many -> parts. part -> has many->part_details.
Tool : id*, name; Parts : id*, name, tool_id; part_details: id, part_id, total;
Question :
Using laravel Model, how can I get Tool with One part that has biggest total on parts_details ??
// Tool Model
public function parts(){
return $this->hasMany(Part::class);
}
// Part Model
public function part(){
return $this->belongsTo(Tool::class);
}
public function part_details(){
return $this->hasMany(PartDetail::class);
}
// PartDetail Model
public function part(){
return $this->belongsTo(Part::class);
}
Now query the Tool model
$tools = Tool::with('parts')->withCount('parts.part_details')->get();
$toolWithMaxCount = $tools->filter(function($tool) use ($tools){
return $tool->parts->max('par_details_count') === $tools->max('parts.part_details_count');
})->first();
You can improve this with adding some raw bindings to optimise it. I think you got the idea.
Tool model
public function parts() {
return $this->hasMany('App\Part');
}
Part Model
public function details() {
return $this->hasMany('App\PartDetail');
}
public function tool() {
return $this->belongsToMany('App\Tool');
}
Detail Model
public function part() {
return $this->belongsToMany('App\Part');
}
Controller
$tools = Tool::with('parts', 'parts.details')
->find($id)
->max('parts.part_details');
Use the the hasManyThrough Relationship to get the all part details related to tool and then you can check the one by one record and get the highest total of the tool part.
// Tool Model
public function partsdetails()
{
return $this->hasManyThrough('App\PartDetail', 'App\Part','tool_id','part_id');
}
In Your controller
$data = Tool::all();
$array = [];
if(isset($data) && !empty($data)) {
foreach ($data as $key => $value) {
$array[$value->id] = Tool::find($value->id)->partsdetails()->sum('total');
}
}
if(is_array($array) && !empty($array)) {
$maxs = array_keys($array, max($array));
print_r($maxs);
}
else{
echo "No Data Available";
}

laravel4 select all data from other table by relation(one to many)

i have two tables users its model (User) ... and servs it model (servs) .... the relation is one to many .... when i try to select all sevices with belong to one user .... it select first service only and ignore others ... this is code i used it
public function getserv(){
return View::make('infos.serv');
}
public function postserv(){
$user = User::find(Auth::user()->id);
$user_id = $user->id;
$serv = servs::where('user_id','=',$user_id);
if($serv->count()){
$serv = $serv->get();
//return $serv->user_id;
foreach ($serv as $servs) {
return $servs->serv_id;
}
}
}
Instead of returning the data at the first loop, you should better do something like this:
$result = array();
foreach ($serv as $servs) {
$result[] = $servs->serv_id;
}
return $result;
Try this.
public function postserv(){
$user = User::find(Auth::user()->id);
$user_id = $user->id;
$serv = servs::where('user_id','=',$user_id)->get()->first;
if($serv)
return $serv->serv_id;
else
return null;
}
You only see the first one because when you return something the function ends and the rest of $serv doesn't get processed.
I recommend you first set up Eloquent relations properly
class User extends Eloquent {
public function servs(){
return $this->hasMany('servs');
}
}
After that you can retrieve all servs for a user like this:
$user = Auth::user();
$servs = $user->servs;
foreach ($servs as $serv) {
echo $serv->serv_id;
}

Unable to assign variable value in model constructor

I am playing with Laravel models and I need one to return a value that is not in the db table but it comes by running a model method. This method runs a query that groups and count grouped results.
The model method works just fine but I don't seem to be able to pre-fill the $quantity variable within the constructor with something different than 0.
So this is an excerpt of the model:
public $quantity;
function __construct($attributes = array(), $exists = false) {
parent::__construct($attributes, $exists);
$this->quantity = $this->quantity();
}
public function quantity()
{
$query = DB::table('carts_shopping')
->select('cart_id', DB::raw('COUNT(*) AS quantity'))
->where('cart_id',$this->cart_id)
->groupBy('cart_id')
->first();
return ($query) ? $query->quantity : 0;
}
While this is how I am trying to retrieve the results from controller:
$cartitems = Auth::user()->cartshopping;
foreach ($cartitems as $cartitem)
{
echo $cartitem->name;
echo $cartitem->quantity;
}
As you may guess 'cartshopping' comes from the user model being related with the model excerpt I pasted.
I also noticed that quantity() method gets called and it returns 0 all the time as if $this->cart_id was empty and, changing $this-cart_id with a real value the query itself doesn't even get executed.
Thanks a lot for any suggestion you guys can share.
Have you tried accessing the properties using $this->attributes?
public $quantity;
function __construct($attributes = array(), $exists = false) {
parent::__construct($attributes, $exists);
$this->quantity = $this->quantity();
}
public function quantity() {
$query = DB::table('carts_shopping')
->select('cart_id', DB::raw('COUNT(*) AS quantity'))
->where('cart_id', $this->attributes['cart_id'])
->groupBy('cart_id')
->first();
return ($query) ? $query->quantity : 0;
}
Failing that, you could try using the Eloquent accessors, which would be the best way to do it. This would make it dynamic as well, which could be useful.
class YourModel {
// Normal model data here
public function getQuantityAttribute() {
$query = DB::table('carts_shopping')
->select('cart_id', DB::raw('COUNT(*) AS quantity'))
->where('cart_id', $this->attributes['cart_id'])
->groupBy('cart_id')
->first();
return ($query) ? $query->quantity : 0;
}
}

How to properly load a Database row into a class in php

I am using Kohana 3.2, not that it matters much, but I am writing an application where I am wrapping any and all returned database records in a specific class. I don't know that I understand the best way to load the database row into the class, because sometimes it is a ORM model and sometimes it might just be an row ID.
So from a controller if I wanted a list of all the users it would look something like:
Controller:
$users = User::find_all();
User Class
public static function find_all()
{
$users_model = ORM::factory('user')->find_all();
$users = array();
foreach ($users_model as $user_model)
{
$users[] = User::instance($user_model);
}
return $users;
}
That works great, but sometimes I need to load a user object with just an id, like after some action, again a example:
Controller
$user_id = $_POST['user_id'];
$user = User::instance($user_id);
So is the User class responsible for trying to identify if an ID or a ORM object was passed into it. It seems like that isn't right for good OOP practices, but I am really not sure what the best way to do it is. What I have been currently doing is in the construct:
public function __construct($user, $load = 'model')
{
if ($load == 'model')
{
$this->user_model = $user;
}
if ($load == 'id')
{
$this->user_model = ORM::factory('user', $user);
}
}
But that really just doesn't feel right. Any advice would be greatly appreciated.
If you already have a user model that extends ORM then you probably don't need static methods in the class to get all users or to get a particular user.
In your controller you can just do to get all the users
$users = ORM::factory('user')->find_all();
To get a single user
$user = ORM::factory('user', $user_id);
If you still want to go down the wrapping route you could use functions like so
public static function all() {
$users = ORM::factory('user')->find_all();
if (count($users)) {
return $users;
}
return false;
}
public static function get($user_id) {
$user = ORM::factory('user', $user_id);
if ($user->id) {
return $user;
}
return false;
}
In your controller, use the ORM to get the user based on the ID.
$user_id = $_POST['user_id'];
$user = ORM::factory('user', $user_id);
Or given that you already have a find all in your user class, add a find_one() method:
User Class
public static function find_one($user_id)
{
$user = ORM::factory('user', $user_id);
return $user;
}
Controller
$user_id = $_POST['user_id'];
$user = User::find_one($user_id);
See the Kohana docs.
http://kohanaframework.org/3.1/guide/orm/using#finding-an-object
http://kohanaframework.org/3.1/guide/orm/examples/simple
Maybe like this:
public function __construct($user)
{
$this->user_model = is_object($user) ? $user : ORM::factory('user', (int)$user);
}

Doctrine : how to manipulate a collection?

With symfony && doctrine 1.2 in an action, i try to display the top ranked website for a user.
I did :
public function executeShow(sfWebRequest $request)
{
$this->user = $this->getRoute()->getObject();
$this->websites = $this->user->Websites;
}
The only problem is that it returns a Doctrine collection with all the websites in it and not only the Top ranked ones.
I already setup a method (getTopRanked()) but if I do :
$this->user->Websites->getTopRanked()
It fails.
If anyone has an idea to alter the Doctrine collection to filter only the top ranked.
Thanks
PS: my method looks like (in websiteTable.class.php) :
public function getTopRanked()
{
$q = Doctrine_Query::create()
->from('Website')
->orderBy('nb_votes DESC')
->limit(5);
return $q->execute();
}
I'd rather pass Doctrine_Query between methods:
//action
public function executeShow(sfWebRequest $request)
{
$this->user = $this->getRoute()->getObject();
$this->websites = $this->getUser()->getWebsites(true);
}
//user
public function getWebsites($top_ranked = false)
{
$q = Doctrine_Query::create()
->from('Website w')
->where('w.user_id = ?', $this->getId());
if ($top_ranked)
{
$q = Doctrine::getTable('Website')->addTopRankedQuery($q);
}
return $q->execute();
}
//WebsiteTable
public function addTopRankedQuery(Doctrine_Query $q)
{
$alias = $q->getRootAlias();
$q->orderBy($alias'.nb_votes DESC')
->limit(5)
return $q
}
If getTopRanked() is a method in your user model, then you would access it with $this->user->getTopRanked()
In your case $this->user->Websites contains ALL user websites. As far as I know there's no way to filter existing doctrine collection (unless you will iterate through it and choose interesting elements).
I'd simply implement getTopRankedWebsites() method in the User class:
class User extends BaseUser
{
public function getTopRankedWebsites()
{
WebsiteTable::getTopRankedByUserId($this->getId());
}
}
And add appropriate query in the WebsiteTable:
class WebsiteTable extends Doctrine_Table
{
public function getTopRankedByUserId($userId)
{
return Doctrine_Query::create()
->from('Website w')
->where('w.user_id = ?', array($userId))
->orderBy('w.nb_votes DESC')
->limit(5)
->execute();
}
}
You can also use the getFirst() function
$this->user->Websites->getTopRanked()->getFirst()
http://www.doctrine-project.org/api/orm/1.2/doctrine/doctrine_collection.html#getFirst()

Categories