Setup CakePHP with an existing Database - php

I have a MySQL server database currently setup which has a few simple tables to track orders, such as tblOrders, tblUsers, tblProducts.
Although I have a website working with it fine now, I'd like to setup CakePHP to act as the server side framework for handling interaction with the database rather than using hand written queries in my PHP pages.
Is there a simple way to setup CakePHP with my existing Database/tables?
If I understand correctly, I will have a main MyApplication class which Extends Controller, as well as Order, User, Product, (... other tables) classes which each extend the MyApplication class.
It looks like the REST guide uses a method in the configuration file called Router::mapResources('recipes');. Will this create the controllers for each table with the default methods to use for REST?
I.e., in the /app/config/routes.php configuration file:
// /app/config/routes.php
Router::mapResources('tblOrders');
Router::mapResources('tblUsers');
Router::mapResources('tblProducts');
// /app/config/database.php
<?php
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/myStoreDB',
'persistent' => false,
'host' => 'localhost',
'login' => 'admin_user',
'password' => 'c4k3roxx!',
'database' => 'main_db',
'prefix' => ''
);
}

If you want Model, Controller and View code created for you, you're looking for baking.
Cake expects your database tables to follow a naming convention. I'm not sure how the bake will go because your tables don't match this convention. You may need to create your model classes by hand and specify the useTable attribute on each class. For example:
<?php
class Order extends AppModel {
public $useTable = 'tblOrders';
}
Once this is done, I expect the baking of Controllers and Views should work as normal. Note that with mapResources you still need Controller code. That function just generates routes.
If Cake is the only thing that will be touching this database, I recommend renaming tables and columns in line with the conventions it expects.

Related

Laravel / Lumen ReadOnly Model?

