query builder equivalent of Model::query(); - php

Good day, please, for some reasons I have to use query builder instead of Eloquent, the reason been that the name of my model is KidsCafe and if I use Eloquent, it will search for a table with myapp.kidscaves, but the name of the table is kidscafes this is throwing errors, so I have to use query builder in my interaction with the db.
Now, I have to implement search functionality, so how do I implement something like this using query builder
$kids = KidsCafe::query();
My question is how do I implement query(); using query builder, and also is there another way I can use eloquent without it
thank you in advance

You can manually specify a table name by defining a table property on your model:
class KidsCafe extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'kidscafes';
}

You can also use the setTable() function do dynamically use another table's name, something like this -
$kidscafes = new KidsCafe;
$kidscafes->setTable('kidscafes');

Related

Extend a Laravel model that always attaches a `where status = 'cancelled'` to select statements?

I'm working with Laravel and Nova. So basically in Laravel, I have a model like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
}
Then, Nova helps me create a nice CMS web interface at https://example.com/admin/resouces/flights that lists all my flights and https://example.com/admin/resouces/flights/<id> to let me CRUD against a particular record. All I have to do to make this happen is create the file app/Nova/Flight.php with the content:
<?php
namespace App\Nova;
//... import other classes like Text Fields, WYSIWYG editors etc.. etc.., that are the nice CMS UI fields to modify each column in my flights table
class Flight extends Resource
{
public static $model = 'App\Flight';
// ... list of fields I want to modify ...
}
This works fine and all, except now I want to make two different urls like:
* `https://example.com/admin/resouces/flights-cancelled` - this should only list the equivalent of `SELECT * FROM flights WHERE status = 'cancelled'`
* `https://example.com/admin/resouces/flights-active` - this should only list the equivalent of `SELECT * FROM flights WHERE status = 'active'`
Things will get a bit more complicated as my project evolves, so I was wondering if there's a way to define a new model called App\FlightCancelled that is exactly the same as App\Flight, except all queries to the database will always include a WHERE status='cancelled' condition. That way I can assign App\FlightCancelled as the model to my Nova resource.
Curious how that's done? Or if there's a better way to achieve my objective?
You can modify $table and override newQuery() - the method that Eloquent use to construct a new query.
FlightCancelled
protected $table = 'flights'
public function newQuery($excludeDeleted = true)
{
return parent::newQuery($excludeDeleted)
->where('status', '=', 'cancelled');
}
In this case, I recommend using lenses, allow you to fully customize the underlying resource Eloquent query.
class FlightCancelled extends Lens
{
public static function query(LensRequest $request, $query)
{
// Query here..
}
//
}

Laravel: passing dynamic table name to model e.g protected $table = "$tablename"

