Is is possible to concatenate a string to Model? The below doesn't seem to work.
I have Car Model and Train Model. Vehicle will be either Car or Train.
$vehicle = 'Car';
$result = $vehicle::where('model', $value)->count() > 0;
The above code exists the following error.
Symfony\Component\Debug\Exception\FatalThrowableError: Class 'Car' not found in file
How can I concatenate? Is it possible?
I think this is the closest to what you need,
you don't have to import anything since you have a dynamic value. (If you have 10 possible models you will have to import all of them)
So you should do something like this
$model = "Car";
$modelsPath = "\\App\\Models\\";
$className = $modelsPath.$model;
// if you need an instance you do this
// $instance = new $className;
$result = $className::where('model', $value)->count() > 0;
dd($result);
What i usually do is create a config file that contains an array of all possibilities where they key is the type (Car,Bus,Train in ur example)
And then i get the value using the key which is the input (car) and the model path will be in the config! that way you can swap it later easy and attach more conditions related to that type of model etc.
I hope this makes sense
Regards
use App\Car; //place this at the top of your page. Make sure the model exists
Yes, you can concatenate a model depending upon the condition. Below, I have added a workable code to implement.
Import both model.
//use App\Car;
//use App\Train;
$isCar = true; // boolean condition to check whether it is a car or train
$classVariable = null;
if ($variable) {
$classVariable = new Car();
}else{
$classVariable = new Train();
}
$result = $classVariable->where('model', $value)->get();
//this will provide you a car model query
dd($result);
Better Approach
A better approach will be to use a Vehicle model and Vehicle Type.
Add a vehicle_type_id in the vehicles table.
So whenever you need to retrieve car types, you can use
//Suppose vehicle_type_id for car is 1
$carVehicle = Vehicle::where('vehicle_type_id', 1)->get();
//Suppose vehicle_type_id for train is 2
$trainVehicle = Vehicle::where('vehicle_type_id', 2)->get();
It's Possible
use App\Car;
use App\Train;
/* Here You can now set Model name dynamically*/
$vehicle = 'Car';
$result = $vehicle::where('model', $value)->count() > 0;
I think one approach can as below:
$vehicle = Car::class; //this will dynamically add full namespace of Car class.
$result = $vehicle::where('model', $value)->count() > 0;
Related
What I'm trying to do seems like it should be simple, but I can't figure it out. All I really want is a simple way to add one model to the database that belongs to another model. I know it's confusing wording so I'll illustrate.
I have a User model and an Address model. I have a user defined with an id of 1 and I want to add an address to that user. I can add the Address like this:
$a = new App\Address;
$a->user_id = 1;
$a->line_1 = '1234 Something Rd.';
$a->city = 'Fort Worth';
$a->state = 'TX';
...
But it would be so much easier if I could just say:
$u = App\User::first();
$u->address->create([array of options]); /* Or something */
So my questions are:
Is this possible?
How can I do it?
What is this called? Does it have a name?
Thanks!
$u = App\User::first();
App\Address::create(['user_id'=>$u->id, etc]);
or
$address = App\Address::create([options]);
$u->address()->save($address);
Do not forget to set Model Address.php like this:
protected $fillable = ['user_id','etc'];
You cannot call
$u->address->create
because as User does not yet have a address model, the method will return NULL, so ->create will fail.
Yes, you can Insert Related Models:
$user = App\User::first();
$address = App\Address::create($attributes);
$user->address()->associate($address);
Note that how you do this depends on the type of relationship.
How do we create a new Eloquent Collection in Laravel 4, without using Query Builder?
There is a newCollection() method which can be overridden by that doesn't really do job because that is only being used when we are querying a set result.
I was thinking of building an empty Collection, then fill it with Eloquent objects. The reason I'm not using array is because I like Eloquent Collections methods such as contains.
If there are other alternatives, I would love to hear them out.
It's not really Eloquent, to add an Eloquent model to your collection you have some options:
In Laravel 5 you can benefit from a helper
$c = collect(new Post);
or
$c = collect();
$c->add(new Post);
OLD Laravel 4 ANSWER
$c = new \Illuminate\Database\Eloquent\Collection;
And then you can
$c->add(new Post);
Or you could use make:
$c = Collection::make(new Post);
As of Laravel 5. I use the global function collect()
$collection = collect([]); // initialize an empty array [] inside to start empty collection
this syntax is very clean and you can also add offsets if you don't want the numeric index, like so:
$collection->offsetSet('foo', $foo_data); // similar to add function but with
$collection->offsetSet('bar', $bar_data); // an assigned index
I've actually found that using newCollection() is more future proof....
Example:
$collection = (new Post)->newCollection();
That way, if you decide to create your own collection class for your model (like I have done several times) at a later stage, it's much easier to refactor your code, as you just override the newCollection() function in your model
Laravel >= 5.5
This may not be related to the original question, but since it's one of the first link in google search, i find this helpful for those like me, who are looking for how to create empty collection.
If you want to manually create a new empty collection, you can use the collect helper method like this:
$new_empty_collection = collect();
You can find this helper in Illuminate\Support\helpers.php
snippet:
if (! function_exists('collect')) {
/**
* Create a collection from the given value.
*
* #param mixed $value
* #return \Illuminate\Support\Collection
*/
function collect($value = null)
{
return new Collection($value);
}
}
Just to add on to the accepted answer, you can also create an alias in config/app.php
'aliases' => array(
...
'Collection' => Illuminate\Database\Eloquent\Collection::class,
Then you simply need to do
$c = new Collection;
In Laravel 5 and Laravel 6 you can resolve the Illuminate\Database\Eloquent\Collection class out of the service container and then add models into it.
$eloquentCollection = resolve(Illuminate\Database\Eloquent\Collection::class);
// or app(Illuminate\Database\Eloquent\Collection::class). Whatever you prefer, app() and resolve() do the same thing.
$eloquentCollection->push(User::first());
For more information about understanding resolving objects out of the service container in laravel take a look here:
https://laravel.com/docs/5.7/container#resolving
I am using this way :
$coll = new Collection();
$coll->name = 'name';
$coll->value = 'value';
$coll->description = 'description';
and using it as normal Collection
dd($coll->name);
It is better to use the Injection Pattern and after $this->collection->make([]) than new Collection
use Illuminate\Support\Collection;
...
// Inside of a clase.
...
public function __construct(Collection $collection){
$this->collection = $collection;
}
public function getResults(){
...
$results = $this->collection->make([]);
...
}
What worked for me was to name the use namespace and instantiate it directly:
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
# Usage
$this->latest_posts = new EloquentCollection();
Allowed me to merge two data subsets of eloquent collection results, this maintains the relationships - a regular collection (collect()) loses relationship and probably some more metadata.
$limit = 5;
$this->latest_posts = new EloquentCollection();
$pinned_posts = PinnedPostReference::where('category', $category)->get();
if($pinned_posts->count() > 0) {
foreach($pinned_posts as $ppost) {
$this->latest_posts->push($ppost->post);
}
}
# Another Eloquent result set ($regular_posts)
foreach($regular_posts as $regular_post) {
$this->latest_posts->push($regular_post);
}
I have a AR model that I am trying to duplicated but just need to manually change the foreign key.
$_POST['competition_id'] = 99;
$prizes = CompetitionPrizes::model()->findAll('competition_id =:competition_id',array(':competition_id'=> $_POST['competition_id']));
This query basically queries the prizes table and gets all the rows for a particular competition. With the prizes object I would like to basically re-insert/duplicate the same information except the competition id which I want to manually set.
I did something similar for an AR object that basically only has one row and that worked well, however in this instance as a competition can have more than one prize this same code won't.
// My existing code for duplication process
$obj = Competitions::model()->find('competition_id=:competition_id', array(':competition_id' => $post['competition_id']));
$clone = clone $obj;
$clone->isNewRecord = true;
unset($clone->competition_id); // i want to remove this so it is auto inserted instead via the db
$clone->save();
This works great - how would I modify this on a 'collection' of prizes and have this duplicated into the database while setting my own 'competition_id' value.
Note - i'm to new to Yii, so please let me know if I have made any obvious errors/bad practice
Cloning won't work. You need to assign the attributes to a new object:
$obj = Competitions::model()->find('competition_id=:competition_id', array(':competition_id' => $post['competition_id']));
$clone = new Competitions;
$clone->attributes = $obj->attributes;
$clone->save();
If a more generic way of duplicating a Model / ActiveRecord in Yii2 Framework is required, you might use this solution:
$copy = clone $model;
$copy->isNewRecord = true;
foreach ($model->getPrimaryKey(true) as $field => $value) {
unset($copy->{$field});
}
$copy->save();
GitHub issue discussion about duplicate models: https://github.com/yiisoft/yii2/issues/7544#issuecomment-77158479
The answer for my problem although Michiel above helped me out - alternatively if you wouldn't mind adding another answer i'll give you the accepted answer.
foreach($models as $model)
{
$clone = new Competitions;
$clone->attributes = $model->attributes;
$clone->competition_id = '123' // custom var i am setting manually.
$clone->save();
}
How about (yii2 syntax):
$model=Competitions::findOne([':competition_id' => $post['competition_id']]);
$model->id = null;
$model->isNewRecord = true;
$model->save();
How would I attach custom methods to a Zend_Db_Table_Row object?
For example if I got a selected a user row from the users table and put it in var $myUser how would I be able to implement something like $myUser->getUsername()
You can extend the default Zend_Db_Table_Row and tell the Zend_Db_Table instance to use your specific implementation. The following example is taken from the manual:
class My_Row extends Zend_Db_Table_Row_Abstract
{
// ...
}
$table = new Zend_Db_Table('bug');
$table->setRowClass('My_Row');
// Returns a rowset containing an array of objects of type My_Row.
$where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW');
$rowsCustom = $table->fetchAll($where);
I'm dealing with database containing of many tables, with many field prefixes (two first letters of every table), so when I have users table I cannot use "name" property ($user->name) but I can use: $user->us_name.
I's there a way to simplify things and set automagic prefix for every field of a table ?
You'd have to extend Zend_Db_Table_Row to accomplish this. Fortunately, ZF includes a _transformColumn() method expressly for this purpose. But I'm getting ahead of myself. First, set up your table class. This assumes your database has a table called "foo_mytable":
class MyTable extends Zend_Db_Table_Abstract {
protected $_name = 'foo_mytable';
protected $_rowClass = 'My_Db_Table_Row';
}
Next, create your custom Row class:
class My_Db_Table_Row extends Zend_Db_Table_Row {
protected function _transformColumn($columnName) {
$columnName = parent::_transformColumn($columnName);
$prefix = 'us_';
return $prefix . $columnName;
}
}
Now, you can do something like this (for simplicity, this example ignores MVC design ideals):
$table = new MyTable();
$records = $table->fetchAll();
foreach ($records as $record) {
echo $record->name;
}
Assuming your table has a column named "us_name", this should work. I tested it myself. Note that in your custom table row, you might want to grab the table prefix from a config file. If you've got it stored in your registry, you could replace $prefix = 'us_'; with $prefix = Zend_Registry::get('tablePrefix');.
I didn't know about _transformColumn(). I'm gonna hop on top of #curtisdf 's example.
I think you should override with this (not tested):
protected function _transformColumn($columnName)
{
$tblName = $this->_table->info(Zend_Db_Table::NAME);
$prefix = substr($tblName, 0, 2);
return $prefix . '_' . parent::_transformColumn($columnName);
}
Using this, you won't need to store prefixes/table-names, as they are retrieved dinamically.