Set a value at NOW() with Propel - propel

I would like to rewrite this kind query in Propel:
UPDATE my_table
SET my_datetime_field = NOW()
WHERE my_id = 99;
Is there a way to do it?

Yes, you have a few options:
Option 1:
Assuming that you define your column as TIMESTAMP in your schema.xml, you can do this:
$row->setMyDateTimeField('now');
Read more about Propel's Temporal Clumns...
Option 2:
You can set up a hook in your class that will be called everytime a row is updated in the table:
<?php
class MyTable extends BaseMyTable
{
public function preUpdate(PropelPDO $con=null)
{
$this->setMyDateTimeField('now');
return true;
}
....
Read more about Propel's Behaviours
Conclusion
Option 2 is more beneficial if you have more than one piece of logic that updates the table, both/all the updates would benefit from this update

Related

Find max value of a column in laravel

The problem started because I have a table (Clientes), in which the primary key is not auto-incremental. I want to select the max value stored in a column database.
Like this select, but with eloquent ORM (Laravel):
SELECT MAX(Id) FROM Clientes
How can I do this?
I tried:
Cliente::with('id')->max(id);
Cliente::select('id')->max(id);
I prefer not to make a simple raw SELECT MAX(ID) FROM Clientes
I cannot make it.
Thanks all!
The correct syntax is:
Cliente::max('id')
https://laravel.com/docs/5.5/queries#aggregates
Laravel makes this very easy, in your case you would use
$maxValue = Cliente::max('id');
But you can also retrieve the newest record from the table, which will be the highest value as well
$newestCliente = Cliente::orderBy('id', 'desc')->first(); // gets the whole row
$maxValue = $newestCliente->id;
or for just the value
$maxValue = Cliente::orderBy('id', 'desc')->value('id'); // gets only the id
Or, if you have a created_at column with the date you could get the value like this
$maxValue = Cliente::latest()->value('id');
Relevant Laravel Documentation: https://laravel.com/docs/5.5/queries#aggregates
$maxValue = DB::table('Clientes')->max('id');
Cliente::where('column_name', $your_Valu)->max('id') // You get any max column
We can use the following code :
$min_id = DB::table('table_name')->max('id');
https://laravel.com/docs/8.x/queries#aggregates

Eloquent insert or update query

I have a settings table which i am trying to update. My table is empty and i need to insert some data into it.
I am using eloquent to insert
$s = new Settings;
$s->language = request('language');
$s->sitename = request('sitename');
$s->user_id = Auth::id();
$s->save();
return redirect('settings');
I have come across this function
$se = Settings::findOrNew($id); // if exist then update else insert
The findOrNew requires me to know the id before i can save.
How can insert or update without knowing the id(which may not even exist in the first place).
Well in that cause you can use firstOrNew
since you said your basis is you wanted to check if that user_id already exist in table then you use it as condition instead of id
first -> you use firstOrNew
this function do is
check if condition exist it then if it exist it will just return the first existing data
if not just insert a new data and return the new insert data
$s = User::firstOrNew(array('user_id' => Auth::id()));
Then -> after that you can now use that object and do what you wanted to do on it
$s->language = request('language');
$s->sitename = request('sitename');
$s->save();

Laravel get all the values of a column beginning with a number

I have a model called "Image" and a table called "images". The table has a column for the "id" and another for the "name". I need to fetch only the rows with the name beginning with a number.
I need to fetch are called something like
16783521_facebook.png
While the others are something like...
twiter.png
Try this:
Image::whereRaw("name REGEXP '^[0-9]'") -> get();
If it's something you're going to use in more than 1 place, consider moving it to a scope.
In your image model define something like:
public function scopeNumeric($query)
{
return $query -> whereRaw("name REGEXP '^[0-9]'");
}
Then you can just use:
Image::numeric() -> get();
I dont know much about laravel, but this plain query will help -
SELECT * FROM mytable WHERE mycolumn REGEXP '^[0-9]+$' or
SELECT * FROM myTable WHERE col1 REGEXP '[0-9]+';
Laravel doesn't have that built-in, so you'll have to make do with raw queries. In its base form:
$results = SomeModel::whereRaw("some_column REGEXP '^[0-9]'")->get();
You can modify this as usual with selects, other limitations, etc. as you require.
Filter the images after the query using one of the collection methods. Like below solved me.
$onlyNumeric = $photos->filter(function ($value, $key) {
return is_numeric(substr($value, 0, 1));
});

Can not Soft delete multiple rows using Query Builder

My model is something like this:
namespace App;
use Illuminate\Database\Eloquent\SoftDeletes;
class Photo extends Model {
use SoftDeletes;
protected $dates = ['deleted_at'];
}
_ I can soft delete using:
$\App\Photo::find(1)->delete();
_ It does not work when I try to use soft delete on multiple rows:
\App\Photo::whereIn('id', [1,2,3])->delete();
Does any one know why?
No, you can't soft delete multiple rows.
The only Laravel way is the DB facade in this case.
Here is how I would soft delete multiple rows.
DB::table('table_name')->whereIn('id', [array of ids])
->update([
'deleted_at' => now()
]);
or
ModelName::whereIn('id', [array of ids])
->update(['deleted_at' => now()]);
Instead of whereIn you can put in any where condition like you usually put and can update the deleted_at key. Soft delete is nothing but marking the column as deleted.
This is also a very efficient solution rather than running soft delete for each model inside a loop which can crash the system if there're too many items in the array.
Hope this helps.
The soft delete functionality only works on an instance of the Eloquent model itself. When you are doing this:
\App\Photo::find(1)->delete();
You are actually first retrieving the Photo with an ID of 1 from the database which is then prepared and made available as an instance of the Eloquent model (which can then use soft delete).
However, when you do this:
\App\Photo::whereIn('id', [1,2,3])->delete();
You are not actually retrieving anything from the database, you are basically just preparing DELETE SQL in a more convenient way. This effectively runs something like:
DELETE FROM `photos` WHERE `id` IN (1,2,3);
This is different from something like:
foreach (\App\Photo::whereIn('id', [1,2,3])->get() as $photo) {
$photo->delete(); # $photo is an eloquent model and can soft-delete
}
Notice the ->get() which is actually grabbing data from the database first and will make it available as a collection of Eloquent models (which then can soft delete).
I don't think you can soft-delete a batch. In my foreach example using ->get() I imagine multiple queries are executed - something like:
UPDATE `photos` SET `deleted_at` = NOW() WHERE `id` = 1;
UPDATE `photos` SET `deleted_at` = NOW() WHERE `id` = 2;
UPDATE `photos` SET `deleted_at` = NOW() WHERE `id` = 3;
Hope that makes sense.
Try this as well:
\App\Photo::whereIn('id', [1,2,3])
->get()
->map(function($photo) {
$photo->delete();
});

How to make doctrine ignore database column prefixes?

Typically i create my entities in symfony2/doctrine from this console commands :
$php app/console doctrine:mapping:import TestSiteBundle yml
$php app/console doctrine:generate:entities Test --path=src/
but my table columns have prefixes like this :
table: user
id_user
id_address (FK)
nm_name
dt_created
bl_active
and it generates entities like this :
$idUser
$idAdress
$nmName
$dtCreated
$blActive
how can i ignore my column prefixes ? do i need to change my entire database column names ?
I think you can add the name like this:
Doctrine\Tests\ORM\Mapping\User:
fields:
created:
name: dt_created
type: datetime
you can see:
http://www.doctrine-project.org/docs/orm/2.1/en/reference/yaml-mapping.html
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
Just so I understand, you want your database column name to be id_user and you want the entity property to be $user? If so, I don't think that's possible without doing some serious hacking of the core libraries. Basically you'd need to intercept the part that generates the entity properties and add your own rules on how to name them. You'd be much better off renaming your columns. IMHO, those prefixes are unnecessary. I would change id_user to user_id, nm_name to name, dt_created to created_at, and bl_active to is_active. Your column names and property names will not only match (this is a good thing) but they'll make more sense.
Hope this helps.
You can patch Doctrine to strip prefixes upon reverse engineering of your database.
Open this file in IDE: https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php
Add method to class DatabaseDriver implements Driver :
private function deprefixFieldName( $fieldName ) {
return implode('_',array_slice(explode('_',$fieldName),1));
}
Edit method:
public function setFieldNameForColumn($tableName, $columnName, $fieldName)
{
/* ADD */ $fieldName = $this->deprefixFieldName($fieldName);
$this->fieldNamesForColumns[$tableName][$columnName] = $fieldName;
}
Edit method:
private function getFieldNameForColumn($tableName, $columnName, $fk = false)
{
/* ... */
/* ADD */ $columnName = $this->deprefixFieldName($columnName);
return Inflector::camelize($columnName);
}
My method is so simple because my prefixes are all consistent ( i took the idea from Media Wiki ), yours may be more complex.
Here's the actual patch taken by Git from working system, just in case i made a typo in description: http://pastebin.com/FHeTCUjZ ( i wonder if patches in posts are allowed).

Resources