There are some tables in our system which are being fed using 3rd party APIs and our system is supposed only read data from them and never Insert or Update anything.
Is there any feature in Laravel/Lumen, where we can mention in the Model to disallow/disable insert/update queries like we have the option public $timestamps = false; to disable the timestamps?
The tables are in same database else we would have restricted based on MySQL user.
There are a few ways.
OPTION 1: Probably the quickest is this "read-only" model trait. https://github.com/michaelachrisco/ReadOnlyTraitLaravel
It protects you from...
create
forceCreate
save
update
firstOrCreate
firstOrNew
delete
destroy
restore
forceDelete
performDeleteOnModel
push
finishSave
performUpdate
touch
insert
truncate
OPTION 2: A completely different way to do it is on the db config and model connection. So, this has 2 parts.
project/config/database.php
Duplicate and tweak the db connection.
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
...
'readonly' => [
'driver' => 'mysql',
'read' => [
'host' => env('DB_HOST', '127.0.0.1')
],
'write' => [
'host' => 'this.will.404'
],
...
project/app/MyReadOnlyModel.php
class MyReadOnlyModel extends Model
{
protected $connection = 'readonly';
...
}
If you are caught in the trap of wanting the Model to be writable sometimes... I would suggest having 2 models on the same table.
app/Normal/MyModel.php
app/ReadOnly/MyModel.php
yes,
as a secure way:
as you can restricting some actions on Database.
ReadOnly Model
but you can disable the eloquent models too.
laravel models are extended from Illuminate\Database\Eloquent\Model
you can extend an ReadOnlyModel from Model.
then extend any model you want from that class.
this class should Override any method which writes data in db,
so i follow the source code:
Update and updateOrFail, push and etc was using used Model->save() method.
While create,creteOrFail , delete and etc were places in Builder which uses Model->save() method
The save() method used performUpdate or performInsert with someevent triggering ...
so the simplest thing you can do to stop model from touching databases is to implement:
<?php
namespace App\ReadOnlyDB;
use Illuminate\Database\Eloquent\Model;
/**
* Just Extend all of Your Models from This Class
*
*/
class ReadOnlyModel extends Model
{
public function save(){
// do nothing
}
}
save() methods in Relation and BelongsTo classes would use Model->save() method too.
The most secure way will be to create a second MySQL user with the readonly only on the tables.
Then in Laravel you can create a specific connection with the restricted MySQL user in your config/database.php.
Then in the Model specify the wanted connection through the protected $connection property.
I think the only proper way to manage this is to have access restrictions at the MySQL user side. Here's why:
If you are stubbing (disabling) save/update methods from the Eloquent class, you only disable save/updates for your own code. This is analogous to locking a door while hanging the key on the door handle. Nothing prevents you from doing the saves/updates since you are not bound to use the Eloquent class.
In addition, 3rd party packages may persist data which does not depend on your code. You basically have to check every single line of code of theirs to make sure your database is not updated.
Therefore, apply these restrictions at the database user level. Then, when for some reason your (or anyone elses) code calls $myModel->save(), you should face an exception from the ORM that states you do not have permission. Then, handle it accordingly (like returning a particular HTTP status code).
Create an additional mySql user with read-only privileges.
in .env file add the following
DB_CONNECTION_SECOND=mysql
DB_HOST_SECOND=127.0.0.1
DB_PORT_SECOND=3306
DB_DATABASE_SECOND=database
DB_USERNAME_SECOND=user_2
DB_PASSWORD_SECOND=secret
in config/database.php add the following
'mysql2' => [
'driver' => env('DB_CONNECTION_SECOND'),
'host' => env('DB_HOST_SECOND'),
'port' => env('DB_PORT_SECOND'),
'database' => env('DB_DATABASE_SECOND'),
'username' => env('DB_USERNAME_SECOND'),
'password' => env('DB_PASSWORD_SECOND'),],
in your controller specify the connection name..
DB::connection('mysql2')->select(...);
Maybe using an empty fillable attribute in your model resolve your problem!
protected $fillable = [];
Set a model accessor to throw an exception when touching an attribute.
But this is more of a read-only attribute instead of a read-only model since it requires one accessor per attribute.
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
protected function value(): Attribute
{
return Attribute::make(
set: fn () => throw new Exception('Model is readonly'),
);
}

How can I call AppController's method based on database tables?

I am trying to make CRUD of all database tables in APP controller instead of all CRUD related functions in inherited controllers.
For example:
www.example.com/settings/edit/1
www.example.com/users/edit/1
www.example.com/news/edit/1
I want to shift this Edit functionality to App controller.
In that case, because of all controllers (settings, users, news) are inherited from APP so they can access AppController's method EDIT.
I want to access this without creating a file of inherited controller.
I am trying with this routes.
$routes->connect('/:table/edit/:recordId', ['controller' => 'app', 'action' => 'edit'],['pass' => ['table', 'id'], 'id' => '\d+']);
But its showing error
Missing argument 2 for App\Controller\AppController::edit()
while in controller I wrote :
public function edit($table, $recordId){
}
Any help regarding this will be really appreciable.
Thanks

Registering a custom validator in Zend 2

I create a custom date Validator. But I keep getting this error message:
"Zend\Validator\ValidatorPluginManager::get was unable to fetch or
create an instance for date_validator"
I did some research and tried adding in module.config.php after the view manager array.
'validators' => array(
'invokables' => array(
'date_validator' => 'Administrativo\InputFilter\Date_Validator'
),
),
What am I missing here?
Your configuration seems okay.
Are you sure you have a file (invokable class) with the name Date_Validator in a folder Administrativo\InputFilter in your module?
Is the namespace inside this class Administrativo\InputFilter and is the class name Date_Validator.
It is important that both the class name and namespace have to be correct as well as the folder names and file name. Otherwise the PluginManager will not be able to find your file.
UPDATE
If all that is fine then there is something else you should check.
If you build your input filters through config array then you should make sure that the factory inside your InputFilter class holds a correctly populated InputFilterPluginManager instance (with both ValidatorManager and FilterManager on board). Otherwise it will not inject those classes in the setInputFilterManager method and it will later create a new empty plugin manager instance which will obviously not hold your validator class.

ZF2 view plugin manager not merging config

On my module.config.php I've got something like:
return [
'view_helpers' => [
'invokables' => [
'mycustomviewhelper' => 'Namespace\View\Helper\MyCustomViewHelper',
],
],
];
I have also got a utility class that will handle the responsibility of rendering a helper. Something like Zend\Paginator.
Zend\Paginator has a __toString() method that proxies to render() call, which instantiates View\Renderer\PhpRenderer() and then calls $view->paginationControl($this).
I am trying to replicate the similar functionality in my utility class, which has similar strategy to what Zend\Paginator already does, the only thing being different is my view helper is a custom one. Hence, my code looks like:
$view->MyCustomViewHelper($this);
This does not work, because the PhpRenderer ignores the config defined manually and does the following in getHelperPluginManager:
$this->setHelperPluginManager(new HelperPluginManager());
I've tried invoking the helpers already defined in ViewHelperManager and this works well.
I did try merging in the config beforehand and then setting the PhpRenderer in the view but then this caused other problems, such as my partials were not found etc.
Now my question is why does ZF not consider any custom registered views when trying to render it in isolation. Is there any other way to do this?
Thank you.
Right, after a bit of a debugging, and playing with the configs, I was able to make this work. Still not sure if this is the best way to do this, but looks like currently there's no other way to make it work.
I created a factory for the utility class, instantiated the PhpRenderer, and then merged in my config with the ViewPluginManager manually. My factory now looks like:
public function createService(ServiceLocatorInterface $serviceLocatorInterface)
{
$dataTable = new DataTable;
$phpRenderer = new PhpRenderer();
$config = new \Zend\ServiceManager\Config([
'invokables' => [
'datatablerenderer' => 'DataTable\View\Helper\DataTableRenderer'
],
]);
$phpRenderer->setHelperPluginManager(new HelperPluginManager($config));
$dataTable->setView($phpRenderer);
return $dataTable;
}
However will have to refactor this so that the config comes from the view_helpers config key and is not hardcoded.

zend module autoloading

I have developed a small application and now I want to create and administrator module. In the future I would like to add different modules but for now i would like to treat this admin as a module and to access it like http://host/module/controller
I have read about zend_autoloader and wrote this in my Bootstrap.php
protected function _initAutoload() {
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Admin',
'basePath' => '/modules/admin'
));
I have created a default IndexController with the default index view file. When I try to access http://host/admin or http://host/admin/index i get an application error and of course the view is not loaded.
What am i doing wrong?
For everyone having the problem this guy sorts it out in the most newbish way possible.
http://www.zfforums.com/zend-framework-general-discussions-1/resources-developers-37/setup-multi-modules-zend-framework-v1-9-13-steps-3737.html

Categories