I am building a custom artisan command that needs to be able to access the database's default values for certain columns. I cannot use the attributes array. So instead I need another way.
I have tried to use Schema. I have been able to get the table DB::table($table) and the column names Schema::getColumnListings($table) but not the default values.
Is there some other way to get the default values?
The Laravel Schema Builder only returns column names by design. But you can use the same approach Laravel uses internally by executing a database statement:
$results = DB::select('
select column_default
from information_schema.columns
where
table_schema = ?
and table_name = ?
', [$database, $table]);
// Flatten the results to get an array of the default values
$defaults = collect($results)->pluck('column_default'))
The above example works for a MySQL database, but you can see the approaches for other databases in the Illuminate\Database\Schema\Grammars namespace of the Laravel source code by searching for the method compileColumnListing.
In Laravel 5+ (including 6 and 7), you can get the db table column metadata (ie type, default value etc) in the following way:
use Illuminate\Support\Facades\Schema;
For all columns:
$columns = Schema::getConnection()->getDoctrineSchemaManager()->listTableColumns('table_name');
For a single column:
$column = Schema::getConnection()->getDoctrineColumn('table_name'', 'column_name');
getDoctrineSchemaManager method returns a array of \Doctrine\DBAL\Schema\Column Class Instances. By using this you can get everything about a db table column.
getDoctrineColumn method returns the instance of \Doctrine\DBAL\Schema\Column class.
Couple of methods from \Doctrine\DBAL\Schema\Column class:
$column->getName();
$column->getNotnull(); // returns true/false
$column->getDefault();
$column->getType();
$column->getLength();
Related
ProductCategory::insert($insertData);
I am using this above statement passing an array for inserting multiple record $insertData working fine but when check my created_at and updated_at column not getting timestamp.
You have to use create() (remember to set $fillable):
foreach($insertData as $data) {
ProductCategory::create($data);
}
You need to use Laravel Eloquent feature to make timestamps written to the Database automatically, when you insert data directly, Laravel does not know about your timestamps. You need to set the timestamps manually in the insert statement.
Use Eloquent models, like following :-
foreach($insertData as $data) {
ProductCategory::create($data);
}
Eloquent ORM
The insert() method is a direct SQL statement by the QueryBuilder. It converts your array of values into a query statement to insert without mutators or other magic.
You can do a couple things to set these values. You can loop through an do a single insert for each row of data using ProductCategory::create($array);. Which will do a query per insert.
Or you can add the created_at and updated_at values to your array collection directly. Laravel has a method built in to set the updated at column on an array \Illuminate\Database\Eloquent\Builder::addUpdatedAtColumn() if you wanted to loop through $insertData and set it. If you look at it you'll see it just applies to the updated_at column. You need the created_at value too.
I would recommend you doing something like this if you wish to keep a single insert statement:
$object = new ProductCategory();
$insertData = array_map(function ($data) use ($object) {
$timestamp = $object->freshTimestampString();
$data[$object->getUpdatedAtColumn()] = $timestamp;
$data[$object->getCreatedAtColumn()] = $timestamp;
return $data;
}, $insertData);
$object->insert($insertData);
i need to get specific columns in the 2 methods that is being chained inside 'with', but it doesnt work, how can i select specific columns in each method inside of the 'with' method.
Event::with('eventBookmakers.bookmakerInfo')->find(2);
It's possible like this:
Event::with('eventBookmakers:column', 'eventBookmakers.bookmakerInfo:column')->find(2);
Remember to select the foreign key columns (e.g. event_id).
Try this, change column name to what column you want to retrieve.
Event::with('eventBookmakers.bookmakerInfo:columnName')->where('id', 2)->get();
or
Event::with('eventBookmakers.bookmakerInfo:columnName')->find(2);
Since you're selecting the two interrelated tables (relations) using dot . You may use select() and with() in a closure to add constraint and add the relations as well. So you'll end up with something like:
Event::with(['eventBookmakers' => function($bookmakers){
$bookmakers->select('id', 'event_id')->with(['bookmakerInfo' => function($info) {
$info->select('id', 'bookmaker_id');
}]);
}])->find(2);
Note the event_id passed to the first select ensure the relationship is loaded between Event and EventBookmaker(you can replace it with the relation_id you use instead) and same thing with using bookmaker_id so that it may load relation between Bookmaker and BookmakerInfo
I am storing destinations field as json type in mysql
example column value ["Goa", "Moonar", "Kochi"]
I would like to get all rows that matches goa as destinations
However this row query returns the desired result
SELECT * FROM `packages`
WHERE JSON_CONTAINS(destinations, '["Goa"]');
But what is the eloquent equivalent of the above query??
Laravel version 5.3
Modelname :Search
Probably forced to use a partially raw query like:
use DB; (top of file definition)
DB::table('packages')->whereRaw('json_contains(destinations, \'["Goa"]\')')->get();
And if you have a model:
Package::whereRaw('json_contains(destinations, \'["' . $keyword . '"]\')')->get();
assuming your query above works in SQL.
In Laravel 5.6 and higher you can use whereJsonContains method:
Package::whereJsonContains('destinations',["Goa"])->get();
But not all DB support it: https://laravel.com/docs/5.6/queries#json-where-clauses
I would like to have an output of all schema tables using propel. When referencing to a particular TableMap
$users = UsersTableMap::getTableMap();
$map = $users->getDatabaseMap();
$tables = $map->getTables(); //yields an object, holds only Users table
Is there a way not to use a particular table (e.g. Users) but have a more general approach? There is a bit outdated question here that faces the same problem.
Should I make a custom query or parse the schema.xml to retrieve all tables?
Update
Some of the solutions given below as answers produce empty array
$map = Propel::getServiceContainer()->getDatabaseMap(); //w & w/o string argument
$tables = $map->getTables(); //an empty array
There's no way in the current version 2 to retrieve all table maps with one call. Why: We would need to load all table maps which is incredible slow and we have no total "map"/"array" listing with all available table maps that was available at buildtime. In Propel3 however, this is possible.
The only solution you should follow is parsing the schema.xml: How do I check if table names are valid in Propel?
What you can additional do is to reverse the real database using the reverse classes of Propel. However, this is very slow as it will read all the time the whole database structure. See https://github.com/propelorm/Propel2/issues/261#issuecomment-40659647
you can access the db map by obtaining the current propel service container, eg:
$dbMap = Propel::getServiceContainer()->getDatabaseMap();
$tables = $dbMap->getTables();
Specifically the code abowe will extract the db map from the default connection, but you can specify another connection configured, let's assume you have a secondary connection called "asdrubale":
$dbMap = Propel::getServiceContainer()->getDatabaseMap('asdrubale');
$tables = $dbMap->getTables();
You could try this:
<?php
use Propel\Runtime\Propel;
$map = Propel::getServiceContainer()->getDatabaseMap('default');
$tables = $map->getTables();
default should be replaced with whatever name you defined for your database connection.
I have a query like e.g
$criteria = new CDbCriteria();
$criteria->select = array(
'CASE
when userid is not null then userid
end
as A',
'CASE
when userid is not null then \'D\'
end
as H');
$result = MyModel::model()->findAll($criteria);
when i foreach the $result, am getting objects in each of those results
and I can only get the actual table column like e.g
$obj->USERID
I want to get the alias that i used in the select statement like e.g
$obj->A OR $obj->H
but if I do that, am getting an error, because A and H are not properties of the MyModel
is it possible to get the "as" names as table columns from the result of the findAll?, if so, how?
In CActiveRecord, properties are automaticallly detected based on a table schema which model base on, as you can see here.
So, the simplest way to add properties, is to add fake columns on a table which is the model base on.
Another way is to override attributeName() method. You can add properties to the model. see here.