In CakePHP 1.x/2.x, it was fairly simple to have a model's data come from a REST API (as opposed to a relational database), by defining a custom datasource. (Neil Crookes' CakePHP-ReST-DataSource-Plugin was a great place to start.) Slap your custom datasource on your model, and you're making calls like $this->MyModel->find() just like you were querying a MySQL table called my_models.
I'm trying to figure out how to achieve this same effect under CakePHP 3.0. That is, make find()/save()/set()/get() calls against a Table/Entity driven by a REST API.
Since 3.0's ORM system is A) fairly new, and B) a rather large departure from the old way of doing things, I haven't found any information about how to do something like this. In fact, based on this SlideShare from
José Lorenzo RodrÃguez, it sounds like it might not be possible.
This means:
not going to connect to stuff that is not a relational database.
Is there someone more familiar with CakePHP 3.0 that could clarify if what I'm looking for is possible under the new ORM system? If so, could you explain what classes you'd have to extend or implement to achieve such a function?
If you want to create a complete adapter for your Rest datasource using the interfaces and classes provided by CakePHP, take a look at this early experiment fro the CakePHP team on making a datasource for Elastic Search.
Elastic Search uses a Rest API and this plugin attempts to create classes that work similar to the CakePHP ORM:
https://github.com/cakephp/elastic-search
What it implements is basically the following:
A Type class that implements the RepositoryInterface
A Document class that implements the EntityInterface
A Query class that can be used as a collection object and has similar methods
In the near future it will provide a paginator adaptor and a form helper adaptor.
If you want to save yourself this trouble, because there for you there is little value in exposing your datasource as something ORM-like, you can just use guzzle or any similar library to interface with your API and use it as a service instead of a full-blown layer.
In the year since I asked this question, UseMuffin has built a Webservice plugin that purports to "bring [...] the power of the CakePHP ORM to your favourite webservices." This sounds like exactly what I wanted at the time.
Related
Supposed you need to interact with/integrate 5+ different web service sources instead of tables from the database.
In first lane each WS supports read methods like search,list and single view (in short, no CUD from CRUD). Write access should also take place later.
What would be your approach to integrate those to extbase?
I'd like to stick to the conventions of models and repositories. In this case, i think we need to use Models and CustomRepositories. Should the repositories interact directly with the webservice or should we think bigger with an PersistenceManagerInterface implementation and extending the Generic/Query to e.g. paginate on the results by extbase conventions? What is about TypeConverters and PropertyMappers for linking between controller actions with the models "as parameters".
How could a mapping from JSON to the models look like? A TCA configuration is required for the DataMapper, but this is not available because no DB is used, so it cannot be used.
Where should you start?
I don't have Gateway available in my landscape and I want to use the ABAP REST library to expose web services: SAP Library - REST Programming Tutorial
With a very simple example, I successfully created a class to read a single domain list of values, the GET call is quite simple:
http://mydomain/domainvalues/XFELD
And the GET implementation is in my class ZCL_REST_DOMAIN_VALUES extending from CL_REST_RESOURCE implementing IF_REST_RESOURCE~GET method.
Now I want to make it possible to read or query multiple domains. I'm not an expert in REST but I've seen two options searching around, one using the same URI as the single entity and one with special URI for queries.
http://mydomain/domainvalues?Id=XFELD,WERKS_D
http://mydomain/query/domainvalues?Id=XFELD,WERKS_D
In the backend, should I use the second approach and create a class only for this call named for instance ZCL_REST_DOMAIN_VALUES_QUERY implementing the GET method again?
Or maybe should I use POST method to send the list of IDs to fetch in the body?
SAP's own in-house guidelines recommend to shape OData and plain REST services alike, to avoid confusion and facilitate switching between the two:
http://mydomain/domainvalues?$filter=Id in ('XFELD', 'WERKS_D')
Both would be served by the same REST endpoint handler class, although of course you are free to create separate methods or delegates for the cases.
Remember to sanitize (= whitelist/blacklist/escape) the query parameters before handing them over to some lower level to prevent SQL injection attacks, as #SandraRossi correctly pointed out below.
I have to select a framework (or role my own) and one of the databases I have to connect to is FoxPro. I found a driver here at http://adodb.sourceforge.net/ and I am guessing it's okay to use, but I don't know if I can use it in Zend. I thought Zend came with an ORM too so I didn't now if I could use it with that. Thanks.
EDIT: A better question may be can zend_db be used with adodb? can I use both of these at the same time in my zend implementation? zend_db and pdo do no have a foxpro adapter.
Zend does include Zend_Db_Adapter which provides a loose abstraction around basic database operations.
It also provides Zend_Db_Table (and other associated classes) which implement the Table Data Gateway pattern.
But you don't have to use any of Zend's database functionality if you don't want to. So the answer to your question is definitely yes. You can use ADODb in a Zend application -- or any other approach to database access that you may prefer. Just build your model objects using your db abstraction of choice, and then use them like normal from within your Zend action controllers.
Before I start to build this myself I thought I'd ask others to share their experience. What's the best / your favorite way to paginate a dataset with an application built upon Zend_Framework and Doctrine as your ORM?
I'm new to Doctrine.
I'm calling the model directly from a View Helper, bypassing the Controller, although I'm still interested if your solution uses controllers.
I did see one article on this topic:
http://ciaranmcnulty.com/blog/2009/06/Simplify-pagination-logic-using-a-custom-zend-paginator-adapter
Devzone has an article using Doctrine, Zend Framework OR Pear, but none of those options mention a #ZF app that uses Doctrine.
You don't need anything special.
Look on Github for ready paginator adapter, e.g. this one.
In theory, one way is to create a custom data source adapter and plug it into Zend Paginator. http://framework.zend.com/manual/en/zend.paginator.advanced.html
I am very experienced with the CakePHP framework but am checking out the Zend Framework for an application that will receive massive traffic.
I'm going through the quickstart tutorial in the documentation and got to the "Create a Model and Database Table" page.
Must I or should I create all those model classes it mentions, i.e.
application/models/DbTable/Guestbook.php
application/models/GuestbookMapper.php
application/models/Guestbook.php
Coming from CakePHP it seems like quite a lot of code for some functionality I would of thought of as quite basic and generic.
Or can I just create application/models/Guestbook.php and have it extend Zend_Db_Table_Abstract?
Any help would be much appreciated.
You can create your model after the DbTable class, however one of the benefits of doing a dataMapper class between your model and your DbTable class is that you can abstract more the data engine and create strong business rules.
Zend Framework does not actually impose any restrictions or requirements on your Model classes and you are free to create them however you would like.
Depending on the requirements and scope of the project I generally still go with subclassing Zend_Db_Table_Abstract (often with my own custom extension of it as well). When it comes to a large or complicated project I have found that using a dataMapper pattern has been very helpful.
At the same time I have had some models that do not extend any class at all. They simply are there to provide some logic and do not relate to a database.