How does loadByCode() works? I have been adding a module to my new project and don't know how to use model uses loadByCode method with a given code.
When you look at magento model class it extends Mage_Core_Model_Abstract which intern extends Varien_Object.
The class Mage_Core_Model_Abstract has function like getId(), load(), save(), delete() etc...
Mysql4 resource files are used to perform database queries on tables.
Suppose we have the file Keyur_Test_Model_Mysql4_Test resource file.
<?php
class Keyur_Test_Model_Mysql4_Test extends Mage_Core_Model_Mysql4_Abstract
{
public function _construct()
{
$this->_init('test/test', 'test_id');
}
public function loadByField($field,$value){
$table = $this->getMainTable();
$where = $this->_getReadAdapter()->quoteInto("$field = ?", $value);
$select = $this->_getReadAdapter()->select()->from($table,array('test_id'))->where($where);
$id = $this->_getReadAdapter()->fetchOne($sql);
return $id;
}
}
And here is the model file Keyur_Test_Model_Test
<?php
class Keyur_Test_Model_Test extends Mage_Core_Model_Abstract
{
public function _construct()
{
parent::_construct();
$this->_init('test/test');
}
public function loadByField($field,$value){
$id = $this->getResource()->loadByField($field,$value);
$this->load($id);
}
}
In this file there are many new functions which have been used. Let’s take them one by one. In our model file, we have used this function -
$id = $this->getResource()->loadByField($field,$value);
$this->getResource() function returns the resource model’s object. So we are simply calling the loadyByField($field,$value) function in the resource model.
getTable() function
Now in our Mysql4 file, in the loadByField() function we have used $table = $this->getMainTable(); .This function returns the table name of the current model, i.e the one defined in the class’s constructor. If you want to get table name of another sql table in magento, we need to the getTable() call e.g
$table = $this->getTable(‘newsletter/subscribe’);
_getReadAdapter() function
Next we have:
$where = $this->_getReadAdapter()->quoteInto(“$field = ?”, $value);
Here the first function too see is the $this->_getReadAdapter() function. This function return an object which has function to perform database query, like fetch(), fetchAll(), query(), etc.
_quoteInfo() function
Another function we have used is quoteInto(): This function is used to create our where conditions.
In this the actual value is substituted into the question mark we have written. For e.g $this->_getReadAdapter()->quoteInto(“user_id = ?”, 3); translates to “user_id = 3″.
Another frequently used variation of quoteInfo() is
$where = $this->_getReadAdapter()->quoteInto("$field IN(?)", array(1,2,3));
this translates to “field in (1,2,3)”
Getting deeper into the quoteInto() function: If we have multiple where conditions we can use
$where = $this->_getReadAdapter()->quoteInto("$field = ? AND ", $value).$this->_getReadAdapter()->quoteInto("$field1 = ? OR ", $value1).$this->_getReadAdapter()->quoteInto("$field2 = ?", $value2);
Continuing on the loadByField function in our resource model, next we have
$select = $this->_getReadAdapter()->select()->from($table,array(‘test_id’))->where($where);
Here we have created the select query using the select(), and on that called the from() function.
from() function
The from() function takes many different parameters, if you want to fire a simple select * query, you need to only pass the table name like from($table).
But right now, I wanted to select just a single column that is test_id, so I passed an array with column name to
select. i.e array(‘test_id’).
If we want to select multiple column, we need to array(‘test_id’,’col1’,’col2’).
This will create a sql like “select test_id,col1,col2 from $table”.
But support we want a sql query like “select test_id as id,col1 as column1 from $table” , i would call -
from($table,array('id'=>'test_id','column1'=>'col1'));
Related
In my laravel/backpack 4.0 project I have three model:
Product: id, name, ...
Pricebook: id, name, ...
Price: id, pricebook_id, value, ...
I need to create a row in prices table every time a new Product is stored id database.
Is there a method like 'before' or 'after' save to hook?
if not, any other solution?
...I got confused about something trivial, probably a mispelling. This is the solution thank's Martin
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\ProductRequest;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
use App\Models\Price;
class ProductCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation {store as traitStore ;}
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
public function store()
{
$request = $this->crud->validateRequest();
$response = $this->traitStore();
//get last inserted row id
$entryID = $this->data['entry']->id;
$price = new Price();
$price->product_id = $entryID;
$price->price = 0;
$price->save();
// show a success message
\Alert::success('New price created in DEFAULT_BASE_PRICEBOOK'))->flash();
return $response;
}
...
There are no such hooks, but you can override these methods that control the database insert/update. From the documentation:
Callbacks
Developers coming from GroceryCRUD on CodeIgniter or other CRUD systems will be looking for callbacks to run before_insert, before_update, after_insert, after_update. There are no callbacks in Backpack. The store() and update() code is inside a trait, so you can easily overwrite that method, and call it inside your new method. For example, here's how we can do things before/after an item is saved in the Create operation:
namespace App\Http\Controllers\Admin;
use Backpack\CRUD\app\Http\Controllers\CrudController;
class ProductCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation { store as traitStore; }
// ...
public function store()
{
// do something before validation, before save, before everything
$response = $this->traitStore();
// do something after save
return $response;
}
Source
Good day.
For example, I have a model People with fields/attributes:
name
surname
and the model also has this method:
public function FullName()
{
return "{$this->name} {$this->surname}";
}
if I make the next request:
$p = $people->all();
I'll get collection with names and surnames as attributes
how i can make function execution for each in all() request?
What is the best practice?
Well, depends on what kind of result do you want.
OPTION A: Have name, surname and full_name in all the items of the array.
Eleazar's answer is correct, but a little bit incomplete.
1. Define a new accessor in your model.
This will define a new attribute in your model, just like name or surname. When the new attribute is defined, you can just do $user->full_name to get the attribute.
As the documentation says, to define an accessor you need to add a method in your model:
// The function name will need to start with `get`and ends with `Attribute`
// with the attribute field in-between in camel case.
public function getFullNameAttribute() // notice that the attribute name is in CamelCase.
{
return $this->name . ' ' . $this->surname;
}
2. Append the attribute to the model
This will make the attribute to be considered just like any other attribute, so whenever a record of the table is called, this attribute will be added to the record.
To accomplish this you'll need to add this new value in the protected $appends configuration property of the model, as you can see in the documentation:
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The accessors to append to the model's array form.
*
* #var array
*/
// notice that here the attribute name is in snake_case
protected $appends = ['full_name'];
}
3. Make sure that this attribute is visible
Notice this important part of the docs:
Once the attribute has been added to the appends list, it will be
included in both the model's array and JSON representations.
Attributes in the appends array will also respect the visible and
hidden settings configured on the model.
4. Query your data.
When doing the following:
$p = $people->all();
The $p array should have name, surname and also the new full_name attribute for each item.
OPTION B: Just get the full_name for specific purposes.
You can do the following when querying, iterate each result to get the attribute.
Now to do this you can iterate the collection with a foreach sentence, but given that whenever querying data, the array returned is always a Collection instance, so you simply use the map function:
$full_names = $p->map(function ($person) {
// This will only return the person full name,
// if you want additional information just custom this part.
return $person->fullname;
});
Using collection higher order messages it can be even shorter:
$full_names = $p->map->fullname;
I use the following:
public function getFullNameAttribute()
{
return "{$this['name']} {$this['lastname']}";
}
and then, I add it in appends:
class User extends Authenticatable {
protected $appends = ['fullname'];
}
What do you think?
In your model write a function to concatenate the name
public function getFullNameAttribute() {
return ucfirst($this->first_name) . ' ' . ucfirst($this->last_name);
}
now you can call it this way
$user = User::find(1);
echo $user->full_name;
or
Auth::user()->full_name;
I am trying to setup Eloquent for a new API that we're working on. I am using relations in a model.
Some relations are complex and aren't really suitable for a quick chained Query Builder statement. For example, I am trying to return metrics and some of those metrics are complex. Such as counting the total clicks generated by a user (it's not just a simple COUNT(*)). Here is the code that I have now:
<?php
namespace App\Models\Eloquent;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
class Affiliate extends Model
{
protected $table = 'user';
public function profile()
{
return $this->belongsTo('App\Models\Eloquent\Profile', 'id');
}
public static function clicks()
{
$sql = "SELECT
user_id,
COUNT(*) / SUM(dummy_metric) AS total_clicks
FROM clicks
WHERE something = 'true'
AND another_thing > 100 # dummy filter for example only
GROUP BY user_id";
$rows = DB::select(DB::raw($sql));
// (PSUEDO CODE) THIS IS WHAT I'D LIKE TO DO IDEALY
return $this->belongsTo($rows, user_id);
}
Possible? I'd like to be able to write our own queries without relying on Query Builder all of the time, but I still want to be able to join the relation to Eloquent.
Assuming you have Clicks model defined, find below the eloquent version of your query.
Click::select(DB:raw("user_id, COUNT(*) / SUM(dummy_metric) AS total_clicks"))
->where(/*condition*/)->groupBy("user_id")->get();
Note:
1) Where method accepts an array of conditions, so you can add more than one condition in same method. Reference
Update
I think thius should be your clicks() method:
public function clicks(){
return $this->hasMany('App\Models\Eloquent\Click',/*relevant ids*/);
}
And, now where you want a count of clicks(in controller for example), you can use following query:
$user = User::find("user_id")->with('clicks')->get();
$clicks = $user->clicks()->count();
To make it more efficient, refer to this article on Tweaking Eloquent relations
Update 2:
You can use Accessor function to retrieve total count
Add following 2 methods in User model.(change clicksCount string to anything you need )
public function clicksCount(){
return $this->hasOne('App\Models\Eloquent\Click')
->select(DB:raw("user_id, COUNT(*) count"))
->groupBy("user_id");
}
public function getClicksCountAttribute(){
return $this->clicksCount->count();
}
Now, you can use $user->clicksCount; to get the count directly.
If you are using Laravel 5.4, you can use withCount() method to easily retrieve the count. Counting Related Models
I have two tables: Users and Images.
So, a user can have some images.
For this relationship I have additional function in model User:
public function images()
{
return $this->hasMany('App\Images', 'idElement', 'id');
}
And in controller I have:
$users = Users::where('id', $id)->with("images")->get();
How can I add additional condition in controller for images table that will be "where images.type = 1"?
Now this tables are connected only by primary keys, but I need to set a new condition yet.
You can filter your images with callback function, try this:
$users = Users::where('id', $id)->with(["images" => function ($query){
$query->where('type', 1);
}])->get();
For something like this, where you want to scope down a subset of images based on their type, you can add another method called something like public function scopedImages() and define it as such:
public function scopedImages() {
return $this->hasMany('App\Images', 'idElement', 'id')->where("images.type", "=", 1);
}
In your controller, you would access this function the same as you would the images() function on User:
$users = Users::where('id', $id)->with(["scopedImages"])->get();
Keep the function images() as well, so if you need to find all images attached to a User, but adding additional functions like this gives you flexibility on what you want to return and when.
I am working through the Laravel 4 From Scratch tutorial at https://laracasts.com/series/laravel-from-scratch. Tutorial 4: Database Access describes several methods for retrieving data from a database.
One in particular I cannot get to work:
In my routes.php, I have
Route::get('/', function()
{
$bottle = DB::table('bottle')->find(1);
dd($bottle);
});
The only output is the "Whoops, looks like something went wrong." page. In the bottle table of my database, the primary key has the name bottle_ID. I would guess this has something to do with the problem, but I cannot find any information on how to change the find() parameter. So how do I use 'find' to return an object from my database?
The following code does work:
// returns everything from bottle table
$bottles = DB::table('brewery')->get();
return $bottles;
// returns all data for the bottle with an ID of 10
$bottle = DB::table('bottle')->where('bottle_ID', '=', 10)->get();
return $bottle;
// returns all ales from the database
$bottles = DB::table('bottle')->where('beer_type', '=', 'Ale')->get();
return $bottles;
When used in the query builder (DB::table()...) the find() method has the primary key column hardcoded as id:
public function find($id, $columns = array('*'))
{
return $this->where('id', '=', $id)->first($columns);
}
What you should do instead is use where() and first():
$bottle = DB::table('bottle')->where('bottle_ID', 1)->first();
Or if you decide to use Eloquent Models you can specify the key column name:
class Bottle extends Eloquent {
protected $primaryKey = 'bottle_ID';
}
And retrieve the model like this:
$bottle = Bottle::find(1);