So my code successfully creates dynamic tables of the exact same structure (I need it this way for my own reasons).
However, the problem comes when I want to add data to any of the dynamically created table because I don't have a model for it, the way I have when I normally create tables/models.
So, I was wondering how can I work around this problem?
Can I use this kind of logic somehow?
namespace App;
use Illuminate\Database\Eloquent\Model;
class sys_cats extends Model
{
// I know we can't use variable in class like this
// but this is just to explain what kind of logic I have
// in mind.
$category = Session::get('catName');
protected $table = "$category";
protected $primarykey = 'id';
protected $fillable = [
.
.
.
So I assume, this way, we can use this model to dynamically change table name to the name stored in a session variable.
So we won't have to create a separate model for each of these tables.
Is this achievable? Or I must create a separate model file as well each time when I dynamically create a table in database?
I am sorry, if what I am suggesting is fundamentally wrong or anything related. I am pretty new to PHP and Laravel.
Waiting for your kind suggestions.
Thanks
better to use fluent query builder db
u can add dynamically table name with insert,update,read,delete
operation
for example
get record from db
DB::table($tableName)->all()
for insert
DB::table($tableName)->insert(['name' => $name]);
for automatically added created_at and updated_at add in migration
$table->timestamp('created_at')->default(\DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(\DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));

How to create a Eloquent model instance from a raw Object?

I need to make a raw database query using Laravel:
$results = DB::select("SELECT * FROM members
INNER JOIN (several other tables)
WHERE (horribly complicated thing)
LIMIT 1");
I get back a plain PHP StdClass Object with fields for the properties on the members table. I'd like to convert that to a Member (an Eloquent model instance), which looks like this:
use Illuminate\Database\Eloquent\Model;
class Member extends Model {
}
I'm not sure how to do it since a Member doesn't have any fields set on it, and I'm worried I will not initialize it properly. What is the best way to achieve that?
You can try to hydrate your results to Model objects:
$results = DB::select("SELECT * FROM members
INNER JOIN (several other tables)
WHERE (horribly complicated thing)
LIMIT 1");
$models = Member::hydrate( $results->toArray() );
Or you can even let Laravel auto-hydrate them for you from the raw query:
$models = Member::hydrateRaw( "SELECT * FROM members...");
EDIT
From Laravel 5.4 hydrateRaw is no more available. We can use fromQuery instead:
$models = Member::fromQuery( "SELECT * FROM members...");
You can simply init a new model:
$member = new App\Member;
Then you can assign the columns:
$member->column = '';
Or if all columns are mass assignable:
$member->fill((array)$results);
Or have I misunderstood something?
You should definetly use Eloquent to perform that.
You might declare the relations between the models, and use the where conditions.
like:
Member::where(......)->get();
This will return an eloquent instance, and you can do whatever you need.

Yii: Use another table than the model table in FROM with CDbCriteria

How do I change the FROM part of the query when using CDbCriteria?
So I can join the main table (of the model) later (News). I need this because the query is much much more efficiƫnt when joining the main table (News) later with the table Tags. (30 seconds VS 0.125 seconds).
Is this possible?
Do I need to create a new CActiveRecord type which extends the object I need (News) but with the other tablename (Tag)?
News and Tags are linked via a linktable NewsTags.
I tried this but it won't work because now it can't map the properties:
<?php
/**
* This is the model class for table "news" but with "tag" as tablename
*
* It is a hacky way to use "tag" in FROM of the search query and join later with "news"
* because this is a lot more efficient for searching.
* CDbCriteria does not allow to change the FROM table and allways uses the one of the model.
**/
class NewsSearchByTagResult extends News
{
/**
* Returns the static model of the specified AR class.
* #return News the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'tag';
}
}
?>
Gives "Property "NewsSearchByTagResult.NewsId" is not defined."
I solved it by splitting it in 2 queries. First getting all the tags with the searchterms and then getting the news with these tags. It's a little bit slower than the preferred solution but it's a lot faster than before.
I guess the thing I wanted is impossible.
Now I still need to figure out how to use MATCH...AGAINST with Yii framework because I can't use params and I can't use mysqli_real_escape_string because I don't have access to the db connection... But that's another question...
Blegh I hate ORM's...

Add custom attribute in eloquent model

Here is a raw SQL query:
SELECT name, area, point(area) AS center FROM places;
I want to get an Eloquent model based on this query. Here is the Model:
class Place extends Model
{
protected $visible = ['name', 'area'];
}
So, I want to get the center property if I run this code:
return response()->json( Place::all() );
center is missing. I don't know how to add the center property in my Place object. I don't want to build a raw query in my controller, is there any solution with mutator or something like this? (The only thing I want to call is Place::all(), I really want to use Eloquent Model in controllers, not an SQL query).
Use a combination of Mutators and the $appends property. Here's an example:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Place extends Model {
protected $appends = ['center'];
public function getCenterAttribute()
{
return $this->point($this->getRawAttribute("area"));
}
protected function point($area)
{
// logic for SQL POINT(), etc
}
}
The $appends property will mean that the mutated attribute is included in JSON/array output when $model->toJson() or $model->toArray() is called (which Response::json() does)
The reason for doing point logic in code is because with eloquent models, you'd hit the N+1 query problem when fetching a list of places and their centers, and that's not a great idea for your database.
Your query wouldn't be used when fetching data for the model from the database, either, since the default query for models is
select * from `table` where id = :id
Which is then figured out internally to set up data on the model.
You may want to take a look at this:
http://laravel.com/docs/5.0/eloquent#global-scopes. It should help you build the query that will always get center along with the rest of data.

Categories